-
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 all commits
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}`, | ||||||||||||||||||||||||||||||
| // 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
+265
to
+271
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, | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
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