Repository navigation
feat(protocol,taiko-client): raise inbox basefee sharing to 100% and rotate raiko2 to v0.9.0 (Proposal0026) - #22127
Conversation
…age to 100% Deploys a MainnetInbox whose basefeeSharingPctg is 100 instead of 75 and upgrades the mainnet inbox proxy to it: one upgradeTo from the DAO controller, no L2 leg, no initializer, immutables only. - MainnetInbox.sol: basefeeSharingPctg 75 -> 100. - LibL1Addrs.ZK_REQUIRED_VERIFIER: the live proof verifier (Proposal0019), so the deploy script reproduces the live immutables from the library. - DeployInboxUpgradeL1: reads the live proxy's getConfig() before broadcasting and aborts unless the new implementation differs from it only in the percentage. - Proposal0024: MAINNET_INBOX_NEW_IMPL is a placeholder until the implementation is deployed; the print mode reverts until then and no action file exists. - Tests pin the encoding, the placeholder phase, the full live configuration as literals, and rehearse the upgrade on a mainnet fork. - Runbook with a TODO for @dantaik on the rationale. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ementation MainnetInbox 0xA18431d42C8dF9778905fBEa912aCF1881b49D2e was deployed on 2026-09-12 in L1 block 25,961,745 by DeployInboxUpgradeL1, with LibForcedInclusion and LibInboxSetup linked (three creates, all with status 1). Its getConfig() equals the live proxy's except the sharing percentage, Etherscan verified it, and its creation code is reproduced byte for byte from this branch. - Proposal0024.MAINNET_INBOX_NEW_IMPL and the test's DEPLOYED_INBOX_IMPL literal are filled in; the placeholder-phase branches are gone. - Proposal0024.action.md generated with `P=0024 pnpm proposal` and pinned by test_actionFileMatchesTheBuiltCalldata; the L1 dry run reverts DryrunSucceeded(); the fork rehearsal executes the committed calldata against the deployed implementation and deploys nothing. - Runbook: deployment facts, addresses, codediff link, and a creation-code comparison in place of forge verify-bytecode, which refuses library-linked contracts. - Deploy script doc: three creates, not two. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…runbook Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… refresh fix Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ences Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… stack limit genesis-docker compiles test/layer1 under the via-IR layer1o profile and failed with "Variable size_1 is 1 too deep in the stack". The action loop in Proposal0024Fork.t.sol::_executeAs is identical to Proposal0023's, but it has a single caller, so the IR inliner folds it into the test, whose live variables push the loop's call temporaries and the concatenated assertion message one slot over the limit. The failure is now a custom error carrying the action index, which needs no string.concat or vm.toString temporaries; the layer1o build passes and the rehearsal still passes against live mainnet state. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Replace the rationale TODO with the case for moving the inbox basefee share from 75% to 100%, and make the runbook precise about where the non-coinbase share actually goes. - Name the two recipients exactly: the coinbase, which both drivers overwrite with the proposal's `proposer` at derivation, so it is always the whitelisted preconfer that proposed the block; and the Anchor contract, which holds its share as a plain ETH balance until the DAO sweeps it with `Anchor.withdraw` through the L2 delegate controller. The runbook previously called the Anchor "the L2 treasury" without saying that nothing forwards the balance anywhere. - State the argument as the asymmetry it is: at current L2 volume the 25% is immaterial to the DAO, while for a proposer it is a per-transaction loss on every sponsored transaction that makes fee sponsorship a business nobody would enter. - Record the two limits of the refund: it is exact only within a preconfer's own proposals, and it covers the L2 fee only. - Add a trade-offs section covering the forgone revenue and its reversibility, and the fact that a proposer's own L2 gas round-trips fully at 100 so L1 data cost becomes its only floor. - Note that the already-accrued Anchor balance is untouched and stays withdrawable. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UhqmeYDadT95CmcUhWzc2B
…100% Match `MainnetInbox` so local and devnet deployments behave like mainnet after Proposal0024 executes. `DevnetInbox` is not in `MainnetInbox`'s dependency tree and no deployed contract reads it; its only consumer is `DeployProtocolOnL1`. The taiko-client integration tests deploy through that script, and two of them asserted the treasury balance strictly grows, which only holds while the percentage is below 100. Derive the expectation from the inbox's own `basefeeSharingPctg` instead, so both tests are correct at any setting: at 100 the treasury gains nothing and the per-transaction reconciliation in `TestTreasuryIncome` still pins the split exactly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UhqmeYDadT95CmcUhWzc2B
`LibL1Addrs.ZK_REQUIRED_VERIFIER` became `ZKEVM_VERIFIER`, but two call sites still referenced the old name and no longer compiled: `DeployInboxUpgradeL1._checkLiveProxy` and the Proposal0024 test that builds `MainnetInbox` with the live address immutables. The address is unchanged. Also update the name in the Proposal0024 config table. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UhqmeYDadT95CmcUhWzc2B
Restore `LibL1Addrs.ZK_REQUIRED_VERIFIER` and its three call sites in `DeployInboxUpgradeL1`, the Proposal0024 test and the Proposal0024 config table. The address `0x7284aaC05555Ae6559bdAd8B4221eC9584254Eec` is unchanged, and the name now matches the deployed contract (`ZkRequiredVerifier`), Proposal0019's own constant and the L1 deployment log, so nothing in the tree still says `ZKEVM_VERIFIER`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UhqmeYDadT95CmcUhWzc2B
…UpgradeL1 `_checkLiveProxy` only rejected a live percentage already equal to the new value, so any other non-100 reading passed the guard — and `_checkConfig` cannot catch it either, because it normalises `basefeeSharingPctg` away before comparing the new implementation with the live one. The NatSpec and the Proposal0024 runbook both claimed the script aborts unless the live value is still 75, which was not what the code did. Add `OLD_BASEFEE_SHARING_PCTG = 75` and require the live proxy to equal it, after the existing `AlreadyUpgraded` check so a re-run following execution still reports itself rather than as a generic mismatch. Reported by the deepseek-review bot on the pull request. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UhqmeYDadT95CmcUhWzc2B
|
Went through the deepseek-review findings. Took the warning, declined both suggestions. Warning — The guard only rejected a live percentage already equal to Suggestion — named constants for 75 in the fork tests. Declining.
Suggestion — pin the fork block in This is the repo's existing convention rather than an oversight. Generated by Claude Code |
|
Second deepseek-review pass. Checked all four against the code; none needs a change, and one is factually wrong about what the script does. Warning 1 — "broadcasts before validating the full config", leaving an orphaned implementation. Not how
Warning 2 — library deployment is implicit. Correct, and deliberately left alone. Forge's implicit linked-library deployment is exactly what ran on 2026-09-12, and the runbook documents the resulting three creates with Suggestion 1 — split the address check from Suggestion 2 — Generated by Claude Code |
…onstants Add contracts/layer1/verifiers/LibSGXConstants.sol next to LibRisc0Constants and LibSP1Constants. It holds the raiko2 v0.8.0-rc1 and v0.9.0-rc1 SGX-geth and SGX-reth (non-EDMM and EDMM) MRENCLAVE values under version-prefixed names, and Proposal0026 now reads them from there instead of declaring its own OLD_/NEW_ constants. The values are unchanged: Proposal0026.action.md regenerates byte-identical. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review of Proposal0026 at Verified:
Open:
Nits:
Generated by Claude Code |
…al0026.md MainnetInbox_Layout.sol lists 17 storage entries, not 18. The file is byte-identical at 9078278, the PR head and main, so only the count in the runbook was wrong. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018jqMkXxqFDncNk8KyJhY99
v0.9.0 (Proposal0026)
#22178 moved Proposal0026 to the final raiko2 v0.9.0 identifiers but left the nine v0.9.0-rc1 constants in LibRisc0Constants, LibSP1Constants and LibSGXConstants. Nothing references them, and none was ever trusted on mainnet, so the libraries keep only the versions the proposal uses. The calldata in Proposal0026.action.md is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🐋 DeepSeek Code Review🟡 Warnings
🔵 Suggestions
🟢 What Looks Good
Automatically triggered on PR update • model: |
What
Proposal0026 is one atomic DAO batch of 21 L1 actions (no L2 leg), executed by the DAO controller
0x75Ba76403b13b26AD1beC70D6eE937314eeaCD0a. It does two things:basefeeSharingPctgfrom 75 to 100. Every L2 block in a proposal made after execution pays its whole basefee to the coinbase (the proposing preconfer). Nothing then accrues in the L2 fee treasury (the Anchor0x1670000000000000000000000000000000010001). The percentage is a constructor immutable, so this is anupgradeToon the inbox proxy to a newMainnetInboximplementation. That implementation is the live one with this single field changed: same five address immutables, same numeric config, same storage, no initializer.2) from both SGX verifiers. This part came in through feat(protocol): rotate raiko2 artifacts to v0.9.0-rc1 (Proposal0026) #22176.0x6f21C543a4aF5189eBdb0723827577e1EF57ef1fupgradeTo(0xA18431d42C8dF9778905fBEa912aCF1881b49D2e)(codediff)0x059dAF31F571da48Ab4e74Ae12F64f907681Cd8bsetImageIdTrusted: untrust 2 v0.8.0-rc1 image IDs, trust 2 v0.9.0-rc1 image IDs0x73A0Db393ef87ce781ac7957bE10D6628432100FsetProgramTrusted: untrust 4 v0.8.0-rc1 vkeys, trust 4 v0.9.0-rc1 vkeys (BN254 + hash-bytes, proposal + aggregation)0x0ffa4A625ED9DB32B70F99180FD00759fc3e9261, SGX-reth attester0x8d7C954960a36a7596d7eA4945dDf891967ca8A3setMrEnclave: untrust 3 v0.8.0-rc1 MRENCLAVEs, trust 3 v0.9.0-rc1 MRENCLAVEs (SGX-geth, SGX-reth, SGX-reth EDMM). MRSIGNER and attribute policy unchanged0x41e79EB4F03aBB5DF8716B759528dc5d8f6a84Ee, SGX-reth verifier0x9D3C595BFf6Ff7D2b2CbdEcF94aD917eB2fCFFd8deleteInstances([2]). v0.9.0-rc1 instances register separately after execution (expected ID3)The v0.9.0-rc1 values come from the release's
guest-digests-summary.jsonandtee-attestation-manifest-v0.9.0-rc1.json. The v0.8.0-rc1 values are the ones Proposal0021 enabled. The full tables and rationale are inProposal0026.md.Why 100%. At 75, a preconfer that sponsors its users' L2 gas loses a quarter of every basefee. At 100 the round trip is exact, so sponsoring costs only the L1 data. The DAO gives up the 25% the Anchor currently accrues; that amount is small and has never been swept. See Rationale in
Proposal0026.md.Code changes
MainnetInbox.sol:basefeeSharingPctg75 → 100. This is the source of the deployed implementation.DevnetInbox.sol: the same flip, so devnet and local deployments match mainnet. Because of it,packages/taiko-client/driver/chain_syncer/event/syncer_test.gonow derives the treasury-income expectation from the inbox'sbasefeeSharingPctg: at 100 the treasury gains nothing.LibL1Addrs.ZK_REQUIRED_VERIFIER = 0x7284aaC05555Ae6559bdAd8B4221eC9584254Eec: the live proof verifier. Until now it was only aProposal0019constant.LibRisc0Constants/LibSP1Constants: add the v0.9.0-rc1 IDs. The newLibSGXConstantsholds the v0.8.0-rc1 and v0.9.0-rc1 SGX MRENCLAVEs.script/layer1/mainnet/DeployInboxUpgradeL1.s.soldeploys the implementation only. It has already run and must not be re-run; it refuses once the proxy answers 100.Proposal0026.{s.sol,md,action.md},Proposal0026.t.sol,Proposal0026Fork.t.sol,Proposal0026Harness.sol, gas report.Deployed implementation
Deployed 2026-09-12 in L1 block 25,961,745 by
0x56706f118e42ae069f20c5636141b844d1324ae1, from source commit9deb5b590b4bf303ff161f0b8b14a49ab518a312. All three contracts are verified on Etherscan.MainnetInboximpl0xA18431d42C8dF9778905fBEa912aCF1881b49D2e0x16532ab9b11251324578fd2f1d42b0dac2986523a19771365cefd9f9af42b533LibInboxSetup(linked)0x526957d1a25E9D3F5ab5a4926d07eEE5d612ED420xbbf8ec0cee3151e09b6286e19d629d4e648de60d3b17824f939dc3ff6310ce40LibForcedInclusion(linked)0x511e1E5D9b9E23958076ccF1dD0033237a8cE4f80xf9a89d6ae2feff8a6f9f6339473fb51731eb621a6ade6052da8238b6302f3d1cConstructor args are the live immutables:
ZK_REQUIRED_VERIFIER,PRECONF_WHITELIST0xFD01…b2ac,PROVER_WHITELIST0xEa79…12Ae,SIGNAL_SERVICE0x9e0a…C77CandTAIKO_TOKEN0x10de…d800. The storage layout is unchanged from the live implementation0x5253D4C91e80b880DdB54B78E74082Abe066F6b9.Verification
Proposal0026.action.mdis whatP=0026 pnpm proposalgenerates, andtest_actionFileMatchesTheBuiltCalldatapins it.L1_FORK_URL=<archive rpc> FOUNDRY_PROFILE=layer1 forge test --match-contract Proposal0026ForkTest -vv.P=0026 pnpm proposal:dryrun:l1reverts withDryrunSucceeded().9deb5b5.Rollout
0x9CBeE534B5D8a6280e01a14844Ee8aF350399C7Fregisters the v0.9.0-rc1 SGX-geth and SGX-reth instances, which is a separate post-execution step. Until then,ZkRequiredVerifierstill accepts RISC0 + SP1.getConfig().basefeeSharingPctgat startup. Drivers and provers read the value from theProposedevent and need no change.🤖 Generated with Claude Code
https://claude.ai/code/session_018jqMkXxqFDncNk8KyJhY99