From 460e800b2b9c2423d4643964d4946163e9ee89ef Mon Sep 17 00:00:00 2001 From: Lukas Rosario <36800180+lukasrosario@users.noreply.github.com> Date: Fri, 24 Nov 2023 17:23:15 -0500 Subject: [PATCH 1/5] prove withdrawa test --- .../FinalizeWithdrawalTransaction.tsx | 4 +- .../components/ProveWithdrawalTransaction.tsx | 4 +- src/_test/config.ts | 24 +++++------ src/_test/constants.ts | 40 +++++++++---------- src/_test/globalSetup.ts | 10 +++-- src/hooks/L1/useProveWithdrawalArgs.ts | 6 +-- src/hooks/L1/useSimulateDepositERC20.test.ts | 2 +- ...seSimulateFinalizeWithdrawalTransaction.ts | 4 +- ...SimulateProveWithdrawalTransaction.test.ts | 19 +++++++++ .../useSimulateProveWithdrawalTransaction.ts | 12 +++--- src/hooks/L1/useWriteDepositERC20.test.ts | 4 +- src/hooks/L1/useWriteDepositETH.test.ts | 2 +- .../useWriteFinalizeWithdrawalTransaction.ts | 4 +- ...useWriteProveWithdrawalTransaction.test.ts | 26 ++++++++++++ .../L1/useWriteProveWithdrawalTransaction.ts | 4 +- 15 files changed, 106 insertions(+), 59 deletions(-) create mode 100644 src/hooks/L1/useSimulateProveWithdrawalTransaction.test.ts create mode 100644 src/hooks/L1/useWriteProveWithdrawalTransaction.test.ts diff --git a/example/components/FinalizeWithdrawalTransaction.tsx b/example/components/FinalizeWithdrawalTransaction.tsx index 7f28ef2..a8b9efc 100644 --- a/example/components/FinalizeWithdrawalTransaction.tsx +++ b/example/components/FinalizeWithdrawalTransaction.tsx @@ -17,7 +17,7 @@ export function FinalizeWithdrawalTransaction({ selectedChainId }: FinalizeWithd useSimulateFinalizeWithdrawalTransaction( { args: { - l1WithdrawalTxHash: withdrawalTxHash as Hash, + withdrawalTxHash: withdrawalTxHash as Hash, }, l2ChainId: selectedChainId, query: { enabled: false, retry: false }, @@ -33,7 +33,7 @@ export function FinalizeWithdrawalTransaction({ selectedChainId }: FinalizeWithd } else { await writeFinalizeWithdrawalTransactionAsync({ args: { - l1WithdrawalTxHash: withdrawalTxHash as Hash, + withdrawalTxHash: withdrawalTxHash as Hash, }, l2ChainId: selectedChainId, }) diff --git a/example/components/ProveWithdrawalTransaction.tsx b/example/components/ProveWithdrawalTransaction.tsx index cdf4d24..1250fe0 100644 --- a/example/components/ProveWithdrawalTransaction.tsx +++ b/example/components/ProveWithdrawalTransaction.tsx @@ -16,7 +16,7 @@ export function ProveWithdrawalTransaction({ selectedChainId }: ProveWithdrawalT const { status: simulateStatus, refetch: simulateProveWithdrawalTransaction } = useSimulateProveWithdrawalTransaction( { args: { - l1WithdrawalTxHash: withdrawalTxHash as Hash, + withdrawalTxHash: withdrawalTxHash as Hash, }, l2ChainId: selectedChainId, query: { enabled: false, retry: false }, @@ -32,7 +32,7 @@ export function ProveWithdrawalTransaction({ selectedChainId }: ProveWithdrawalT } else { await writeProveWithdrawalTransactionAsync({ args: { - l1WithdrawalTxHash: withdrawalTxHash as Hash, + withdrawalTxHash: withdrawalTxHash as Hash, }, l2ChainId: selectedChainId, }) diff --git a/src/_test/config.ts b/src/_test/config.ts index 5dd77ff..2936ce1 100644 --- a/src/_test/config.ts +++ b/src/_test/config.ts @@ -9,23 +9,23 @@ import { getRpcUrls } from './utils.js' const mainnet = { ...viem_mainnet, ...getRpcUrls({ port: 8545 }), - fork: { - blockNumber: process.env.VITE_MAINNET_FORK_BLOCK_NUMBER - ? BigInt(Number(process.env.VITE_MAINNET_FORK_BLOCK_NUMBER)) - : 18136086n, - url: process.env.VITE_MAINNET_FORK_URL ?? 'https://cloudflare-eth.com', - }, + // fork: { + // blockNumber: process.env.VITE_MAINNET_FORK_BLOCK_NUMBER + // ? BigInt(Number(process.env.VITE_MAINNET_FORK_BLOCK_NUMBER)) + // : 18136086n, + // url: process.env.VITE_MAINNET_FORK_URL ?? 'https://cloudflare-eth.com', + // }, } const base = { ...viem_base, ...getRpcUrls({ port: 8546 }), - fork: { - blockNumber: process.env.VITE_OPTIMISM_FORK_BLOCK_NUMBER - ? BigInt(Number(process.env.VITE_OPTIMISM_FORK_BLOCK_NUMBER)) - : 5940037n, - url: process.env.VITE_OPTIMISM_FORK_URL ?? 'https://mainnet.base.org', - }, + // fork: { + // blockNumber: process.env.VITE_OPTIMISM_FORK_BLOCK_NUMBER + // ? BigInt(Number(process.env.VITE_OPTIMISM_FORK_BLOCK_NUMBER)) + // : 3960000n, + // url: process.env.VITE_OPTIMISM_FORK_URL ?? 'https://mainnet.base.org', + // }, } export const config: OpConfig = { diff --git a/src/_test/constants.ts b/src/_test/constants.ts index b9fc906..8c732c1 100644 --- a/src/_test/constants.ts +++ b/src/_test/constants.ts @@ -16,15 +16,15 @@ function warn(message: string) { } } -export let forkBlockNumber: bigint -if (process.env.VITE_ANVIL_BLOCK_NUMBER) { - forkBlockNumber = BigInt(Number(process.env.VITE_ANVIL_BLOCK_NUMBER)) -} else { - forkBlockNumber = 18136086n - warn( - `\`VITE_ANVIL_BLOCK_NUMBER\` not found. Falling back to \`${forkBlockNumber}\`.`, - ) -} +// export let forkBlockNumber: bigint +// if (process.env.VITE_ANVIL_BLOCK_NUMBER) { +// forkBlockNumber = BigInt(Number(process.env.VITE_ANVIL_BLOCK_NUMBER)) +// } else { +// forkBlockNumber = 18136086n +// warn( +// `\`VITE_ANVIL_BLOCK_NUMBER\` not found. Falling back to \`${forkBlockNumber}\`.`, +// ) +// } export let forkUrl: string if (process.env.VITE_ANVIL_FORK_URL) { @@ -42,17 +42,17 @@ if (process.env.VITE_ANVIL_BLOCK_TIME) { warn(`\`VITE_ANVIL_BLOCK_TIME\` not found. Falling back to \`${blockTime}\`.`) } -export let rollupForkBlockNumber: bigint -if (process.env.VITE_ANVIL_ROLLUP_BLOCK_NUMBER) { - rollupForkBlockNumber = BigInt( - Number(process.env.VITE_ANVIL_ROLLUP_BLOCK_NUMBER), - ) -} else { - rollupForkBlockNumber = 3709321n - warn( - `\`VITE_ANVIL_ROLLUP_BLOCK_NUMBER\` not found. Falling back to \`${rollupForkBlockNumber}\`.`, - ) -} +// export let rollupForkBlockNumber: bigint +// if (process.env.VITE_ANVIL_ROLLUP_BLOCK_NUMBER) { +// rollupForkBlockNumber = BigInt( +// Number(process.env.VITE_ANVIL_ROLLUP_BLOCK_NUMBER), +// ) +// } else { +// rollupForkBlockNumber = 3709321n +// warn( +// `\`VITE_ANVIL_ROLLUP_BLOCK_NUMBER\` not found. Falling back to \`${rollupForkBlockNumber}\`.`, +// ) +// } export let rollupForkUrl: string if (process.env.VITE_ANVIL_ROLLUP_FORK_URL) { diff --git a/src/_test/globalSetup.ts b/src/_test/globalSetup.ts index 3595a9d..33c6d58 100644 --- a/src/_test/globalSetup.ts +++ b/src/_test/globalSetup.ts @@ -3,10 +3,10 @@ import { startProxy } from '@viem/anvil' import { blockTime, - forkBlockNumber, + // forkBlockNumber, forkUrl, rollupBlockTime, - rollupForkBlockNumber, + // rollupForkBlockNumber, rollupForkUrl, } from './constants.js' @@ -37,7 +37,8 @@ export default async function() { port: 8545, options: { forkUrl, - forkBlockNumber, + // TODO: Figure out forking / archive node issues + // forkBlockNumber, blockTime, }, }) @@ -45,7 +46,8 @@ export default async function() { port: 8546, options: { forkUrl: rollupForkUrl, - forkBlockNumber: rollupForkBlockNumber, + // TODO: Figure out forking / archive node issues + // forkBlockNumber: rollupForkBlockNumber, blockTime: rollupBlockTime, }, }) diff --git a/src/hooks/L1/useProveWithdrawalArgs.ts b/src/hooks/L1/useProveWithdrawalArgs.ts index 3e3778d..348d1b5 100644 --- a/src/hooks/L1/useProveWithdrawalArgs.ts +++ b/src/hooks/L1/useProveWithdrawalArgs.ts @@ -14,9 +14,9 @@ import { useGetL2OutputIndexAfter } from './useGetL2OutputIndexAfter.js' export function useProveWithdrawalArgs({ l2ChainId, config, - l1WithdrawalTxHash, + withdrawalTxHash, }: { - l1WithdrawalTxHash: Hash + withdrawalTxHash: Hash l2ChainId: number config?: Config }) { @@ -47,7 +47,7 @@ export function useProveWithdrawalArgs({ }) const { data: withdrawalReceipt } = useWaitForTransactionReceipt({ - hash: l1WithdrawalTxHash, + hash: withdrawalTxHash, chainId: l2Chain.chainId, }) diff --git a/src/hooks/L1/useSimulateDepositERC20.test.ts b/src/hooks/L1/useSimulateDepositERC20.test.ts index f95457d..c3ff7be 100644 --- a/src/hooks/L1/useSimulateDepositERC20.test.ts +++ b/src/hooks/L1/useSimulateDepositERC20.test.ts @@ -127,4 +127,4 @@ test('useSimulateDepositERC20', async () => { "status": "success", } `) -}) +}, { retry: 3 }) diff --git a/src/hooks/L1/useSimulateFinalizeWithdrawalTransaction.ts b/src/hooks/L1/useSimulateFinalizeWithdrawalTransaction.ts index 4d2b0c0..5d0f020 100644 --- a/src/hooks/L1/useSimulateFinalizeWithdrawalTransaction.ts +++ b/src/hooks/L1/useSimulateFinalizeWithdrawalTransaction.ts @@ -21,7 +21,7 @@ export type UseSimulateFinalizeWithdrawalTransactionParameters< & UseSimulateOPActionBaseParameters & { args: { - l1WithdrawalTxHash: Hash + withdrawalTxHash: Hash } l2ChainId: number } @@ -60,7 +60,7 @@ export function useSimulateFinalizeWithdrawalTransaction< const query = { async queryFn() { const withdrawalMessages = await getWithdrawalMessages(l2PublicClient, { - hash: args.l1WithdrawalTxHash, + hash: args.withdrawalTxHash, }) return simulateFinalizeWithdrawalTransaction(l1PublicClient, { diff --git a/src/hooks/L1/useSimulateProveWithdrawalTransaction.test.ts b/src/hooks/L1/useSimulateProveWithdrawalTransaction.test.ts new file mode 100644 index 0000000..699488c --- /dev/null +++ b/src/hooks/L1/useSimulateProveWithdrawalTransaction.test.ts @@ -0,0 +1,19 @@ +import { expect, test } from 'vitest' +import { renderHook, waitFor } from '../../_test/react.js' +import { useSimulateProveWithdrawalTransaction } from './useSimulateProveWithdrawalTransaction.js' + +test('useSimulateProveWithdrawalTransaction', async () => { + const { result } = renderHook(() => + useSimulateProveWithdrawalTransaction({ + args: { + withdrawalTxHash: '0xf735fdde9e33a002dcfe8d3fb2ca059c585d538a0e3ddc561d6fdcc303cff408', + }, + l2ChainId: 8453, + query: { retry: false }, + }) + ) + + // We're only checking that we're able to successfully call the contract. The snapshot + // will continue to change as blocks get procuded, and this check is sufficient. + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()) +}, { retry: 3 }) diff --git a/src/hooks/L1/useSimulateProveWithdrawalTransaction.ts b/src/hooks/L1/useSimulateProveWithdrawalTransaction.ts index 60e1aac..7e9cf8f 100644 --- a/src/hooks/L1/useSimulateProveWithdrawalTransaction.ts +++ b/src/hooks/L1/useSimulateProveWithdrawalTransaction.ts @@ -27,7 +27,7 @@ export type UseSimulateProveWithdrawalTransactionParameters< & UseSimulateOPActionBaseParameters & { args: { - l1WithdrawalTxHash: Hash + withdrawalTxHash: Hash } l2ChainId: number } @@ -55,7 +55,7 @@ export function useSimulateProveWithdrawalTransaction< throw new Error('L2 chain not configured') } - const { address } = useAccount() + const account = useAccount(rest) const l1PublicClient = usePublicClient({ chainId: l2Chain.l1ChainId }) const l2PublicClient = usePublicClient({ chainId: l2ChainId }) const l1Addresses = opConfig.l2chains[l2ChainId].l1Addresses @@ -63,7 +63,7 @@ export function useSimulateProveWithdrawalTransaction< const query = { async queryFn() { const withdrawalMessages = await getWithdrawalMessages(l2PublicClient, { - hash: args.l1WithdrawalTxHash, + hash: args.withdrawalTxHash, }) const { l2BlockNumber } = await getLatestProposedL2BlockNumber(l1PublicClient, { @@ -82,7 +82,7 @@ export function useSimulateProveWithdrawalTransaction< return simulateProveWithdrawalTransaction(l1PublicClient, { args: simulateProveWithdrawalTransactionArgs, - account: address, + account: account.address, ...l1Addresses, }) }, @@ -97,13 +97,13 @@ export function useSimulateProveWithdrawalTransaction< value: undefined, ...args, }, - account: address, + account: account.address, chainId: l2Chain.l1ChainId, action: 'proveWithdrawalTransaction', }), } - const enabled = Boolean(address) && (queryOverride?.enabled ?? true) + const enabled = Boolean(account.address) && (queryOverride?.enabled ?? true) return { ...useQuery({ ...query, queryKeyHashFn: hashFn, enabled }), queryKey: query.queryKey, diff --git a/src/hooks/L1/useWriteDepositERC20.test.ts b/src/hooks/L1/useWriteDepositERC20.test.ts index 11f66e8..367f812 100644 --- a/src/hooks/L1/useWriteDepositERC20.test.ts +++ b/src/hooks/L1/useWriteDepositERC20.test.ts @@ -3,7 +3,7 @@ import { accounts } from '../../_test/constants.js' import { renderHook, waitFor } from '../../_test/react.js' import { useWriteDepositERC20 } from './useWriteDepositERC20.js' -test(useWriteDepositERC20.name, async () => { +test('useWriteDepositERC20', async () => { const { result } = renderHook(() => useWriteDepositERC20()) expect(result.current.writeDepositERC20).toBeDefined() @@ -791,4 +791,4 @@ test(useWriteDepositERC20.name, async () => { "writeDepositERC20Async": [Function], } `) -}) +}, { retry: 3 }) diff --git a/src/hooks/L1/useWriteDepositETH.test.ts b/src/hooks/L1/useWriteDepositETH.test.ts index dd93253..832e8ca 100644 --- a/src/hooks/L1/useWriteDepositETH.test.ts +++ b/src/hooks/L1/useWriteDepositETH.test.ts @@ -3,7 +3,7 @@ import { accounts } from '../../_test/constants.js' import { renderHook, waitFor } from '../../_test/react.js' import { useWriteDepositETH } from './useWriteDepositETH.js' -test(useWriteDepositETH.name, async () => { +test('useWriteDepositETH', async () => { const { result } = renderHook(() => useWriteDepositETH()) // write contract lazily writes diff --git a/src/hooks/L1/useWriteFinalizeWithdrawalTransaction.ts b/src/hooks/L1/useWriteFinalizeWithdrawalTransaction.ts index a16ea78..4ab6b5a 100644 --- a/src/hooks/L1/useWriteFinalizeWithdrawalTransaction.ts +++ b/src/hooks/L1/useWriteFinalizeWithdrawalTransaction.ts @@ -22,7 +22,7 @@ export type WriteFinalizeWithdrawalTransactionParameters< chainId extends config['chains'][number]['id'] = number, > = WriteOPContractBaseParameters & { args: { - l1WithdrawalTxHash: Hash + withdrawalTxHash: Hash } l2ChainId: number } @@ -62,7 +62,7 @@ async function writeMutation( const l1Addresses = config.l2chains[l2ChainId].l1Addresses const withdrawalMessages = await getWithdrawalMessages(l2PublicClient, { - hash: args.l1WithdrawalTxHash, + hash: args.withdrawalTxHash, }) await simulateFinalizeWithdrawalTransaction(l1PublicClient, { diff --git a/src/hooks/L1/useWriteProveWithdrawalTransaction.test.ts b/src/hooks/L1/useWriteProveWithdrawalTransaction.test.ts new file mode 100644 index 0000000..2abc4e6 --- /dev/null +++ b/src/hooks/L1/useWriteProveWithdrawalTransaction.test.ts @@ -0,0 +1,26 @@ +import { expect, test } from 'vitest' +import { renderHook, waitFor } from '../../_test/react.js' +import { useWriteProveWithdrawalTransaction } from './useWriteProveWithdrawalTransaction.js' + +test('useWriteProveWithdrawalTransaction', async () => { + const { result } = renderHook(() => useWriteProveWithdrawalTransaction()) + + expect(result.current.writeProveWithdrawalTransaction).toBeDefined() + expect(result.current.writeProveWithdrawalTransaction).toBeDefined() + expect(result.current.data).toBeUndefined() + expect(result.current.isIdle).toBe(true) + + result.current.writeProveWithdrawalTransaction({ + args: { + withdrawalTxHash: '0xf735fdde9e33a002dcfe8d3fb2ca059c585d538a0e3ddc561d6fdcc303cff408', + }, + l2ChainId: 8453, + }) + + await waitFor(() => { + expect(result.current.error).toBeNull() + // We're only checking that we're able to successfully call the contract. The snapshot + // will continue to change as blocks get procuded, and this check is sufficient. + expect(result.current.isSuccess).toBeTruthy() + }) +}, { retry: 3 }) diff --git a/src/hooks/L1/useWriteProveWithdrawalTransaction.ts b/src/hooks/L1/useWriteProveWithdrawalTransaction.ts index b4e0ebf..ef00d22 100644 --- a/src/hooks/L1/useWriteProveWithdrawalTransaction.ts +++ b/src/hooks/L1/useWriteProveWithdrawalTransaction.ts @@ -25,7 +25,7 @@ export type WriteProveWithdrawalTransactionParameters< chainId extends config['chains'][number]['id'] = number, > = WriteOPContractBaseParameters & { args: { - l1WithdrawalTxHash: Hash + withdrawalTxHash: Hash } l2ChainId: number } @@ -65,7 +65,7 @@ async function writeMutation( const l1Addresses = config.l2chains[l2ChainId].l1Addresses const withdrawalMessages = await getWithdrawalMessages(l2PublicClient, { - hash: args.l1WithdrawalTxHash, + hash: args.withdrawalTxHash, }) const { l2BlockNumber } = await getLatestProposedL2BlockNumber(l1PublicClient, { From 9a686ba2562f24a1f40ae01d2b98576fe6e88fb6 Mon Sep 17 00:00:00 2001 From: Lukas Rosario <36800180+lukasrosario@users.noreply.github.com> Date: Fri, 24 Nov 2023 17:34:20 -0500 Subject: [PATCH 2/5] finalize tests --- ...ulateFinalizeWithdrawalTransaction.test.ts | 148 ++++++++++++++++++ ...WriteFinalizeWithdrawalTransaction.test.ts | 50 ++++++ 2 files changed, 198 insertions(+) create mode 100644 src/hooks/L1/useSimulateFinalizeWithdrawalTransaction.test.ts create mode 100644 src/hooks/L1/useWriteFinalizeWithdrawalTransaction.test.ts diff --git a/src/hooks/L1/useSimulateFinalizeWithdrawalTransaction.test.ts b/src/hooks/L1/useSimulateFinalizeWithdrawalTransaction.test.ts new file mode 100644 index 0000000..00ae1f5 --- /dev/null +++ b/src/hooks/L1/useSimulateFinalizeWithdrawalTransaction.test.ts @@ -0,0 +1,148 @@ +import { expect, test } from 'vitest' +import { renderHook, waitFor } from '../../_test/react.js' +import { useSimulateFinalizeWithdrawalTransaction } from './useSimulateFinalizeWithdrawalTransaction.js' + +test('useSimulateFinalizeWithdrawalTransaction', async () => { + const { result } = renderHook(() => + useSimulateFinalizeWithdrawalTransaction({ + args: { + withdrawalTxHash: '0xe602bbed1f47b362d5dfde374f4a390d89a282d27772fc16db162f1b1f33df43', + }, + l2ChainId: 8453, + query: { retry: false }, + }) + ) + + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()) + + expect(result.current).toMatchInlineSnapshot(` + { + "data": { + "request": { + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256", + }, + { + "internalType": "address", + "name": "sender", + "type": "address", + }, + { + "internalType": "address", + "name": "target", + "type": "address", + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256", + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256", + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes", + }, + ], + "internalType": "struct Types.WithdrawalTransaction", + "name": "_tx", + "type": "tuple", + }, + ], + "name": "finalizeWithdrawalTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + }, + ], + "account": { + "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "type": "json-rpc", + }, + "address": "0x49048044D57e1C92A77f79988d21Fa8fAF74E97e", + "args": [ + { + "data": "0xd764ad0b000100000000000000000000000000000000000000000000000000000000072800000000000000000000000042000000000000000000000000000000000000100000000000000000000000003154cf16ccdb4c6d922629664174b904d80f2c35000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001040166a07a000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000d9aaec86b65d86f6a7b5b1b0c42ffa531710b6ca000000000000000000000000b85c1a4062c877145b5cbf623d3625158611b1500000000000000000000000007aa3fca04e32189529f8b24f6d3cf4a8ada68ca6000000000000000000000000000000000000000000000000000000000000138800000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": 390747n, + "nonce": 1766847064778384329583297500742918515827483896875618958121606201292645266n, + "sender": "0x4200000000000000000000000000000000000007", + "target": "0x866E82a600A1414e583f7F13623F1aC5d58b0Afa", + "value": 0n, + "withdrawalHash": "0x72ad06241743ba6acbe9f54279780f39140f14f111aa0cb4a34b8bffaa0ce389", + }, + ], + "dataSuffix": undefined, + "functionName": "finalizeWithdrawalTransaction", + "l1CrossDomainMessenger": { + "address": "0x866E82a600A1414e583f7F13623F1aC5d58b0Afa", + "blockCreated": 17482143, + "chainId": 1, + }, + "l1Erc721Bridge": { + "address": "0x608d94945A64503E642E6370Ec598e519a2C1E53", + "blockCreated": 17482143, + "chainId": 1, + }, + "l1StandardBridge": { + "address": "0x3154Cf16ccdb4C6d922629664174b904d80F2C35", + "blockCreated": 17482143, + "chainId": 1, + }, + "l2OutputOracle": { + "address": "0x56315b90c40730925ec5485cf004d835058518A0", + "blockCreated": 17482143, + "chainId": 1, + }, + }, + "result": undefined, + }, + "dataUpdatedAt": 1700438400000, + "error": null, + "errorUpdateCount": 0, + "errorUpdatedAt": 0, + "failureCount": 0, + "failureReason": null, + "fetchStatus": "idle", + "isError": false, + "isFetched": true, + "isFetchedAfterMount": true, + "isFetching": false, + "isInitialLoading": false, + "isLoading": false, + "isLoadingError": false, + "isPaused": false, + "isPending": false, + "isPlaceholderData": false, + "isRefetchError": false, + "isRefetching": false, + "isStale": true, + "isSuccess": true, + "queryKey": [ + "simulateContract", + { + "account": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "action": "finalizeWithdrawalTransaction", + "blockNumber": undefined, + "chainId": 1, + "gasPrice": undefined, + "type": undefined, + "value": undefined, + "withdrawalTxHash": "0xe602bbed1f47b362d5dfde374f4a390d89a282d27772fc16db162f1b1f33df43", + }, + ], + "refetch": [Function], + "status": "success", + } + `) +}, { retry: 3 }) diff --git a/src/hooks/L1/useWriteFinalizeWithdrawalTransaction.test.ts b/src/hooks/L1/useWriteFinalizeWithdrawalTransaction.test.ts new file mode 100644 index 0000000..6eb1069 --- /dev/null +++ b/src/hooks/L1/useWriteFinalizeWithdrawalTransaction.test.ts @@ -0,0 +1,50 @@ +import { expect, test } from 'vitest' +import { renderHook, waitFor } from '../../_test/react.js' +import { useWriteFinalizeWithdrawalTransaction } from './useWriteFinalizeWithdrawalTransaction.js' + +test('useWriteFinalizeWithdrawalTransaction', async () => { + const { result } = renderHook(() => useWriteFinalizeWithdrawalTransaction()) + + expect(result.current.writeFinalizeWithdrawalTransaction).toBeDefined() + expect(result.current.writeFinalizeWithdrawalTransaction).toBeDefined() + expect(result.current.data).toBeUndefined() + expect(result.current.isIdle).toBe(true) + + result.current.writeFinalizeWithdrawalTransaction({ + args: { + withdrawalTxHash: '0xe602bbed1f47b362d5dfde374f4a390d89a282d27772fc16db162f1b1f33df43', + }, + l2ChainId: 8453, + }) + + await waitFor(() => { + expect(result.current.error).toBeNull() + expect(result.current.isSuccess).toBeTruthy() + }) + + expect(result.current).toMatchInlineSnapshot(` + { + "context": undefined, + "data": "${result.current.data}", + "error": null, + "failureCount": 0, + "failureReason": null, + "isError": false, + "isIdle": false, + "isPaused": false, + "isPending": false, + "isSuccess": true, + "reset": [Function], + "status": "success", + "submittedAt": 1700438400000, + "variables": { + "args": { + "withdrawalTxHash": "0xe602bbed1f47b362d5dfde374f4a390d89a282d27772fc16db162f1b1f33df43", + }, + "l2ChainId": 8453, + }, + "writeFinalizeWithdrawalTransaction": [Function], + "writeFinalizeWithdrawalTransactionAsync": [Function], + } + `) +}, { retry: 3 }) From 17a802c71d20f3f079da7132f0e1b846f7b6bcb9 Mon Sep 17 00:00:00 2001 From: Lukas Rosario <36800180+lukasrosario@users.noreply.github.com> Date: Fri, 24 Nov 2023 17:35:48 -0500 Subject: [PATCH 3/5] update finalize hook to get account from config --- src/hooks/L1/useSimulateFinalizeWithdrawalTransaction.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hooks/L1/useSimulateFinalizeWithdrawalTransaction.ts b/src/hooks/L1/useSimulateFinalizeWithdrawalTransaction.ts index 5d0f020..626ea4b 100644 --- a/src/hooks/L1/useSimulateFinalizeWithdrawalTransaction.ts +++ b/src/hooks/L1/useSimulateFinalizeWithdrawalTransaction.ts @@ -52,7 +52,7 @@ export function useSimulateFinalizeWithdrawalTransaction< throw new Error('L2 chain not configured') } - const { address } = useAccount() + const account = useAccount(rest) const l1PublicClient = usePublicClient({ chainId: l2Chain.l1ChainId }) const l2PublicClient = usePublicClient({ chainId: l2ChainId }) const l1Addresses = opConfig.l2chains[l2ChainId].l1Addresses @@ -65,7 +65,7 @@ export function useSimulateFinalizeWithdrawalTransaction< return simulateFinalizeWithdrawalTransaction(l1PublicClient, { withdrawal: withdrawalMessages.messages[0], - account: address, + account: account.address, ...l1Addresses, }) }, @@ -80,13 +80,13 @@ export function useSimulateFinalizeWithdrawalTransaction< value: undefined, ...args, }, - account: address, + account: account.address, chainId: l2Chain.l1ChainId, action: 'finalizeWithdrawalTransaction', }), } - const enabled = Boolean(address) && (queryOverride?.enabled ?? true) + const enabled = Boolean(account.address) && (queryOverride?.enabled ?? true) return { ...useQuery({ ...query, queryKeyHashFn: hashFn, enabled }), queryKey: query.queryKey, From 0966042e8ac493621383f4eef6ad853be35294fe Mon Sep 17 00:00:00 2001 From: Lukas Rosario <36800180+lukasrosario@users.noreply.github.com> Date: Fri, 24 Nov 2023 18:21:46 -0500 Subject: [PATCH 4/5] let viem handle chain mistmatch errors --- src/hooks/L1/useWriteDepositERC20.ts | 14 ++++---------- src/hooks/L1/useWriteDepositETH.ts | 6 ------ .../L1/useWriteFinalizeWithdrawalTransaction.ts | 7 +------ src/hooks/L1/useWriteProveWithdrawalTransaction.ts | 7 +------ src/hooks/L2/useSimulateWithdrawERC20.ts | 4 +++- src/hooks/L2/useSimulateWithdrawETH.ts | 4 +++- src/hooks/L2/useWriteWithdrawERC20.ts | 11 +---------- src/hooks/L2/useWriteWithdrawETH.ts | 14 ++++---------- 8 files changed, 17 insertions(+), 50 deletions(-) diff --git a/src/hooks/L1/useWriteDepositERC20.ts b/src/hooks/L1/useWriteDepositERC20.ts index 5b6375d..24b5802 100644 --- a/src/hooks/L1/useWriteDepositERC20.ts +++ b/src/hooks/L1/useWriteDepositERC20.ts @@ -1,7 +1,7 @@ import { l1StandardBridgeABI } from '@eth-optimism/contracts-ts' import { type Config } from '@wagmi/core' import { type WriteDepositERC20Parameters as WriteDepositERC20ActionParameters } from 'op-viem/actions' -import { useChainId, useWriteContract } from 'wagmi' +import { useAccount, useWriteContract } from 'wagmi' import type { OpConfig } from '../../types/OpConfig.js' import type { UseWriteOPActionBaseParameters } from '../../types/UseWriteOPActionBaseParameters.js' import type { UseWriteOPActionBaseReturnType } from '../../types/UseWriteOPActionBaseReturnType.js' @@ -44,7 +44,7 @@ export function useWriteDepositERC20 { const config = useOpConfig(args) const { writeContract, writeContractAsync, ...writeReturn } = useWriteContract() - const currentChainId = useChainId() + const account = useAccount(args) return { writeDepositERC20: ({ l2ChainId, args, ...rest }: WriteDepositERC20Parameters) => { @@ -54,16 +54,13 @@ export function useWriteDepositERC20 = {}, ): UseWriteDepositETHReturnType { const opConfig = useOpConfig(args) - const currentChainId = useChainId() const mutation = { mutationFn({ l2ChainId, args, ...rest }: WriteDepositETHParameters) { @@ -95,10 +93,6 @@ export function useWriteDepositETH = {}, ): UseWriteFinalizeWithdrawalTransactionReturnType { const opConfig = useOpConfig(args) - const currentChainId = useChainId() const mutation = { mutationFn({ l2ChainId, args, ...rest }: WriteFinalizeWithdrawalTransactionParameters) { @@ -98,10 +97,6 @@ export function useWriteFinalizeWithdrawalTransaction = {}, ): UseWriteProveWithdrawalTransactionReturnType { const opConfig = useOpConfig(args) - const currentChainId = useChainId() const mutation = { mutationFn({ l2ChainId, args, ...rest }: WriteProveWithdrawalTransactionParameters) { @@ -115,10 +114,6 @@ export function useWriteProveWithdrawalTransaction { const opConfig = useOpConfig(rest) const l2Chain = opConfig.l2chains[chainId] + const account = useAccount(rest) if (!l2Chain) { throw new Error('L2 chain not configured') @@ -51,6 +52,7 @@ export function useSimulateWithdrawERC20< functionName: FUNCTION, args: [args.l2Token, args.to, args.amount, args.minGasLimit ?? 0, args.extraData ?? '0x'], query: query as UseSimulateContractParameters['query'], + account: account.address, ...rest, }) as unknown as UseSimulateWithdrawERC20ReturnType } diff --git a/src/hooks/L2/useSimulateWithdrawETH.ts b/src/hooks/L2/useSimulateWithdrawETH.ts index da86257..9fb371d 100644 --- a/src/hooks/L2/useSimulateWithdrawETH.ts +++ b/src/hooks/L2/useSimulateWithdrawETH.ts @@ -3,7 +3,7 @@ import { l2StandardBridgeABI } from '@eth-optimism/contracts-ts' import type { Config } from '@wagmi/core' import { type SimulateWithdrawETHParameters } from 'op-viem/actions' -import { useSimulateContract, type UseSimulateContractParameters } from 'wagmi' +import { useAccount, useSimulateContract, type UseSimulateContractParameters } from 'wagmi' import type { OpConfig } from '../../types/OpConfig.js' import type { UseSimulateOPActionBaseParameters } from '../../types/UseSimulateOPActionBaseParameters.js' import type { UseSimulateOPActionBaseReturnType } from '../../types/UseSimulateOPActionBaseReturnType.js' @@ -40,6 +40,7 @@ export function useSimulateWithdrawETH< ): UseSimulateWithdrawETHReturnType { const opConfig = useOpConfig(rest) const l2Chain = opConfig.l2chains[chainId] + const account = useAccount(rest) if (!l2Chain) { throw new Error('L2 chain not configured') @@ -53,6 +54,7 @@ export function useSimulateWithdrawETH< args: [OVM_ETH, args.to, args.amount, args.minGasLimit ?? 0, args.extraData ?? '0x'], value: args.amount, query: query as UseSimulateContractParameters['query'], + account: account.address, ...rest, }) as unknown as UseSimulateWithdrawETHReturnType } diff --git a/src/hooks/L2/useWriteWithdrawERC20.ts b/src/hooks/L2/useWriteWithdrawERC20.ts index 31baea9..689ab4f 100644 --- a/src/hooks/L2/useWriteWithdrawERC20.ts +++ b/src/hooks/L2/useWriteWithdrawERC20.ts @@ -1,7 +1,7 @@ import { l2StandardBridgeABI } from '@eth-optimism/contracts-ts' import { type Config } from '@wagmi/core' import { type WriteWithdrawERC20Parameters as WriteWithdrawERC20ActionParameters } from 'op-viem/actions' -import { useChainId, useWriteContract } from 'wagmi' +import { useWriteContract } from 'wagmi' import type { OpConfig } from '../../types/OpConfig.js' import type { UseWriteOPActionBaseParameters } from '../../types/UseWriteOPActionBaseParameters.js' import type { UseWriteOPActionBaseReturnType } from '../../types/UseWriteOPActionBaseReturnType.js' @@ -44,14 +44,9 @@ export function useWriteWithdrawERC20 { const config = useOpConfig(args) const { writeContract, writeContractAsync, ...writeReturn } = useWriteContract() - const currentChainId = useChainId() return { writeWithdrawERC20: ({ chainId, args, ...rest }: WriteWithdrawERC20Parameters) => { - if (currentChainId !== chainId) { - throw new Error(`Chain mismatch. Expected ${chainId}, got ${currentChainId}.`) - } - const l2Chain = config.l2chains[chainId] if (!l2Chain) { @@ -68,10 +63,6 @@ export function useWriteWithdrawERC20 { - if (currentChainId !== chainId) { - throw new Error(`Chain mismatch. Expected ${chainId}, got ${currentChainId}.`) - } - const l2Chain = config.l2chains[chainId] if (!l2Chain) { diff --git a/src/hooks/L2/useWriteWithdrawETH.ts b/src/hooks/L2/useWriteWithdrawETH.ts index 4465f68..bfc48e6 100644 --- a/src/hooks/L2/useWriteWithdrawETH.ts +++ b/src/hooks/L2/useWriteWithdrawETH.ts @@ -1,7 +1,7 @@ import { l2StandardBridgeABI } from '@eth-optimism/contracts-ts' import { type Config } from '@wagmi/core' import { type WriteWithdrawETHParameters as WriteWithdrawETHActionParameters } from 'op-viem/actions' -import { useChainId, useWriteContract } from 'wagmi' +import { useAccount, useWriteContract } from 'wagmi' import type { OpConfig } from '../../types/OpConfig.js' import type { UseWriteOPActionBaseParameters } from '../../types/UseWriteOPActionBaseParameters.js' import type { UseWriteOPActionBaseReturnType } from '../../types/UseWriteOPActionBaseReturnType.js' @@ -45,14 +45,10 @@ export function useWriteWithdrawETH { const config = useOpConfig(args) const { writeContract, writeContractAsync, ...writeReturn } = useWriteContract() - const currentChainId = useChainId() + const account = useAccount(args) return { writeWithdrawETH: ({ chainId, args, ...rest }: WriteWithdrawETHParameters) => { - if (currentChainId !== chainId) { - throw new Error(`Chain mismatch. Expected ${chainId}, got ${currentChainId}.`) - } - const l2Chain = config.l2chains[chainId] if (!l2Chain) { @@ -66,14 +62,11 @@ export function useWriteWithdrawETH { - if (currentChainId !== chainId) { - throw new Error(`Chain mismatch. Expected ${chainId}, got ${currentChainId}.`) - } - const l2Chain = config.l2chains[chainId] if (!l2Chain) { @@ -87,6 +80,7 @@ export function useWriteWithdrawETH Date: Fri, 24 Nov 2023 18:22:11 -0500 Subject: [PATCH 5/5] l2 tests --- src/hooks/L1/useWriteDepositERC20.test.ts | 1 + src/hooks/L2/useSimulateWithdrawERC20.test.ts | 121 ++++ src/hooks/L2/useSimulateWithdrawETH.test.ts | 122 ++++ src/hooks/L2/useWriteWithdrawERC20.test.ts | 657 +++++++++++++++++ src/hooks/L2/useWriteWithdrawETH.test.ts | 658 ++++++++++++++++++ 5 files changed, 1559 insertions(+) create mode 100644 src/hooks/L2/useSimulateWithdrawERC20.test.ts create mode 100644 src/hooks/L2/useSimulateWithdrawETH.test.ts create mode 100644 src/hooks/L2/useWriteWithdrawERC20.test.ts create mode 100644 src/hooks/L2/useWriteWithdrawETH.test.ts diff --git a/src/hooks/L1/useWriteDepositERC20.test.ts b/src/hooks/L1/useWriteDepositERC20.test.ts index 367f812..4202d9b 100644 --- a/src/hooks/L1/useWriteDepositERC20.test.ts +++ b/src/hooks/L1/useWriteDepositERC20.test.ts @@ -775,6 +775,7 @@ test('useWriteDepositERC20', async () => { "type": "receive", }, ], + "account": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "address": "0x3154Cf16ccdb4C6d922629664174b904d80F2C35", "args": [ "0xbe9895146f7af43049ca1c1ae358b0541ea49704", diff --git a/src/hooks/L2/useSimulateWithdrawERC20.test.ts b/src/hooks/L2/useSimulateWithdrawERC20.test.ts new file mode 100644 index 0000000..b472c3f --- /dev/null +++ b/src/hooks/L2/useSimulateWithdrawERC20.test.ts @@ -0,0 +1,121 @@ +import { expect, test } from 'vitest' +import { accounts } from '../../_test/constants.js' +import { renderHook, waitFor } from '../../_test/react.js' +import { useSimulateWithdrawERC20 } from './useSimulateWithdrawERC20.js' + +test('useSimulateWithdrawERC20', async () => { + const { result } = renderHook(() => + useSimulateWithdrawERC20({ + args: { + l2Token: '0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22', + to: accounts[0], + amount: 0n, + }, + chainId: 8453, + dataSuffix: '0x1234', + }) + ) + + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()) + + expect(result.current).toMatchInlineSnapshot(` + { + "data": { + "request": { + "__mode": "prepared", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_l2Token", + "type": "address", + }, + { + "internalType": "address", + "name": "_to", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "withdrawTo", + "outputs": [], + "stateMutability": "payable", + "type": "function", + }, + ], + "account": { + "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "type": "json-rpc", + }, + "address": "0x4200000000000000000000000000000000000010", + "args": [ + "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + 0n, + 0, + "0x", + ], + "chainId": 8453, + "dataSuffix": "0x1234", + "functionName": "withdrawTo", + }, + "result": undefined, + }, + "dataUpdatedAt": 1700438400000, + "error": null, + "errorUpdateCount": 0, + "errorUpdatedAt": 0, + "failureCount": 0, + "failureReason": null, + "fetchStatus": "idle", + "isError": false, + "isFetched": true, + "isFetchedAfterMount": true, + "isFetching": false, + "isInitialLoading": false, + "isLoading": false, + "isLoadingError": false, + "isPaused": false, + "isPending": false, + "isPlaceholderData": false, + "isRefetchError": false, + "isRefetching": false, + "isStale": true, + "isSuccess": true, + "queryKey": [ + "simulateContract", + { + "account": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "address": "0x4200000000000000000000000000000000000010", + "args": [ + "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + 0n, + 0, + "0x", + ], + "chainId": 8453, + "dataSuffix": "0x1234", + "functionName": "withdrawTo", + }, + ], + "refetch": [Function], + "status": "success", + } + `) +}, { retry: 3 }) diff --git a/src/hooks/L2/useSimulateWithdrawETH.test.ts b/src/hooks/L2/useSimulateWithdrawETH.test.ts new file mode 100644 index 0000000..af1cda6 --- /dev/null +++ b/src/hooks/L2/useSimulateWithdrawETH.test.ts @@ -0,0 +1,122 @@ +import { expect, test } from 'vitest' +import { accounts } from '../../_test/constants.js' +import { renderHook, waitFor } from '../../_test/react.js' +import { useSimulateWithdrawETH } from './useSimulateWithdrawETH.js' + +test('useSimulateWithdrawETH', async () => { + const { result } = renderHook(() => + useSimulateWithdrawETH({ + args: { + to: accounts[0], + amount: 1n, + }, + chainId: 8453, + dataSuffix: '0x1234', + }) + ) + + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()) + + expect(result.current).toMatchInlineSnapshot(` + { + "data": { + "request": { + "__mode": "prepared", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_l2Token", + "type": "address", + }, + { + "internalType": "address", + "name": "_to", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "withdrawTo", + "outputs": [], + "stateMutability": "payable", + "type": "function", + }, + ], + "account": { + "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "type": "json-rpc", + }, + "address": "0x4200000000000000000000000000000000000010", + "args": [ + "0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000", + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + 1n, + 0, + "0x", + ], + "chainId": 8453, + "dataSuffix": "0x1234", + "functionName": "withdrawTo", + "value": 1n, + }, + "result": undefined, + }, + "dataUpdatedAt": 1700438400000, + "error": null, + "errorUpdateCount": 0, + "errorUpdatedAt": 0, + "failureCount": 0, + "failureReason": null, + "fetchStatus": "idle", + "isError": false, + "isFetched": true, + "isFetchedAfterMount": true, + "isFetching": false, + "isInitialLoading": false, + "isLoading": false, + "isLoadingError": false, + "isPaused": false, + "isPending": false, + "isPlaceholderData": false, + "isRefetchError": false, + "isRefetching": false, + "isStale": true, + "isSuccess": true, + "queryKey": [ + "simulateContract", + { + "account": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "address": "0x4200000000000000000000000000000000000010", + "args": [ + "0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000", + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + 1n, + 0, + "0x", + ], + "chainId": 8453, + "dataSuffix": "0x1234", + "functionName": "withdrawTo", + "value": 1n, + }, + ], + "refetch": [Function], + "status": "success", + } + `) +}) diff --git a/src/hooks/L2/useWriteWithdrawERC20.test.ts b/src/hooks/L2/useWriteWithdrawERC20.test.ts new file mode 100644 index 0000000..afce93b --- /dev/null +++ b/src/hooks/L2/useWriteWithdrawERC20.test.ts @@ -0,0 +1,657 @@ +import { expect, test } from 'vitest' +import { useSwitchChain } from 'wagmi' +import { accounts } from '../../_test/constants.js' +import { renderHook, waitFor } from '../../_test/react.js' +import { useWriteWithdrawERC20 } from './useWriteWithdrawERC20.js' + +test('useWriteWithdrawERC20', async () => { + const { result } = renderHook(() => ({ + useWriteWithdrawERC20: useWriteWithdrawERC20(), + useSwitchChain: useSwitchChain(), + })) + + // Mocked account is connected to L1 by default, so switch to L2 first. + await result.current.useSwitchChain.switchChainAsync({ chainId: 8453 }) + + expect(result.current.useWriteWithdrawERC20.writeWithdrawERC20).toBeDefined() + expect(result.current.useWriteWithdrawERC20.writeWithdrawERC20).toBeDefined() + expect(result.current.useWriteWithdrawERC20.data).toBeUndefined() + expect(result.current.useWriteWithdrawERC20.isIdle).toBe(true) + + result.current.useWriteWithdrawERC20.writeWithdrawERC20({ + args: { + to: accounts[0], + l2Token: '0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22', + amount: 0n, + }, + chainId: 8453, + }) + + await waitFor(() => { + expect(result.current.useWriteWithdrawERC20.error).toBeNull() + expect(result.current.useWriteWithdrawERC20.isSuccess).toBeTruthy() + }) + + expect(result.current.useWriteWithdrawERC20).toMatchInlineSnapshot(` + { + "context": undefined, + "data": "${result.current.useWriteWithdrawERC20.data}", + "error": null, + "failureCount": 0, + "failureReason": null, + "isError": false, + "isIdle": false, + "isPaused": false, + "isPending": false, + "isSuccess": true, + "reset": [Function], + "status": "success", + "submittedAt": 1700438400000, + "variables": { + "abi": [ + { + "inputs": [ + { + "internalType": "address payable", + "name": "_otherBridge", + "type": "address", + }, + ], + "stateMutability": "nonpayable", + "type": "constructor", + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Token", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Token", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address", + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address", + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256", + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes", + }, + ], + "name": "DepositFinalized", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "localToken", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address", + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address", + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256", + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes", + }, + ], + "name": "ERC20BridgeFinalized", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "localToken", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address", + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address", + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256", + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes", + }, + ], + "name": "ERC20BridgeInitiated", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address", + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256", + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes", + }, + ], + "name": "ETHBridgeFinalized", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address", + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256", + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes", + }, + ], + "name": "ETHBridgeInitiated", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Token", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Token", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address", + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address", + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256", + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes", + }, + ], + "name": "WithdrawalInitiated", + "type": "event", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_localToken", + "type": "address", + }, + { + "internalType": "address", + "name": "_remoteToken", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "bridgeERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_localToken", + "type": "address", + }, + { + "internalType": "address", + "name": "_remoteToken", + "type": "address", + }, + { + "internalType": "address", + "name": "_to", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "bridgeERC20To", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "bridgeETH", + "outputs": [], + "stateMutability": "payable", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address", + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "bridgeETHTo", + "outputs": [], + "stateMutability": "payable", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address", + }, + { + "internalType": "address", + "name": "", + "type": "address", + }, + ], + "name": "deposits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256", + }, + ], + "stateMutability": "view", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_localToken", + "type": "address", + }, + { + "internalType": "address", + "name": "_remoteToken", + "type": "address", + }, + { + "internalType": "address", + "name": "_from", + "type": "address", + }, + { + "internalType": "address", + "name": "_to", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "finalizeBridgeERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address", + }, + { + "internalType": "address", + "name": "_to", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "finalizeBridgeETH", + "outputs": [], + "stateMutability": "payable", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address", + }, + { + "internalType": "address", + "name": "_l2Token", + "type": "address", + }, + { + "internalType": "address", + "name": "_from", + "type": "address", + }, + { + "internalType": "address", + "name": "_to", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "finalizeDeposit", + "outputs": [], + "stateMutability": "payable", + "type": "function", + }, + { + "inputs": [], + "name": "l1TokenBridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address", + }, + ], + "stateMutability": "view", + "type": "function", + }, + { + "inputs": [], + "name": "messenger", + "outputs": [ + { + "internalType": "contract CrossDomainMessenger", + "name": "", + "type": "address", + }, + ], + "stateMutability": "view", + "type": "function", + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string", + }, + ], + "stateMutability": "view", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l2Token", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "payable", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l2Token", + "type": "address", + }, + { + "internalType": "address", + "name": "_to", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "withdrawTo", + "outputs": [], + "stateMutability": "payable", + "type": "function", + }, + { + "stateMutability": "payable", + "type": "receive", + }, + ], + "address": "0x4200000000000000000000000000000000000010", + "args": [ + "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + 0n, + 0, + "0x", + ], + "chainId": 8453, + "functionName": "withdrawTo", + }, + "writeWithdrawERC20": [Function], + "writeWithdrawERC20Async": [Function], + } + `) +}, { retry: 3 }) diff --git a/src/hooks/L2/useWriteWithdrawETH.test.ts b/src/hooks/L2/useWriteWithdrawETH.test.ts new file mode 100644 index 0000000..8807d50 --- /dev/null +++ b/src/hooks/L2/useWriteWithdrawETH.test.ts @@ -0,0 +1,658 @@ +import { expect, test } from 'vitest' +import { useSwitchChain } from 'wagmi' +import { accounts } from '../../_test/constants.js' +import { renderHook, waitFor } from '../../_test/react.js' +import { useWriteWithdrawETH } from './useWriteWithdrawETH.js' + +test('useWriteWithdrawETH', async () => { + const { result } = renderHook(() => ({ + useWriteWithdrawETH: useWriteWithdrawETH(), + useSwitchChain: useSwitchChain(), + })) + + // Mocked account is connected to L1 by default, so switch to L2 first. + await result.current.useSwitchChain.switchChainAsync({ chainId: 8453 }) + + expect(result.current.useWriteWithdrawETH.writeWithdrawETH).toBeDefined() + expect(result.current.useWriteWithdrawETH.writeWithdrawETH).toBeDefined() + expect(result.current.useWriteWithdrawETH.data).toBeUndefined() + expect(result.current.useWriteWithdrawETH.isIdle).toBe(true) + + result.current.useWriteWithdrawETH.writeWithdrawETH({ + args: { + to: accounts[0], + amount: 0n, + }, + chainId: 8453, + }) + + await waitFor(() => { + expect(result.current.useWriteWithdrawETH.error).toBeNull() + expect(result.current.useWriteWithdrawETH.isSuccess).toBeTruthy() + }) + + expect(result.current.useWriteWithdrawETH).toMatchInlineSnapshot(` + { + "context": undefined, + "data": "${result.current.useWriteWithdrawETH.data}", + "error": null, + "failureCount": 0, + "failureReason": null, + "isError": false, + "isIdle": false, + "isPaused": false, + "isPending": false, + "isSuccess": true, + "reset": [Function], + "status": "success", + "submittedAt": 1700438400000, + "variables": { + "abi": [ + { + "inputs": [ + { + "internalType": "address payable", + "name": "_otherBridge", + "type": "address", + }, + ], + "stateMutability": "nonpayable", + "type": "constructor", + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Token", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Token", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address", + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address", + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256", + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes", + }, + ], + "name": "DepositFinalized", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "localToken", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address", + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address", + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256", + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes", + }, + ], + "name": "ERC20BridgeFinalized", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "localToken", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address", + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address", + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256", + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes", + }, + ], + "name": "ERC20BridgeInitiated", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address", + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256", + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes", + }, + ], + "name": "ETHBridgeFinalized", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address", + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256", + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes", + }, + ], + "name": "ETHBridgeInitiated", + "type": "event", + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Token", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Token", + "type": "address", + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address", + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address", + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256", + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes", + }, + ], + "name": "WithdrawalInitiated", + "type": "event", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_localToken", + "type": "address", + }, + { + "internalType": "address", + "name": "_remoteToken", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "bridgeERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_localToken", + "type": "address", + }, + { + "internalType": "address", + "name": "_remoteToken", + "type": "address", + }, + { + "internalType": "address", + "name": "_to", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "bridgeERC20To", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "bridgeETH", + "outputs": [], + "stateMutability": "payable", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address", + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "bridgeETHTo", + "outputs": [], + "stateMutability": "payable", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address", + }, + { + "internalType": "address", + "name": "", + "type": "address", + }, + ], + "name": "deposits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256", + }, + ], + "stateMutability": "view", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_localToken", + "type": "address", + }, + { + "internalType": "address", + "name": "_remoteToken", + "type": "address", + }, + { + "internalType": "address", + "name": "_from", + "type": "address", + }, + { + "internalType": "address", + "name": "_to", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "finalizeBridgeERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address", + }, + { + "internalType": "address", + "name": "_to", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "finalizeBridgeETH", + "outputs": [], + "stateMutability": "payable", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address", + }, + { + "internalType": "address", + "name": "_l2Token", + "type": "address", + }, + { + "internalType": "address", + "name": "_from", + "type": "address", + }, + { + "internalType": "address", + "name": "_to", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "finalizeDeposit", + "outputs": [], + "stateMutability": "payable", + "type": "function", + }, + { + "inputs": [], + "name": "l1TokenBridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address", + }, + ], + "stateMutability": "view", + "type": "function", + }, + { + "inputs": [], + "name": "messenger", + "outputs": [ + { + "internalType": "contract CrossDomainMessenger", + "name": "", + "type": "address", + }, + ], + "stateMutability": "view", + "type": "function", + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string", + }, + ], + "stateMutability": "view", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l2Token", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "payable", + "type": "function", + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l2Token", + "type": "address", + }, + { + "internalType": "address", + "name": "_to", + "type": "address", + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256", + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32", + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes", + }, + ], + "name": "withdrawTo", + "outputs": [], + "stateMutability": "payable", + "type": "function", + }, + { + "stateMutability": "payable", + "type": "receive", + }, + ], + "account": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "address": "0x4200000000000000000000000000000000000010", + "args": [ + "0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000", + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + 0n, + 0, + "0x", + ], + "chainId": 8453, + "functionName": "withdrawTo", + "value": 0n, + }, + "writeWithdrawETH": [Function], + "writeWithdrawETHAsync": [Function], + } + `) +}, { retry: 3 })