Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contracts/.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
PRIVATE_KEY='<0x encoded private key>'
ALCHEMY_API_KEY=''
INFURA_API_KEY='<key>'
ETHERSCAN_API_KEY='<key>'
GNOSISSCAN_API_KEY='<key>'
Expand Down
97 changes: 97 additions & 0 deletions contracts/docs/Bridging.md
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.
Comment on lines +2 to +4
Copy link
Contributor

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 handleNotifiedRequest or handleRejectedRequest after receiveArbitrationRequest is automatically called.

Copy link
Contributor Author

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. handleNotifiedRequest is the default function, while handleRejectedRequest is rather edge case. But I will add the steps for relaying the question back to Reality as it's a bit tricky



## 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
38 changes: 33 additions & 5 deletions contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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}`,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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.ts

Repository: 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 -n

Repository: 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 -20

Repository: 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 ts

Repository: 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 -n

Repository: 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 rst

Repository: kleros/cross-chain-realitio-proxy

Length of output: 106


🏁 Script executed:

# Check if any .env files or examples exist
fd -t f -e env

Repository: kleros/cross-chain-realitio-proxy

Length of output: 105


🏁 Script executed:

# Check README.md for ALCHEMY_API_KEY
rg 'ALCHEMY_API_KEY' README.md

Repository: 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.md

Repository: kleros/cross-chain-realitio-proxy

Length of output: 59


🏁 Script executed:

# Check chains.env content
cat contracts/scripts/chains.env

Repository: kleros/cross-chain-realitio-proxy

Length of output: 1431


🏁 Script executed:

# Look at the root README to understand setup instructions
head -100 README.md

Repository: 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
In contracts/hardhat.config.ts around line 89, ALCHEMY_API_KEY is referenced for
network RPCs but is not documented; add ALCHEMY_API_KEY to project setup docs
and provide a .env.example. Update README.md (or contracts/README.md) to mention
ALCHEMY_API_KEY in the "Adding support for a new chain" and environment setup
sections, and create a top-level .env.example file that lists ALCHEMY_API_KEY
(with placeholder value and brief comment) alongside other env vars so
contributors know to set it before running tests or configuring networks.

// 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"],
Expand Down Expand Up @@ -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,
},
},
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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
Copy link

Choose a reason for hiding this comment

The 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 (!) on lines 267-270 will throw runtime errors if the environment variables are undefined. This can cause Hardhat to fail even for tasks that don't require Etherscan verification.

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

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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!
},
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 || ""
},
🤖 Prompt for AI Agents
In contracts/hardhat.config.ts around lines 265 to 271, the apiKey entries use
non-null assertions (process.env.VAR!) which will throw at runtime if those env
vars are missing; replace the non-null assertions with a safe fallback by using
optional chaining or default values (e.g., process.env.OPTIMISM_API_KEY ?? "" or
process.env.OPTIMISM_API_KEY || "") so the config loads even when keys are
undefined, ensuring tasks that don’t need Etherscan won’t fail.

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://base.blockscout.com"
}
},
]
},
namedAccounts: {
deployer: {
default: 0,
Expand Down
1 change: 0 additions & 1 deletion contracts/hardhat.config.zksync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import "@matterlabs/hardhat-zksync-solc";
import "@matterlabs/hardhat-zksync-verify";
import "hardhat-deploy";
import "./tasks/update-deployments";
// import "./tasks/generate-metaevidence";

import type { HardhatUserConfig } from "hardhat/config";

Expand Down
14 changes: 12 additions & 2 deletions contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand All @@ -106,11 +115,12 @@
},
"dependencies": {
"@arbitrum/nitro-contracts": "^1.3.0",
"@arbitrum/sdk": "^v3.1.9",
"@arbitrum/sdk": "^4.0.4",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

@arbitrum/sdk v4.0.0 breaking changes migration guide

💡 Result:

Here’s a concise migration checklist for @arbitrum/sdk v3 → v4 with the main breaking changes and quick code notes.

  1. Terminology and API renames
  • L1/L2 → parent/child terminology; many types/functions renamed accordingly. Use Parent/Child where appropriate. [1]
  1. Network types & registration
  • L2Network → ArbitrumNetwork; getL2Network → getArbitrumNetwork; l2Networks → getArbitrumNetworks.
  • L1Network, Network, getL1Network, getParentForNetwork removed.
  • Only Arbitrum networks (Arbitrum One, Arbitrum testnets, Orbit chains) are registered; use registerCustomArbitrumNetwork and getArbitrumNetworks / getChildrenForNetwork. [1][2]
  1. Bridger classes updated
  • AssetBridger/Erc20Bridger APIs changed; new bridgers named EthBridger, Erc20Bridger, EthL1L3Bridger, Erc20L1L3Bridger (see updated constructors/usage). Instantiate with an ArbitrumNetwork (not generic Network). [1][2]
  1. Message classes & lifecycle
  • Message classes renamed/reshaped to ParentToChildMessage and ChildToParentMessage; creation/receipt parsing flows updated (constructors and helper methods changed). Review message creation from tx receipts. [1]
  1. Network helper functions
  • New helpers: getArbitrumNetworks, getChildrenForNetwork. Use these instead of the removed getParentForNetwork/getL1Network. [1]
  1. Registration requirement
  • registerCustomArbitrumNetwork must be used for custom Arbitrum chains before using bridgers or message utilities. [1][2]
  1. Code example (v4 pattern)
  • Fetch network: const child = await getArbitrumNetwork(childChainId)
  • Create bridger: const ethBridger = new EthBridger(child)
  • Deposit: await ethBridger.deposit({ amount, parentSigner })
    (See repo docs for full method signatures.) [2]

Where to read full details and examples

  • Official migration doc (v3 → v4) — primary migration guide and detailed breaking-change list. [1]
  • @arbitrum/sdk v4 repository and README (examples, API reference). [2]

References
[1] Arbitrum SDK migration guide (v3 → v4) — docs.arbitrum.io/sdk/migrate.
[2] OffchainLabs/arbitrum-sdk (v4) — GitHub README & repo.


Review @arbitrum/sdk v4 breaking changes before upgrade.

The update from v3.1.9 to v4.0.4 introduces substantial breaking changes:

  • Terminology shift: L1/L2 → parent/child (affects types, functions, and method names)
  • API changes: L2NetworkArbitrumNetwork, getL2NetworkgetArbitrumNetwork, and several removed functions
  • Bridger classes restructured with updated constructors and signatures
  • Message classes renamed: MessageParentToChildMessage/ChildToParentMessage
  • New requirement: registerCustomArbitrumNetwork must be called for custom chains

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
In contracts/package.json around line 123, the dependency bump to
"@arbitrum/sdk": "^4.0.4" may break existing code because v4 renamed types and
methods (L1/L2 → parent/child, L2Network → ArbitrumNetwork, getL2Network →
getArbitrumNetwork), restructured Bridger constructors, renamed Message classes,
and requires registerCustomArbitrumNetwork for custom chains; update all
imports/usages across the codebase to the v4 API (rename
types/functions/classes, adjust constructor/signature calls, replace Message
usages with ParentToChildMessage/ChildToParentMessage, and call
registerCustomArbitrumNetwork where custom chains are used), run the migration
guide at docs.arbitrum.io/sdk/migrate to map each old API to its v4 equivalent,
and run tests to ensure no remaining references to v3 APIs.

"@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"
}
}
52 changes: 27 additions & 25 deletions contracts/scripts/execute_proof.js
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.");
Expand All @@ -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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Preserve the proxy address formatting

Casting l1MessageSentEvent.address to BigInt and back removes any leading zeros, so ethers.Contract will reject addresses whose high nibble is 0x0. Use the address string directly (normalized with ethers.getAddress) to avoid intermittent failures.

Apply this diff:

-  const homeProxy = `0x${BigInt(l1MessageSentEvent.address).toString(16)}`;
+  const homeProxy = ethers.getAddress(l1MessageSentEvent.address);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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(
const blockNumber = l1MessageSentEvent.blockNumber;
const homeProxy = ethers.getAddress(l1MessageSentEvent.address);
const msgHash = l1MessageSentEvent.msgHash;
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(
🤖 Prompt for AI Agents
In contracts/scripts/execute_proof.js around lines 27 to 33, the code converts
l1MessageSentEvent.address to BigInt and back which strips leading zeros and can
create invalid addresses for ethers.Contract; replace that conversion with the
original address string normalized via ethers.getAddress (or ensure it already
starts with "0x" and pass ethers.getAddress(l1MessageSentEvent.address)) so the
resulting homeProxy preserves leading zeros and is a checksummed valid address
for the Contract constructor.

await homeProxyContract.foreignProxy(),
RealitioForeignArbitrationProxy.abi,
l2Provider
l1Provider
);

console.log(`Event: ${l1MessageSentEvent.name}`);
Expand All @@ -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,
Expand All @@ -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)
Expand All @@ -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,
};
Expand Down
4 changes: 2 additions & 2 deletions contracts/scripts/get_event_properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ async function getL1MessageSentEvent(transactionHash, contractInterface, provide
}

function getFunctionSelector(functionSignature) {
const hash = ethers.utils.id(functionSignature);
const hash = ethers.id(functionSignature);
const selector = hash.slice(0, 10); // 0x + first 4 bytes

return selector;
Expand All @@ -40,7 +40,7 @@ function encodeWithSelector(selector, ...params) {
}

// Otherwise, encode using defaultAbiCoder
return ethers.utils.defaultAbiCoder.encode([param.type], [param.value]).slice(2);
return ethers.AbiCoder.defaultAbiCoder().encode([param.type], [param.value]).slice(2);
});

const encodedData = selector + encodedParams.join("");
Expand Down
Loading