diff --git a/lib/constants.ts b/lib/constants.ts index d8705f23..cb34437a 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -31,3 +31,6 @@ export const HARPIE_API_KEY = process.env.HARPIE_API_KEY ?? process.env.NEXT_PUB export const WEBACY_API_KEY = process.env.WEBACY_API_KEY ?? process.env.NEXT_PUBLIC_WEBACY_API_KEY; export const NEFTURE_API_KEY = process.env.NEFTURE_API_KEY ?? process.env.NEXT_PUBLIC_NEFTURE_API_KEY; export const RESERVOIR_API_KEY = process.env.RESERVOIR_API_KEY ?? process.env.NEXT_PUBLIC_RESERVOIR_API_KEY; + +// https://etherscan.io/tx/0xdf137dccbf456e51ac371eb23e00337329e376e2ca968f7a83470542e6dc609b +export const DOMAIN_SUFFIX = '0x4EE96F33' as const; diff --git a/lib/hooks/ethereum/useMarketplaces.tsx b/lib/hooks/ethereum/useMarketplaces.tsx index 1d8edd06..2ed56d18 100644 --- a/lib/hooks/ethereum/useMarketplaces.tsx +++ b/lib/hooks/ethereum/useMarketplaces.tsx @@ -6,7 +6,13 @@ import eventsDB from 'lib/databases/events'; import type { Marketplace, MarketplaceConfig, OnCancel } from 'lib/interfaces'; import ky from 'lib/ky'; import { getLogsProvider } from 'lib/providers'; -import { addressToTopic, getWalletAddress, isNullish, logSorterChronological } from 'lib/utils'; +import { + addressToTopic, + getWalletAddress, + isNullish, + logSorterChronological, + writeContractUnlessExcessiveGas, +} from 'lib/utils'; import { createViemPublicClientForChain } from 'lib/utils/chains'; import type { TimeLog } from 'lib/utils/events'; import { mapAsync } from 'lib/utils/promises'; @@ -60,7 +66,7 @@ export const useMarketplaces = () => { ], approvalFilterAddress: '0x1E0049783F008A0085193E00003D00cd54003c71', cancelSignatures: async (walletClient: WalletClient): Promise => { - return walletClient.writeContract({ + return writeContractUnlessExcessiveGas(publicClient, walletClient, { address: '0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC', abi: OPENSEA_SEAPORT_ABI, account: await getWalletAddress(walletClient), @@ -83,7 +89,7 @@ export const useMarketplaces = () => { chains: [ChainId.EthereumMainnet], approvalFilterAddress: '0x2f18F339620a63e43f0839Eeb18D7de1e1Be4DfB', cancelSignatures: async (walletClient: WalletClient): Promise => { - return walletClient.writeContract({ + return writeContractUnlessExcessiveGas(publicClient, walletClient, { address: '0xb2ecfE4E4D61f8790bbb9DE2D1259B9e2410CEA5', abi: BLUR_ABI, account: await getWalletAddress(walletClient), diff --git a/lib/utils/allowances.ts b/lib/utils/allowances.ts index 2a9cb554..197555e5 100644 --- a/lib/utils/allowances.ts +++ b/lib/utils/allowances.ts @@ -5,7 +5,13 @@ import type { useHandleTransaction } from 'lib/hooks/ethereum/useHandleTransacti import { type TransactionSubmitted, TransactionType } from 'lib/interfaces'; import type { TransactionStore } from 'lib/stores/transaction-store'; import { type Address, type PublicClient, type WalletClient, type WriteContractParameters, formatUnits } from 'viem'; -import { deduplicateArray, isNullish, waitForTransactionConfirmation, writeContractUnlessExcessiveGas } from '.'; +import { + deduplicateArray, + estimateContractGas, + isNullish, + waitForTransactionConfirmation, + writeContractUnlessExcessiveGas, +} from '.'; import { track } from './analytics'; import { isNetworkError, isRevertedError, isUserRejectionError, parseErrorMessage, stringifyError } from './errors'; import { @@ -409,7 +415,7 @@ export const prepareRevokeErc721Allowance = async ( value: 0n as any as never, // Workaround for Gnosis Safe, TODO: remove when fixed }; - const gas = await allowance.contract.publicClient.estimateContractGas(transactionRequest); + const gas = await estimateContractGas(allowance.contract.publicClient, transactionRequest); return { ...transactionRequest, gas }; } @@ -422,7 +428,7 @@ export const prepareRevokeErc721Allowance = async ( value: 0n as any as never, // Workaround for Gnosis Safe, TODO: remove when fixed }; - const gas = await allowance.contract.publicClient.estimateContractGas(transactionRequest); + const gas = await estimateContractGas(allowance.contract.publicClient, transactionRequest); return { ...transactionRequest, gas }; }; @@ -474,7 +480,7 @@ export const prepareUpdateErc20Allowance = async ( args: [allowance.payload.spender, newAmount] as const, }; - const gas = await allowance.contract.publicClient.estimateContractGas(transactionRequest); + const gas = await estimateContractGas(allowance.contract.publicClient, transactionRequest); return { ...transactionRequest, gas }; } catch (e) { if (!isRevertedError(parseErrorMessage(e))) throw e; @@ -489,7 +495,7 @@ export const prepareUpdateErc20Allowance = async ( args: [allowance.payload.spender, differenceAmount] as const, }; - const gas = await allowance.contract.publicClient.estimateContractGas(transactionRequest); + const gas = await estimateContractGas(allowance.contract.publicClient, transactionRequest); return { ...transactionRequest, gas }; } @@ -501,7 +507,7 @@ export const prepareUpdateErc20Allowance = async ( args: [allowance.payload.spender, -differenceAmount] as const, }; - const gas = await allowance.contract.publicClient.estimateContractGas(transactionRequest); + const gas = await estimateContractGas(allowance.contract.publicClient, transactionRequest); return { ...transactionRequest, gas }; } }; diff --git a/lib/utils/index.ts b/lib/utils/index.ts index cd4352a0..4ea20c7c 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -1,4 +1,5 @@ import { ChainId } from '@revoke.cash/chains'; +import { DOMAIN_SUFFIX } from 'lib/constants'; import type { TransactionSubmitted } from 'lib/interfaces'; import ky from 'lib/ky'; import type { getTranslations } from 'next-intl/server'; @@ -137,9 +138,16 @@ export const writeContractUnlessExcessiveGas = async ( walletClient: WalletClient, transactionRequest: WriteContractParameters, ) => { - const estimatedGas = transactionRequest.gas ?? (await publicClient.estimateContractGas(transactionRequest)); + const transactionRequestWithDataSuffix = { ...transactionRequest, dataSuffix: DOMAIN_SUFFIX }; + const estimatedGas = + transactionRequest.gas ?? (await publicClient.estimateContractGas(transactionRequestWithDataSuffix)); throwIfExcessiveGas(transactionRequest.chain!.id, transactionRequest.address, estimatedGas); - return walletClient.writeContract({ ...transactionRequest, gas: estimatedGas }); + return walletClient.writeContract({ ...transactionRequestWithDataSuffix, gas: estimatedGas }); +}; + +export const estimateContractGas = async (publicClient: PublicClient, transactionRequest: WriteContractParameters) => { + const transactionRequestWithDataSuffix = { ...transactionRequest, dataSuffix: DOMAIN_SUFFIX }; + return publicClient.estimateContractGas(transactionRequestWithDataSuffix); }; export const waitForTransactionConfirmation = async (hash: Hash, publicClient: PublicClient) => { diff --git a/lib/utils/permit.ts b/lib/utils/permit.ts index 0a4cea31..5223e40c 100644 --- a/lib/utils/permit.ts +++ b/lib/utils/permit.ts @@ -30,7 +30,7 @@ export const permit = async ( // DAI uses a different form of permit if (DAI_ADDRESSES.includes(verifyingContract)) { const { v, r, s } = await signDaiPermit(walletClient, domain, address, spender, nonce, deadline, false); - return walletClient.writeContract({ + return writeContractUnlessExcessiveGas(contract.publicClient, walletClient, { ...contract, account: address, abi: DAI_PERMIT_ABI, diff --git a/lib/utils/permit2.ts b/lib/utils/permit2.ts index 19aa6a25..b31f64ee 100644 --- a/lib/utils/permit2.ts +++ b/lib/utils/permit2.ts @@ -1,7 +1,7 @@ import { PERMIT2_ABI } from 'lib/abis'; import blocksDB from 'lib/databases/blocks'; import type { Address, WalletClient } from 'viem'; -import { deduplicateArray, getWalletAddress, writeContractUnlessExcessiveGas } from '.'; +import { deduplicateArray, estimateContractGas, getWalletAddress, writeContractUnlessExcessiveGas } from '.'; import { AllowanceType, type Permit2Erc20Allowance } from './allowances'; import { type Permit2Event, type TokenEvent, TokenEventType } from './events'; import { SECOND } from './time'; @@ -101,7 +101,7 @@ export const preparePermit2Approve = async ( value: 0n as any as never, // Workaround for Gnosis Safe, TODO: remove when fixed }; - const gas = await tokenContract.publicClient.estimateContractGas(transactionRequest); + const gas = await estimateContractGas(tokenContract.publicClient, transactionRequest); return { ...transactionRequest, gas }; };