Skip to content

fix(proposal-6): WorldChain & XLayer v4 activation must use CrossChainAccount (XDM), not OptimismPortal2#149

Merged
jtriley2p merged 1 commit into
jtriley2p/v4-fees-and-robinhoodfrom
fix/worldchain-xlayer-v4-activation-encoder
Jul 17, 2026
Merged

fix(proposal-6): WorldChain & XLayer v4 activation must use CrossChainAccount (XDM), not OptimismPortal2#149
jtriley2p merged 1 commit into
jtriley2p/v4-fees-and-robinhoodfrom
fix/worldchain-xlayer-v4-activation-encoder

Conversation

@hensha256

Copy link
Copy Markdown
Contributor

Summary

The v4 fee activation proposal (V4FeeProposal in script/proposal-6/V4FeesProposal.s.sol) activates WorldChain and XLayer via OptimismPortal2Encoder, which delivers setProtocolFeeController from the aliased Timelock. But both PoolManagers are owned by their CrossChainAccount, so the L2 call reverts on onlyOwner — the L1 proposal executes "successfully" while v4 fees silently never activate on those two chains. Because it's an OP-stack deposit (not an Arbitrum retryable), the spent message can't be retried without a fresh governance vote.

This switches both to L1CrossDomainMessengerEncoderCrossChainAccount.forward, matching the five other OP-stack chains (Base/Celo/Optimism/Soneium/Zora).

Onchain verification

Verified owner() on all reachable target PoolManagers against the L2 sender each encoder produces — only WorldChain and XLayer were mismatched; the other 9 already line up. Full authority chain for the two fixed chains:

Chain PoolManager .owner() CrossChainAccount l1Owner messenger
WorldChain its CrossChainAccount ✓ mainnet Timelock ✓ L2CrossDomainMessenger ✓
XLayer its CrossChainAccount ✓ mainnet Timelock ✓ L2CrossDomainMessenger ✓

i.e. Timelock → L1CrossDomainMessenger → CrossChainAccount (owned by Timelock) → forward → PoolManager resolves cleanly. The previously-used OptimismPortal2 (aliased-Timelock) path does not, because aliased-Timelock ≠ owner.

Changes

  • WorldChain & XLayer activation → L1CrossDomainMessengerEncoder
  • Removed the now-unused OptimismPortal2Encoder and IL1CrossDomainMessenger imports
  • forge build passes; V4FeeProposal compiles

Note

This only affects Part 2 of the activation (WorldChain/XLayer are both in Part 2). Part 1 is unaffected.

🤖 Generated with Claude Code

…ccount (XDM), not OptimismPortal2

WorldChain and XLayer v4 PoolManagers are owned by their CrossChainAccount, not
the aliased Timelock -- verified onchain: PoolManager.owner() == crossChainAccount,
and crossChainAccount.l1Owner == mainnet Timelock via the L2CrossDomainMessenger.

Activating via OptimismPortal2Encoder delivers setProtocolFeeController from the
aliased Timelock, so the L1 proposal executes but the L2 call reverts on onlyOwner
-- v4 fees never activate on these two chains, and the OP deposit (unlike an
Arbitrum retryable) cannot be retried without a new governance vote.

Switch both to L1CrossDomainMessengerEncoder -> CrossChainAccount.forward, matching
the other five OP-stack chains (Base/Celo/Optimism/Soneium/Zora). Remove the
now-unused OptimismPortal2Encoder and IL1CrossDomainMessenger imports.

Verified owner-vs-encoder-sender onchain for all reachable target chains; only
WorldChain and XLayer were mismatched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jtriley2p
jtriley2p merged commit 7e21071 into jtriley2p/v4-fees-and-robinhood Jul 17, 2026
4 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