diff --git a/apps/web/src/components/new-safe/create/logic/index.test.ts b/apps/web/src/components/new-safe/create/logic/index.test.ts index 4870901e89..ac350705ba 100644 --- a/apps/web/src/components/new-safe/create/logic/index.test.ts +++ b/apps/web/src/components/new-safe/create/logic/index.test.ts @@ -10,7 +10,7 @@ import { getRedirect, createNewUndeployedSafeWithoutSalt, } from '@/components/new-safe/create/logic/index' -import * as relaying from '@/services/tx/relaying' +import { relayTransaction } from '@safe-global/safe-gateway-typescript-sdk' import { toBeHex } from 'ethers' import { Gnosis_safe__factory, @@ -21,6 +21,7 @@ import { getReadOnlyGnosisSafeContract, getReadOnlyProxyFactoryContract, } from '@/services/contracts/safeContracts' +import * as gateway from '@safe-global/safe-gateway-typescript-sdk' import { FEATURES, getLatestSafeVersion } from '@/utils/chains' import { chainBuilder } from '@/tests/builders/chains' import { type ReplayedSafeProps } from '@/store/slices' @@ -64,14 +65,13 @@ describe('create/logic', () => { }) it('returns taskId if create Safe successfully relayed', async () => { - const gasLimit = faker.string.numeric() const mockSafeProvider = { getExternalProvider: jest.fn(), getExternalSigner: jest.fn(), getChainId: jest.fn().mockReturnValue(BigInt(1)), } as unknown as SafeProvider - jest.spyOn(relaying, 'relayTransaction').mockResolvedValue({ taskId: '0x123' }) + jest.spyOn(gateway, 'relayTransaction').mockResolvedValue({ taskId: '0x123' }) jest.spyOn(sdkHelpers, 'getSafeProvider').mockImplementation(() => mockSafeProvider) jest.spyOn(contracts, 'getReadOnlyFallbackHandlerContract').mockResolvedValue({ @@ -120,22 +120,20 @@ describe('create/logic', () => { expectedSaltNonce, ]) - const taskId = await relaySafeCreation(mockChainInfo, undeployedSafeProps, gasLimit) + const taskId = await relaySafeCreation(mockChainInfo, undeployedSafeProps) expect(taskId).toEqual('0x123') - expect(relaying.relayTransaction).toHaveBeenCalledTimes(1) - expect(relaying.relayTransaction).toHaveBeenCalledWith('1', { + expect(relayTransaction).toHaveBeenCalledTimes(1) + expect(relayTransaction).toHaveBeenCalledWith('1', { to: proxyFactoryAddress, data: expectedCallData, version: latestSafeVersion, - gasLimit, }) }) it('should throw an error if relaying fails', () => { - const gasLimit = faker.string.numeric() const relayFailedError = new Error('Relay failed') - jest.spyOn(relaying, 'relayTransaction').mockRejectedValue(relayFailedError) + jest.spyOn(gateway, 'relayTransaction').mockRejectedValue(relayFailedError) const undeployedSafeProps: ReplayedSafeProps = { safeAccountConfig: { @@ -154,7 +152,7 @@ describe('create/logic', () => { saltNonce: '69', } - expect(relaySafeCreation(mockChainInfo, undeployedSafeProps, gasLimit)).rejects.toEqual(relayFailedError) + expect(relaySafeCreation(mockChainInfo, undeployedSafeProps)).rejects.toEqual(relayFailedError) }) }) describe('getRedirect', () => { diff --git a/apps/web/src/components/new-safe/create/logic/index.ts b/apps/web/src/components/new-safe/create/logic/index.ts index 22d060fab2..0361d80caf 100644 --- a/apps/web/src/components/new-safe/create/logic/index.ts +++ b/apps/web/src/components/new-safe/create/logic/index.ts @@ -2,8 +2,7 @@ import type { SafeVersion } from '@safe-global/safe-core-sdk-types' import { type Eip1193Provider, type Provider } from 'ethers' import semverSatisfies from 'semver/functions/satisfies' -import { getSafeInfo, type SafeInfo, type ChainInfo } from '@safe-global/safe-gateway-typescript-sdk' -import { relayTransaction } from '@/services/tx/relaying' +import { getSafeInfo, type SafeInfo, type ChainInfo, relayTransaction } from '@safe-global/safe-gateway-typescript-sdk' import { getReadOnlyProxyFactoryContract } from '@/services/contracts/safeContracts' import type { UrlObject } from 'url' import { AppRoutes } from '@/config/routes' @@ -179,11 +178,7 @@ export const getRedirect = ( return redirectUrl + `${appendChar}safe=${address}` } -export const relaySafeCreation = async ( - chain: ChainInfo, - undeployedSafeProps: UndeployedSafeProps, - gasLimit: string | undefined, -) => { +export const relaySafeCreation = async (chain: ChainInfo, undeployedSafeProps: UndeployedSafeProps) => { const replayedSafeProps = assertNewUndeployedSafeProps(undeployedSafeProps, chain) const encodedSafeCreationTx = encodeSafeCreationTx(replayedSafeProps, chain) @@ -191,7 +186,6 @@ export const relaySafeCreation = async ( to: replayedSafeProps.factoryAddress, data: encodedSafeCreationTx, version: replayedSafeProps.safeVersion, - gasLimit, }) return relayResponse.taskId diff --git a/apps/web/src/components/new-safe/create/steps/ReviewStep/index.tsx b/apps/web/src/components/new-safe/create/steps/ReviewStep/index.tsx index e17a7f7a00..1e388ad0ce 100644 --- a/apps/web/src/components/new-safe/create/steps/ReviewStep/index.tsx +++ b/apps/web/src/components/new-safe/create/steps/ReviewStep/index.tsx @@ -336,7 +336,7 @@ const ReviewStep = ({ data, onSubmit, onBack, setStep }: StepRenderProps { try { if (willRelay) { - const taskId = await relaySafeCreation(chain, undeployedSafe.props, options?.gasLimit?.toString()) + const taskId = await relaySafeCreation(chain, undeployedSafe.props) safeCreationDispatch(SafeCreationEvent.RELAYING, { groupKey: CF_TX_GROUP_KEY, taskId, safeAddress }) onSubmit() diff --git a/apps/web/src/services/tx/__tests__/relaying.test.ts b/apps/web/src/services/tx/__tests__/relaying.test.ts deleted file mode 100644 index d93cce0521..0000000000 --- a/apps/web/src/services/tx/__tests__/relaying.test.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { faker } from '@faker-js/faker' -import { relayTransaction as _relayTransaction } from '@safe-global/safe-gateway-typescript-sdk' - -import { relayTransaction } from '@/services/tx/relaying' -import { getWeb3ReadOnly } from '@/hooks/wallets/web3' - -jest.mock('@/hooks/wallets/web3') -jest.mock('@safe-global/safe-gateway-typescript-sdk') - -describe('relayTransaction', () => { - let chainId: string - let body: { - version: string - to: string - data: string - gasLimit: string | undefined - } - - beforeEach(() => { - jest.clearAllMocks() - - chainId = faker.string.numeric() - body = { - version: faker.system.semver(), - to: faker.finance.ethereumAddress(), - data: faker.string.hexadecimal(), - gasLimit: undefined, - } - }) - - it('should relay with the correct parameters when gasLimit is provided', async () => { - const bodyWithGasLimit = { - ...body, - gasLimit: faker.string.numeric(), - } - - await relayTransaction(chainId, bodyWithGasLimit) - - expect(_relayTransaction).toHaveBeenCalledWith(chainId, bodyWithGasLimit) - }) - - it('should estimate gasLimit if not provided and relay with the estimated gasLimit', async () => { - const gasLimit = faker.number.bigInt() - const mockProvider = { - estimateGas: jest.fn().mockResolvedValue(gasLimit), - } - ;(getWeb3ReadOnly as jest.Mock).mockReturnValue(mockProvider) - - await relayTransaction(chainId, body) - - expect(mockProvider.estimateGas).toHaveBeenCalledWith(body) - expect(_relayTransaction).toHaveBeenCalledWith(chainId, { ...body, gasLimit: gasLimit.toString() }) - }) - - it('should relay with undefined gasLimit if estimation fails', async () => { - const mockProvider = { - estimateGas: jest.fn().mockRejectedValue(new Error('Estimation failed')), - } - ;(getWeb3ReadOnly as jest.Mock).mockReturnValue(mockProvider) - - await relayTransaction(chainId, body) - - expect(mockProvider.estimateGas).toHaveBeenCalledWith(body) - expect(_relayTransaction).toHaveBeenCalledWith(chainId, { ...body, gasLimit: undefined }) - }) -}) diff --git a/apps/web/src/services/tx/relaying.ts b/apps/web/src/services/tx/relaying.ts deleted file mode 100644 index 9b147ccbb7..0000000000 --- a/apps/web/src/services/tx/relaying.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { relayTransaction as _relayTransaction } from '@safe-global/safe-gateway-typescript-sdk' - -import { getWeb3ReadOnly } from '@/hooks/wallets/web3' - -export async function relayTransaction( - chainId: string, - body: { version: string; to: string; data: string; gasLimit: string | undefined }, -) { - /** - * Ensures `gasLimit` is estimate so 150k execution overhead buffer can be added by CGW. - * - * @see https://github.com/safe-global/safe-client-gateway/blob/b7640ed4bd7416ecb7696d21ba105fcb5af52a10/src/datasources/relay-api/gelato-api.service.ts#L62-L75 - * - * - If provided, CGW adds a 150k buffer before submission to Gelato. - * - If not provided, no buffer is added, and Gelato estimates the it. - * - * Note: particularly important on networks like Arbitrum, where estimation is unreliable. - */ - if (!body.gasLimit) { - const provider = getWeb3ReadOnly() - - body.gasLimit = await provider - ?.estimateGas(body) - .then(String) - .catch(() => undefined) - } - - return _relayTransaction(chainId, body) -} diff --git a/apps/web/src/services/tx/tx-sender/__tests__/ts-sender.test.ts b/apps/web/src/services/tx/tx-sender/__tests__/ts-sender.test.ts index 81afaf8fd9..190434c93d 100644 --- a/apps/web/src/services/tx/tx-sender/__tests__/ts-sender.test.ts +++ b/apps/web/src/services/tx/tx-sender/__tests__/ts-sender.test.ts @@ -22,7 +22,6 @@ import { type JsonRpcProvider, type JsonRpcSigner, } from 'ethers' -import { faker } from '@faker-js/faker' import * as safeContracts from '@/services/contracts/safeContracts' import * as web3 from '@/hooks/wallets/web3' @@ -516,13 +515,6 @@ describe('txSender', () => { describe('dispatchBatchExecutionRelay', () => { it('should relay a batch execution', async () => { - const gasLimit = faker.number.bigInt() - jest.spyOn(web3, 'getWeb3ReadOnly').mockImplementation(() => { - return { - estimateGas: jest.fn(() => Promise.resolve(gasLimit)), - } as unknown as JsonRpcProvider - }) - const mockMultisendAddress = zeroPadValue('0x1234', 20) const safeAddress = toBeHex('0x567', 20) diff --git a/apps/web/src/services/tx/tx-sender/dispatch.ts b/apps/web/src/services/tx/tx-sender/dispatch.ts index 37d9cab6db..b1edb9f9e0 100644 --- a/apps/web/src/services/tx/tx-sender/dispatch.ts +++ b/apps/web/src/services/tx/tx-sender/dispatch.ts @@ -2,8 +2,12 @@ import type { ConnectedWallet } from '@/hooks/wallets/useOnboard' import { isMultisigExecutionInfo } from '@/utils/transaction-guards' import { isHardwareWallet, isSmartContractWallet } from '@/utils/wallets' import type { MultiSendCallOnlyContractImplementationType } from '@safe-global/protocol-kit' -import { type ChainInfo, type SafeInfo, type TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk' -import { relayTransaction } from '@/services/tx/relaying' +import { + type ChainInfo, + relayTransaction, + type SafeInfo, + type TransactionDetails, +} from '@safe-global/safe-gateway-typescript-sdk' import type { SafeSignature, SafeTransaction, @@ -554,8 +558,6 @@ export const dispatchBatchExecutionRelay = async ( to, data, version: safeVersion, - // We have no estimation in place - gasLimit: undefined, }) } catch (error) { txs.forEach(({ txId }) => {