viem 2.30.0 → 2.30.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/_cjs/actions/public/call.js +2 -2
- package/_cjs/actions/public/call.js.map +1 -1
- package/_cjs/actions/public/estimateGas.js +1 -1
- package/_cjs/actions/public/estimateGas.js.map +1 -1
- package/_cjs/actions/public/simulateBlocks.js +1 -1
- package/_cjs/actions/public/simulateBlocks.js.map +1 -1
- package/_cjs/actions/public/waitForTransactionReceipt.js +9 -3
- package/_cjs/actions/public/waitForTransactionReceipt.js.map +1 -1
- package/_cjs/actions/public/watchBlocks.js +4 -2
- package/_cjs/actions/public/watchBlocks.js.map +1 -1
- package/_cjs/chains/definitions/bitkub.js +3 -3
- package/_cjs/chains/definitions/bitkub.js.map +1 -1
- package/_cjs/chains/definitions/chiliz.js +1 -1
- package/_cjs/chains/definitions/chiliz.js.map +1 -1
- package/_cjs/chains/definitions/jbc.js +1 -1
- package/_cjs/chains/definitions/jbc.js.map +1 -1
- package/_cjs/chains/definitions/riseTestnet.js +29 -0
- package/_cjs/chains/definitions/riseTestnet.js.map +1 -0
- package/_cjs/chains/index.js +6 -4
- package/_cjs/chains/index.js.map +1 -1
- package/_cjs/errors/version.js +1 -1
- package/_cjs/utils/rpc/socket.js +8 -4
- package/_cjs/utils/rpc/socket.js.map +1 -1
- package/_cjs/zksync/actions/claimFailedDeposit.js +146 -0
- package/_cjs/zksync/actions/claimFailedDeposit.js.map +1 -0
- package/_cjs/zksync/actions/deposit.js +51 -4
- package/_cjs/zksync/actions/deposit.js.map +1 -1
- package/_cjs/zksync/actions/finalizeWithdrawal.js +41 -41
- package/_cjs/zksync/actions/finalizeWithdrawal.js.map +1 -1
- package/_cjs/zksync/actions/getDefaultBridgeAddresses.js +2 -0
- package/_cjs/zksync/actions/getDefaultBridgeAddresses.js.map +1 -1
- package/_cjs/zksync/actions/isWithdrawalFinalized.js +2 -17
- package/_cjs/zksync/actions/isWithdrawalFinalized.js.map +1 -1
- package/_cjs/zksync/actions/withdraw.js +49 -8
- package/_cjs/zksync/actions/withdraw.js.map +1 -1
- package/_cjs/zksync/constants/address.js +4 -1
- package/_cjs/zksync/constants/address.js.map +1 -1
- package/_cjs/zksync/decorators/walletL1.js +2 -0
- package/_cjs/zksync/decorators/walletL1.js.map +1 -1
- package/_cjs/zksync/errors/bridge.js +23 -1
- package/_cjs/zksync/errors/bridge.js.map +1 -1
- package/_cjs/zksync/index.js +4 -2
- package/_cjs/zksync/index.js.map +1 -1
- package/_esm/actions/public/call.js +2 -2
- package/_esm/actions/public/call.js.map +1 -1
- package/_esm/actions/public/estimateGas.js +1 -1
- package/_esm/actions/public/estimateGas.js.map +1 -1
- package/_esm/actions/public/simulateBlocks.js +1 -1
- package/_esm/actions/public/simulateBlocks.js.map +1 -1
- package/_esm/actions/public/waitForTransactionReceipt.js +10 -3
- package/_esm/actions/public/waitForTransactionReceipt.js.map +1 -1
- package/_esm/actions/public/watchBlocks.js +4 -2
- package/_esm/actions/public/watchBlocks.js.map +1 -1
- package/_esm/chains/definitions/bitkub.js +3 -3
- package/_esm/chains/definitions/bitkub.js.map +1 -1
- package/_esm/chains/definitions/chiliz.js +1 -1
- package/_esm/chains/definitions/chiliz.js.map +1 -1
- package/_esm/chains/definitions/jbc.js +1 -1
- package/_esm/chains/definitions/jbc.js.map +1 -1
- package/_esm/chains/definitions/riseTestnet.js +26 -0
- package/_esm/chains/definitions/riseTestnet.js.map +1 -0
- package/_esm/chains/index.js +2 -0
- package/_esm/chains/index.js.map +1 -1
- package/_esm/errors/version.js +1 -1
- package/_esm/utils/rpc/socket.js +10 -6
- package/_esm/utils/rpc/socket.js.map +1 -1
- package/_esm/zksync/actions/claimFailedDeposit.js +199 -0
- package/_esm/zksync/actions/claimFailedDeposit.js.map +1 -0
- package/_esm/zksync/actions/deposit.js +61 -11
- package/_esm/zksync/actions/deposit.js.map +1 -1
- package/_esm/zksync/actions/finalizeWithdrawal.js +42 -42
- package/_esm/zksync/actions/finalizeWithdrawal.js.map +1 -1
- package/_esm/zksync/actions/getDefaultBridgeAddresses.js +2 -0
- package/_esm/zksync/actions/getDefaultBridgeAddresses.js.map +1 -1
- package/_esm/zksync/actions/isWithdrawalFinalized.js +3 -18
- package/_esm/zksync/actions/isWithdrawalFinalized.js.map +1 -1
- package/_esm/zksync/actions/withdraw.js +54 -10
- package/_esm/zksync/actions/withdraw.js.map +1 -1
- package/_esm/zksync/constants/address.js +3 -0
- package/_esm/zksync/constants/address.js.map +1 -1
- package/_esm/zksync/decorators/walletL1.js +2 -0
- package/_esm/zksync/decorators/walletL1.js.map +1 -1
- package/_esm/zksync/errors/bridge.js +19 -0
- package/_esm/zksync/errors/bridge.js.map +1 -1
- package/_esm/zksync/index.js +1 -0
- package/_esm/zksync/index.js.map +1 -1
- package/_types/actions/public/call.d.ts +1 -1
- package/_types/actions/public/estimateGas.d.ts +1 -1
- package/_types/actions/public/waitForTransactionReceipt.d.ts.map +1 -1
- package/_types/actions/public/watchBlocks.d.ts.map +1 -1
- package/_types/chains/definitions/bitkub.d.ts +3 -3
- package/_types/chains/definitions/chiliz.d.ts +1 -1
- package/_types/chains/definitions/jbc.d.ts +1 -1
- package/_types/chains/definitions/riseTestnet.d.ts +35 -0
- package/_types/chains/definitions/riseTestnet.d.ts.map +1 -0
- package/_types/chains/index.d.ts +2 -0
- package/_types/chains/index.d.ts.map +1 -1
- package/_types/errors/version.d.ts +1 -1
- package/_types/utils/rpc/socket.d.ts.map +1 -1
- package/_types/zksync/actions/claimFailedDeposit.d.ts +77 -0
- package/_types/zksync/actions/claimFailedDeposit.d.ts.map +1 -0
- package/_types/zksync/actions/deposit.d.ts +0 -1
- package/_types/zksync/actions/deposit.d.ts.map +1 -1
- package/_types/zksync/actions/finalizeWithdrawal.d.ts.map +1 -1
- package/_types/zksync/actions/getDefaultBridgeAddresses.d.ts.map +1 -1
- package/_types/zksync/actions/isWithdrawalFinalized.d.ts.map +1 -1
- package/_types/zksync/actions/withdraw.d.ts +1 -1
- package/_types/zksync/actions/withdraw.d.ts.map +1 -1
- package/_types/zksync/constants/address.d.ts +3 -0
- package/_types/zksync/constants/address.d.ts.map +1 -1
- package/_types/zksync/decorators/walletL1.d.ts +32 -1
- package/_types/zksync/decorators/walletL1.d.ts.map +1 -1
- package/_types/zksync/errors/bridge.d.ts +23 -0
- package/_types/zksync/errors/bridge.d.ts.map +1 -1
- package/_types/zksync/index.d.ts +1 -0
- package/_types/zksync/index.d.ts.map +1 -1
- package/_types/zksync/types/contract.d.ts +2 -0
- package/_types/zksync/types/contract.d.ts.map +1 -1
- package/_types/zksync/types/eip1193.d.ts +2 -0
- package/_types/zksync/types/eip1193.d.ts.map +1 -1
- package/actions/public/call.ts +3 -3
- package/actions/public/estimateGas.ts +2 -2
- package/actions/public/simulateBlocks.ts +1 -1
- package/actions/public/waitForTransactionReceipt.ts +159 -158
- package/actions/public/watchBlocks.ts +7 -5
- package/chains/definitions/bitkub.ts +3 -3
- package/chains/definitions/chiliz.ts +1 -1
- package/chains/definitions/jbc.ts +1 -1
- package/chains/definitions/riseTestnet.ts +26 -0
- package/chains/index.ts +2 -0
- package/errors/version.ts +1 -1
- package/package.json +7 -7
- package/utils/rpc/socket.ts +10 -8
- package/zksync/actions/claimFailedDeposit.ts +319 -0
- package/zksync/actions/deposit.ts +116 -14
- package/zksync/actions/finalizeWithdrawal.ts +53 -51
- package/zksync/actions/getDefaultBridgeAddresses.ts +3 -0
- package/zksync/actions/isWithdrawalFinalized.ts +4 -22
- package/zksync/actions/withdraw.ts +64 -8
- package/zksync/constants/address.ts +9 -0
- package/zksync/decorators/walletL1.ts +49 -1
- package/zksync/errors/bridge.ts +35 -0
- package/zksync/index.ts +6 -0
- package/zksync/types/contract.ts +2 -0
- package/zksync/types/eip1193.ts +2 -0
@@ -0,0 +1,319 @@
|
|
1
|
+
import { type Address, parseAbi } from 'abitype'
|
2
|
+
import { ethers } from 'ethers'
|
3
|
+
import type { Account } from '../../accounts/types.js'
|
4
|
+
import { getTransaction } from '../../actions/public/getTransaction.js'
|
5
|
+
import { getTransactionReceipt } from '../../actions/public/getTransactionReceipt.js'
|
6
|
+
import { readContract } from '../../actions/public/readContract.js'
|
7
|
+
import {
|
8
|
+
type SendTransactionErrorType,
|
9
|
+
type SendTransactionParameters,
|
10
|
+
type SendTransactionReturnType,
|
11
|
+
sendTransaction,
|
12
|
+
} from '../../actions/wallet/sendTransaction.js'
|
13
|
+
import type { Client } from '../../clients/createClient.js'
|
14
|
+
import type { Transport } from '../../clients/transports/createTransport.js'
|
15
|
+
import { AccountNotFoundError } from '../../errors/account.js'
|
16
|
+
import { ClientChainNotConfiguredError } from '../../errors/chain.js'
|
17
|
+
import type { TransactionReceiptNotFoundErrorType } from '../../errors/transaction.js'
|
18
|
+
import type { GetAccountParameter } from '../../types/account.js'
|
19
|
+
import type {
|
20
|
+
Chain,
|
21
|
+
DeriveChain,
|
22
|
+
GetChainParameter,
|
23
|
+
} from '../../types/chain.js'
|
24
|
+
import type { Hash } from '../../types/misc.js'
|
25
|
+
import type { Hex } from '../../types/misc.js'
|
26
|
+
import type { UnionEvaluate, UnionOmit } from '../../types/utils.js'
|
27
|
+
import {
|
28
|
+
type FormattedTransactionRequest,
|
29
|
+
decodeAbiParameters,
|
30
|
+
decodeFunctionData,
|
31
|
+
encodeAbiParameters,
|
32
|
+
encodeFunctionData,
|
33
|
+
isAddressEqual,
|
34
|
+
parseAccount,
|
35
|
+
} from '../../utils/index.js'
|
36
|
+
import { bootloaderFormalAddress } from '../constants/address.js'
|
37
|
+
import {
|
38
|
+
CannotClaimSuccessfulDepositError,
|
39
|
+
type CannotClaimSuccessfulDepositErrorType,
|
40
|
+
L2BridgeNotFoundError,
|
41
|
+
type L2BridgeNotFoundErrorType,
|
42
|
+
LogProofNotFoundError,
|
43
|
+
type LogProofNotFoundErrorType,
|
44
|
+
} from '../errors/bridge.js'
|
45
|
+
import type { ChainEIP712 } from '../types/chain.js'
|
46
|
+
import type { BridgeContractAddresses } from '../types/contract.js'
|
47
|
+
import type { ZksyncTransactionReceipt } from '../types/transaction.js'
|
48
|
+
import { undoL1ToL2Alias } from '../utils/bridge/undoL1ToL2Alias.js'
|
49
|
+
import { getDefaultBridgeAddresses } from './getDefaultBridgeAddresses.js'
|
50
|
+
import { getLogProof } from './getLogProof.js'
|
51
|
+
|
52
|
+
export type ClaimFailedDepositParameters<
|
53
|
+
chain extends Chain | undefined = Chain | undefined,
|
54
|
+
account extends Account | undefined = Account | undefined,
|
55
|
+
chainOverride extends Chain | undefined = Chain | undefined,
|
56
|
+
chainL2 extends ChainEIP712 | undefined = ChainEIP712 | undefined,
|
57
|
+
accountL2 extends Account | undefined = Account | undefined,
|
58
|
+
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
|
59
|
+
> = UnionEvaluate<
|
60
|
+
UnionOmit<FormattedTransactionRequest<_derivedChain>, 'data' | 'to' | 'from'>
|
61
|
+
> &
|
62
|
+
Partial<GetChainParameter<chain, chainOverride>> &
|
63
|
+
Partial<GetAccountParameter<account>> & {
|
64
|
+
/** L2 client. */
|
65
|
+
client: Client<Transport, chainL2, accountL2>
|
66
|
+
/** The L2 transaction hash of the failed deposit. */
|
67
|
+
depositHash: Hash
|
68
|
+
}
|
69
|
+
|
70
|
+
export type ClaimFailedDepositReturnType = SendTransactionReturnType
|
71
|
+
|
72
|
+
export type ClaimFailedDepositErrorType =
|
73
|
+
| SendTransactionErrorType
|
74
|
+
| TransactionReceiptNotFoundErrorType
|
75
|
+
| CannotClaimSuccessfulDepositErrorType
|
76
|
+
| LogProofNotFoundErrorType
|
77
|
+
| L2BridgeNotFoundErrorType
|
78
|
+
|
79
|
+
/**
|
80
|
+
* Withdraws funds from the initiated deposit, which failed when finalizing on L2.
|
81
|
+
* If the deposit L2 transaction has failed, it sends an L1 transaction calling `claimFailedDeposit` method of the
|
82
|
+
* L1 bridge, which results in returning L1 tokens back to the depositor.
|
83
|
+
*
|
84
|
+
* @param client - Client to use
|
85
|
+
* @param parameters - {@link ClaimFailedDepositParameters}
|
86
|
+
* @returns hash - The [Transaction](https://viem.sh/docs/glossary/terms#transaction) hash. {@link ClaimFailedDepositReturnType}
|
87
|
+
*
|
88
|
+
* @example
|
89
|
+
* import { createPublicClient, http } from 'viem'
|
90
|
+
* import { privateKeyToAccount } from 'viem/accounts'
|
91
|
+
* import { zksync, mainnet } from 'viem/chains'
|
92
|
+
* import { claimFailedDeposit, publicActionsL2 } from 'viem/zksync'
|
93
|
+
*
|
94
|
+
* const client = createPublicClient({
|
95
|
+
* chain: mainnet,
|
96
|
+
* transport: http(),
|
97
|
+
* })
|
98
|
+
*
|
99
|
+
* const clientL2 = createPublicClient({
|
100
|
+
* chain: zksync,
|
101
|
+
* transport: http(),
|
102
|
+
* }).extend(publicActionsL2())
|
103
|
+
*
|
104
|
+
* const account = privateKeyToAccount('0x…')
|
105
|
+
*
|
106
|
+
* const hash = await claimFailedDeposit(client, {
|
107
|
+
* client: clientL2,
|
108
|
+
* account,
|
109
|
+
* depositHash: <L2_HASH_OF_FAILED_DEPOSIT>,
|
110
|
+
* })
|
111
|
+
*
|
112
|
+
* @example Account Hoisting
|
113
|
+
* import { createPublicClient, createWalletClient, http } from 'viem'
|
114
|
+
* import { privateKeyToAccount } from 'viem/accounts'
|
115
|
+
* import { zksync, mainnet } from 'viem/chains'
|
116
|
+
* import { publicActionsL2 } from 'viem/zksync'
|
117
|
+
*
|
118
|
+
* const walletClient = createWalletClient({
|
119
|
+
* chain: mainnet,
|
120
|
+
* transport: http(),
|
121
|
+
* account: privateKeyToAccount('0x…'),
|
122
|
+
* })
|
123
|
+
*
|
124
|
+
* const clientL2 = createPublicClient({
|
125
|
+
* chain: zksync,
|
126
|
+
* transport: http(),
|
127
|
+
* }).extend(publicActionsL2())
|
128
|
+
*
|
129
|
+
* const hash = await claimFailedDeposit(walletClient, {
|
130
|
+
* client: clientL2,
|
131
|
+
* depositHash: <L2_HASH_OF_FAILED_DEPOSIT>,
|
132
|
+
* })
|
133
|
+
*/
|
134
|
+
export async function claimFailedDeposit<
|
135
|
+
chain extends Chain | undefined,
|
136
|
+
account extends Account | undefined,
|
137
|
+
chainOverride extends Chain | undefined = Chain | undefined,
|
138
|
+
chainL2 extends ChainEIP712 | undefined = ChainEIP712 | undefined,
|
139
|
+
accountL2 extends Account | undefined = Account | undefined,
|
140
|
+
_derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>,
|
141
|
+
>(
|
142
|
+
client: Client<Transport, chain, account>,
|
143
|
+
parameters: ClaimFailedDepositParameters<
|
144
|
+
chain,
|
145
|
+
account,
|
146
|
+
chainOverride,
|
147
|
+
chainL2,
|
148
|
+
accountL2
|
149
|
+
>,
|
150
|
+
): Promise<ClaimFailedDepositReturnType> {
|
151
|
+
const {
|
152
|
+
account: account_ = client.account,
|
153
|
+
chain: chain_ = client.chain,
|
154
|
+
client: l2Client,
|
155
|
+
depositHash,
|
156
|
+
...rest
|
157
|
+
} = parameters
|
158
|
+
|
159
|
+
const account = account_ ? parseAccount(account_) : client.account
|
160
|
+
if (!account)
|
161
|
+
throw new AccountNotFoundError({
|
162
|
+
docsPath: '/docs/actions/wallet/sendTransaction',
|
163
|
+
})
|
164
|
+
if (!l2Client.chain) throw new ClientChainNotConfiguredError()
|
165
|
+
|
166
|
+
const receipt = <ZksyncTransactionReceipt>(
|
167
|
+
await getTransactionReceipt(l2Client, { hash: depositHash })
|
168
|
+
)
|
169
|
+
|
170
|
+
const successL2ToL1LogIndex = receipt.l2ToL1Logs.findIndex(
|
171
|
+
(l2ToL1log) =>
|
172
|
+
isAddressEqual(<Hex>l2ToL1log.sender, bootloaderFormalAddress) &&
|
173
|
+
l2ToL1log.key === depositHash,
|
174
|
+
)
|
175
|
+
const successL2ToL1Log = receipt.l2ToL1Logs[successL2ToL1LogIndex]
|
176
|
+
if (successL2ToL1Log?.value !== ethers.ZeroHash)
|
177
|
+
throw new CannotClaimSuccessfulDepositError({ hash: depositHash })
|
178
|
+
|
179
|
+
const tx = await getTransaction(l2Client, { hash: depositHash })
|
180
|
+
|
181
|
+
// Undo the aliasing, since the Mailbox contract set it as for contract address.
|
182
|
+
const l1BridgeAddress = undoL1ToL2Alias(receipt.from)
|
183
|
+
const l2BridgeAddress = receipt.to
|
184
|
+
if (!l2BridgeAddress) throw new L2BridgeNotFoundError()
|
185
|
+
|
186
|
+
const l1NativeTokenVault = (await getBridgeAddresses(client, l2Client))
|
187
|
+
.l1NativeTokenVault
|
188
|
+
|
189
|
+
let depositSender: Hex
|
190
|
+
let assetId: Hex
|
191
|
+
let assetData: Hex
|
192
|
+
try {
|
193
|
+
const { args } = decodeFunctionData({
|
194
|
+
abi: parseAbi([
|
195
|
+
'function finalizeDeposit(address _l1Sender, address _l2Receiver, address _l1Token, uint256 _amount, bytes _data)',
|
196
|
+
]),
|
197
|
+
data: tx.input,
|
198
|
+
})
|
199
|
+
assetData = encodeAbiParameters(
|
200
|
+
[{ type: 'uint256' }, { type: 'address' }, { type: 'address' }],
|
201
|
+
[args[3], args[1], args[2]],
|
202
|
+
)
|
203
|
+
assetId = await readContract(client, {
|
204
|
+
address: l1NativeTokenVault,
|
205
|
+
abi: parseAbi(['function assetId(address token) view returns (bytes32)']),
|
206
|
+
functionName: 'assetId',
|
207
|
+
args: [args[2]],
|
208
|
+
})
|
209
|
+
depositSender = args[0]
|
210
|
+
if (assetId === ethers.ZeroHash)
|
211
|
+
throw new Error(`Token ${args[2]} not registered in NTV`)
|
212
|
+
} catch (_e) {
|
213
|
+
const { args } = decodeFunctionData({
|
214
|
+
abi: parseAbi([
|
215
|
+
'function finalizeDeposit(uint256 _chainId, bytes32 _assetId, bytes _transferData)',
|
216
|
+
]),
|
217
|
+
data: tx.input,
|
218
|
+
})
|
219
|
+
assetId = args[1]
|
220
|
+
const transferData = args[2]
|
221
|
+
const l1TokenAddress = await readContract(client, {
|
222
|
+
address: l1NativeTokenVault,
|
223
|
+
abi: parseAbi([
|
224
|
+
'function tokenAddress(bytes32 assetId) view returns (address)',
|
225
|
+
]),
|
226
|
+
functionName: 'tokenAddress',
|
227
|
+
args: [assetId],
|
228
|
+
})
|
229
|
+
const transferDataDecoded = decodeAbiParameters(
|
230
|
+
[
|
231
|
+
{ type: 'address' },
|
232
|
+
{ type: 'address' },
|
233
|
+
{ type: 'address' },
|
234
|
+
{ type: 'uint256' },
|
235
|
+
{ type: 'bytes' },
|
236
|
+
],
|
237
|
+
transferData,
|
238
|
+
)
|
239
|
+
assetData = encodeAbiParameters(
|
240
|
+
[{ type: 'uint256' }, { type: 'address' }, { type: 'address' }],
|
241
|
+
[transferDataDecoded[3], transferDataDecoded[1], l1TokenAddress],
|
242
|
+
)
|
243
|
+
depositSender = transferDataDecoded[0]
|
244
|
+
}
|
245
|
+
|
246
|
+
const proof = await getLogProof(l2Client, {
|
247
|
+
txHash: depositHash,
|
248
|
+
index: successL2ToL1LogIndex,
|
249
|
+
})
|
250
|
+
if (!proof)
|
251
|
+
throw new LogProofNotFoundError({
|
252
|
+
hash: depositHash,
|
253
|
+
index: successL2ToL1LogIndex,
|
254
|
+
})
|
255
|
+
|
256
|
+
const data = encodeFunctionData({
|
257
|
+
abi: parseAbi([
|
258
|
+
'function bridgeRecoverFailedTransfer(uint256 _chainId, address _depositSender, bytes32 _assetId, bytes _assetData, bytes32 _l2TxHash, uint256 _l2BatchNumber, uint256 _l2MessageIndex, uint16 _l2TxNumberInBatch, bytes32[] _merkleProof)',
|
259
|
+
]),
|
260
|
+
functionName: 'bridgeRecoverFailedTransfer',
|
261
|
+
args: [
|
262
|
+
BigInt(l2Client.chain.id),
|
263
|
+
depositSender,
|
264
|
+
assetId,
|
265
|
+
assetData,
|
266
|
+
depositHash,
|
267
|
+
receipt.l1BatchNumber!,
|
268
|
+
BigInt(proof.id),
|
269
|
+
Number(receipt.l1BatchTxIndex),
|
270
|
+
proof.proof,
|
271
|
+
],
|
272
|
+
})
|
273
|
+
|
274
|
+
return await sendTransaction(client, {
|
275
|
+
chain: chain_,
|
276
|
+
account,
|
277
|
+
to: l1BridgeAddress,
|
278
|
+
data,
|
279
|
+
...rest,
|
280
|
+
} as SendTransactionParameters)
|
281
|
+
}
|
282
|
+
|
283
|
+
async function getBridgeAddresses<
|
284
|
+
chain extends Chain | undefined,
|
285
|
+
chainL2 extends ChainEIP712 | undefined,
|
286
|
+
>(
|
287
|
+
client: Client<Transport, chain>,
|
288
|
+
l2Client: Client<Transport, chainL2>,
|
289
|
+
): Promise<
|
290
|
+
BridgeContractAddresses & {
|
291
|
+
l1Nullifier: Address
|
292
|
+
l1NativeTokenVault: Address
|
293
|
+
}
|
294
|
+
> {
|
295
|
+
const addresses = await getDefaultBridgeAddresses(l2Client)
|
296
|
+
let l1Nullifier = addresses.l1Nullifier
|
297
|
+
let l1NativeTokenVault = addresses.l1NativeTokenVault
|
298
|
+
|
299
|
+
if (!l1Nullifier)
|
300
|
+
l1Nullifier = await readContract(client, {
|
301
|
+
address: addresses.sharedL1,
|
302
|
+
abi: parseAbi(['function L1_NULLIFIER() view returns (address)']),
|
303
|
+
functionName: 'L1_NULLIFIER',
|
304
|
+
args: [],
|
305
|
+
})
|
306
|
+
if (!l1NativeTokenVault)
|
307
|
+
l1NativeTokenVault = await readContract(client, {
|
308
|
+
address: addresses.sharedL1,
|
309
|
+
abi: parseAbi(['function nativeTokenVault() view returns (address)']),
|
310
|
+
functionName: 'nativeTokenVault',
|
311
|
+
args: [],
|
312
|
+
})
|
313
|
+
|
314
|
+
return {
|
315
|
+
...addresses,
|
316
|
+
l1Nullifier,
|
317
|
+
l1NativeTokenVault,
|
318
|
+
}
|
319
|
+
}
|
@@ -1,4 +1,5 @@
|
|
1
|
-
import { type Address, parseAbi
|
1
|
+
import { type Address, parseAbi } from 'abitype'
|
2
|
+
import { ethers } from 'ethers'
|
2
3
|
import type { Account } from '../../accounts/types.js'
|
3
4
|
import {
|
4
5
|
type EstimateGasParameters,
|
@@ -33,14 +34,17 @@ import type { Hex } from '../../types/misc.js'
|
|
33
34
|
import type { UnionEvaluate, UnionOmit } from '../../types/utils.js'
|
34
35
|
import {
|
35
36
|
type FormattedTransactionRequest,
|
37
|
+
concatHex,
|
36
38
|
encodeAbiParameters,
|
37
39
|
encodeFunctionData,
|
38
40
|
isAddressEqual,
|
41
|
+
keccak256,
|
39
42
|
parseAccount,
|
40
43
|
} from '../../utils/index.js'
|
41
44
|
import { bridgehubAbi } from '../constants/abis.js'
|
42
45
|
import {
|
43
46
|
ethAddressInContracts,
|
47
|
+
l2NativeTokenVaultAddress,
|
44
48
|
legacyEthAddress,
|
45
49
|
} from '../constants/address.js'
|
46
50
|
import { requiredL1ToL2GasPerPubdataLimit } from '../constants/number.js'
|
@@ -184,7 +188,6 @@ export type DepositErrorType =
|
|
184
188
|
*
|
185
189
|
* const hash = await deposit(walletClient, {
|
186
190
|
* client: clientL2,
|
187
|
-
* account,
|
188
191
|
* token: legacyEthAddress,
|
189
192
|
* to: walletClient.account.address,
|
190
193
|
* amount: 1_000_000_000_000_000_000n,
|
@@ -228,7 +231,7 @@ export async function deposit<
|
|
228
231
|
|
229
232
|
if (isAddressEqual(token, legacyEthAddress)) token = ethAddressInContracts
|
230
233
|
|
231
|
-
const bridgeAddresses = await
|
234
|
+
const bridgeAddresses = await getBridgeAddresses(client, l2Client)
|
232
235
|
const bridgehub = await getBridgehubContractAddress(l2Client)
|
233
236
|
const baseToken = await readContract(client, {
|
234
237
|
address: bridgehub,
|
@@ -240,7 +243,6 @@ export async function deposit<
|
|
240
243
|
const { mintValue, tx } = await getL1DepositTx(
|
241
244
|
client,
|
242
245
|
account,
|
243
|
-
// @ts-ignore
|
244
246
|
{ ...parameters, token },
|
245
247
|
bridgeAddresses,
|
246
248
|
bridgehub,
|
@@ -296,7 +298,10 @@ async function getL1DepositTx<
|
|
296
298
|
accountL2,
|
297
299
|
_derivedChain
|
298
300
|
>,
|
299
|
-
bridgeAddresses: BridgeContractAddresses
|
301
|
+
bridgeAddresses: BridgeContractAddresses & {
|
302
|
+
l1Nullifier: Address
|
303
|
+
l1NativeTokenVault: Address
|
304
|
+
},
|
300
305
|
bridgehub: Address,
|
301
306
|
baseToken: Address,
|
302
307
|
) {
|
@@ -406,9 +411,12 @@ async function getL1DepositTx<
|
|
406
411
|
refundRecipient,
|
407
412
|
secondBridgeAddress: bridgeAddress,
|
408
413
|
secondBridgeValue: 0n,
|
409
|
-
secondBridgeCalldata:
|
410
|
-
|
411
|
-
|
414
|
+
secondBridgeCalldata: await getSecondBridgeCalldata(
|
415
|
+
client,
|
416
|
+
bridgeAddresses.l1NativeTokenVault,
|
417
|
+
token,
|
418
|
+
amount,
|
419
|
+
to,
|
412
420
|
),
|
413
421
|
},
|
414
422
|
],
|
@@ -435,9 +443,12 @@ async function getL1DepositTx<
|
|
435
443
|
refundRecipient,
|
436
444
|
secondBridgeAddress: bridgeAddress,
|
437
445
|
secondBridgeValue: amount,
|
438
|
-
secondBridgeCalldata:
|
439
|
-
|
440
|
-
|
446
|
+
secondBridgeCalldata: await getSecondBridgeCalldata(
|
447
|
+
client,
|
448
|
+
bridgeAddresses.l1NativeTokenVault,
|
449
|
+
ethAddressInContracts,
|
450
|
+
amount,
|
451
|
+
to,
|
441
452
|
),
|
442
453
|
},
|
443
454
|
],
|
@@ -464,9 +475,12 @@ async function getL1DepositTx<
|
|
464
475
|
refundRecipient,
|
465
476
|
secondBridgeAddress: bridgeAddress,
|
466
477
|
secondBridgeValue: 0n,
|
467
|
-
secondBridgeCalldata:
|
468
|
-
|
469
|
-
|
478
|
+
secondBridgeCalldata: await getSecondBridgeCalldata(
|
479
|
+
client,
|
480
|
+
bridgeAddresses.l1NativeTokenVault,
|
481
|
+
token,
|
482
|
+
amount,
|
483
|
+
to,
|
470
484
|
),
|
471
485
|
},
|
472
486
|
],
|
@@ -839,6 +853,94 @@ async function encodeDefaultBridgeData<chain extends Chain | undefined>(
|
|
839
853
|
)
|
840
854
|
}
|
841
855
|
|
856
|
+
async function getSecondBridgeCalldata<chain extends Chain | undefined>(
|
857
|
+
client: Client<Transport, chain>,
|
858
|
+
l1NativeTokenVault: Address,
|
859
|
+
token: Address,
|
860
|
+
amount: bigint,
|
861
|
+
to: Address,
|
862
|
+
): Promise<Hex> {
|
863
|
+
let assetId: Hex
|
864
|
+
let token_ = token
|
865
|
+
if (isAddressEqual(token, legacyEthAddress)) token_ = ethAddressInContracts
|
866
|
+
|
867
|
+
const assetIdFromNTV = await readContract(client, {
|
868
|
+
address: l1NativeTokenVault,
|
869
|
+
abi: parseAbi(['function assetId(address token) view returns (bytes32)']),
|
870
|
+
functionName: 'assetId',
|
871
|
+
args: [token_],
|
872
|
+
})
|
873
|
+
|
874
|
+
if (assetIdFromNTV && assetIdFromNTV !== ethers.ZeroHash)
|
875
|
+
assetId = assetIdFromNTV
|
876
|
+
else {
|
877
|
+
// Okay, the token have not been registered within the Native token vault.
|
878
|
+
// There are two cases when it is possible:
|
879
|
+
// - The token is native to L1 (it may or may not be bridged), but it has not been
|
880
|
+
// registered within NTV after the Gateway upgrade. We assume that this is not the case
|
881
|
+
// as the SDK is expected to work only after the full migration is done.
|
882
|
+
// - The token is native to the current chain and it has never been bridged.
|
883
|
+
|
884
|
+
if (!client.chain) throw new ClientChainNotConfiguredError()
|
885
|
+
assetId = keccak256(
|
886
|
+
encodeAbiParameters(
|
887
|
+
[{ type: 'uint256' }, { type: 'address' }, { type: 'address' }],
|
888
|
+
[BigInt(client.chain.id), l2NativeTokenVaultAddress, token_],
|
889
|
+
),
|
890
|
+
)
|
891
|
+
}
|
892
|
+
|
893
|
+
const ntvData = encodeAbiParameters(
|
894
|
+
[{ type: 'uint256' }, { type: 'address' }, { type: 'address' }],
|
895
|
+
[BigInt(amount), to, token_],
|
896
|
+
)
|
897
|
+
|
898
|
+
const data = encodeAbiParameters(
|
899
|
+
[{ type: 'bytes32' }, { type: 'bytes' }],
|
900
|
+
[assetId, ntvData],
|
901
|
+
)
|
902
|
+
|
903
|
+
return concatHex(['0x01', data])
|
904
|
+
}
|
905
|
+
|
906
|
+
async function getBridgeAddresses<
|
907
|
+
chain extends Chain | undefined,
|
908
|
+
chainL2 extends ChainEIP712 | undefined,
|
909
|
+
>(
|
910
|
+
client: Client<Transport, chain>,
|
911
|
+
l2Client: Client<Transport, chainL2>,
|
912
|
+
): Promise<
|
913
|
+
BridgeContractAddresses & {
|
914
|
+
l1Nullifier: Address
|
915
|
+
l1NativeTokenVault: Address
|
916
|
+
}
|
917
|
+
> {
|
918
|
+
const addresses = await getDefaultBridgeAddresses(l2Client)
|
919
|
+
let l1Nullifier = addresses.l1Nullifier
|
920
|
+
let l1NativeTokenVault = addresses.l1NativeTokenVault
|
921
|
+
|
922
|
+
if (!l1Nullifier)
|
923
|
+
l1Nullifier = await readContract(client, {
|
924
|
+
address: addresses.sharedL1,
|
925
|
+
abi: parseAbi(['function L1_NULLIFIER() view returns (address)']),
|
926
|
+
functionName: 'L1_NULLIFIER',
|
927
|
+
args: [],
|
928
|
+
})
|
929
|
+
if (!l1NativeTokenVault)
|
930
|
+
l1NativeTokenVault = await readContract(client, {
|
931
|
+
address: addresses.sharedL1,
|
932
|
+
abi: parseAbi(['function nativeTokenVault() view returns (address)']),
|
933
|
+
functionName: 'nativeTokenVault',
|
934
|
+
args: [],
|
935
|
+
})
|
936
|
+
|
937
|
+
return {
|
938
|
+
...addresses,
|
939
|
+
l1Nullifier,
|
940
|
+
l1NativeTokenVault,
|
941
|
+
}
|
942
|
+
}
|
943
|
+
|
842
944
|
function scaleGasLimit(gasLimit: bigint): bigint {
|
843
945
|
return (gasLimit * BigInt(12)) / BigInt(10)
|
844
946
|
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import type
|
1
|
+
import { type Address, parseAbi } from 'abitype'
|
2
2
|
import type { Account } from '../../accounts/types.js'
|
3
3
|
import { readContract } from '../../actions/public/readContract.js'
|
4
4
|
import {
|
@@ -20,17 +20,15 @@ import type { Hex } from '../../types/misc.js'
|
|
20
20
|
import {
|
21
21
|
decodeAbiParameters,
|
22
22
|
encodeFunctionData,
|
23
|
-
isAddressEqual,
|
24
23
|
parseAccount,
|
25
24
|
slice,
|
26
25
|
} from '../../utils/index.js'
|
27
|
-
import { l1SharedBridgeAbi, l2SharedBridgeAbi } from '../constants/abis.js'
|
28
|
-
import { l2BaseTokenAddress } from '../constants/address.js'
|
29
26
|
import {
|
30
27
|
WithdrawalLogNotFoundError,
|
31
28
|
type WithdrawalLogNotFoundErrorType,
|
32
29
|
} from '../errors/bridge.js'
|
33
30
|
import type { ChainEIP712 } from '../types/chain.js'
|
31
|
+
import type { BridgeContractAddresses } from '../types/contract.js'
|
34
32
|
import { getWithdrawalL2ToL1Log } from '../utils/bridge/getWithdrawalL2ToL1Log.js'
|
35
33
|
import { getWithdrawalLog } from '../utils/bridge/getWithdrawalLog.js'
|
36
34
|
import { getDefaultBridgeAddresses } from './getDefaultBridgeAddresses.js'
|
@@ -149,52 +147,35 @@ export async function finalizeWithdrawal<
|
|
149
147
|
})
|
150
148
|
if (!l2Client.chain) throw new ChainNotFoundError()
|
151
149
|
|
152
|
-
const {
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
message,
|
157
|
-
sender,
|
158
|
-
proof,
|
159
|
-
} = await getFinalizeWithdrawalParams(l2Client, { hash, index })
|
160
|
-
|
161
|
-
let l1Bridge: Address
|
150
|
+
const finalizeWithdrawalParams = await getFinalizeWithdrawalParams(l2Client, {
|
151
|
+
hash,
|
152
|
+
index,
|
153
|
+
})
|
162
154
|
|
163
|
-
|
164
|
-
l1Bridge = (await getDefaultBridgeAddresses(l2Client)).sharedL1
|
165
|
-
else if (!(await isLegacyBridge(l2Client, { address: sender })))
|
166
|
-
l1Bridge = await readContract(l2Client, {
|
167
|
-
address: sender,
|
168
|
-
abi: l2SharedBridgeAbi,
|
169
|
-
functionName: 'l1SharedBridge',
|
170
|
-
args: [],
|
171
|
-
})
|
172
|
-
else
|
173
|
-
l1Bridge = await readContract(l2Client, {
|
174
|
-
address: sender,
|
175
|
-
abi: l2SharedBridgeAbi,
|
176
|
-
functionName: 'l1Bridge',
|
177
|
-
args: [],
|
178
|
-
})
|
155
|
+
const l1Nullifier = (await getBridgeAddresses(client, l2Client)).l1Nullifier
|
179
156
|
|
180
157
|
const data = encodeFunctionData({
|
181
|
-
abi:
|
182
|
-
|
158
|
+
abi: parseAbi([
|
159
|
+
'function finalizeDeposit((uint256 chainId, uint256 l2BatchNumber, uint256 l2MessageIndex, address l2Sender, uint16 l2TxNumberInBatch, bytes message, bytes32[] merkleProof) _finalizeWithdrawalParams)',
|
160
|
+
]),
|
161
|
+
functionName: 'finalizeDeposit',
|
183
162
|
args: [
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
163
|
+
{
|
164
|
+
chainId: BigInt(l2Client.chain.id),
|
165
|
+
l2BatchNumber: finalizeWithdrawalParams.l1BatchNumber!,
|
166
|
+
l2MessageIndex: BigInt(finalizeWithdrawalParams.l2MessageIndex),
|
167
|
+
l2Sender: finalizeWithdrawalParams.sender,
|
168
|
+
l2TxNumberInBatch: Number(finalizeWithdrawalParams.l2TxNumberInBlock),
|
169
|
+
message: finalizeWithdrawalParams.message,
|
170
|
+
merkleProof: finalizeWithdrawalParams.proof,
|
171
|
+
},
|
190
172
|
],
|
191
173
|
})
|
192
174
|
|
193
175
|
return await sendTransaction(client, {
|
194
176
|
account,
|
195
|
-
to:
|
177
|
+
to: l1Nullifier,
|
196
178
|
data,
|
197
|
-
value: 0n,
|
198
179
|
...rest,
|
199
180
|
} as SendTransactionParameters)
|
200
181
|
}
|
@@ -230,19 +211,40 @@ async function getFinalizeWithdrawalParams<
|
|
230
211
|
}
|
231
212
|
}
|
232
213
|
|
233
|
-
async function
|
214
|
+
async function getBridgeAddresses<
|
234
215
|
chain extends Chain | undefined,
|
235
|
-
|
236
|
-
>(
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
216
|
+
chainL2 extends ChainEIP712 | undefined,
|
217
|
+
>(
|
218
|
+
client: Client<Transport, chain>,
|
219
|
+
l2Client: Client<Transport, chainL2>,
|
220
|
+
): Promise<
|
221
|
+
BridgeContractAddresses & {
|
222
|
+
l1Nullifier: Address
|
223
|
+
l1NativeTokenVault: Address
|
224
|
+
}
|
225
|
+
> {
|
226
|
+
const addresses = await getDefaultBridgeAddresses(l2Client)
|
227
|
+
let l1Nullifier = addresses.l1Nullifier
|
228
|
+
let l1NativeTokenVault = addresses.l1NativeTokenVault
|
229
|
+
|
230
|
+
if (!l1Nullifier)
|
231
|
+
l1Nullifier = await readContract(client, {
|
232
|
+
address: addresses.sharedL1,
|
233
|
+
abi: parseAbi(['function L1_NULLIFIER() view returns (address)']),
|
234
|
+
functionName: 'L1_NULLIFIER',
|
242
235
|
args: [],
|
243
236
|
})
|
244
|
-
|
245
|
-
|
246
|
-
|
237
|
+
if (!l1NativeTokenVault)
|
238
|
+
l1NativeTokenVault = await readContract(client, {
|
239
|
+
address: addresses.sharedL1,
|
240
|
+
abi: parseAbi(['function nativeTokenVault() view returns (address)']),
|
241
|
+
functionName: 'nativeTokenVault',
|
242
|
+
args: [],
|
243
|
+
})
|
244
|
+
|
245
|
+
return {
|
246
|
+
...addresses,
|
247
|
+
l1Nullifier,
|
248
|
+
l1NativeTokenVault,
|
247
249
|
}
|
248
250
|
}
|
@@ -14,9 +14,12 @@ export async function getDefaultBridgeAddresses<
|
|
14
14
|
client: Client<Transport, chain, account, PublicZksyncRpcSchema>,
|
15
15
|
): Promise<GetDefaultBridgeAddressesReturnType> {
|
16
16
|
const addresses = await client.request({ method: 'zks_getBridgeContracts' })
|
17
|
+
|
17
18
|
return {
|
18
19
|
erc20L1: addresses.l1Erc20DefaultBridge,
|
19
20
|
sharedL1: addresses.l1SharedDefaultBridge,
|
20
21
|
sharedL2: addresses.l2SharedDefaultBridge,
|
22
|
+
l1Nullifier: addresses.l1Nullifier,
|
23
|
+
l1NativeTokenVault: addresses.l1NativeTokenVault,
|
21
24
|
}
|
22
25
|
}
|