Skip to content

Update Scripts and add Mainnet deployments#95

Merged
luiz-lvj merged 9 commits into
mainfrom
scripts
Apr 6, 2026
Merged

Update Scripts and add Mainnet deployments#95
luiz-lvj merged 9 commits into
mainfrom
scripts

Conversation

@luiz-lvj
Copy link
Copy Markdown
Collaborator

@luiz-lvj luiz-lvj commented Mar 24, 2026

This PR introduces initial mainnet deployment address on all major chains and updates the scripts to be modular with both testnet and mainnet environments

Summary by CodeRabbit

  • New Features

    • Added deployment support and manifests for additional networks, including Base.
  • Chores

    • Updated on-chain deployment addresses across multiple networks.
    • Added deployment configuration files for Ethereum, Arbitrum, Linea, Scroll, Optimism, ZkSync, and Base.
    • Improved deployment automation to use numeric chain IDs and include automated contract verification flags during runs.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 24, 2026

📝 Walkthrough

Walkthrough

This PR adds mainnet deployment manifests, updates multiple sepolia testnet addresses, fills .env.example L2 fields, shifts buffer/pusher scripts to use numeric chain IDs and dynamic chain-name resolution, changes StateProverPointer salts to keccak256(abi.encode(...)), and adds conditional verification flags to deployment scripts.

Changes

Cohort / File(s) Summary
Environment Configuration
\.env.example
Populated previously-empty Linea, Scroll, Optimism, and zkSync env vars with concrete default values (chain IDs, rollup/anchor fields, slots, gateway IDs).
New Mainnet Deployment Manifests
deployments/arbitrum.json, deployments/ethereum.json, deployments/linea.json, deployments/optimism.json, deployments/scroll.json, deployments/zksync.json, deployments/base.json
Added per-network JSON manifests: contracts, copies (cross-chain addresses), and provers/pushers entries for mainnet usage.
Testnet Deployment Updates
deployments/*-sepolia.json (e.g., deployments/arbitrum-sepolia.json, .../linea-sepolia.json, .../optimism-sepolia.json, .../scroll-sepolia.json, .../zksync-sepolia.json, deployments/ethereum-sepolia.json)
Replaced broadcaster and receiver addresses across sepolia manifests; minor JSON punctuation/formatting adjustments.
Chain Name Mapping
scripts/deployment/DeployBase.s.sol
Added mainnet chainId -> chain name mappings (ethereum, arbitrum, linea, scroll, optimism, zksync, base) in _chainName(uint256).
Buffer & Pusher Deploy Logic
scripts/deployment/block-hash-pusher/DeployBuffers.s.sol, scripts/deployment/block-hash-pusher/DeployPushers.s.sol
Switch from string PARENT_CHAIN/CHILD_CHAIN to numeric PARENT_CHAIN_ID/CHILD_CHAIN_ID; derive names via _chainName(chainId); introduce Base as an Optimism-style pusher target and generalize pusher name handling.
Prover Salt Computation
scripts/deployment/provers/Deploy*ChildToParent.s.sol, scripts/deployment/provers/Deploy*ParentToChild.s.sol
Changed deterministic deployment salt for StateProverPointer from bytes32(targetChainId) to keccak256(abi.encode(targetChainId)) across all prover scripts (Arbitrum, Linea, Scroll, Optimism, ZkSync).
Shell Scripts — Verification Flags
scripts/deployment/block-hash-pusher/deploy-buffers.sh, scripts/deployment/block-hash-pusher/deploy-pushers.sh, scripts/deployment/deploy-protocol.sh, scripts/deployment/provers/deploy-child-provers.sh, scripts/deployment/provers/deploy-parent-provers.sh
Introduce conditional VERIFY_FLAGS based on $VERIFIER (etherscan vs generic URL) and append verification flags to forge script invocations.
Main Deploy Orchestration
scripts/deployment/deploy.sh
Replaced direct ./script.sh runs with bash script.sh, removed chmod +x calls, added Base chain deployment steps, switched buffer deploys to use chain ID env vars, and adjusted prover deployment env usage.
Minor Deployment Sepolia Patch
deployments/arbitrum-sepolia.json, deployments/ethereum-sepolia.json, deployments/linea-sepolia.json, deployments/optimism-sepolia.json, deployments/scroll-sepolia.json, deployments/zksync-sepolia.json
Updated specific contract addresses for broadcaster/receiver (new address values).

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Dev/CI
    participant Orchestrator as scripts/deploy.sh
    participant Script as deploy-*.sh (child)
    participant Forge as forge script
    participant Node as RPC (chain nodes)
    participant Verifier as Verifier (Etherscan / verifier-url)

    Dev->>Orchestrator: run deploy.sh (env including CHAIN_IDs, VERIFIER)
    Orchestrator->>Script: bash deploy-protocol.sh / deploy-buffers.sh ...
    Script->>Forge: forge script --broadcast + $VERIFY_FLAGS --rpc-url
    Forge->>Node: broadcast txs to target chain(s)
    Forge->>Verifier: optionally call verification endpoint (if VERIFY_FLAGS present)
    Verifier-->>Forge: verification result
    Node-->>Forge: tx receipts
    Forge-->>Script: deployment addresses written to deployments/*.json
    Script-->>Orchestrator: exit status
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • pepebndc
  • nahimterrazas
  • frangio

Poem

🐰
I hopped through manifests, tidy and bright,
Gave chain IDs names and salts a new bite,
Scripts now verify with flags set in view,
Mainnet and testnet — deployments anew,
A carrot of config for each chain in sight.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title "Update Scripts and add Mainnet deployments" directly and clearly summarizes the main changes: script refactoring and addition of mainnet deployment configurations across multiple chains.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch scripts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/deployment/provers/DeployScrollParentToChild.s.sol (1)

10-10: ⚠️ Potential issue | 🔴 Critical

Contract name mismatch: should be DeployScrollParentToChild.

The contract is named DeployArbitrumParentToChild but the file is DeployScrollParentToChild.s.sol. This appears to be a copy-paste error that will cause deployment script invocations to fail or deploy the wrong contract.

🐛 Proposed fix
-contract DeployArbitrumParentToChild is DeployBase {
+contract DeployScrollParentToChild is DeployBase {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/deployment/provers/DeployScrollParentToChild.s.sol` at line 10,
Rename the contract declaration currently named DeployArbitrumParentToChild to
DeployScrollParentToChild to match the file name and intended deployment script;
update the contract identifier in the contract header (the "contract
DeployArbitrumParentToChild is DeployBase" declaration) to "contract
DeployScrollParentToChild is DeployBase" and verify any references to the old
name within the file or deployment tooling are updated accordingly.
🧹 Nitpick comments (4)
scripts/deployment/provers/DeployZkSyncChildToParent.s.sol (1)

48-48: Extract the pointer salt derivation into DeployBase.

This CREATE2 salt now appears inline across the prover deployers in this PR, and it defines externally consumed addresses. A shared helper like _stateProverPointerSalt(targetChainId) would keep the derivation consistent and give you one place to document future migration semantics.

♻️ Suggested direction
-            pointer = _deploy(pointerCreationCode, keccak256(abi.encode(targetChainId)));
+            pointer = _deploy(pointerCreationCode, _stateProverPointerSalt(targetChainId));
function _stateProverPointerSalt(uint256 targetChainId) internal pure returns (bytes32) {
    return keccak256(abi.encode(targetChainId));
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/deployment/provers/DeployZkSyncChildToParent.s.sol` at line 48,
Replace the inline CREATE2 salt derivation
(keccak256(abi.encode(targetChainId))) with a shared helper on DeployBase named
_stateProverPointerSalt(uint256 targetChainId) that returns bytes32; add the
internal pure function _stateProverPointerSalt in DeployBase and update
DeployZkSyncChildToParent.s.sol (and other prover deployers) to call
_stateProverPointerSalt(targetChainId) where the current inline salt is used
(e.g., the _deploy call assigning pointer).
scripts/deployment/provers/deploy-parent-provers.sh (1)

64-72: Remove excessive trailing blank lines.

There are 9 consecutive blank lines at the end of the file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/deployment/provers/deploy-parent-provers.sh` around lines 64 - 72,
Remove the excessive trailing blank lines at the end of the shell script by
trimming the file so it ends immediately after the last meaningful line (no more
than a single newline at EOF); open the script, delete the 9 consecutive blank
lines at the end, and ensure the file ends with a single newline character to
avoid superfluous empty lines.
scripts/deployment/block-hash-pusher/deploy-pushers.sh (1)

3-13: Consider guarding against missing verifier configuration and quoting $VERIFY_FLAGS.

Two minor concerns:

  1. The else branch unconditionally appends --verify --verifier-url $VERIFIER_URL. If VERIFIER_URL is unset/empty, forge will fail with an unclear error.
  2. $VERIFY_FLAGS is unquoted on line 13, which could cause word-splitting issues (though unlikely with current flag values).
♻️ Optional: Add guard and quote the variable
 if [ "$VERIFIER" = "etherscan" ]; then
   VERIFY_FLAGS="--verify --verifier etherscan --etherscan-api-key $ETHERSCAN_API_KEY"
+elif [ -n "$VERIFIER_URL" ]; then
+  VERIFY_FLAGS="--verify --verifier-url $VERIFIER_URL"
 else
-  VERIFY_FLAGS="--verify --verifier-url $VERIFIER_URL"
+  VERIFY_FLAGS=""
 fi
 
 forge script scripts/deployment/block-hash-pusher/DeployPushers.s.sol \
   --rpc-url "$RPC_URL" \
   --private-key "$DEPLOYER_PRIVATE_KEY" \
-  --broadcast \
-  $VERIFY_FLAGS
+  --broadcast $VERIFY_FLAGS
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/deployment/block-hash-pusher/deploy-pushers.sh` around lines 3 - 13,
The script sets VERIFY_FLAGS without guarding for empty VERIFIER_URL and passes
$VERIFY_FLAGS unquoted to forge; update the logic in deploy-pushers.sh to (1)
validate VERIFIER when it equals "etherscan" require ETHERSCAN_API_KEY and build
VERIFY_FLAGS accordingly, (2) when VERIFIER is not "etherscan" only set
VERIFY_FLAGS to "--verify --verifier-url $VERIFIER_URL" if VERIFIER_URL is
non-empty (otherwise leave VERIFY_FLAGS empty or emit a clear error), and (3)
use the quoted variable "$VERIFY_FLAGS" in the forge command invocation to avoid
word-splitting; reference the VERIFY_FLAGS, VERIFIER, VERIFIER_URL, and
ETHERSCAN_API_KEY symbols and the forge command where to make these changes.
scripts/deployment/deploy.sh (1)

49-75: Remove unused CHAIN_TYPE variable from parent prover deployment invocations.

The CHAIN_TYPE environment variable is set for each invocation (lines 49, 54, 59, 64, 69, 74) but deploy-parent-provers.sh does not use it. The script relies on HOME_CHAIN_ID and TARGET_CHAIN_ID from the environment and executes all prover deployments unconditionally. Remove the CHAIN_TYPE assignments to eliminate unused code and reduce confusion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/deployment/deploy.sh` around lines 49 - 75, The CHAIN_TYPE
environment variable is set before each deploy-parent-provers.sh invocation but
is unused; remove the CHAIN_TYPE=... assignments from the deployment calls so
you only export the needed RPC_URL (e.g., change lines that currently set
CHAIN_TYPE="ethereum" \ RPC_URL=... bash
scripts/deployment/provers/deploy-parent-provers.sh to just RPC_URL=... bash
scripts/deployment/provers/deploy-parent-provers.sh), ensuring the script relies
on HOME_CHAIN_ID and TARGET_CHAIN_ID as intended and avoiding the unused
CHAIN_TYPE variable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.env.example:
- Around line 20-44: The .env.example currently contains network-specific
Sepolia defaults (e.g., LINEA_CHAIN_ID, LINEA_ROLLUP,
LINEA_STATE_ROOT_HASHES_SLOT, SCROLL_CHAIN_ID, SCROLL_CHAIN,
SCROLL_FINALIZED_STATE_ROOT_SLOT, OPTIMISM_CHAIN_ID, OPTIMISM_ANCHOR_GAME_SLOT,
ZKSYNC_CHAIN_ID, ZKSYNC_DIAMOND, etc.); replace those hardcoded values with
blank placeholders (KEY=) or remove them from the shared example, or
alternatively publish separate example files per environment (e.g.,
.env.example.mainnet and .env.example.sepolia) so consumers cannot accidentally
deploy with testnet rollup addresses or slot IDs. Ensure each variable name
remains present for guidance but with no environment-specific value.

In `@deployments/ethereum-sepolia.json`:
- Around line 35-39: The copies object in deployments/ethereum-sepolia.json uses
mainnet chain names which prevents _isCopyDeployed() lookups: change the parent
key "ethereum" to "ethereum-sepolia" and the nested key "arbitrum" to
"arbitrum-sepolia" so the "copies" mapping follows the testnet naming convention
used across other files (ensure you update the keys in the "copies" object
rather than values).

In `@deployments/linea.json`:
- Around line 5-6: The linea.json deployment has the pusher and buffer fields
both set to the same address; update the "pusher" value so it points to the
correct Ethereum L1 pusher contract (distinct from the Linea L2 "buffer"
address) by looking up the deployed L1 pusher address and replacing the current
"pusher" entry while leaving "buffer" as the Linea L2 address; ensure the
"pusher" and "buffer" fields are different and consistent with other mainnet
deployment files.

In `@deployments/scroll.json`:
- Around line 1-25: The file is missing a final newline; open the JSON
containing the "contracts" (e.g., broadcaster, receiver, pusher, buffer,
broadcaster-oracle, input-settler-escrow, output-settler-simple) and
"copies"/"provers" sections and add a single trailing newline character at the
end of the file so it ends with a POSIX-compliant line break.

In `@scripts/deployment/block-hash-pusher/DeployBuffers.s.sol`:
- Around line 14-19: The script currently mixes sources for chain identity
(CHAIN_TYPE env and block.chainid) which can cause mismatches; update
DeployBuffers.s.sol so the child chain is a single source of truth by
deriving/asserting chain info from CHILD_CHAIN_ID: use
vm.envUint("CHILD_CHAIN_ID") (childChainId) and _chainName(childChainId)
(childChain) everywhere the child is needed, add an explicit runtime check that
block.chainid == childChainId (revert or vm.expect) to prevent accidental
deployment on the wrong chain, and derive or assert the rollup/buffer
implementation (currently selected from chainType/CHAIN_TYPE) from the same
childChainId source instead of CHAIN_TYPE to keep all decisions consistent.
Ensure references to parentChain/parentChainId remain from PARENT_CHAIN_ID and
only use CHAIN_TYPE after validating it matches the derived rollup type if you
must keep it.

In `@scripts/deployment/deploy-protocol.sh`:
- Around line 3-13: The script currently always appends verification flags which
can expand to invalid empty args; change the VERIFY_FLAGS logic in
deploy-protocol.sh so verification is opt-in: if VERIFIER is empty, set
VERIFY_FLAGS="" and proceed to broadcast only; if VERIFIER="etherscan" require
ETHERSCAN_API_KEY is set (otherwise exit non-zero with a clear error), and if
VERIFIER is non-empty and not "etherscan" require VERIFIER_URL is set (otherwise
exit non-zero); ensure the final forge script invocation uses the VERIFY_FLAGS
variable but will be empty when verification is not enabled. Reference:
variables VERIFIER, ETHERSCAN_API_KEY, VERIFIER_URL, VERIFY_FLAGS and the
DeployProtocol.s.sol forge invocation.

In `@scripts/deployment/provers/deploy-child-provers.sh`:
- Around line 2-6: The VERIFY_FLAGS construction is unconditional and yields a
broken "--verifier-url $VERIFIER_URL" token when VERIFIER is unset; update the
script so VERIFY_FLAGS is only set when verification is intentionally enabled:
check if VERIFIER is non-empty (if [ -n "$VERIFIER" ]) and then branch—if
VERIFIER="etherscan" set VERIFY_FLAGS to "--verify --verifier etherscan
--etherscan-api-key $ETHERSCAN_API_KEY", else if VERIFIER_URL is non-empty set
VERIFY_FLAGS="--verify --verifier-url $VERIFIER_URL"; otherwise set
VERIFY_FLAGS="" (empty) so the subsequent five forge script invocations use no
verifier flags unless explicitly requested. Ensure the same guarded logic is
applied before the first prover deployment and reused for the other four forge
script calls.

In `@scripts/deployment/provers/DeployArbitrumParentToChild.s.sol`:
- Line 50: The CREATE2 salt used to derive the StateProverPointer address was
changed by replacing the legacy salt with keccak256(abi.encode(targetChainId)),
which rotates deterministic addresses and breaks existing deployments; restore
the original salt derivation used by DeployBase.s.sol (the legacy salt
value/encoding) in DeployArbitrumParentToChild.s.sol where pointer is created
(pointerCreationCode / _deploy) or add a clear migration/versioning step that
detects an existing pointer at the legacy CREATE2 address and reconciles it to
the new address (or re-deploys/updates a manifest) before changing salts; ensure
this preserves the intended behavior of the existing deployment guards
(_isProverDeployed and _isCopyDeployed) and documents the change for
deploy-parent-provers.sh runs.

---

Outside diff comments:
In `@scripts/deployment/provers/DeployScrollParentToChild.s.sol`:
- Line 10: Rename the contract declaration currently named
DeployArbitrumParentToChild to DeployScrollParentToChild to match the file name
and intended deployment script; update the contract identifier in the contract
header (the "contract DeployArbitrumParentToChild is DeployBase" declaration) to
"contract DeployScrollParentToChild is DeployBase" and verify any references to
the old name within the file or deployment tooling are updated accordingly.

---

Nitpick comments:
In `@scripts/deployment/block-hash-pusher/deploy-pushers.sh`:
- Around line 3-13: The script sets VERIFY_FLAGS without guarding for empty
VERIFIER_URL and passes $VERIFY_FLAGS unquoted to forge; update the logic in
deploy-pushers.sh to (1) validate VERIFIER when it equals "etherscan" require
ETHERSCAN_API_KEY and build VERIFY_FLAGS accordingly, (2) when VERIFIER is not
"etherscan" only set VERIFY_FLAGS to "--verify --verifier-url $VERIFIER_URL" if
VERIFIER_URL is non-empty (otherwise leave VERIFY_FLAGS empty or emit a clear
error), and (3) use the quoted variable "$VERIFY_FLAGS" in the forge command
invocation to avoid word-splitting; reference the VERIFY_FLAGS, VERIFIER,
VERIFIER_URL, and ETHERSCAN_API_KEY symbols and the forge command where to make
these changes.

In `@scripts/deployment/deploy.sh`:
- Around line 49-75: The CHAIN_TYPE environment variable is set before each
deploy-parent-provers.sh invocation but is unused; remove the CHAIN_TYPE=...
assignments from the deployment calls so you only export the needed RPC_URL
(e.g., change lines that currently set CHAIN_TYPE="ethereum" \ RPC_URL=... bash
scripts/deployment/provers/deploy-parent-provers.sh to just RPC_URL=... bash
scripts/deployment/provers/deploy-parent-provers.sh), ensuring the script relies
on HOME_CHAIN_ID and TARGET_CHAIN_ID as intended and avoiding the unused
CHAIN_TYPE variable.

In `@scripts/deployment/provers/deploy-parent-provers.sh`:
- Around line 64-72: Remove the excessive trailing blank lines at the end of the
shell script by trimming the file so it ends immediately after the last
meaningful line (no more than a single newline at EOF); open the script, delete
the 9 consecutive blank lines at the end, and ensure the file ends with a single
newline character to avoid superfluous empty lines.

In `@scripts/deployment/provers/DeployZkSyncChildToParent.s.sol`:
- Line 48: Replace the inline CREATE2 salt derivation
(keccak256(abi.encode(targetChainId))) with a shared helper on DeployBase named
_stateProverPointerSalt(uint256 targetChainId) that returns bytes32; add the
internal pure function _stateProverPointerSalt in DeployBase and update
DeployZkSyncChildToParent.s.sol (and other prover deployers) to call
_stateProverPointerSalt(targetChainId) where the current inline salt is used
(e.g., the _deploy call assigning pointer).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 379c5b35-499a-4dc3-bd41-c3f2da91ca7c

📥 Commits

Reviewing files that changed from the base of the PR and between 0419217 and be18414.

📒 Files selected for processing (32)
  • .env.example
  • deployments/arbitrum-sepolia.json
  • deployments/arbitrum.json
  • deployments/ethereum-sepolia.json
  • deployments/ethereum.json
  • deployments/linea-sepolia.json
  • deployments/linea.json
  • deployments/optimism-sepolia.json
  • deployments/optimism.json
  • deployments/scroll-sepolia.json
  • deployments/scroll.json
  • deployments/zksync-sepolia.json
  • deployments/zksync.json
  • scripts/deployment/DeployBase.s.sol
  • scripts/deployment/block-hash-pusher/DeployBuffers.s.sol
  • scripts/deployment/block-hash-pusher/DeployPushers.s.sol
  • scripts/deployment/block-hash-pusher/deploy-buffers.sh
  • scripts/deployment/block-hash-pusher/deploy-pushers.sh
  • scripts/deployment/deploy-protocol.sh
  • scripts/deployment/deploy.sh
  • scripts/deployment/provers/DeployArbitrumChildToParent.s.sol
  • scripts/deployment/provers/DeployArbitrumParentToChild.s.sol
  • scripts/deployment/provers/DeployLineaChildToParent.s.sol
  • scripts/deployment/provers/DeployLineaParentToChild.s.sol
  • scripts/deployment/provers/DeployOptimismChildToParent.s.sol
  • scripts/deployment/provers/DeployOptimismParentToChild.s.sol
  • scripts/deployment/provers/DeployScrollChildToParent.s.sol
  • scripts/deployment/provers/DeployScrollParentToChild.s.sol
  • scripts/deployment/provers/DeployZkSyncChildToParent.s.sol
  • scripts/deployment/provers/DeployZkSyncParentToChild.s.sol
  • scripts/deployment/provers/deploy-child-provers.sh
  • scripts/deployment/provers/deploy-parent-provers.sh

Comment thread .env.example
Comment on lines +20 to +44
LINEA_CHAIN_ID=59141
LINEA_ROLLUP=0xB218f8A4Bc926cF1cA7b3423c154a0D627Bdb7E5
LINEA_STATE_ROOT_HASHES_SLOT=282
LINEA_L2_MESSAGE_SERVICE=0x971e727e956690b9957be6d51Ec16E73AcAC83A7

# Scroll Envs
SCROLL_CHAIN_ID=
SCROLL_CHAIN_SEPOLIA=
SCROLL_FINALIZED_STATE_ROOT_SLOT=
L1_SCROLL_MESSENGER=
L2_SCROLL_MESSENGER=
SCROLL_CHAIN_ID=534351
SCROLL_CHAIN=0x2D567EcE699Eabe5afCd141eDB7A4f2D0D6ce8a0
SCROLL_FINALIZED_STATE_ROOT_SLOT=158
L1_SCROLL_MESSENGER=0x50c7d3e7f7c656493D1D76aaa1a836CedfCBB16A
L2_SCROLL_MESSENGER=0xBa50f5340FB9F3Bd074bD638c9BE13eCB36E603d

# Optimism Envs
OPTIMISM_CHAIN_ID=
OPTIMISM_ANCHOR_GAME_SLOT=
OPTIMISM_ANCHOR_STATE_REGISTRY=
OPTIMISM_L1_CROSS_DOMAIN_MESSENGER_PROXY=
OPTIMISM_L2_CROSS_DOMAIN_MESSENGER=
OPTIMISM_CHAIN_ID=11155420
OPTIMISM_ANCHOR_GAME_SLOT=2
OPTIMISM_ANCHOR_STATE_REGISTRY=0xa1Cec548926eb5d69aa3B7B57d371EdBdD03e64b
OPTIMISM_L1_CROSS_DOMAIN_MESSENGER_PROXY=0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef
OPTIMISM_L2_CROSS_DOMAIN_MESSENGER=0x4200000000000000000000000000000000000007

# ZkSync Envs
ZKSYNC_CHAIN_ID=
ZKSYNC_DIAMOND=
ZKSYNC_GATEWAY_ZK_CHAIN=
ZKSYNC_L2_LOGS_ROOT_HASH_SLOT=
ZKSYNC_GATEWAY_CHAIN_ID=
ZKSYNC_CHAIN_ID=300
ZKSYNC_DIAMOND=0x9A6DE0f62Aa270A8bCB1e2610078650D539B1Ef9
ZKSYNC_GATEWAY_ZK_CHAIN=0xFFDbb7B7F35A8b81618F64d95BCc878297759744
ZKSYNC_L2_LOGS_ROOT_HASH_SLOT=15
ZKSYNC_GATEWAY_CHAIN_ID=32657
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Split Sepolia defaults out of the shared example.

These values are all network-specific Sepolia settings, but the rest of this PR now supports mainnet too. Copying .env.example and only swapping RPC URLs or top-level chain IDs can leave rollup addresses and storage slots pointed at testnet, which is an easy way to produce broken mainnet deployments. Please either keep these blank or publish separate example env files per environment.

🧰 Tools
🪛 dotenv-linter (4.0.0)

[warning] 23-23: [UnorderedKey] The LINEA_L2_MESSAGE_SERVICE key should go before the LINEA_ROLLUP key

(UnorderedKey)


[warning] 27-27: [UnorderedKey] The SCROLL_CHAIN key should go before the SCROLL_CHAIN_ID key

(UnorderedKey)


[warning] 29-29: [UnorderedKey] The L1_SCROLL_MESSENGER key should go before the SCROLL_CHAIN key

(UnorderedKey)


[warning] 30-30: [UnorderedKey] The L2_SCROLL_MESSENGER key should go before the SCROLL_CHAIN key

(UnorderedKey)


[warning] 34-34: [UnorderedKey] The OPTIMISM_ANCHOR_GAME_SLOT key should go before the OPTIMISM_CHAIN_ID key

(UnorderedKey)


[warning] 35-35: [UnorderedKey] The OPTIMISM_ANCHOR_STATE_REGISTRY key should go before the OPTIMISM_CHAIN_ID key

(UnorderedKey)


[warning] 44-44: [UnorderedKey] The ZKSYNC_GATEWAY_CHAIN_ID key should go before the ZKSYNC_GATEWAY_ZK_CHAIN key

(UnorderedKey)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.env.example around lines 20 - 44, The .env.example currently contains
network-specific Sepolia defaults (e.g., LINEA_CHAIN_ID, LINEA_ROLLUP,
LINEA_STATE_ROOT_HASHES_SLOT, SCROLL_CHAIN_ID, SCROLL_CHAIN,
SCROLL_FINALIZED_STATE_ROOT_SLOT, OPTIMISM_CHAIN_ID, OPTIMISM_ANCHOR_GAME_SLOT,
ZKSYNC_CHAIN_ID, ZKSYNC_DIAMOND, etc.); replace those hardcoded values with
blank placeholders (KEY=) or remove them from the shared example, or
alternatively publish separate example files per environment (e.g.,
.env.example.mainnet and .env.example.sepolia) so consumers cannot accidentally
deploy with testnet rollup addresses or slot IDs. Ensure each variable name
remains present for guidance but with no environment-specific value.

Comment thread deployments/ethereum-sepolia.json Outdated
Comment on lines 35 to 39
"copies": {
"ethereum": {
"arbitrum": "0xfdB7609b3fFd817454fDF8409b01399DF4a45adD"
}
}
Copy link
Copy Markdown

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:

#!/bin/bash
# Verify naming conventions used in other sepolia deployment files
echo "=== Checking copies sections in sepolia deployment files ==="
for f in deployments/*-sepolia.json; do
  echo "--- $f ---"
  jq '.copies // empty' "$f" 2>/dev/null
done

Repository: openintentsframework/broadcaster

Length of output: 1993


Fix inconsistent chain naming in copies section—use testnet chain names.

The copies section uses ethereum (mainnet name) instead of ethereum-sepolia. All other testnet deployment files (arbitrum-sepolia.json, linea-sepolia.json, optimism-sepolia.json, scroll-sepolia.json, zksync-sepolia.json) correctly use testnet chain names like ethereum-sepolia as the parent key.

Change "ethereum" to "ethereum-sepolia" and "arbitrum" to "arbitrum-sepolia" to match the testnet naming convention and ensure _isCopyDeployed() lookups succeed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deployments/ethereum-sepolia.json` around lines 35 - 39, The copies object in
deployments/ethereum-sepolia.json uses mainnet chain names which prevents
_isCopyDeployed() lookups: change the parent key "ethereum" to
"ethereum-sepolia" and the nested key "arbitrum" to "arbitrum-sepolia" so the
"copies" mapping follows the testnet naming convention used across other files
(ensure you update the keys in the "copies" object rather than values).

Comment thread deployments/linea.json
Comment on lines +5 to +6
"pusher": "0xe0f5B1750670FBea7f8c9D825DdBfa6A34a7727b",
"buffer": "0xe0f5B1750670FBea7f8c9D825DdBfa6A34a7727b",
Copy link
Copy Markdown

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:

#!/bin/bash
# Compare pusher and buffer addresses across mainnet deployment files
echo "=== Comparing pusher and buffer addresses ==="
for f in deployments/arbitrum.json deployments/linea.json deployments/optimism.json deployments/scroll.json deployments/zksync.json; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    jq '{pusher: .contracts.pusher, buffer: .contracts.buffer}' "$f" 2>/dev/null
  fi
done

Repository: openintentsframework/broadcaster

Length of output: 879


🏁 Script executed:

#!/bin/bash
# Search for pusher and buffer contract references in the codebase
echo "=== Searching for pusher contract references ==="
rg -i "pusher" --max-count 20 -A 3 -B 3

echo ""
echo "=== Searching for buffer contract references ==="
rg -i "buffer" --max-count 20 -A 3 -B 3

Repository: openintentsframework/broadcaster

Length of output: 50389


🏁 Script executed:

#!/bin/bash
# Check the deployment files for patterns and comments
echo "=== Full content of deployment files ==="
for f in deployments/arbitrum.json deployments/linea.json deployments/optimism.json deployments/scroll.json deployments/zksync.json; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    cat -n "$f"
    echo ""
  fi
done

Repository: openintentsframework/broadcaster

Length of output: 5916


🏁 Script executed:

#!/bin/bash
# Search for Linea-specific configuration or notes
echo "=== Searching for Linea-specific documentation or comments ==="
find . -type f \( -name "*.md" -o -name "*.sol" -o -name "*.sh" -o -name "*.json" \) | xargs grep -l -i "linea" | head -20

Repository: openintentsframework/broadcaster

Length of output: 869


🏁 Script executed:

#!/bin/bash
# Check Linea documentation
cat docs/provers/LINEA.md

Repository: openintentsframework/broadcaster

Length of output: 14074


🏁 Script executed:

#!/bin/bash
# Check deployment scripts for Linea-specific configuration
echo "=== Checking Linea deployment scripts ==="
find scripts/deployment -name "*inea*" -o -name "*inea*" | xargs cat -n 2>/dev/null

Repository: openintentsframework/broadcaster

Length of output: 6535


Fix duplicate pusher and buffer addresses in linea.json.

The pusher and buffer fields are currently set to the same address (0xe0f5B1750670FBea7f8c9D825DdBfa6A34a7727b). The pusher contract is deployed on Ethereum L1, while the buffer contract is deployed on Linea L2—they must have distinct addresses. All other mainnet deployment files (arbitrum.json, optimism.json, scroll.json, zksync.json) correctly use different addresses for these two contracts. Verify the correct L1 pusher address for Linea and update the configuration accordingly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deployments/linea.json` around lines 5 - 6, The linea.json deployment has the
pusher and buffer fields both set to the same address; update the "pusher" value
so it points to the correct Ethereum L1 pusher contract (distinct from the Linea
L2 "buffer" address) by looking up the deployed L1 pusher address and replacing
the current "pusher" entry while leaving "buffer" as the Linea L2 address;
ensure the "pusher" and "buffer" fields are different and consistent with other
mainnet deployment files.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The contracts are right, it's a coincidence

Comment thread deployments/scroll.json
Comment on lines +1 to +25
{
"contracts": {
"broadcaster": "0x536c398D9bBAf896b128C99bB7c78CfA3243AE27",
"receiver": "0x16681d01c9169aacaFB6BbCBaF4c7C3002C63059",
"pusher": "0x331475638c7B3356c3E1d1Ff0c1477F7D8B8fB04",
"buffer": "0x58b67c85CeCAa0e2c4476Ed1Be03970EFbce298c",
"broadcaster-oracle": "0x0a6edD8A400b6db1bbe0d21Ecef07c4Fce983248",
"input-settler-escrow": "0x15eA18EAcD9C35b454CF1456ed1bD05636B46147",
"output-settler-simple": "0x1DCE289d62C2068584C5D0CFb5C1fD538e832847"
},
"copies": {
"ethereum": {
"arbitrum": "0xfdB7609b3fFd817454fDF8409b01399DF4a45adD",
"linea": "0x347Fdf829FeE4289c520F23b3537e273EA41AE30",
"optimism": "0x6B0e07592261540cF9D141d894b8A17FE1A04a98",
"zksync": "0x4148d6E5cF0a095dB68f20A99DBf1232D8BB1cC6"
}
},
"provers": {
"ethereum": {
"pointer": "0x1c7ca0a4d176A03Fe93C1f5d6555f2ED724B6b04",
"prover": "0xe8cBb8F5B085ECE491673E6d1239081b77f0Ca9a"
}
}
} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if the broadcaster contract is verified on Scroll mainnet
echo "Checking Scroll mainnet broadcaster contract..."
curl -s "https://api.scrollscan.com/api?module=contract&action=getsourcecode&address=0x536c398D9bBAf896b128C99bB7c78CfA3243AE27" | jq '.result[0].ContractName // "Not verified or error"'

Repository: openintentsframework/broadcaster

Length of output: 198


🏁 Script executed:

# Check the scroll.json file and verify its structure
file_path="deployments/scroll.json"

# Check if file exists and view it with line numbers to see trailing newline
echo "=== File content with line numbers ==="
cat -n "$file_path"

echo ""
echo "=== Check for trailing newline ==="
if [ -z "$(tail -c 1 "$file_path")" ]; then
  echo "File HAS a trailing newline"
else
  echo "File DOES NOT have a trailing newline"
fi

echo ""
echo "=== Validate JSON structure ==="
python3 << 'PYTHON_EOF'
import json
try:
    with open('deployments/scroll.json', 'r') as f:
        data = json.load(f)
    print("✓ Valid JSON structure")
    print(f"✓ Keys present: {list(data.keys())}")
    
    # Validate address formats
    all_addresses = []
    def extract_addresses(obj):
        if isinstance(obj, dict):
            for v in obj.values():
                if isinstance(v, str) and v.startswith('0x'):
                    all_addresses.append(v)
                extract_addresses(v)
        elif isinstance(obj, list):
            for item in obj:
                extract_addresses(item)
    
    extract_addresses(data)
    print(f"✓ Total addresses found: {len(all_addresses)}")
    
    # Validate hex format
    invalid_addresses = []
    for addr in all_addresses:
        if not (len(addr) == 42 and all(c in '0123456789abcdefABCDEF' for c in addr[2:])):
            invalid_addresses.append(addr)
    
    if invalid_addresses:
        print(f"✗ Invalid address formats: {invalid_addresses}")
    else:
        print(f"✓ All {len(all_addresses)} addresses have valid format (42 chars, 0x prefix)")
        
except json.JSONDecodeError as e:
    print(f"✗ Invalid JSON: {e}")
PYTHON_EOF

Repository: openintentsframework/broadcaster

Length of output: 1509


Add trailing newline to maintain POSIX compliance.

The JSON structure and all 13 contract addresses are valid. The file is missing a final newline character; add it to the end of deployments/scroll.json.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deployments/scroll.json` around lines 1 - 25, The file is missing a final
newline; open the JSON containing the "contracts" (e.g., broadcaster, receiver,
pusher, buffer, broadcaster-oracle, input-settler-escrow, output-settler-simple)
and "copies"/"provers" sections and add a single trailing newline character at
the end of the file so it ends with a POSIX-compliant line break.

Comment on lines 14 to +19
string memory chainType = vm.envString("CHAIN_TYPE");
string memory parentChain = vm.envString("PARENT_CHAIN");
string memory childChain = vm.envString("CHILD_CHAIN");

uint256 parentChainId = vm.envUint("PARENT_CHAIN_ID");
uint256 childChainId = vm.envUint("CHILD_CHAIN_ID");
string memory parentChain = _chainName(parentChainId);
string memory childChain = _chainName(childChainId);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Use one source of truth for the child chain.

parentChain/childChain now come from env IDs, but the buffer implementation is still selected from CHAIN_TYPE and the output manifest is still keyed off block.chainid. If those drift, this script can read the pusher for one chain pair, deploy another chain’s buffer, and write it into a third chain’s JSON. Add an explicit block.chainid == CHILD_CHAIN_ID check and derive or assert the rollup type from that same source.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/deployment/block-hash-pusher/DeployBuffers.s.sol` around lines 14 -
19, The script currently mixes sources for chain identity (CHAIN_TYPE env and
block.chainid) which can cause mismatches; update DeployBuffers.s.sol so the
child chain is a single source of truth by deriving/asserting chain info from
CHILD_CHAIN_ID: use vm.envUint("CHILD_CHAIN_ID") (childChainId) and
_chainName(childChainId) (childChain) everywhere the child is needed, add an
explicit runtime check that block.chainid == childChainId (revert or vm.expect)
to prevent accidental deployment on the wrong chain, and derive or assert the
rollup/buffer implementation (currently selected from chainType/CHAIN_TYPE) from
the same childChainId source instead of CHAIN_TYPE to keep all decisions
consistent. Ensure references to parentChain/parentChainId remain from
PARENT_CHAIN_ID and only use CHAIN_TYPE after validating it matches the derived
rollup type if you must keep it.

Comment on lines +3 to +13
if [ "$VERIFIER" = "etherscan" ]; then
VERIFY_FLAGS="--verify --verifier etherscan --etherscan-api-key $ETHERSCAN_API_KEY"
else
VERIFY_FLAGS="--verify --verifier-url $VERIFIER_URL"
fi

CHAIN_TYPE=$CHAIN_TYPE forge script scripts/deployment/DeployProtocol.s.sol \
--rpc-url "$RPC_URL" \
--private-key "$DEPLOYER_PRIVATE_KEY" \
--broadcast
--broadcast \
$VERIFY_FLAGS
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Make verification opt-in, or fail fast on missing verifier config.

With the current .env.example, VERIFIER, VERIFIER_URL, and ETHERSCAN_API_KEY are unset. This script still appends verification flags on every run, so an empty VERIFIER expands to a bare --verify --verifier-url and the command dies before broadcasting anything. Default to broadcast-only unless verifier settings are present, or validate the required env vars explicitly.

Proposed fix
-if [ "$VERIFIER" = "etherscan" ]; then
-  VERIFY_FLAGS="--verify --verifier etherscan --etherscan-api-key $ETHERSCAN_API_KEY"
-else
-  VERIFY_FLAGS="--verify --verifier-url $VERIFIER_URL"
-fi
+VERIFY_FLAGS=()
+if [ -n "$VERIFIER" ]; then
+  if [ "$VERIFIER" = "etherscan" ]; then
+    [ -n "$ETHERSCAN_API_KEY" ] || {
+      echo "ETHERSCAN_API_KEY is required when VERIFIER=etherscan" >&2
+      exit 1
+    }
+    VERIFY_FLAGS=(--verify --verifier etherscan --etherscan-api-key "$ETHERSCAN_API_KEY")
+  else
+    [ -n "$VERIFIER_URL" ] || {
+      echo "VERIFIER_URL is required when VERIFIER=$VERIFIER" >&2
+      exit 1
+    }
+    VERIFY_FLAGS=(--verify --verifier "$VERIFIER" --verifier-url "$VERIFIER_URL")
+  fi
+fi
 
 CHAIN_TYPE=$CHAIN_TYPE forge script scripts/deployment/DeployProtocol.s.sol \
   --rpc-url "$RPC_URL" \
   --private-key "$DEPLOYER_PRIVATE_KEY" \
   --broadcast \
-  $VERIFY_FLAGS
+  "${VERIFY_FLAGS[@]}"
📝 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
if [ "$VERIFIER" = "etherscan" ]; then
VERIFY_FLAGS="--verify --verifier etherscan --etherscan-api-key $ETHERSCAN_API_KEY"
else
VERIFY_FLAGS="--verify --verifier-url $VERIFIER_URL"
fi
CHAIN_TYPE=$CHAIN_TYPE forge script scripts/deployment/DeployProtocol.s.sol \
--rpc-url "$RPC_URL" \
--private-key "$DEPLOYER_PRIVATE_KEY" \
--broadcast
--broadcast \
$VERIFY_FLAGS
if [ -n "$VERIFIER" ]; then
if [ "$VERIFIER" = "etherscan" ]; then
[ -n "$ETHERSCAN_API_KEY" ] || {
echo "ETHERSCAN_API_KEY is required when VERIFIER=etherscan" >&2
exit 1
}
VERIFY_FLAGS=(--verify --verifier etherscan --etherscan-api-key "$ETHERSCAN_API_KEY")
else
[ -n "$VERIFIER_URL" ] || {
echo "VERIFIER_URL is required when VERIFIER=$VERIFIER" >&2
exit 1
}
VERIFY_FLAGS=(--verify --verifier "$VERIFIER" --verifier-url "$VERIFIER_URL")
fi
else
VERIFY_FLAGS=()
fi
CHAIN_TYPE=$CHAIN_TYPE forge script scripts/deployment/DeployProtocol.s.sol \
--rpc-url "$RPC_URL" \
--private-key "$DEPLOYER_PRIVATE_KEY" \
--broadcast \
"${VERIFY_FLAGS[@]}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/deployment/deploy-protocol.sh` around lines 3 - 13, The script
currently always appends verification flags which can expand to invalid empty
args; change the VERIFY_FLAGS logic in deploy-protocol.sh so verification is
opt-in: if VERIFIER is empty, set VERIFY_FLAGS="" and proceed to broadcast only;
if VERIFIER="etherscan" require ETHERSCAN_API_KEY is set (otherwise exit
non-zero with a clear error), and if VERIFIER is non-empty and not "etherscan"
require VERIFIER_URL is set (otherwise exit non-zero); ensure the final forge
script invocation uses the VERIFY_FLAGS variable but will be empty when
verification is not enabled. Reference: variables VERIFIER, ETHERSCAN_API_KEY,
VERIFIER_URL, VERIFY_FLAGS and the DeployProtocol.s.sol forge invocation.

Comment on lines +2 to +6
if [ "$VERIFIER" = "etherscan" ]; then
VERIFY_FLAGS="--verify --verifier etherscan --etherscan-api-key $ETHERSCAN_API_KEY"
else
VERIFY_FLAGS="--verify --verifier-url $VERIFIER_URL"
fi
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Guard VERIFY_FLAGS before the first prover deployment.

This script has the same unconditional verification path as scripts/deployment/deploy-protocol.sh, but here it fans out into five forge script calls. With an unset VERIFIER, every invocation gets a bare --verifier-url token and fails immediately. Reuse the same opt-in or explicit-validation logic here before the first deployment.

Also applies to: 13-14, 21-22, 29-30, 37-38, 45-46

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/deployment/provers/deploy-child-provers.sh` around lines 2 - 6, The
VERIFY_FLAGS construction is unconditional and yields a broken "--verifier-url
$VERIFIER_URL" token when VERIFIER is unset; update the script so VERIFY_FLAGS
is only set when verification is intentionally enabled: check if VERIFIER is
non-empty (if [ -n "$VERIFIER" ]) and then branch—if VERIFIER="etherscan" set
VERIFY_FLAGS to "--verify --verifier etherscan --etherscan-api-key
$ETHERSCAN_API_KEY", else if VERIFIER_URL is non-empty set
VERIFY_FLAGS="--verify --verifier-url $VERIFIER_URL"; otherwise set
VERIFY_FLAGS="" (empty) so the subsequent five forge script invocations use no
verifier flags unless explicitly requested. Ensure the same guarded logic is
applied before the first prover deployment and reused for the other four forge
script calls.

bytes memory pointerCreationCode =
abi.encodePacked(type(StateProverPointer).creationCode, abi.encode(owner));
pointer = _deploy(pointerCreationCode, bytes32(targetChainId));
pointer = _deploy(pointerCreationCode, keccak256(abi.encode(targetChainId)));
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Mar 24, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

This rotates deterministic pointer addresses without migrating existing deployments.

scripts/deployment/DeployBase.s.sol derives the CREATE2 address directly from the supplied salt, so this changes the StateProverPointer address for the same HOME/TARGET pair. The current guards only prevent duplicate work; they do not reconcile prior pointers, so environments already deployed with the legacy salt can diverge from fresh deployments. Please keep the legacy salt for already-live networks or land an explicit deployment-manifest/versioning migration before applying this same salt rotation across the sibling deployers. Based on learnings, deploy-parent-provers.sh is intentionally rerun per chain and relies on _isProverDeployed / _isCopyDeployed to skip existing deployments.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/deployment/provers/DeployArbitrumParentToChild.s.sol` at line 50, The
CREATE2 salt used to derive the StateProverPointer address was changed by
replacing the legacy salt with keccak256(abi.encode(targetChainId)), which
rotates deterministic addresses and breaks existing deployments; restore the
original salt derivation used by DeployBase.s.sol (the legacy salt
value/encoding) in DeployArbitrumParentToChild.s.sol where pointer is created
(pointerCreationCode / _deploy) or add a clear migration/versioning step that
detects an existing pointer at the legacy CREATE2 address and reconciles it to
the new address (or re-deploys/updates a manifest) before changing salts; ensure
this preserves the intended behavior of the existing deployment guards
(_isProverDeployed and _isCopyDeployed) and documents the change for
deploy-parent-provers.sh runs.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

we don't want to reconcile earlier deployments. We want to skip if deployed contracts exist

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@luiz-lvj, understood — the existing _isProverDeployed / _isCopyDeployed guards already handle skipping chains where contracts are deployed, so the salt rotation simply targets fresh (mainnet) deployments without disturbing existing ones. My concern is resolved.

(∩^ω^)⊃━☆゚.*・。゚


✏️ Learnings added
Learnt from: luiz-lvj
Repo: openintentsframework/broadcaster PR: 95
File: scripts/deployment/provers/DeployArbitrumParentToChild.s.sol:50-50
Timestamp: 2026-03-25T15:02:30.470Z
Learning: In `scripts/deployment/provers/DeployArbitrumParentToChild.s.sol` (and all sibling prover deployers), the salt for `StateProverPointer` was intentionally changed from `bytes32(targetChainId)` to `keccak256(abi.encode(targetChainId))` for mainnet deployments. There is no intent to reconcile prior (e.g. testnet) deployments; the existing `_isProverDeployed` and `_isCopyDeployed` guards in `DeployBase.s.sol` are relied upon to skip chains where contracts already exist. Do not flag this salt rotation as a breaking change.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: luiz-lvj
Repo: openintentsframework/broadcaster PR: 50
File: scripts/deployment/deploy.sh:49-71
Timestamp: 2026-03-11T20:05:33.999Z
Learning: In `scripts/deployment/deploy.sh`, `deploy-parent-provers.sh` is intentionally invoked multiple times — once per chain (Ethereum, Arbitrum, Linea, Scroll, Optimism, ZkSync) — each with its respective `RPC_URL`. This is by design to deploy prover copies on each chain. The scripts use `_isProverDeployed` and `_isCopyDeployed` guards in `DeployBase.s.sol` to prevent duplicate deployments.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
scripts/deployment/block-hash-pusher/DeployBuffers.s.sol (1)

14-19: ⚠️ Potential issue | 🟠 Major

Unify chain identity source to prevent cross-chain misdeployment.

CHAIN_TYPE still drives buffer selection while CHILD_CHAIN_ID drives pusher lookup and block.chainid drives manifest writes. A mismatch can deploy the wrong buffer and persist it under the wrong chain file.

Suggested fix
-        string memory chainType = vm.envString("CHAIN_TYPE");
-
         uint256 parentChainId = vm.envUint("PARENT_CHAIN_ID");
         uint256 childChainId = vm.envUint("CHILD_CHAIN_ID");
         string memory parentChain = _chainName(parentChainId);
         string memory childChain = _chainName(childChainId);
+        require(block.chainid == childChainId, "CHILD_CHAIN_ID != current chain");
+        string memory chainType = childChain;

Also applies to: 35-47

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/deployment/block-hash-pusher/DeployBuffers.s.sol` around lines 14 -
19, The code mixes CHAIN_TYPE, CHILD_CHAIN_ID and block.chainid which can select
different chains; unify the source by deriving chain identity from
CHILD_CHAIN_ID (or from a single canonical source) and use it for buffer
selection, pusher lookup and manifest writes: replace usages of
vm.envString("CHAIN_TYPE")/chainType with a canonical value computed from
childChainId (e.g., via _chainName(childChainId)), ensure
parentChainId/parentChain remain as-is for parent references, and make sure any
places that read block.chainid or CHAIN_TYPE (buffer selection, pusher lookup,
manifest writes) use the same canonical child-derived chain identifier so
selection and persistence cannot diverge.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/deployment/provers/deploy-parent-provers.sh`:
- Around line 3-7: The script currently always sets VERIFY_FLAGS causing forge
to fail when verification inputs are missing; change the logic so VERIFY_FLAGS
is only set when an explicit opt-in flag (e.g. VERIFICATION_ENABLED or
VERIFY="true") is present, and then validate required inputs: if VERIFIER ==
"etherscan" ensure ETHERSCAN_API_KEY is non-empty before setting VERIFY_FLAGS,
otherwise ensure VERIFIER_URL is non-empty; if validation fails leave
VERIFY_FLAGS empty (or unset) and emit a clear warning. Update the block that
assigns VERIFY_FLAGS (referencing VERIFY_FLAGS, VERIFIER, ETHERSCAN_API_KEY,
VERIFIER_URL) to perform these checks and only enable verification when all
required env vars and the opt-in flag are provided.

---

Duplicate comments:
In `@scripts/deployment/block-hash-pusher/DeployBuffers.s.sol`:
- Around line 14-19: The code mixes CHAIN_TYPE, CHILD_CHAIN_ID and block.chainid
which can select different chains; unify the source by deriving chain identity
from CHILD_CHAIN_ID (or from a single canonical source) and use it for buffer
selection, pusher lookup and manifest writes: replace usages of
vm.envString("CHAIN_TYPE")/chainType with a canonical value computed from
childChainId (e.g., via _chainName(childChainId)), ensure
parentChainId/parentChain remain as-is for parent references, and make sure any
places that read block.chainid or CHAIN_TYPE (buffer selection, pusher lookup,
manifest writes) use the same canonical child-derived chain identifier so
selection and persistence cannot diverge.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 00e4aa84-6dd1-43a7-9713-6aad1a0654ed

📥 Commits

Reviewing files that changed from the base of the PR and between be18414 and f279fb4.

📒 Files selected for processing (14)
  • deployments/arbitrum.json
  • deployments/base.json
  • deployments/ethereum-sepolia.json
  • deployments/ethereum.json
  • deployments/linea.json
  • deployments/optimism.json
  • deployments/scroll.json
  • deployments/zksync.json
  • scripts/deployment/DeployBase.s.sol
  • scripts/deployment/block-hash-pusher/DeployBuffers.s.sol
  • scripts/deployment/block-hash-pusher/DeployPushers.s.sol
  • scripts/deployment/deploy.sh
  • scripts/deployment/provers/deploy-child-provers.sh
  • scripts/deployment/provers/deploy-parent-provers.sh
✅ Files skipped from review due to trivial changes (8)
  • deployments/optimism.json
  • deployments/zksync.json
  • deployments/scroll.json
  • deployments/arbitrum.json
  • deployments/ethereum-sepolia.json
  • deployments/ethereum.json
  • deployments/linea.json
  • deployments/base.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/deployment/deploy.sh

Comment on lines +3 to +7
if [ "$VERIFIER" = "etherscan" ]; then
VERIFY_FLAGS="--verify --verifier etherscan --etherscan-api-key $ETHERSCAN_API_KEY"
else
VERIFY_FLAGS="--verify --verifier-url $VERIFIER_URL"
fi
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Guard verification flags behind explicit opt-in.

This currently enables verification unconditionally. When verification inputs are missing, every forge script call can fail before deployment.

💡 Proposed fix
-if [ "$VERIFIER" = "etherscan" ]; then
-  VERIFY_FLAGS="--verify --verifier etherscan --etherscan-api-key $ETHERSCAN_API_KEY"
-else
-  VERIFY_FLAGS="--verify --verifier-url $VERIFIER_URL"
-fi
+VERIFY_FLAGS=""
+if [ -n "$VERIFIER" ]; then
+  if [ "$VERIFIER" = "etherscan" ]; then
+    VERIFY_FLAGS="--verify --verifier etherscan --etherscan-api-key $ETHERSCAN_API_KEY"
+  elif [ -n "$VERIFIER_URL" ]; then
+    VERIFY_FLAGS="--verify --verifier-url $VERIFIER_URL"
+  fi
+fi
📝 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
if [ "$VERIFIER" = "etherscan" ]; then
VERIFY_FLAGS="--verify --verifier etherscan --etherscan-api-key $ETHERSCAN_API_KEY"
else
VERIFY_FLAGS="--verify --verifier-url $VERIFIER_URL"
fi
VERIFY_FLAGS=""
if [ -n "$VERIFIER" ]; then
if [ "$VERIFIER" = "etherscan" ]; then
VERIFY_FLAGS="--verify --verifier etherscan --etherscan-api-key $ETHERSCAN_API_KEY"
elif [ -n "$VERIFIER_URL" ]; then
VERIFY_FLAGS="--verify --verifier-url $VERIFIER_URL"
fi
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/deployment/provers/deploy-parent-provers.sh` around lines 3 - 7, The
script currently always sets VERIFY_FLAGS causing forge to fail when
verification inputs are missing; change the logic so VERIFY_FLAGS is only set
when an explicit opt-in flag (e.g. VERIFICATION_ENABLED or VERIFY="true") is
present, and then validate required inputs: if VERIFIER == "etherscan" ensure
ETHERSCAN_API_KEY is non-empty before setting VERIFY_FLAGS, otherwise ensure
VERIFIER_URL is non-empty; if validation fails leave VERIFY_FLAGS empty (or
unset) and emit a clear warning. Update the block that assigns VERIFY_FLAGS
(referencing VERIFY_FLAGS, VERIFIER, ETHERSCAN_API_KEY, VERIFIER_URL) to perform
these checks and only enable verification when all required env vars and the
opt-in flag are provided.

@luiz-lvj luiz-lvj merged commit b7df689 into main Apr 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants