-
Notifications
You must be signed in to change notification settings - Fork 1
docs: L2 bridging doc #97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 3 commits
4efde21
d66b925
ec06dd4
982a130
b7d430d
3cb5b61
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| # Manual Actions for L2 → L1 Bridging | ||
| For Reality Cross-chain proxies L1 → L2 bridging is automatic for every bridge. | ||
| However, L2 → L1 bridging requires manual steps, which differ by chain. | ||
| Use this guide until bots are configured to handle everything automatically. | ||
|
|
||
|
|
||
| ## Gnosis | ||
| After sending a transaction from L2 (e.g., `handleNotifiedRequest`), refer to this page: | ||
| https://docs.gnosischain.com/bridges/using-amb | ||
|
|
||
| It's recommended to use **Blockscout** instead of GnosisScan due to possible encoding issues. | ||
|
|
||
| Before using `getSignatures` on the `AMBHelper` contract, wait until the message is processed | ||
| (usually within an hour). After that, `getSignatures` will return a result you can pass into | ||
| `executeSignatures`. | ||
|
|
||
|
|
||
| ## Polygon | ||
| After sending the L2 transaction you'll need to manually call `receiveMessage` | ||
| on `foreignProxy` contract. | ||
|
|
||
| The argument for the function can be obtained from this template URL (usually generated in **1–3 hours**): | ||
|
|
||
| ``` | ||
| https://proof-generator.polygon.technology/api/v1/matic/exit-payload/<your_L2_tx_hash>?eventSignature=0x8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036 | ||
| ``` | ||
|
|
||
| This URL contains: | ||
| - Your L2 tx hash that you need to manually insert | ||
| - The event signature required by Polygon API (same for every tx, belongs to `messageSent` event) | ||
|
|
||
| More details: | ||
| https://github.com/0xPolygon/fx-portal?tab=readme-ov-file#proof-generation | ||
|
|
||
|
|
||
| ## zkSync | ||
| After sending the tx to L1, check its status on zkSync Etherscan. | ||
| When the status becomes **"Executed"** (usually in 2-4 hours), use the script: | ||
|
|
||
| https://github.com/kleros/cross-chain-realitio-proxy/blob/master/contracts/scripts/execute_proof.js | ||
|
|
||
| Steps: | ||
| 1. Insert your `txHash` into the script. | ||
| 2. Run `yarn zksync:proof:production` from `contracts` folder. | ||
|
|
||
| This script retrieves the proof and executes the tx on L1 automatically. | ||
|
|
||
| Requirements: | ||
| - `yarn install` | ||
| - `.env` file setup (`PRIVATE_KEY`, `INFURA_API_KEY`) | ||
|
|
||
| zkSync docs: | ||
| https://code.zksync.io/tutorials/how-to-send-l2-l1-message | ||
|
|
||
| If the status is "Executed" but proof is `null`, wait longer. | ||
| Once executed successfully, a dispute will be created on KlerosCourt with `ForeignProxy` as arbitrable. | ||
|
|
||
|
|
||
| ## Arbitrum | ||
| Execution occurs only after the **one-week challenge period** has passed, thus a week after sending a tx to L1, navigate to `contracts` folder and run: | ||
|
|
||
| ``` | ||
| yarn relay:production --txhash <your_tx_hash> | ||
| ``` | ||
|
|
||
| Requirements: | ||
| - `yarn install` | ||
| - `.env` file setup (`PRIVATE_KEY`, `INFURA_API_KEY`) | ||
|
|
||
| Note: this task currently works only with **ethers v5** | ||
|
|
||
| Official docs page: | ||
| https://docs.arbitrum.io/build-decentralized-apps/cross-chain-messaging | ||
| https://github.com/OffchainLabs/arbitrum-tutorials/blob/master/packages/outbox-execute/scripts/exec.js | ||
|
|
||
|
|
||
| ## Optimism (Base, Redstone, Unichain, etc.) | ||
| After sending the L2 tx run the command corresponding to the chosen chain, e.g.: | ||
|
|
||
| ``` | ||
| yarn relay-op:base --txhash <your_tx_hash> | ||
| ``` | ||
|
|
||
| You must run this command **twice**: | ||
| 1. Shortly after sending the tx (usually within an hour), to prove the message. Console should show `Proven` if successful | ||
| 2. One week later, to finalize it | ||
|
|
||
| Requirements: | ||
| - `yarn install` | ||
| - `.env` file setup (`PRIVATE_KEY`, `INFURA_API_KEY`, `ALCHEMY_API_KEY`) | ||
|
|
||
| Extra notes: | ||
| - Optimism stack requires `eth_getProof`, unsupported by Infura therefore **Alchemy** is used for L2 RPC. | ||
| - L1 RPC can still use Infura. | ||
|
|
||
| Official docs page: | ||
| https://docs.optimism.io/app-developers/tutorials/bridging/cross-dom-solidity#interact-with-the-l2-greeter | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,6 +4,7 @@ import "hardhat-deploy"; | |||||||||||||||||||||||||||||
| import "hardhat-deploy-ethers"; | ||||||||||||||||||||||||||||||
| import "./tasks/generate-metaevidence"; | ||||||||||||||||||||||||||||||
| import "./tasks/relay-arbitrum"; | ||||||||||||||||||||||||||||||
| import "./tasks/relay-op"; | ||||||||||||||||||||||||||||||
| import "./tasks/find-dispute-id"; | ||||||||||||||||||||||||||||||
| import "./tasks/update-deployments"; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
@@ -84,7 +85,7 @@ const config: HardhatUserConfig = { | |||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| optimismSepolia: { | ||||||||||||||||||||||||||||||
| chainId: 11155420, | ||||||||||||||||||||||||||||||
| url: `https://optimism-sepolia.infura.io/v3/${process.env.INFURA_API_KEY}`, | ||||||||||||||||||||||||||||||
| url: `https://opt-sepolia.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`, | ||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # Check if .env.example exists and examine its contents
fd -t f '.env.example' --exec cat {}Repository: kleros/cross-chain-realitio-proxy Length of output: 59 🏁 Script executed: # Also check the hardhat.config.ts file to see the lines in question
wc -l contracts/hardhat.config.tsRepository: kleros/cross-chain-realitio-proxy Length of output: 108 🏁 Script executed: # Read the relevant sections of hardhat.config.ts (lines 85-95, 195-210, 225-240)
sed -n '85,95p;195,210p;225,240p' contracts/hardhat.config.ts | cat -nRepository: kleros/cross-chain-realitio-proxy Length of output: 1754 🏁 Script executed: # Search for any documentation that mentions ALCHEMY_API_KEY
rg 'ALCHEMY_API_KEY' --type-list | head -20Repository: kleros/cross-chain-realitio-proxy Length of output: 466 🏁 Script executed: # Search for ALCHEMY_API_KEY usage in the codebase
rg 'ALCHEMY_API_KEY' --type tsRepository: kleros/cross-chain-realitio-proxy Length of output: 1042 🏁 Script executed: # Get exact lines 201 and 231 with context
sed -n '195,210p' contracts/hardhat.config.ts | cat -n
echo "---"
sed -n '225,235p' contracts/hardhat.config.ts | cat -nRepository: kleros/cross-chain-realitio-proxy Length of output: 1066 🏁 Script executed: # Check for documentation files (README, setup guides, etc.)
fd -t f '(README|readme|SETUP|setup|\.env\.example)' --extension md --extension txt --extension rstRepository: kleros/cross-chain-realitio-proxy Length of output: 106 🏁 Script executed: # Check if any .env files or examples exist
fd -t f -e envRepository: kleros/cross-chain-realitio-proxy Length of output: 105 🏁 Script executed: # Check README.md for ALCHEMY_API_KEY
rg 'ALCHEMY_API_KEY' README.mdRepository: kleros/cross-chain-realitio-proxy Length of output: 59 🏁 Script executed: # Check contracts/README.md for ALCHEMY_API_KEY
rg 'ALCHEMY_API_KEY' contracts/README.mdRepository: kleros/cross-chain-realitio-proxy Length of output: 59 🏁 Script executed: # Check chains.env content
cat contracts/scripts/chains.envRepository: kleros/cross-chain-realitio-proxy Length of output: 1431 🏁 Script executed: # Look at the root README to understand setup instructions
head -100 README.mdRepository: kleros/cross-chain-realitio-proxy Length of output: 5536 Add ALCHEMY_API_KEY to documentation and create .env.example. ALCHEMY_API_KEY is used across multiple networks (optimismSepolia, optimism, base, baseSepolia, gnosis) in hardhat.config.ts and SDK tests, but is not documented in the project's setup instructions or .env guidance. Create a .env.example file with ALCHEMY_API_KEY listed, and update README.md (or contracts/README.md) to mention this requirement in the "Adding support for a new chain" and environment setup sections. 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
| // url: `http://127.0.0.1:8547`, // fork with `anvil --fork-url https://optimism-sepolia.infura.io/v3/${process.env.INFURA_API_KEY} --port 8547` | ||||||||||||||||||||||||||||||
| accounts: [process.env.PRIVATE_KEY as string], | ||||||||||||||||||||||||||||||
| tags: ["home"], | ||||||||||||||||||||||||||||||
|
|
@@ -149,7 +150,7 @@ const config: HardhatUserConfig = { | |||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| verify: { | ||||||||||||||||||||||||||||||
| etherscan: { | ||||||||||||||||||||||||||||||
| apiUrl: "https://api.etherscan.io/api", | ||||||||||||||||||||||||||||||
| apiUrl: "https://api.etherscan.io/v2/api?chainid=1", | ||||||||||||||||||||||||||||||
| apiKey: process.env.ETHERSCAN_API_KEY, | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
|
|
@@ -186,7 +187,7 @@ const config: HardhatUserConfig = { | |||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| optimism: { | ||||||||||||||||||||||||||||||
| chainId: 10, | ||||||||||||||||||||||||||||||
| url: `https://optimism-mainnet.infura.io/v3/${process.env.INFURA_API_KEY}`, | ||||||||||||||||||||||||||||||
| url: `https://opt-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`, | ||||||||||||||||||||||||||||||
| accounts: [process.env.PRIVATE_KEY as string], | ||||||||||||||||||||||||||||||
| tags: ["home"], | ||||||||||||||||||||||||||||||
| companionNetworks: { | ||||||||||||||||||||||||||||||
|
|
@@ -216,7 +217,7 @@ const config: HardhatUserConfig = { | |||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| base: { | ||||||||||||||||||||||||||||||
| chainId: 8453, | ||||||||||||||||||||||||||||||
| url: `https://base-mainnet.infura.io/v3/${process.env.INFURA_API_KEY}`, | ||||||||||||||||||||||||||||||
| url: `https://base-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`, | ||||||||||||||||||||||||||||||
| accounts: [process.env.PRIVATE_KEY as string], | ||||||||||||||||||||||||||||||
| tags: ["home"], | ||||||||||||||||||||||||||||||
| companionNetworks: { | ||||||||||||||||||||||||||||||
|
|
@@ -254,12 +255,39 @@ const config: HardhatUserConfig = { | |||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| verify: { | ||||||||||||||||||||||||||||||
| etherscan: { | ||||||||||||||||||||||||||||||
| apiUrl: "https://api.polygonscan.com/api", | ||||||||||||||||||||||||||||||
| apiUrl: "https://api.etherscan.io/v2/api?chainid=137", | ||||||||||||||||||||||||||||||
| apiKey: process.env.POLYGONSCAN_API_KEY, | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| etherscan: { | ||||||||||||||||||||||||||||||
| apiKey: { | ||||||||||||||||||||||||||||||
| // These are separate from Ethereum's etherscan API key | ||||||||||||||||||||||||||||||
| optimisticEthereum: process.env.OPTIMISM_API_KEY!, | ||||||||||||||||||||||||||||||
| mainnet: process.env.ETHERSCAN_API_KEY!, | ||||||||||||||||||||||||||||||
| polygon: process.env.ETHERSCAN_API_KEY!, | ||||||||||||||||||||||||||||||
| base: process.env.ETHERSCAN_API_KEY! | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
|
Comment on lines
276
to
284
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Use optional chaining or default values instead of non-null assertions. The non-null assertion operator ( Consider using optional chaining with fallback values: etherscan: {
apiKey: {
// These are separate from Ethereum's etherscan API key
- optimisticEthereum: process.env.OPTIMISM_API_KEY!,
- mainnet: process.env.ETHERSCAN_API_KEY!,
- polygon: process.env.ETHERSCAN_API_KEY!,
- base: process.env.ETHERSCAN_API_KEY!
+ optimisticEthereum: process.env.OPTIMISM_API_KEY || "",
+ mainnet: process.env.ETHERSCAN_API_KEY || "",
+ polygon: process.env.ETHERSCAN_API_KEY || "",
+ base: process.env.ETHERSCAN_API_KEY || ""
},📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
| customChains: [ | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| network: "base", | ||||||||||||||||||||||||||||||
| chainId: 8453, | ||||||||||||||||||||||||||||||
| urls: { | ||||||||||||||||||||||||||||||
| apiURL: "https://api.etherscan.io/v2/api?chainid=8453", | ||||||||||||||||||||||||||||||
| browserURL: "https://basescan.org/" | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| network: "polygon", | ||||||||||||||||||||||||||||||
| chainId: 137, | ||||||||||||||||||||||||||||||
| urls: { | ||||||||||||||||||||||||||||||
| apiURL: "https://api.etherscan.io/v2/api?chainid=137", | ||||||||||||||||||||||||||||||
| browserURL: "https://polygonscan.com/" | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| namedAccounts: { | ||||||||||||||||||||||||||||||
| deployer: { | ||||||||||||||||||||||||||||||
| default: 0, | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,14 @@ | |
| "hardhat-zksync": "hardhat --config hardhat.config.zksync.ts", | ||
| "zksync:proof:staging": "yarn hardhat-zksync run ./scripts/execute_proof.js --network zkSyncSepolia", | ||
| "zksync:proof:production": "yarn hardhat-zksync run ./scripts/execute_proof.js --network zkSyncMainnet", | ||
| "relay:staging": "hardhat relay-arbitrum --network arbitrumSepolia", | ||
| "relay:production": "hardhat relay-arbitrum --network arbitrum", | ||
| "relay-op:optimism": "hardhat relay-op --network optimism", | ||
| "relay-op:redstone": "hardhat relay-op --network redstone", | ||
| "relay-op:base": "hardhat relay-op --network base", | ||
| "relay-op:unichain": "hardhat relay-op --network unichain", | ||
| "relay-op:opSepolia": "hardhat relay-op --network optimismSepolia", | ||
| "relay-op:uniSepolia": "hardhat relay-op --network unichainSepolia", | ||
| "etherscan-verify": "hardhat etherscan-verify", | ||
| "format:js": "biome format --write scripts deploy tasks", | ||
| "check:js": "biome check --write scripts deploy tasks", | ||
|
|
@@ -90,6 +98,7 @@ | |
| "@types/node": "^22.14.0", | ||
| "chai": "^4.5.0", | ||
| "ethers": "^6.13.5", | ||
| "ethers5": "npm:ethers@5.7.2", | ||
| "hardhat": "^2.22.18", | ||
| "hardhat-deploy": "^0.14.0", | ||
| "hardhat-deploy-ethers": "^0.4.2", | ||
|
|
@@ -106,11 +115,12 @@ | |
| }, | ||
| "dependencies": { | ||
| "@arbitrum/nitro-contracts": "^1.3.0", | ||
| "@arbitrum/sdk": "^v3.1.9", | ||
| "@arbitrum/sdk": "^4.0.4", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: Here’s a concise migration checklist for @arbitrum/sdk v3 → v4 with the main breaking changes and quick code notes.
Where to read full details and examples
References Review @arbitrum/sdk v4 breaking changes before upgrade. The update from v3.1.9 to v4.0.4 introduces substantial breaking changes:
Ensure all SDK usage in this codebase is updated to match the v4 API. Refer to the migration guide at docs.arbitrum.io/sdk/migrate. 🤖 Prompt for AI Agents |
||
| "@kleros/dispute-resolver-interface-contract-0.7": "npm:@kleros/dispute-resolver-interface-contract@^2.0.0", | ||
| "@kleros/dispute-resolver-interface-contract-0.8": "npm:@kleros/dispute-resolver-interface-contract@^8.0.0", | ||
| "@kleros/ethereum-libraries": "^7.0.0", | ||
| "@matterlabs/zksync-contracts": "^0.6.1", | ||
| "dotenv": "^16.4.7" | ||
| "dotenv": "^16.4.7", | ||
| "viem": "^2.38.3" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,25 +1,24 @@ | ||||||||||||||||||||||||||||||||||
| const hre = require("hardhat"); | ||||||||||||||||||||||||||||||||||
| const { Provider, utils } = require("zksync-web3"); | ||||||||||||||||||||||||||||||||||
| const ethers = require("ethers"); | ||||||||||||||||||||||||||||||||||
| const { Provider, utils } = require("zksync-ethers"); | ||||||||||||||||||||||||||||||||||
| const { getL1MessageSentEvent, getCalldata } = require("./get_event_properties"); | ||||||||||||||||||||||||||||||||||
| const RealitioForeignArbitrationProxy = require("@kleros/cross-chain-realitio-contracts/artifacts-zk/src/zkRealitioForeignProxy.sol/zkRealitioForeignProxy.json"); | ||||||||||||||||||||||||||||||||||
| const RealitioHomeArbitrationProxy = require("@kleros/cross-chain-realitio-contracts/artifacts-zk/src/zkRealitioHomeProxy.sol/zkRealitioHomeProxy.json"); | ||||||||||||||||||||||||||||||||||
| const RealitioForeignArbitrationProxy = require("@kleros/cross-chain-realitio-contracts/artifacts-zk/src/0.8/RealitioForeignProxyZkSync.sol/RealitioForeignProxyZkSync.json"); | ||||||||||||||||||||||||||||||||||
| const RealitioHomeArbitrationProxy = require("@kleros/cross-chain-realitio-contracts/artifacts-zk/src/0.8/RealitioHomeProxyZkSync.sol/RealitioHomeProxyZkSync.json"); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| async function executeProof() { | ||||||||||||||||||||||||||||||||||
| // https://era.zksync.io/docs/dev/how-to/send-message-l2-l1.html | ||||||||||||||||||||||||||||||||||
| // https://code.zksync.io/tutorials/how-to-send-l2-l1-message | ||||||||||||||||||||||||||||||||||
| const txHash = ""; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const { providers } = ethers; | ||||||||||||||||||||||||||||||||||
| const foreignNetworks = { | ||||||||||||||||||||||||||||||||||
| 324: hre.config.networks.mainnet, | ||||||||||||||||||||||||||||||||||
| 300: hre.config.networks.sepolia, | ||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||
| const chainId = hre.network.config.chainId; | ||||||||||||||||||||||||||||||||||
| const url = foreignNetworks[chainId]; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const l1Provider = new Provider(hre.network.config.url); | ||||||||||||||||||||||||||||||||||
| const l2Provider = new providers.JsonRpcProvider(url); | ||||||||||||||||||||||||||||||||||
| const l1Provider = new ethers.JsonRpcProvider(foreignNetworks[chainId]?.url); | ||||||||||||||||||||||||||||||||||
| const l2Provider = new Provider(hre.network.config.url); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const l1MessageSentEvent = await getL1MessageSentEvent(txHash, utils.L1_MESSENGER, l1Provider); | ||||||||||||||||||||||||||||||||||
| const l1MessageSentEvent = await getL1MessageSentEvent(txHash, utils.L1_MESSENGER, l2Provider); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if (!l1MessageSentEvent) { | ||||||||||||||||||||||||||||||||||
| throw new Error("No L1MessageSent event found in the transaction."); | ||||||||||||||||||||||||||||||||||
|
|
@@ -28,13 +27,13 @@ async function executeProof() { | |||||||||||||||||||||||||||||||||
| const blockNumber = l1MessageSentEvent.blockNumber; | ||||||||||||||||||||||||||||||||||
| const homeProxy = `0x${BigInt(l1MessageSentEvent.address).toString(16)}`; | ||||||||||||||||||||||||||||||||||
| const msgHash = l1MessageSentEvent.msgHash; | ||||||||||||||||||||||||||||||||||
| const eventData = await getCalldata(txHash, l1Provider); | ||||||||||||||||||||||||||||||||||
| const homeProxyContract = new ethers.Contract(homeProxy, RealitioHomeArbitrationProxy.abi, l1Provider); | ||||||||||||||||||||||||||||||||||
| const eventData = await getCalldata(txHash, l2Provider); | ||||||||||||||||||||||||||||||||||
| const homeProxyContract = new ethers.Contract(homeProxy, RealitioHomeArbitrationProxy.abi, l2Provider); | ||||||||||||||||||||||||||||||||||
| console.log(await homeProxyContract.foreignProxy()); | ||||||||||||||||||||||||||||||||||
| const foreignProxyContract = new ethers.Contract( | ||||||||||||||||||||||||||||||||||
|
Comment on lines
27
to
33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Preserve the proxy address formatting Casting Apply this diff: - const homeProxy = `0x${BigInt(l1MessageSentEvent.address).toString(16)}`;
+ const homeProxy = ethers.getAddress(l1MessageSentEvent.address);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| await homeProxyContract.foreignProxy(), | ||||||||||||||||||||||||||||||||||
| RealitioForeignArbitrationProxy.abi, | ||||||||||||||||||||||||||||||||||
| l2Provider | ||||||||||||||||||||||||||||||||||
| l1Provider | ||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| console.log(`Event: ${l1MessageSentEvent.name}`); | ||||||||||||||||||||||||||||||||||
|
|
@@ -43,14 +42,18 @@ async function executeProof() { | |||||||||||||||||||||||||||||||||
| console.log("Hash:", msgHash); | ||||||||||||||||||||||||||||||||||
| console.log("Message:", eventData); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const proof = await getL1MessageProof(blockNumber, l1Provider, homeProxy, msgHash); | ||||||||||||||||||||||||||||||||||
| console.log("Proof is: ", proof); | ||||||||||||||||||||||||||||||||||
| const { l1BatchNumber, l1BatchTxIndex } = await l1Provider.getTransactionReceipt(txHash); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const l2Receipt = await l2Provider.getTransactionReceipt(txHash); | ||||||||||||||||||||||||||||||||||
| console.log(l2Receipt); | ||||||||||||||||||||||||||||||||||
| const logIndex = l2Receipt.l2ToL1Logs[0].logIndex; | ||||||||||||||||||||||||||||||||||
| console.log(`L2 transaction included in block ${l2Receipt.blockNumber} with log index ${logIndex}`); | ||||||||||||||||||||||||||||||||||
| const { l1BatchNumber, l1BatchTxIndex } = l2Receipt; | ||||||||||||||||||||||||||||||||||
| console.log("L1 Index for Tx in block :>> ", l1BatchTxIndex); | ||||||||||||||||||||||||||||||||||
| console.log("L1 Batch for block :>> ", l1BatchNumber); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const result = await proveL1MessageInclusion( | ||||||||||||||||||||||||||||||||||
| const proof = await getLogProof(txHash, logIndex, l2Provider); | ||||||||||||||||||||||||||||||||||
| console.log("Proof is: ", proof); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const result = await proveL2MessageInclusion( | ||||||||||||||||||||||||||||||||||
| l1BatchNumber, | ||||||||||||||||||||||||||||||||||
| proof, | ||||||||||||||||||||||||||||||||||
| l1BatchTxIndex, | ||||||||||||||||||||||||||||||||||
|
|
@@ -63,7 +66,7 @@ async function executeProof() { | |||||||||||||||||||||||||||||||||
| console.log("Result is :>> ", result); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if (result) { | ||||||||||||||||||||||||||||||||||
| const signer = new ethers.Wallet(process.env.PRIVATE_KEY, l2Provider); | ||||||||||||||||||||||||||||||||||
| const signer = new ethers.Wallet(process.env.PRIVATE_KEY, l1Provider); | ||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||
| await foreignProxyContract | ||||||||||||||||||||||||||||||||||
| .connect(signer) | ||||||||||||||||||||||||||||||||||
|
|
@@ -78,17 +81,16 @@ async function executeProof() { | |||||||||||||||||||||||||||||||||
| process.exit(); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| async function getL1MessageProof(blockNumber, l1Provider, homeProxy, msgHash) { | ||||||||||||||||||||||||||||||||||
| console.log(`Getting L1 message proof for block ${blockNumber}`); | ||||||||||||||||||||||||||||||||||
| return await l1Provider.getMessageProof(blockNumber, homeProxy, msgHash); | ||||||||||||||||||||||||||||||||||
| async function getLogProof(txHash, l2TxIndex, l2Provider) { | ||||||||||||||||||||||||||||||||||
| return await l2Provider.getLogProof(txHash, l2TxIndex); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| async function proveL1MessageInclusion(l1BatchNumber, proof, trxIndex, l1Provider, l2Provider, homeProxy, message) { | ||||||||||||||||||||||||||||||||||
| const zkAddress = await l1Provider.getMainContractAddress(); | ||||||||||||||||||||||||||||||||||
| async function proveL2MessageInclusion(l1BatchNumber, proof, trxIndex, l1Provider, l2Provider, homeProxy, message) { | ||||||||||||||||||||||||||||||||||
| const zkAddress = await l2Provider.getMainContractAddress(); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const mailboxL1Contract = new ethers.Contract(zkAddress, utils.ZKSYNC_MAIN_ABI, l2Provider); | ||||||||||||||||||||||||||||||||||
| const mailboxL1Contract = new ethers.Contract(zkAddress, utils.ZKSYNC_MAIN_ABI, l1Provider); | ||||||||||||||||||||||||||||||||||
| const messageInfo = { | ||||||||||||||||||||||||||||||||||
| txNumberInBlock: trxIndex, | ||||||||||||||||||||||||||||||||||
| txNumberInBatch: trxIndex, | ||||||||||||||||||||||||||||||||||
| sender: homeProxy, | ||||||||||||||||||||||||||||||||||
| data: message, | ||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@unknownunknown1 this doc is very useful, thanks!
Would be nice if we can have the full cycle and specify all the methods that must be called until the bot is there.
For example, the L1->L2 usually is automatically bridged as you have said, but we need to call
handleNotifiedRequestorhandleRejectedRequestafterreceiveArbitrationRequestis automatically called.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is not much to add to be honest.
handleNotifiedRequestis the default function, whilehandleRejectedRequestis rather edge case. But I will add the steps for relaying the question back to Reality as it's a bit tricky