Fix address distro bug#3716
Conversation
…t fix (#3716) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #3716 +/- ##
==========================================
- Coverage 59.32% 58.36% -0.96%
==========================================
Files 2274 2188 -86
Lines 188703 179345 -9358
==========================================
- Hits 111939 104667 -7272
+ Misses 66691 65379 -1312
+ Partials 10073 9299 -774
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
d630529 to
156eae4
Compare
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PR SummaryHigh Risk Overview Pre-association before SetCode: New helpers recover EIP-7702 authorization signers and decide which authorities need association via Distribution hardening: Reviewed by Cursor Bugbot for commit e72abc7. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
A well-scoped, well-tested fix for an EIP-7702 address-association bug: it pre-associates SetCode authorization authorities to their true pubkey-derived Sei address (in the V2 ante handler), defers such txs off the giga executor, and hardens the distribution validator-removal hook to route commission to the community pool instead of panicking in EndBlock. No blocking issues found; a couple of non-blocking notes below.
Findings: 0 blocking | 4 non-blocking | 1 posted inline
Blockers
- None at the file/PR level.
Non-blocking
- Cursor's second-opinion review (cursor-review.md) was empty — that pass produced no output.
- The giga guard
setCodeTxRequiresAuthorityAssociationrecovers the authority viaRecoverAddressesFromAuthorizationbut (unlike the ante handler) does not cross-checkauth.Authority(). This is safe today because the two are proven equivalent by tests, but note the minor asymmetry: an authorization with an invalid signature that recovers without error could cause an unnecessary deferral to V2 (a perf cost, not a correctness issue, since V2's ante and EVM both skip invalid authorizations). - Consider adding an end-to-end/integration test exercising the full staking→associatePubKey→validator-removal scenario that motivated the fix (the current tests cover the units well, but the original chain-halt path is only exercised in isolation via the distribution hook test).
- 1 suggestion(s)/nit(s) flagged inline on specific lines.
| } | ||
| ethTx := ethtypes.NewTx(setCodeTx.AsEthereumData()) | ||
| for _, auth := range ethTx.SetCodeAuthorizations() { | ||
| evmAddr, seiAddr, pubkey, err := helpers.RecoverAddressesFromAuthorization(auth) |
There was a problem hiding this comment.
[suggestion] Codex flagged (as High) that this associates every recoverable authorization without checking EIP-7702 applicability (chainID / authority nonce / existing code), so a replayed authorization could trigger association even when EVM execution skips it. I'd downgrade this from a blocker: the association target is derived purely from the signature, so it always maps the authority's EVM address to its own true pubkey-derived Sei address, and MigrateBalance only moves the victim's own funds between two addresses they control — there is no wrong-address or theft vector, and the resulting state equals the association the victim would get on their first Sei tx anyway. Associating broadly (even for authorizations the EVM will skip) is arguably the safer choice here since it guarantees no mutable direct-cast mapping is ever created. Worth a comment noting this is intentional, but not a correctness/security bug.
Mirror go-ethereum's authorization validity checks (chain id, nonce, and account state) in a shared helper so authority pre-association only runs for authorizations the EVM will actually apply. Applied on both the ante and giga paths, with tests covering the non-local chain id case. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
A well-scoped, well-tested fix for an EIP-7702 authority-association bug: authorities are pre-associated to their true pubkey-derived Sei address (with a correct guard against cross-chain authorization replay), the giga executor defers such txs to V2, and the distribution validator-removal hook routes commission to the community pool instead of panicking when the recipient can't receive. No blocking issues found.
Findings: 0 blocking | 3 non-blocking | 0 posted inline
Blockers
- None at the file/PR level.
Non-blocking
- Cursor review (./cursor-review.md) and the repo's REVIEW_GUIDELINES.md are both empty, so no second-opinion signal from Cursor and no repo-specific standards were available; Codex reported no issues but noted its focused tests could not run because the sandbox Go module cache was read-only, so treat the external passes as low-signal.
- The giga-path guard now RLP-encodes and ECDSA-recovers every authorization on each SetCode tx before execution. This is correct and bounded, but adds per-tx signature-recovery cost on the hot path for SetCode txs that will proceed; acceptable given SetCode tx frequency, just worth being aware of.
- Consider a test covering the self-sponsored case where the authorization authority equals the outer tx sender: because pre-association runs before the EVM increments the sender nonce, GetNonce(evmAddr) != auth.Nonce and AuthorityToPreAssociate returns false — this is fine since the sender is already associated via the normal sender path, but an explicit test would pin that behavior.
There was a problem hiding this comment.
The chain-ID (and nonce/code/account-nonce) validation I flagged in my prior review is now in place in AuthorityToPreAssociate and covered by TestPreprocessSkipsForeignChainSetCodeAuthority — the specific replay concern is resolved. I still don't feel comfortable shadow-approving: this PR is app-hash-breaking, touches EIP-7702 ante semantics, Giga↔V2 routing, and the EndBlock distribution hook, so a human review is warranted for the consensus-critical surface area.
Extended reasoning...
Overview
The PR fixes a class of address-association bugs around EIP-7702 SetCode plus a chain-halt risk in the distribution AfterValidatorRemoved hook:
utils/helpers/address.go— newRecoverAddressesFromAuthorizationandAuthorityToPreAssociate(the latter mirrors go-ethereum'svalidateAuthorization).x/evm/ante/preprocess.go— pre-associates 7702 authorities to their pubkey-derived Sei address before EVM execution.app/app.go— Giga executor defers SetCode txs that still need authority pre-association to V2 (parallels the balance-migration deferral).sei-cosmos/x/distribution/keeper/hooks.go— routes unpayable commission to the community pool instead of panicking in EndBlock.- New tests for each surface, including a foreign-chain-authorization negative test.
Security risks
The main historical risk on this PR (replaying a public cross-chain 7702 authorization to force-associate a victim) was raised in my prior review and is now closed by the chain-ID/nonce/code/account-nonce checks in AuthorityToPreAssociate. The bug hunter found no new issues this run, and I did not spot others in reading the fix. Residual questions I'd want a human to look at: (a) whether every code path that could add EVM->Sei mappings during a SetCode tx is covered by the pre-association or the Giga deferral, and (b) whether the community-pool routing in AfterValidatorRemoved interacts correctly with any downstream commission-accounting invariants.
Level of scrutiny
High. The changes are consensus-critical (app-hash-breaking label), span the ante handler, Giga executor, and a Cosmos SDK module hook, and modify EndBlock behavior on validator removal. Even though the individual diffs are small and the tests are targeted, a human familiar with the Giga/V2 routing and the distribution module invariants should sign off.
Other factors
- My prior review flagged a concrete critical bug that has been directly addressed by commit
e72abc7, with a dedicated regression test. - Codecov shows patch coverage at 64%, with the new code paths covered by targeted tests.
- The Cursor bugbot summary aligns with my read of the change surface.
- The seidroid[bot] suggestion to downgrade the chain-ID concern is superseded by the fact that the fix was applied — the safer position (mirror go-ethereum's validateAuthorization) is now in the code.
* main: fix(evm): bound store-cache depth amplification from stacked EVM snapshots (#3713) Fix address distro bug (#3716) fix(giga): route EVM validation failures to v2 fallback (CON-368) (#3753) feat(seidb): composite + replay digest modes and migration-boundary omission for evm-logical-digest (#3711) feat(scripts): add SC read-path RPC probe (consistency check + load) (#3751) fix(feegrant): bound DenomsSubsetOf cost and cap allowance denoms (#3710)
No description provided.