fix(hardfork): regenerate Zeta StakePool bytecode for PR #73#338
Merged
nekomoto911 merged 2 commits intogravity-testnet-v1.5from Apr 27, 2026
Merged
fix(hardfork): regenerate Zeta StakePool bytecode for PR #73#338nekomoto911 merged 2 commits intogravity-testnet-v1.5from
nekomoto911 merged 2 commits intogravity-testnet-v1.5from
Conversation
The Zeta hardfork was including bytecodes/gamma/stakepool.bin for every existing pool with the rationale that PR #73 added "no new immutables" so the Gamma template was still correct. That conflated two orthogonal concerns: immutable layout (which controls per-instance patching) is unrelated to whether the runtime bytecode template itself changed. PR #73 (#73 in gravity-chain-core-contracts) replaces the role-change surface on StakePool: removed: setStaker / setOperator / setVoter added: proposeStaker / acceptStaker / cancelStakerChange proposeOperator / acceptOperator / cancelOperatorChange proposeVoter / acceptVoter / cancelVoterChange setStakerChangeDelay / setOperatorChangeDelay / setVoterChangeDelay MIN_ROLE_CHANGE_DELAY (constant) Both the dispatcher selector table and the code section change. With the Gamma template, the upgrade is effectively a no-op: each pool's bytecode is "replaced" with what it already runs, the new ABI is missing on chain, the deprecated immediate setters remain callable, and the timelock is inert. scripts/verify_hardfork/hardforks/zeta.sh would fail at every PR #73 assertion (proposeStaker / acceptStaker / MIN_ROLE_CHANGE_DELAY / *ChangeDelay views). Fix: - Regenerate bytecodes/zeta/StakePool.bin from the v1.5 contract artifact (out/StakePool.sol/StakePool.json, deployedBytecode.object, 9223 bytes) with the FACTORY immutable patched at the two immutableReferences offsets (3061 and 5098) to the Staking system address (0x...01625F2000). All four pools share the same FACTORY (singleton Staking), so a single template applies to every entry in STAKEPOOL_ADDRESSES — same pattern as Gamma and Beta. - Point STAKEPOOL_BYTECODE in zeta.rs at the new bin and rewrite the misleading comment to spell out the dispatcher / code-section change. Verified empirically against the new bin: dispatcher contains the proposeStaker / acceptStaker / MIN_ROLE_CHANGE_DELAY selectors and no longer contains setStaker.
nekomoto911
approved these changes
Apr 27, 2026
Pre-existing on `gravity-testnet-v1.5` but surfaced by lint CI on this
PR (the previous Zeta merge slipped past with broken fmt/clippy):
- doc_markdown: backtick `StakePool` in the ZETA_EXTRA_UPGRADES doc
comment.
- rustfmt: collapse multi-line `B256::new(hex_to_bytes32("…"))` calls in
ALLOWED_POOLS_SLOTS into single lines, and rewrap module-level doc
comments (`use_small_heuristics = "Max"`, `comment_width = 100`).
No semantic changes. `cargo fmt --all --check` and
`cargo clippy --lib --tests --benches -p reth-evm-ethereum --all-features
--locked` now pass under nightly-2026-02-01 (the CI toolchain).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
bytecodes/gamma/stakepool.binfor every pool, justified by a comment that "PR feat(pipe): modifyPipeExecLayerApito adapt to gravity sdk #73 added no new immutables so the Gamma template still works." That reasoning is wrong: immutable layout governs per-instance patching, not whether the runtime template changed.PipeExecLayerApito adapt to gravity sdk #73 (gravity-chain-core-contracts feat(pipe): modifyPipeExecLayerApito adapt to gravity sdk #73) removessetStaker / setOperator / setVoterand adds the propose/accept/cancel + per-role-delay surface plusMIN_ROLE_CHANGE_DELAY. Both the dispatcher selector table and the code section change, so the Gamma template no-ops the upgrade.bytecodes/zeta/StakePool.binfrom the v1.5 contract artifact with the FACTORY immutable patched, and pointSTAKEPOOL_BYTECODEinzeta.rsat it.What would have broken on testnet without this fix
With the Gamma template applied, on every existing pool:
proposeStaker / acceptStaker / cancelStakerChange / proposeOperator / proposeVoter / *ChangeDelay() / MIN_ROLE_CHANGE_DELAY()would not exist on chain.setStaker / setOperator / setVoter) would still be callable, leaving the timelock inert.scripts/verify_hardfork/hardforks/zeta.shwould fail at every PR feat(pipe): modifyPipeExecLayerApito adapt to gravity sdk #73 assertion in the StakePool block.How the bytecode was regenerated
out/StakePool.sol/StakePool.json(deployedBytecode.object, 9223 bytes) compiled fromgravity-chain-core-contractsgravity-testnet-v1.5(commitc112da2,fix(staking): 2-step timelock for StakePool role changes).immutableReferenceshas a single entry (67435=FACTORY) at offsets3061and5098, length 32 each. Both are zero placeholders in the fresh artifact and get patched with the Staking system address (0x00000000000000000000000000000001625F2000) left-padded to a 32-byte word.STAKEPOOL_ADDRESSESshare the sameFACTORY(singletonStaking), so one template applies to every pool — same pattern as Gamma and Beta.Empirical verification
Selector check against the new bin (PUSH4 pattern
63XXXXXXXX):proposeStaker(address)06bec93aacceptStaker()2315c946MIN_ROLE_CHANGE_DELAY()d49be641setStaker(address)a29a43bbcargo check -p reth-evm-ethereumpasses.Reflection — why the original mistake happened
FACTORYis still the only immutable) but irrelevant: any added/removed external function changes the dispatcher and code section regardless of immutables. The argument needed to be "no selectors added/removed and no opcode changes" — which PR feat(pipe): modifyPipeExecLayerApito adapt to gravity sdk #73 obviously violates.bytecodes/zeta/StakePool.bin. The Zeta bundle was assembled from whatever bins the contracts repo produced. StakePool was missing. Instead of pushing back, the reth side rationalized using the Gamma bin. The right move would have been to regenerate the artifact (this PR does that).gravity-chain-core-contractsat the pinned commit and diffs againstbytecodes/<hardfork>/*.bin) would have surfaced this immediately.verify_hardfork/zeta.shwould have caught this on a real upgrade rehearsal, but it runs against a live RPC after activation. There is no equivalent assertion at the reth crate level (e.g., a unit test that searches for the PR feat(pipe): modifyPipeExecLayerApito adapt to gravity sdk #73 selectors insideSTAKEPOOL_BYTECODE). A trivial test likeassert!(STAKEPOOL_BYTECODE.windows(5).any(|w| w == [0x63, 0x06, 0xbe, 0xc9, 0x3a]))(proposeStaker push4) would have made this a compile-time /cargo testfailure. Worth a follow-up.Test plan
cargo check -p reth-evm-ethereum(done locally)cargo test -p reth-evm-ethereumagainst this branchscripts/verify_hardfork/verify.sh zeta <rpc>after activation and confirm the StakePool block inzeta.shpasses (MIN_ROLE_CHANGE_DELAY == 86400,proposeStaker / acceptStaker / cancelStakerChange / proposeOperator / proposeVoterall present,stakerChangeDelay / operatorChangeDelay / voterChangeDelayall readable, FACTORY view returns the Staking address).cast code <pool>after activation has codehash equal tokeccak256(bytecodes/zeta/StakePool.bin).Follow-up suggestions (not in this PR)
cargo testthat asserts the presence/absence of a few selectors perSTAKEPOOL_BYTECODEper hardfork (cheap regression guard).xtask) that recompiles the contracts repo at the pinned commit and diffs against the bundled bins.