Skip to content
This repository has been archived by the owner on Nov 10, 2023. It is now read-only.

Commit

Permalink
fix: Check both multisend contract addresses for isSupportedMultiSend…
Browse files Browse the repository at this point in the history
…Address (#4040)
  • Loading branch information
usame-algan authored Aug 5, 2022
1 parent 36f7569 commit 524f8d7
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { generateSafeRoute, history, SAFE_ROUTES } from 'src/routes/routes'
const MULTISEND_ADDRESS = '0x4242424242424242424242424242424242424242'
jest.mock('src/logic/contracts/safeContracts', () => ({
...jest.requireActual('src/logic/contracts/safeContracts'),
getMultisendContractAddress: () => MULTISEND_ADDRESS,
getMultiSendCallOnlyContractAddress: () => MULTISEND_ADDRESS,
}))

const safeAddress = '0x57CB13cbef735FbDD65f5f2866638c546464E45F'
Expand Down
39 changes: 36 additions & 3 deletions src/logic/contracts/safeContracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@ import { SignMessageLib } from 'src/types/contracts/sign_message_lib.d'
import { MultiSend } from 'src/types/contracts/multi_send.d'
import { getSafeInfo } from 'src/logic/safe/utils/safeInformation'
import { NonPayableTransactionObject } from 'src/types/contracts/types'
import { getMultiSendDeployment } from '@gnosis.pm/safe-deployments/dist/libs'
import { MultiSendCallOnly } from 'src/types/contracts/multi_send_call_only'

export const SENTINEL_ADDRESS = '0x0000000000000000000000000000000000000001'

let proxyFactoryMaster: ProxyFactory
let safeMaster: GnosisSafe
let fallbackHandler: CompatibilityFallbackHandler
let multiSendCallOnly: MultiSendCallOnly
let multiSend: MultiSend

const getSafeContractDeployment = ({ safeVersion }: { safeVersion: string }): SingletonDeployment | undefined => {
Expand Down Expand Up @@ -130,13 +133,32 @@ const getFallbackHandlerContractInstance = (web3: Web3, chainId: ChainId): Compa
* @param {Web3} web3
* @param {ChainId} chainId
*/
const getMultiSendContractInstance = (web3: Web3, chainId: ChainId): MultiSend => {
const getMultiSendCallOnlyContractInstance = (web3: Web3, chainId: ChainId): MultiSendCallOnly => {
const multiSendDeployment =
getMultiSendCallOnlyDeployment({
network: chainId.toString(),
}) || getMultiSendCallOnlyDeployment()
const contractAddress = multiSendDeployment?.networkAddresses[chainId]

if (!contractAddress) {
throw new Error(`MultiSendCallOnly contract not found for chainId: ${chainId}`)
}

return new web3.eth.Contract(multiSendDeployment?.abi as AbiItem[], contractAddress) as unknown as MultiSendCallOnly
}

/**
* Creates a Contract instance of the MultiSend contract
* @param {Web3} web3
* @param {ChainId} chainId
*/
const getMultiSendContractInstance = (web3: Web3, chainId: ChainId): MultiSend => {
const multiSendDeployment =
getMultiSendDeployment({
network: chainId.toString(),
}) || getMultiSendDeployment()
const contractAddress = multiSendDeployment?.networkAddresses[chainId]

if (!contractAddress) {
throw new Error(`MultiSend contract not found for chainId: ${chainId}`)
}
Expand Down Expand Up @@ -212,6 +234,9 @@ export const instantiateSafeContracts = (): void => {

// Create MultiSend contract
multiSend = getMultiSendContractInstance(web3, chainId)

// Create MultiSendCallOnly contract
multiSendCallOnly = getMultiSendCallOnlyContractInstance(web3, chainId)
}

export const getSafeMasterContract = (): GnosisSafe => {
Expand All @@ -227,11 +252,19 @@ export const getFallbackHandlerContractAddress = (): string => {
return fallbackHandler.options.address
}

export const getMultisendContract = (): MultiSend => {
export const getMultiSendCallOnlyContract = (): MultiSendCallOnly => {
return multiSendCallOnly
}

export const getMultiSendCallOnlyContractAddress = (): string => {
return multiSendCallOnly.options.address
}

export const getMultiSendContract = (): MultiSend => {
return multiSend
}

export const getMultisendContractAddress = (): string => {
export const getMultiSendContractAddress = (): string => {
return multiSend.options.address
}

Expand Down
4 changes: 2 additions & 2 deletions src/logic/safe/store/actions/TxMultiSender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { isMultisigExecutionInfo, Transaction } from 'src/logic/safe/store/model
import { MultiSend } from 'src/types/contracts/multi_send.d'
import { addPendingTransaction, removePendingTransaction } from 'src/logic/safe/store/actions/pendingTransactions'
import { Errors, logError } from 'src/logic/exceptions/CodedException'
import { getMultisendContract } from 'src/logic/contracts/safeContracts'
import { getMultiSendCallOnlyContract } from 'src/logic/contracts/safeContracts'
import { createTxNotifications } from 'src/logic/notifications'
import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions'
import * as aboutToExecuteTx from 'src/logic/safe/utils/aboutToExecuteTx'
Expand Down Expand Up @@ -31,7 +31,7 @@ export class TxMultiSender {
constructor({ transactions, multiSendCallData, dispatch, account, safeAddress }: TxMultiSenderProps) {
this.transactions = transactions
this.multiSendCallData = multiSendCallData
this.multiSendContract = getMultisendContract()
this.multiSendContract = getMultiSendCallOnlyContract()
this.dispatch = dispatch
this.account = account
this.notifications = createTxNotifications(dispatch, TX_NOTIFICATION_TYPES.STANDARD_TX)
Expand Down
3 changes: 2 additions & 1 deletion src/logic/safe/transactions/__tests__/multisend.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { isSupportedMultiSendCall } from 'src/logic/safe/transactions/multisend'
const MULTISEND_ADDRESS = '0x40a2accbd92bca938b02010e17a5b8929b49130d'
jest.mock('src/logic/contracts/safeContracts', () => ({
...jest.requireActual('src/logic/contracts/safeContracts'),
getMultisendContractAddress: () => MULTISEND_ADDRESS,
getMultiSendCallOnlyContractAddress: () => MULTISEND_ADDRESS,
getMultiSendContractAddress: () => MULTISEND_ADDRESS,
}))

describe('isSupportedMultiSendCall', () => {
Expand Down
13 changes: 9 additions & 4 deletions src/logic/safe/transactions/multisend.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { Transaction } from '@gnosis.pm/safe-apps-sdk-v1'

import { getWeb3 } from 'src/logic/wallets/getWeb3'
import { getMultisendContract, getMultisendContractAddress } from 'src/logic/contracts/safeContracts'
import {
getMultiSendCallOnlyContract,
getMultiSendCallOnlyContractAddress,
getMultiSendContractAddress,
} from 'src/logic/contracts/safeContracts'
import { MultiSend, TransactionInfo } from '@gnosis.pm/safe-react-gateway-sdk'
import { isCustomTxInfo } from 'src/logic/safe/store/models/types/gateway.d'
import { sameString } from 'src/utils/strings'
Expand All @@ -13,7 +17,7 @@ export interface MultiSendTx {
}

export const encodeMultiSendCall = (txs: Transaction[]): string => {
const multiSend = getMultisendContract()
const multiSend = getMultiSendCallOnlyContract()
const joinedTxs = getMultiSendJoinedTxs(txs)

return multiSend.methods.multiSend(joinedTxs).encodeABI()
Expand All @@ -40,9 +44,10 @@ export const getMultiSendJoinedTxs = (txs: Transaction[]): string => {

export const isSupportedMultiSendAddress = (txInfo: TransactionInfo): boolean => {
const toAddress = isCustomTxInfo(txInfo) ? txInfo.to.value : ''
const multiSendAddress = getMultisendContractAddress()
const multiSendCallOnlyAddress = getMultiSendCallOnlyContractAddress()
const multiSendAddress = getMultiSendContractAddress()

return sameString(multiSendAddress, toAddress)
return sameString(multiSendAddress, toAddress) || sameString(multiSendCallOnlyAddress, toAddress)
}

export const isSupportedMultiSendCall = (txInfo: TransactionInfo): txInfo is MultiSend =>
Expand Down
4 changes: 2 additions & 2 deletions src/logic/safe/utils/__tests__/upgradeSafe.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const SAFE_MASTER_COPY_ADDRESS = '0x34CfAC646f301356fAa8B21e94227e3583Fe3F5F'
const DEFAULT_FALLBACK_HANDLER_ADDRESS = '0xd5D82B6aDDc9027B22dCA772Aa68D5d74cdBdF44'

jest.mock('src/logic/contracts/safeContracts', () => ({
getMultisendContract: jest.fn(),
getMultiSendCallOnlyContract: jest.fn(),
}))

describe('Upgrade a < 1.3.0 Safe', () => {
Expand All @@ -23,7 +23,7 @@ describe('Upgrade a < 1.3.0 Safe', () => {

// Mock multisend contract instance
const multiSendCallOnlyDeployment = getMultiSendCallOnlyDeployment()
safeContracts.getMultisendContract.mockReturnValue(
safeContracts.getMultiSendCallOnlyContract.mockReturnValue(
new web3.eth.Contract(multiSendCallOnlyDeployment?.abi as AbiItem[]) as unknown as MultiSend,
)

Expand Down
4 changes: 2 additions & 2 deletions src/logic/safe/utils/spendingLimits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { CreateTransactionArgs } from 'src/logic/safe/store/actions/createTransa
import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions'
import { enableModuleTx, isModuleEnabled } from 'src/logic/safe/utils/modules'
import generateBatchRequests from 'src/logic/contracts/generateBatchRequests'
import { getMultisendContractAddress } from 'src/logic/contracts/safeContracts'
import { getMultiSendCallOnlyContractAddress } from 'src/logic/contracts/safeContracts'
import { SpendingLimit } from 'src/logic/safe/store/models/safe'
import { sameAddress, ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses'
import { getWeb3ReadOnly } from 'src/logic/wallets/getWeb3'
Expand Down Expand Up @@ -258,7 +258,7 @@ export const spendingLimitMultiSendTx = ({
safeAddress,
}: SpendingLimitMultiSendTx): CreateTransactionArgs => ({
safeAddress,
to: getMultisendContractAddress(),
to: getMultiSendCallOnlyContractAddress(),
valueInWei: ZERO_VALUE,
txData: encodeMultiSendCall(transactions),
notifiedTransaction: TX_NOTIFICATION_TYPES.NEW_SPENDING_LIMIT_TX,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import * as estimateTxGas from 'src/logic/hooks/useEstimateTransactionGas'
const MULTISEND_ADDRESS = '0x4242424242424242424242424242424242424242'
jest.mock('src/logic/contracts/safeContracts', () => ({
...jest.requireActual('src/logic/contracts/safeContracts'),
getMultisendContractAddress: () => MULTISEND_ADDRESS,
getMultisendContract: () => ({
getMultiSendCallOnlyContractAddress: () => MULTISEND_ADDRESS,
getMultiSendCallOnlyContract: () => ({
methods: {
multiSend: () => ({
encodeABI: () => '0x',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import styled from 'styled-components'
import { toBN } from 'web3-utils'

import { createTransaction } from 'src/logic/safe/store/actions/createTransaction'
import { getMultisendContractAddress } from 'src/logic/contracts/safeContracts'
import { getMultiSendCallOnlyContractAddress } from 'src/logic/contracts/safeContracts'
import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions'
import { encodeMultiSendCall } from 'src/logic/safe/transactions/multisend'
import { getExplorerInfo, getNativeCurrency } from 'src/config'
Expand Down Expand Up @@ -79,7 +79,7 @@ export const ReviewConfirm = ({
const isOwner = useSelector(grantedSelector)

const txRecipient: string | undefined = useMemo(
() => (isMultiSend ? getMultisendContractAddress() : txs[0]?.to),
() => (isMultiSend ? getMultiSendCallOnlyContractAddress() : txs[0]?.to),
[txs, isMultiSend],
)
const txData: string | undefined = useMemo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jest.mock('src/logic/hooks/useEstimateTransactionGas', () => {

describe('Advanced Settings Component', () => {
beforeEach(() => {
jest.spyOn(safeContracts, 'getMultisendContractAddress').mockReturnValue('mockAddress')
jest.spyOn(safeContracts, 'getMultiSendCallOnlyContractAddress').mockReturnValue('mockAddress')
})
it('Renders Advanced Settings Component', () => {
const customState = {
Expand Down
6 changes: 3 additions & 3 deletions src/routes/safe/components/Settings/UpdateSafeModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Paragraph from 'src/components/layout/Paragraph'
import Row from 'src/components/layout/Row'
import { getUpgradeSafeTransactionHash } from 'src/logic/safe/utils/upgradeSafe'
import { createTransaction } from 'src/logic/safe/store/actions/createTransaction'
import { getMultisendContractAddress } from 'src/logic/contracts/safeContracts'
import { getMultiSendCallOnlyContractAddress } from 'src/logic/contracts/safeContracts'
import { EMPTY_DATA } from 'src/logic/wallets/ethTransactions'
import { TxParameters } from 'src/routes/safe/container/hooks/useTransactionParameters'
import { ModalHeader } from 'src/routes/safe/components/Balances/SendModal/screens/ModalHeader'
Expand Down Expand Up @@ -39,7 +39,7 @@ export const UpdateSafeModal = ({ onClose, safeAddress, safeCurrentVersion }: Pr
dispatch(
createTransaction({
safeAddress,
to: getMultisendContractAddress(),
to: getMultiSendCallOnlyContractAddress(),
valueInWei: '0',
txData: multiSendCallData,
txNonce: txParameters.safeNonce,
Expand All @@ -56,7 +56,7 @@ export const UpdateSafeModal = ({ onClose, safeAddress, safeCurrentVersion }: Pr
return (
<TxModalWrapper
txData={multiSendCallData}
txTo={getMultisendContractAddress()}
txTo={getMultiSendCallOnlyContractAddress()}
operation={Operation.DELEGATE}
onSubmit={handleSubmit}
onClose={onClose}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { isCustomTxInfo, Transaction } from 'src/logic/safe/store/models/types/g
import { fetchSafeTransaction } from 'src/logic/safe/transactions/api/fetchSafeTransaction'
import { generateSignaturesFromTxConfirmations } from 'src/logic/safe/safeTxSigner'
import { getExecutionTransaction } from 'src/logic/safe/transactions'
import { getGnosisSafeInstanceAt, getMultisendContractAddress } from 'src/logic/contracts/safeContracts'
import { getGnosisSafeInstanceAt, getMultiSendCallOnlyContractAddress } from 'src/logic/contracts/safeContracts'
import { EMPTY_DATA } from 'src/logic/wallets/ethTransactions'
import { encodeMultiSendCall, getMultiSendJoinedTxs, MultiSendTx } from 'src/logic/safe/transactions/multisend'
import { userAccountSelector } from 'src/logic/wallets/store/selectors'
Expand Down Expand Up @@ -141,7 +141,7 @@ export const BatchExecute = React.memo((): ReactElement | null => {
const dispatch = useDispatch<Dispatch>()
const { address: safeAddress, currentVersion } = useSelector(currentSafe)
const account = useSelector(userAccountSelector)
const multiSendContractAddress = getMultisendContractAddress()
const multiSendContractAddress = getMultiSendCallOnlyContractAddress()
const batchableTransactions = useSelector(getBatchableTransactions)
const [txsWithDetails, setTxsWithDetails] = useState<Transaction[]>([])
const [isModalOpen, setModalOpen] = useState(false)
Expand Down Expand Up @@ -195,7 +195,7 @@ export const BatchExecute = React.memo((): ReactElement | null => {
const txs = toMultiSendTxs(txsWithDetails, safeAddress, currentVersion, account)
return {
data: encodeMultiSendCall(txs),
to: getMultisendContractAddress(),
to: getMultiSendCallOnlyContractAddress(),
}
}, [account, txsWithDetails, currentVersion, safeAddress])

Expand Down

0 comments on commit 524f8d7

Please sign in to comment.