# Bridge Parameters
08-11: Update L2 status for the front-end:
```
const { L1TransactionReceipt } = require('@arbitrum/sdk')
const receipt = await l1Provider.getTransactionReceipt(txnHash)
const l1Receipt = new L1TransactionReceipt(receipt)
const message = await l1Receipt.getL1ToL2Message(l2Wallet)
const status = (await message.waitForStatus()).status
if (status === 4) {
console.log(`L2 retryable txn is already executed 🥳 ${message.l2TxHash}`)
return
} else {
console.log(
`L2 retryable txn failed with status ${L1ToL2MessageStatus[status]}`
)
}
```
其中status的状态如下:
```
/**
* The retryable ticket has yet to be created
*/
NOT_YET_CREATED = 1,
/**
* An attempt was made to create the retryable ticket, but it failed.
* This could be due to not enough submission cost being paid by the L1 transaction
*/
CREATION_FAILED = 2,
/**
* The retryable ticket has been created but has not been redeemed. This could be due to the
* auto redeem failing, or if the params (max l2 gas price) * (max l2 gas) = 0 then no auto
* redeem tx is ever issued. An auto redeem is also never issued for ETH deposits.
* A manual redeem is now required.
*/
FUNDS_DEPOSITED_ON_L2 = 3,
/**
* The retryable ticket has been redeemed (either by auto, or manually) and the
* l2 transaction has been executed
*/
REDEEMED = 4,
/**
* The message has either expired or has been canceled. It can no longer be redeemed.
*/
EXPIRED = 5
```
08-01:Update bridge parameters calculation
安装新的依赖包:
```
npm install @arbitrum/sdk
```
运行以下程序:
```
import { L1ToL2MessageGasEstimator } from "@arbitrum/sdk-nitro"
const { BigNumber, providers, utils } = require('ethers')
const l1GatewayABI = [
{
inputs: [
{
internalType: 'address',
name: 'l1Token',
type: 'address',
},
{
internalType: 'address',
name: 'from',
type: 'address',
},
{
internalType: 'address',
name: 'to',
type: 'address',
},
{
internalType: 'uint256',
name: 'amount',
type: 'uint256',
},
{
internalType: 'bytes',
name: 'data',
type: 'bytes',
},
],
name: 'getOutboundCalldata',
outputs: [
{
internalType: 'bytes',
name: 'outboundCalldata',
type: 'bytes',
},
],
stateMutability: 'pure',
type: 'function',
},
]
async function main() {
const l1Provider_1 = new providers.JsonRpcProvider(
'https://rinkeby.infura.io/v3/5b56b37c7e9844f7b58373cac2fafa1d'
)
const l2Provider_1 = new providers.JsonRpcProvider(
'https://rinkeby.arbitrum.io/rpc'
)
const gasEstimator = new L1ToL2MessageGasEstimator(l2Provider_1)
const l1USXAddress = '0x2D76117C2C85c2E9C9FBF08199C9Be59af887526'
const l1GatewayAddress = '0x6729B1425DF1750e14CEb171919c346f58014913'
const from = '0xbA32Bc6396152025608a37005D80E0346aB4740b'
const to = '0xbA32Bc6396152025608a37005D80E0346aB4740b'
const baseFee = (await l1Provider_1.getBlock('latest')).baseFeePerGas
const estimateGasCallValue = BigNumber.from('0')
const tokenGasOverrides = {
gasLimit: { min: BigNumber.from(275000) },
}
const depositAmount = utils.parseEther('3')
const l1Gateway = new ethers.Contract(
l1GatewayAddress,
l1GatewayABI,
l1Provider_1
)
const abiCoder = new ethers.utils.AbiCoder()
const data = abiCoder.encode(
['uint256', 'bytes'],
[estimates.maxSubmissionFee, '0x']
)
const depositCalldata = await l1Gateway.getOutboundCalldata(
l1USXAddress,
from,
to,
depositAmount,
'0x'
)
console.log('depositCalldata', depositCalldata)
const estimates = await gasEstimator.estimateAll(
l1GatewayAddress,
to,
depositCalldata,
estimateGasCallValue,
baseFee,
from,
from,
l1Provider_1,
tokenGasOverrides
)
console.log('\n 1. max gas: ', estimates.gasLimit.toString())
console.log('\n 2. gas price bid: ', estimates.maxFeePerGas.toString())
console.log('\n 3. data: ', data)
console.log('\n 4. eth value: ', estimates.totalL2GasCosts.toString())
}
```
## Overview:
USX:
ETH -> Arbitrum/Optimism: dForce bridge
ETH -> BNB: cBridge
Arbitrum/Optimism/BNB -> ETH: cBridge
DF:
ETH -> Arbitrum/Optimism: L2 bridge
ETH -> BNB: cBridge
Arbitrum/Optimism/BNB -> ETH: cBridge
## Ethereum -> Arbitrum:
### USX(使用dForce的bridge):
Rinkeby L1 USX Address: `0x2D76117C2C85c2E9C9FBF08199C9Be59af887526` (可以调用[allocateTo](https://rinkeby.etherscan.io/address/0x2D76117C2C85c2E9C9FBF08199C9Be59af887526#writeContract) 获得)
查询余额为:balanceOf(account_address) (decimals 为18)
Rinkeby L1 USX Bridge: `0x9f94c5136A80B994AD53acfeF5e3F27609D221a8`
Rinkeby L1 USX Approval: `0x9f94c5136A80B994AD53acfeF5e3F27609D221a8`
Arbitrum-Test L2 USX Address: `0x53876c224Ef395428c97b368236Eb7132400c4B3`
Arbitrum-Test L2 USX Bridge: `0x1e572B08e311C229FF8cfAaB0142e36474c3640D`
Arbitrum-Test L2 Provider:
```
var Web3 = require('web3');
l2_provider = new Web3(new Web3.providers.HttpProvider('https://rinkeby.arbitrum.io/rpc'));
```
Mainnet L1 USX Address: `0x0a5E677a6A24b2F1A2Bf4F3bFfC443231d2fDEc8`
查询余额为:balanceOf(account_address) (decimals 为18)
Mainnet L1 USX Bridge: `0x870ac6a76A30742800609F205c741E86Db9b71a2`
Mainnet L1 USX Approval: `0x870ac6a76A30742800609F205c741E86Db9b71a2`
Arbitrum-Mainnet L2 USX Address: `0x641441c631e2F909700d2f41FD87F0aA6A6b4EDb`
Arbitrum-Mainnet L2 USX Bridge: `0x1C4d5eCFBf2AF57251f20a524D0f0c1b4f6ED1C9`
Arbitrum-Mainnet L2 Provider:
```
var Web3 = require('web3');
l2_provider = new Web3(new Web3.providers.HttpProvider('https://arb1.arbitrum.io/rpc'));
```
跨链发交易之前先检查授权额度:allowance(user_address, L1_USX_Approval)
如果上面的授权额度值小于想要跨链的USX的数量,调用 USX.approve(L1_USX_Approval, MAX)
MAX = web3.utils.toTwosComplement('-1')
此项检查通过后,获得用户想要跨链的USX的数量:depositAmount
调用: L1_USX_Bridge.methods.outboundTransfer(L1_USX, user_address, depositAmount, max_gas, gas_price_bid, data).send({value: eth_value})
其中,`const gas_price_bid = await l2_provider.eth.getGasPrice();`
max_gas:
```
const l1_bridge = new web3.eth.Contract(bridge_abi, bridge_address);
const deposit_calldata = await l1_bridge.methods.getOutboundCalldata(l1_usx_address, from, to, depositAmount, '0x');
const max_submission_price = await getMaxSubmissionPrice(l2_provider, deposit_calldata);
const max_gas = await getMaxGas(
l2_provider,
l1_usx_bridge,
l2_usx_bridge,
from,
max_submission_price,
gas_price_bid,
deposit_calldata,
);
```
**所需方法和ABI在此处:[arbitrum_helpers](https://gist.github.com/Skyge/563854ef619bba23e2554af0d3a8bcf0#file-arbitrum_helpers-js)**
data:
```
const data = web3.eth.abi.encodeParameters(['uint256','bytes'], [max_submission_price, '0x']);
```
eth_value:
```
const eth_value = await max_submission_price.add(gas_price_bid.mul(max_gas))
```
交易确定后,从交易中获得event,找到`InboxMessageDelivered`,
第一个参数为需要的 MessagesSequenceNum,通过这个数字来计算L2的交易hash,L2 hash:
```
const request_id = await calculateL2TransactionHash(MessagesSequenceNum);
const L2_hash = await calculateL2RetryableTransactionHash(request_id);
```
L2 交易的确定大概是10分钟。
trigger on Arbitrum testnet: [0xb0A5C5136A80b994ad53acfEf5e3F27609D232b9](https://testnet.arbiscan.io/address/0xb0A5C5136A80b994ad53acfEf5e3F27609D232b9)
trigger on Arbitrum Mainnet: [0x981bc6a76a30742800609f205c741e86db9b82b3](https://arbiscan.io/address/0x981bc6a76a30742800609f205c741e86db9b82b3)
### DF
Mainnet L1 DF Address: `0x431ad2ff6a9C365805eBaD47Ee021148d6f7DBe0`
查询余额为:balanceOf(account_address) (decimals 为18)
Mainnet L1 DF Router(Bridge): `0x72Ce9c846789fdB6fC1f34aC4AD25Dd9ef7031ef`
Mainnet L1 DF Approval: `0xcEe284F754E854890e311e3280b767F80797180d`
Arbitrum-Mainnet L2 DF Address: `0xaE6aab43C4f3E0cea4Ab83752C278f8dEbabA689`
Arbitrum-Mainnet L2 Provider:
```
var Web3 = require('web3');
l2_provider = new Web3(new Web3.providers.HttpProvider('https://arb1.arbitrum.io/rpc'));
```
其余的方法同USX
## Arbitrum -> Ethereum:
### USX(使用celer的bridge):
Arbitrum-Test L2 cBridge: 0xFFe5f3dDdA62A9c5b0339AcD3632a99266dabe4e
Mainnet cBridge: 0x5427FEFA711Eff984124bFBB1AB6fbf5E3DA1820
BNB cBridge: 0xdd90E5E87A2081Dcf0391920868eBc2FFB81a1aF
BNB DF: 0x4A9A2b2b04549C3927dd2c9668A5eF3fCA473623
BNB USX:0xB5102CeE1528Ce2C760893034A4603663495fD72
Arbitrum cBridge: 0x1619DE6B6B20eD217a58d00f37B9d47C7663feca
Optimism cBridge: 0x9D39Fc627A6d9d9F8C831c16995b209548cc3401
Polygon cBridge: 0x88DCDC47D2f83a99CF0000FDF667A468bB958a78
**所需的ABI在此处: [cbridge_json](https://gist.github.com/Skyge/563854ef619bba23e2554af0d3a8bcf0#file-cbridge-json)**
前提,查看 `USX.allowance(caller_address, cBridge_address)`, 如果返回值allowance小于跨链token的数量,先`USX.approve(cBridge_address, amount)`
转移token的方法:`cBridge.methods.send(_receiver, _token, _amount, _dstChainId, _timestamp, _maxSlippage)`
其中,`_receiver`: 默认是调用者地址
`_token`: L2 转移token的地址(USX/DF)
`_amount`: L2 转移token的数量
`_dstChainId`: 目标跨链的chain id, 例如从Arbitrum -> ETH, 则目标链为ETH,获得chain id,可根据目标链的 `web3.eth.getChainId()` 或者
```
mainnet: 1
rinkeby: 4
Görli: 5
optimism: 10
kovan: 42
BNB(BSC): 56
optimism kovan: 69
BNB(BSC) Test: 97
Polygon: 137
Arbitrum: 42161
Polygon Test(Mumbai): 80001
Arbitrum Rinkeby: 421611
```
`_timestamp`: 取当前时间戳
`_maxSlippage`: 取下面结果的 `max_slippage` ,直接填入就可以
```
通过请求API:
https://cbridge-prod2.celer.network/v2/estimateAmt?src_chain_id=42161&dst_chain_id=56&token_symbol=DF&amt=1000000000000000000&usr_addr=0xa0183E85b199Cb4437200B9E87809d38b6Ed325f&slippage_tolerance=3000
src_chain_id:调用链的chain ID
dst_chain_id:目标链的chain ID
token_symbol:USX/DF(只能是大写)
amt:转移的token数量(带decimals,USX和DF的decimals都是18)
usr_addr:调用者地址
slippage_tolerance:用户前端选用的滑点,例子:3000,代表0.3%
返回结果示例:
{
"err": null,
"eq_value_token_amt": "1000000000000000000",
"bridge_rate": 1,
"perc_fee": "0",
"base_fee": "14182106305582652666",
"slippage_tolerance": 3000,
"max_slippage": 1000000,
"estimated_receive_amt": "-13182106305582652666", // 预计跨链得到的数量
"drop_gas_amt": "2000000000000000"
}
```
**说明:**
首先判断error是否为空,可能出现 `insufficient funds`等问题,
如果不为空,对于拿到的结果 `perc_fee` 和 `base_fee` 是跨链的费用(会扣除的DF/USX的数量),两者需相加,注意的是两者都是18位的,DF,USX 的decimals 都是18,默认就可以了。
total fee 是上述两个值相加。
`estimated_receive_amt` 是展示给用户预计接收的数量。当该数值为负数时表示,跨链的数量无法支付跨链的费用。
`estimated_receive_amt` = 跨链数量 - perc_fee - base_fee
*此API不要频繁请求,只在发交易时请求*
**cBridge查询跨链结果:**
首先计算出 transactionId,
```
// result = 0xfbb252266bf72bd50c20cce12911fc3dcb42af5d47ffe33d8e60491932fb5c6a
web3.utils.soliditySha3(
{type: 'address', value: '0xdad9d86885d217b92a47370e1e785897dd09a4f3'}, /// User's wallet address
{type: 'address', value: '0xdad9d86885d217b92a47370e1e785897dd09a4f3'}, /// User's wallet address
{type: 'address', value: '0x7d43aabc515c356145049227cee54b608342c0ad'}, /// ETH / ERC20 token address
{type: 'uint256', value: '10000000000'}, /// Send amount in String
{type: 'uint64', value: '5'}, /// Destination chain id
{type: 'uint64', value: '1638862397751'}, /// timestamp
{type: 'uint64', value: '4002'}) /// Source chain id
```
所以transaction_id = "fbb252266bf72bd50c20cce12911fc3dcb42af5d47ffe33d8e60491932fb5c6a",
请求:
```
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
var raw = JSON.stringify({
"transfer_id": "fbb252266bf72bd50c20cce12911fc3dcb42af5d47ffe33d8e60491932fb5c6a"
});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("https://cbridge-prod2.celer.network/v2/getTransferStatus", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
```
结果:

### Refund
当上述查询结果为 **TRANSFER_TO_BE_REFUNDED**, 即返回结果代码为6, 则跨链交易失败,需要用户手动取出自己的资产。流程如下:
- https://cbridge-docs.celer.network/developer/cbridge-pool-based-transfer-xliquidity/transfer-refund
## Ethereum -> Optimism:
### USX(使用dForce的bridge):
**Kovan:**
L1 USX: 0xF76eAd4da04BbeB97d29F83e2Ec3a621d0FB3c6e
L1 messenger: 0x4361d0F75A0186C05f971c566dC6bEa5957483fD
L1 USX bridge: 0x40E862341b2416345F02c41Ac70df08525150dC7
L2 USX: 0xab7020476D814C52629ff2e4cebC7A8cdC04F18E
首先调用USX的allowance方法查询用户是否授过足够的额度,方法为`USX.allowance(User_Address, l1_usx_bridge)`
如果该结果的allowance是0或者小于欲转移token的数量,调用approve进行授权。
进行授权方法:`USX.approve(l1_usx_bridge, -1)`
token跨链调用的方法为 `l1_usx_bridge.depositERC20()`:
```
depositERC20(
address _l1Token, // L1 USX 地址
address _l2Token, // L2 USX 地址
uint256 _amount, // 转移token的数量
uint32 _l2Gas, // 1000000 写死该数值
bytes calldata _data // "0x"
)
```
所需合约的ABI在此处:[L1 optimism USX bridge](https://gist.github.com/Skyge/563854ef619bba23e2554af0d3a8bcf0#file-l1_optimism_bridge-json)
跨链交易发送成功后,先获取该交易hash, 然后通过以下方法查询L2结果:
首先安装辅助package: `npm install @eth-optimism/core-utils ethers`
```
const ethers = require('ethers')
const { Watcher } = require('@eth-optimism/core-utils')
// 替换成metamask有效的链接
const l1RpcProvider = new ethers.providers.JsonRpcProvider('https://eth-kovan.alchemyapi.io/v2/xxx')
// 替换成metamask有效的链接
const l2RpcProvider = new ethers.providers.JsonRpcProvider('https://opt-kovan.g.alchemy.com/v2/xxx')
const watcher = new Watcher({
l1: {
provider: l1RpcProvider,
messengerAddress: "0x4361d0F75A0186C05f971c566dC6bEa5957483fD" // (Op-Kovan)
// messengerAddress: "0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1" // (Op-Mainnet)
},
l2: {
provider: l2RpcProvider,
messengerAddress: "0x4200000000000000000000000000000000000007" //(Op-Kovan)
// messengerAddress: "0x4200000000000000000000000000000000000007" //(Op-mainnet 同 Op-kovan)
}
})
const [ msgHash1 ] = await watcher.getMessageHashesFromL1Tx(transaction_hash)
const receipt = await watcher.getL2TransactionReceipt(msgHash1, true)
console.log("receipt hash", receipt.transactionHash)
```
Mainnet:
L1 USX: 0x0a5e677a6a24b2f1a2bf4f3bffc443231d2fdec8
L1 messenger: 0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1
L1 USX bridge: 0xC5b1EC605738eF73a4EFc562274c1c0b6609cF59
L2 USX: 0xbfD291DA8A403DAAF7e5E9DC1ec0aCEaCd4848B9
L1 DF: 0x431ad2ff6a9C365805eBaD47Ee021148d6f7DBe0
L1 DF bridge: 0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1
L2 DF: 0x9e5AAC1Ba1a2e6aEd6b32689DFcF62A509Ca96f3
~~L2 DF bridge: 0x4200000000000000000000000000000000000010~~
## Ethereum -> Polygon:(无测试网)
### USX(使用c-bridge):
Polygon USX: 0xCf66EB3D546F0415b368d98A95EAF56DeD7aA752
使用方法同USX 使用cBridge 从 Arbitrum 到 Ethereum.
### DF(使用官方Bridge)
L1 DF: 0x431ad2ff6a9C365805eBaD47Ee021148d6f7DBe0
L1 approve: 0x40ec5B33f54e0E8A33A975908C5BA1c14e5BbbDf
L1 bridge: 0xA0c68C638235ee32657e8f720a23ceC1bFc77C77
Polygon DF: 0x08C15FA26E519A78a666D19CE5C646D55047e0a3
同上,首先检查allowance 是否足够。
跨链调用方法为
```
L1_bridge.depositFor(
address user, // 用户地址
address rootToken, // df 地址
bytes calldata depositData // 10进制的存款数量转换为16进制,例如:0x0000000000000000000000000000000000000000000000056bc75e2d63100000
)
```
事件查询方法:
```
const WebSocket = require("ws");
const Web3 = require("web3");
// For Mumbai
const ws = new WebSocket("wss://ws-mumbai.matic.today/");
// For Polygon mainnet: wss://ws-mainnet.matic.network/
const web3 = new Web3();
const abiCoder = web3.eth.abi;
async function checkDepositStatus(
userAccount,
rootToken,
depositAmount,
childChainManagerProxy
) {
return new Promise((resolve, reject) => {
ws.on("open", () => {
ws.send(
`{"id": 1, "method": "eth_subscribe", "params": ["newDeposits", {"Contract": "${childChainManagerProxy}"}]}`
);
ws.on("message", (msg) => {
const parsedMsg = JSON.parse(msg);
if (
parsedMsg &&
parsedMsg.params &&
parsedMsg.params.result &&
parsedMsg.params.result.Data
) {
const fullData = parsedMsg.params.result.Data;
const { 0: syncType, 1: syncData } = abiCoder.decodeParameters(
["bytes32", "bytes"],
fullData
);
// check if sync is of deposit type (keccak256("DEPOSIT"))
const depositType =
"0x87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f821";
if (syncType.toLowerCase() === depositType.toLowerCase()) {
const {
0: userAddress,
1: rootTokenAddress,
2: depositData,
} = abiCoder.decodeParameters(
["address", "address", "bytes"],
syncData
);
// depositData can be further decoded to get amount, tokenId etc. based on token type
// For ERC20 tokens
const { 0: amount } = abiCoder.decodeParameters(
["uint256"],
depositData
);
if (
userAddress.toLowerCase() === userAccount.toLowerCase() &&
rootToken.toLowerCase() === rootTokenAddress.toLowerCase() &&
depositAmount === amount
) {
resolve(true);
}
}
}
});
ws.on("error", () => {
reject(false);
});
ws.on("close", () => {
reject(false);
});
});
});
}
// Param1 - user address
// Param2 - contract address on main chain
// Param3 - amount deposited on main chain
// Param4 - child chain manager proxy address (0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa for mainnet)
checkDepositStatus(
"0xFd71Dc9721d9ddCF0480A582927c3dCd42f3064C",
"0x47195A03fC3Fc2881D084e8Dc03bD19BE8474E46",
"1000000000000000000",
"0xb5505a6d998549090530911180f38aC5130101c6"
)
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
```
## cBridge Test
cBridge test 网络体验:https://dev-cbridge-v2.netlify.app/#/transfer
所连接的测试网为Görli,添加该网络可前往:https://chainlist.org/
先选择Testnets, 然后搜索该网络,连接钱包,添加即可。
前往此处获得测试币:https://faucet.paradigm.xyz/
Görli weth 地址为: 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6
BNB test weth: 0xE0dfD58A528085912a03C4d093905707FC4EDac7
支持 weth 在 Görli, BNB test, 这两个网络之间相互跨链
cBridge Testnet Endpoint
The testnet endpoint is: https://cbridge-v2-test.celer.network/
## Ethereum -> Arbitrum:
### DF(使用Arbitrum的bridge):
具体方法同之前的usx 从 [ethereum 到 arbitrum 的跨链](https://hackmd.io/5QvObfeMRme4ZJC6DuJYQg?view#Ethereum--gt-Arbitrum)
Ethereum DF: 0x431ad2ff6a9C365805eBaD47Ee021148d6f7DBe0
Ethereum l1 erc20 gateway(approval): 0xa3A7B6F88361F48403514059F1F16C8E78d60EeC
Ethereum l1 gateway router: 0x72Ce9c846789fdB6fC1f34aC4AD25Dd9ef7031ef
Arbitrum DF: 0xaE6aab43C4f3E0cea4Ab83752C278f8dEbabA689
Arbitrum l2 gateway: 0x5288c571Fd7aD117beA99bF60FE0846C4E84F933
Arbitrum l2 destination: 0xb4B8B6F88361F48403514059f1f16C8E78d61FFD
Rinkeby l1 erc20 gateway(approval): 0x91169Dbb45e6804743F94609De50D511C437572E
Rinkeby l1 gateway router: 0x70C143928eCfFaf9F5b406f7f4fC28Dc43d68380
Arbitrum Test l2 gateway: 0x9413AD42910c1eA60c737dB5f58d1C504498a3cD
Arbitrum Test l2 destination: 0x81D243928eCFFAf9f5B406F7f4fC28Dc43D69491
getMaxGas(
l2_provider,
l1_erc20_gateway, // <<<----
l2_destination, // <<<----
## 在 Ethereum 上 claim DF
安装所需要的package: `npm install @arbitrum/sdk ethers`
首先拿到 `txnHash`, 它是 L2 触发跨链的交易哈希,拿到交易哈希后,解析event
合约: https://arbiscan.io/address/0x5288c571fd7ad117bea99bf60fe0846c4e84f933#readProxyContract
解析topics为 `0x5baaa87db386365b5c161be377bc3d8e317e8d98d71a3ca7ed7d555340c8f767` 的 event,拿到最后一个topic的数值,记为 `batchNum`,例如 这笔交易: https://arbiscan.io/tx/0x742b611b4e5741d4c5ffd2f85d8463b703ff74a3ac20dce71d564b1305e72a25#eventlog ,topics 为`0x5baaa87db386365b5c161be377bc3d8e317e8d98d71a3ca7ed7d555340c8f767`的最后一个数值为:`0x00000000000000000000000000000000000000000000000000000000000018eb`
然后运行以下程序,得到所需的`poolInfo`,
helper.js
```
const { providers, Wallet } = require('ethers')
const {
L2TransactionReceipt,
getL2Network,
L2ToL1MessageStatus,
} = require('@arbitrum/sdk')
// Set up: instantiate L1 wallet connected to provider
const walletPrivateKey = "0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709"
// Ethereum-Arbitrum
// const l1Provider = new providers.JsonRpcProvider(xxxx)
// const l2Provider = new providers.JsonRpcProvider("https://arb1.arbitrum.io/rpc")
// Rinkeby-Arbitrum_Test
const l1Provider = new providers.JsonRpcProvider(xxxx)
const l2Provider = new providers.JsonRpcProvider("https://rinkeby.arbitrum.io/rpc")
const l1Wallet = new Wallet(walletPrivateKey, l1Provider)
// First, let's find the Arbitrum txn from the txn hash provided
const receipt = await l2Provider.getTransactionReceipt(txnHash)
const l2Receipt = new L2TransactionReceipt(receipt)
// Note that in principle, a single transaction could trigger any number of outgoing messages; the common case will be there's only one.
// For the sake of this script, we assume there's only one / just grad the first one.
const messages = await l2Receipt.getL2ToL1Messages(l1Wallet, l2Provider)
const l2ToL1Msg = messages[0]
// Check if already executed
// if ((await l2ToL1Msg.status(l2Provider)) == L2ToL1MessageStatus.EXECUTED) {
// return
// }
// Now fetch the proof info we'll need in order to execute, or check execution
const proofInfo = await l2ToL1Msg.getOutboxProof(l2Provider)
```
以上 `proofInfo` 返回结构为:
```
{
proof: string[];
path: BigNumber;
l2Sender: string;
l1Dest: string;
l2Block: BigNumber;
l1Block: BigNumber;
timestamp: BigNumber;
amount: BigNumber;
calldataForL1: string;
}
```
所以 调用的方法为:
```
claimFunds(
uint256 batchNum,
bytes32[] calldata proof,
uint256 index,
address l2Sender,
address destAddr,
uint256 l2Block,
uint256 l1Block,
uint256 l2Timestamp,
uint256 amount,
bytes calldata calldataForL1
)
```
所需的参数均可以通过以上获取到。