From 426ca2f07639d53f7b8f45a378b00db4c71a58e0 Mon Sep 17 00:00:00 2001 From: Aaron Cook Date: Tue, 26 Sep 2023 08:32:57 +0200 Subject: [PATCH] fix: use MultiSendCallOnly 1.3.0 for older Safes (#2528) --- .../contracts/__tests__/safeContracts.test.ts | 16 +++++++++++++++- src/services/contracts/safeContracts.ts | 17 +++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/services/contracts/__tests__/safeContracts.test.ts b/src/services/contracts/__tests__/safeContracts.test.ts index 729baad7bf..2ae282a360 100644 --- a/src/services/contracts/__tests__/safeContracts.test.ts +++ b/src/services/contracts/__tests__/safeContracts.test.ts @@ -1,5 +1,5 @@ import { ImplementationVersionState } from '@safe-global/safe-gateway-typescript-sdk' -import { _getValidatedGetContractProps, isValidMasterCopy } from '../safeContracts' +import { _getValidatedGetContractProps, isValidMasterCopy, _getMinimumMultiSendCallOnlyVersion } from '../safeContracts' describe('safeContracts', () => { describe('isValidMasterCopy', () => { @@ -53,4 +53,18 @@ describe('safeContracts', () => { expect(() => _getValidatedGetContractProps('1', '')).toThrow(' is not a valid Safe Account version') }) }) + + describe('_getMinimumMultiSendCallOnlyVersion', () => { + it('should return the initial version if the Safe version is null', () => { + expect(_getMinimumMultiSendCallOnlyVersion(null)).toBe('1.3.0') + }) + + it('should return the initial version if the Safe version is lower than the initial version', () => { + expect(_getMinimumMultiSendCallOnlyVersion('1.0.0')).toBe('1.3.0') + }) + + it('should return the Safe version if the Safe version is higher than the initial version', () => { + expect(_getMinimumMultiSendCallOnlyVersion('1.4.1')).toBe('1.4.1') + }) + }) }) diff --git a/src/services/contracts/safeContracts.ts b/src/services/contracts/safeContracts.ts index 5da8cdd528..ada870c7db 100644 --- a/src/services/contracts/safeContracts.ts +++ b/src/services/contracts/safeContracts.ts @@ -15,6 +15,7 @@ import type CompatibilityFallbackHandlerEthersContract from '@safe-global/safe-e import type { Web3Provider } from '@ethersproject/providers' import type GnosisSafeContractEthers from '@safe-global/safe-ethers-lib/dist/src/contracts/GnosisSafe/GnosisSafeContractEthers' import type EthersAdapter from '@safe-global/safe-ethers-lib' +import semver from 'semver' // `UNKNOWN` is returned if the mastercopy does not match supported ones // @see https://github.com/safe-global/safe-client-gateway/blob/main/src/routes/safes/handlers/safes.rs#L28-L31 @@ -69,24 +70,36 @@ export const getReadOnlyGnosisSafeContract = (chain: ChainInfo, safeVersion: str // MultiSend +export const _getMinimumMultiSendCallOnlyVersion = (safeVersion: SafeInfo['version']) => { + const INITIAL_CALL_ONLY_VERSION = '1.3.0' + + if (!safeVersion) { + return INITIAL_CALL_ONLY_VERSION + } + + return semver.gte(safeVersion, INITIAL_CALL_ONLY_VERSION) ? safeVersion : INITIAL_CALL_ONLY_VERSION +} + export const getMultiSendCallOnlyContract = ( chainId: string, safeVersion: SafeInfo['version'], provider: Web3Provider, ) => { const ethAdapter = createEthersAdapter(provider) + const multiSendVersion = _getMinimumMultiSendCallOnlyVersion(safeVersion) return ethAdapter.getMultiSendCallOnlyContract({ - singletonDeployment: getMultiSendCallOnlyContractDeployment(chainId, safeVersion), + singletonDeployment: getMultiSendCallOnlyContractDeployment(chainId, multiSendVersion), ..._getValidatedGetContractProps(chainId, safeVersion), }) } export const getReadOnlyMultiSendCallOnlyContract = (chainId: string, safeVersion: SafeInfo['version']) => { const ethAdapter = createReadOnlyEthersAdapter() + const multiSendVersion = _getMinimumMultiSendCallOnlyVersion(safeVersion) return ethAdapter.getMultiSendCallOnlyContract({ - singletonDeployment: getMultiSendCallOnlyContractDeployment(chainId, safeVersion), + singletonDeployment: getMultiSendCallOnlyContractDeployment(chainId, multiSendVersion), ..._getValidatedGetContractProps(chainId, safeVersion), }) }