github.com/ethereum-optimism/optimism@v1.7.2/packages/fee-estimation/src/estimateFees.spec.ts (about) 1 /** 2 * The first 2 test cases are good documentation of how to use this library 3 */ 4 import { vi, test, expect, beforeEach } from 'vitest' 5 import { formatEther } from 'viem/utils' 6 import { 7 baseFee, 8 decimals, 9 estimateFees, 10 gasPrice, 11 getL1Fee, 12 getL1GasUsed, 13 getL2Client, 14 l1BaseFee, 15 overhead, 16 scalar, 17 version, 18 } from './estimateFees' 19 import { 20 optimistABI, 21 optimistAddress, 22 l2StandardBridgeABI, 23 l2StandardBridgeAddress, 24 } from '@eth-optimism/contracts-ts' 25 import { parseEther, parseGwei } from 'viem' 26 27 vi.mock('viem', async () => { 28 const _viem = (await vi.importActual('viem')) as any 29 return { 30 ..._viem, 31 // no way to get historical gas price 32 createPublicClient: (...args: [any]) => { 33 const client = _viem.createPublicClient(...args) 34 client.getGasPrice = async () => parseGwei('0.00000042') 35 return client 36 }, 37 } 38 }) 39 40 // using this optimist https://optimistic.etherscan.io/tx/0xaa291efba7ea40b0742e5ff84a1e7831a2eb6c2fc35001fa03ba80fd3b609dc9 41 const blockNumber = BigInt(107028270) 42 const optimistOwnerAddress = 43 '0x77194aa25a06f932c10c0f25090f3046af2c85a6' as const 44 const functionDataBurn = { 45 functionName: 'burn', 46 // this is an erc721 abi 47 abi: optimistABI, 48 args: [BigInt(optimistOwnerAddress)], 49 account: optimistOwnerAddress, 50 to: optimistAddress[10], 51 chainId: 10, 52 } as const 53 const functionDataBurnWithPriorityFees = { 54 ...functionDataBurn, 55 maxFeePerGas: parseGwei('2'), 56 maxPriorityFeePerGas: parseGwei('2'), 57 } as const 58 // This tx 59 // https://optimistic.etherscan.io/tx/0xe6f3719be7327a991b9cb562ebf8d979cbca72bbdb2775f55a18274f4d0c9bbf 60 const functionDataWithdraw = { 61 abi: l2StandardBridgeABI, 62 functionName: 'withdraw', 63 value: BigInt(parseEther('0.00000001')), 64 account: '0x6387a88a199120aD52Dd9742C7430847d3cB2CD4', 65 // currently a bug is making chain id 10 not exist 66 to: l2StandardBridgeAddress[420], 67 chainId: 10, 68 args: [ 69 // l2 token address 70 '0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000', 71 // amount 72 BigInt(parseEther('0.00000001')), 73 // l1 gas 74 0, 75 // extra data 76 '0x0', 77 ], 78 maxFeePerGas: parseGwei('.2'), 79 maxPriorityFeePerGas: parseGwei('.1'), 80 } as const 81 82 const clientParams = { 83 chainId: functionDataBurn.chainId, 84 rpcUrl: process.env.VITE_L2_RPC_URL ?? 'https://mainnet.optimism.io', 85 } as const 86 87 const viemClient = getL2Client(clientParams) 88 89 const paramsWithRpcUrl = { 90 client: clientParams, 91 blockNumber, 92 } as const 93 const paramsWithViemClient = { 94 client: viemClient, 95 viemClient, 96 blockNumber, 97 } as const 98 const blockNumberWithdraw = BigInt(107046472) 99 const paramsWithRpcUrlWithdraw = { 100 client: clientParams, 101 blockNumber: blockNumberWithdraw, 102 } as const 103 104 beforeEach(() => { 105 vi.resetAllMocks() 106 }) 107 108 test('estimateFees should return correct fees', async () => { 109 // burn 110 const res = await estimateFees({ ...paramsWithRpcUrl, ...functionDataBurn }) 111 expect(res).toMatchInlineSnapshot('20573203833264n') 112 expect(formatEther(res)).toMatchInlineSnapshot('"0.000020573203833264"') 113 expect( 114 await estimateFees({ ...paramsWithRpcUrl, ...functionDataBurn }) 115 ).toMatchInlineSnapshot('20573203833264n') 116 expect( 117 await estimateFees({ ...paramsWithViemClient, ...functionDataBurn }) 118 ).toMatchInlineSnapshot('20573203833264n') 119 expect( 120 await estimateFees({ 121 ...paramsWithRpcUrl, 122 ...functionDataBurnWithPriorityFees, 123 }) 124 ).toMatchInlineSnapshot('21536992690265n') 125 // what is the l2 and l1 part of the fees for reference? 126 const l1Fee = await getL1Fee({ ...paramsWithRpcUrl, ...functionDataBurn }) 127 const l2Fee = res - l1Fee 128 expect(l1Fee).toMatchInlineSnapshot('20573185216764n') 129 expect(formatEther(l1Fee)).toMatchInlineSnapshot('"0.000020573185216764"') 130 expect(l2Fee).toMatchInlineSnapshot('18616500n') 131 expect(formatEther(l2Fee)).toMatchInlineSnapshot('"0.0000000000186165"') 132 133 // withdraw 134 const res2 = await estimateFees({ 135 ...paramsWithRpcUrlWithdraw, 136 ...functionDataWithdraw, 137 }) 138 expect(res2).toMatchInlineSnapshot('62857090247510n') 139 expect( 140 await estimateFees({ ...paramsWithRpcUrlWithdraw, ...functionDataWithdraw }) 141 ).toMatchInlineSnapshot('62857090247510n') 142 expect( 143 await estimateFees({ ...paramsWithRpcUrlWithdraw, ...functionDataWithdraw }) 144 ).toMatchInlineSnapshot('62857090247510n') 145 expect( 146 await estimateFees({ ...paramsWithRpcUrlWithdraw, ...functionDataWithdraw }) 147 ).toMatchInlineSnapshot('62857090247510n') 148 expect(formatEther(res2)).toMatchInlineSnapshot('"0.00006285709024751"') 149 // what is the l2 and l1 part of the fees for reference? 150 const l1Fee2 = await getL1Fee({ 151 ...paramsWithRpcUrlWithdraw, 152 ...functionDataWithdraw, 153 }) 154 const l2Fee2 = res2 - l1Fee 155 expect(l1Fee2).toMatchInlineSnapshot('62857038894110n') 156 expect(formatEther(l1Fee2)).toMatchInlineSnapshot('"0.00006285703889411"') 157 expect(l2Fee2).toMatchInlineSnapshot('42283905030746n') 158 expect(formatEther(l2Fee2)).toMatchInlineSnapshot('"0.000042283905030746"') 159 }) 160 161 test('baseFee should return the correct result', async () => { 162 expect(await baseFee(paramsWithRpcUrl)).toMatchInlineSnapshot('64n') 163 expect(await baseFee(paramsWithViemClient)).toMatchInlineSnapshot('64n') 164 }) 165 166 test('decimals should return the correct result', async () => { 167 expect(await decimals(paramsWithRpcUrl)).toMatchInlineSnapshot('6n') 168 expect(await decimals(paramsWithViemClient)).toMatchInlineSnapshot('6n') 169 }) 170 171 test('gasPrice should return the correct result', async () => { 172 expect(await gasPrice(paramsWithRpcUrl)).toMatchInlineSnapshot('64n') 173 expect(await gasPrice(paramsWithViemClient)).toMatchInlineSnapshot('64n') 174 }) 175 176 test('getL1Fee should return the correct result', async () => { 177 // burn 178 expect( 179 await getL1Fee({ ...paramsWithRpcUrl, ...functionDataBurn }) 180 ).toMatchInlineSnapshot('20573185216764n') 181 expect( 182 await getL1Fee({ ...paramsWithViemClient, ...functionDataBurn }) 183 ).toMatchInlineSnapshot('20573185216764n') 184 expect( 185 await getL1Fee({ 186 ...paramsWithViemClient, 187 ...functionDataBurnWithPriorityFees, 188 }) 189 ).toMatchInlineSnapshot('21536974073765n') 190 expect( 191 formatEther( 192 await getL1Fee({ ...paramsWithViemClient, ...functionDataBurn }) 193 ) 194 ).toMatchInlineSnapshot('"0.000020573185216764"') 195 // withdraw 196 expect( 197 await getL1Fee({ ...paramsWithRpcUrlWithdraw, ...functionDataWithdraw }) 198 ).toMatchInlineSnapshot('62857038894110n') 199 expect( 200 formatEther( 201 await getL1Fee({ ...paramsWithRpcUrlWithdraw, ...functionDataWithdraw }) 202 ) 203 ).toMatchInlineSnapshot('"0.00006285703889411"') 204 }) 205 206 test('getL1GasUsed should return the correct result', async () => { 207 // burn 208 expect( 209 await getL1GasUsed({ ...paramsWithRpcUrl, ...functionDataBurn }) 210 ).toMatchInlineSnapshot('2220n') 211 expect( 212 await getL1GasUsed({ ...paramsWithViemClient, ...functionDataBurn }) 213 ).toMatchInlineSnapshot('2220n') 214 expect( 215 await getL1GasUsed({ 216 ...paramsWithViemClient, 217 ...functionDataBurnWithPriorityFees, 218 }) 219 ).toMatchInlineSnapshot('2324n') 220 // withdraw 221 expect( 222 await getL1GasUsed({ ...paramsWithRpcUrlWithdraw, ...functionDataWithdraw }) 223 ).toMatchInlineSnapshot('2868n') 224 }) 225 226 test('l1BaseFee should return the correct result', async () => { 227 expect(await l1BaseFee(paramsWithRpcUrl)).toMatchInlineSnapshot( 228 '13548538813n' 229 ) 230 expect(await l1BaseFee(paramsWithViemClient)).toMatchInlineSnapshot( 231 '13548538813n' 232 ) 233 }) 234 235 test('overhead should return the correct result', async () => { 236 expect(await overhead(paramsWithRpcUrl)).toMatchInlineSnapshot('188n') 237 expect(await overhead(paramsWithViemClient)).toMatchInlineSnapshot('188n') 238 }) 239 240 test('scalar should return the correct result', async () => { 241 expect(await scalar(paramsWithRpcUrl)).toMatchInlineSnapshot('684000n') 242 expect(await scalar(paramsWithViemClient)).toMatchInlineSnapshot('684000n') 243 }) 244 245 test('version should return the correct result', async () => { 246 expect(await version(paramsWithRpcUrl)).toMatchInlineSnapshot('"1.0.0"') 247 expect(await version(paramsWithViemClient)).toMatchInlineSnapshot('"1.0.0"') 248 })