Skip to content

Fix address distro bug#3716

Merged
codchen merged 5 commits into
mainfrom
claude/nifty-jepsen-d36530
Jul 15, 2026
Merged

Fix address distro bug#3716
codchen merged 5 commits into
mainfrom
claude/nifty-jepsen-d36530

Conversation

@codchen

@codchen codchen commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

codchen added a commit that referenced this pull request Jul 7, 2026
…t fix (#3716)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedJul 13, 2026, 3:27 AM

@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 66.07143% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 58.36%. Comparing base (4d7769c) to head (e72abc7).
⚠️ Report is 21 commits behind head on main.

Files with missing lines Patch % Lines
utils/helpers/address.go 50.00% 7 Missing and 6 partials ⚠️
app/app.go 71.42% 2 Missing ⚠️
sei-cosmos/x/distribution/keeper/hooks.go 71.42% 1 Missing and 1 partial ⚠️
x/evm/ante/preprocess.go 87.50% 1 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            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     
Flag Coverage Δ
sei-chain-pr 55.63% <66.07%> (?)
sei-db 70.41% <ø> (-0.22%) ⬇️
sei-db-state-db ?

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
app/app.go 67.62% <71.42%> (-3.55%) ⬇️
sei-cosmos/x/distribution/keeper/hooks.go 91.48% <71.42%> (+1.01%) ⬆️
x/evm/ante/preprocess.go 80.87% <87.50%> (+0.63%) ⬆️
utils/helpers/address.go 81.15% <50.00%> (-18.85%) ⬇️

... and 90 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codchen codchen changed the title fix(distribution): don't halt on unreceivable validator commission recipient fix(distribution): fee recipient issue Jul 7, 2026
@codchen codchen changed the title fix(distribution): fee recipient issue fix(evm): associate EIP-7702 authorities to true Sei address; backstop distribution halt Jul 7, 2026
@masih masih changed the title fix(evm): associate EIP-7702 authorities to true Sei address; backstop distribution halt fux address distro bug Jul 7, 2026
@masih masih changed the title fux address distro bug Fix address distro bug Jul 7, 2026
@masih
masih force-pushed the claude/nifty-jepsen-d36530 branch from d630529 to 156eae4 Compare July 7, 2026 10:37
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codchen
codchen marked this pull request as ready for review July 10, 2026 03:18
@cursor

cursor Bot commented Jul 10, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Touches EIP-7702 association semantics, ante preprocessing, Giga/V2 routing, and EndBlock distribution hooks—areas that can affect consensus behavior and chain liveness if misapplied.

Overview
Fixes a class of bugs where EIP-7702 SetCode could leave EVM→Sei mappings on mutable direct-cast identities, so a later associatePubKey could remap addresses and orphan staking/distribution state (including chain halts on validator removal).

Pre-association before SetCode: New helpers recover EIP-7702 authorization signers and decide which authorities need association via AuthorityToPreAssociate (mirrors go-ethereum’s validateAuthorization, including wrong-chain replay protection). The EVM preprocess ante path associates each applicable authority to its pubkey-derived Sei address before execution. The Giga executor defers SetCode txs that still need that association to V2 (same as balance-migration fallback).

Distribution hardening: AfterValidatorRemoved no longer panics when commission payout targets an unreceivable withdraw/operator address (e.g. after EVM re-association); unpaid commission is credited to the community pool instead.

Reviewed by Cursor Bugbot for commit e72abc7. Bugbot is set up for automated code reviews on this repo. Configure here.

@seidroid seidroid Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 setCodeTxRequiresAuthorityAssociation recovers the authority via RecoverAddressesFromAuthorization but (unlike the ante handler) does not cross-check auth.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.

Comment thread x/evm/ante/preprocess.go Outdated
}
ethTx := ethtypes.NewTx(setCodeTx.AsEthereumData())
for _, auth := range ethTx.SetCodeAuthorizations() {
evmAddr, seiAddr, pubkey, err := helpers.RecoverAddressesFromAuthorization(auth)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[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.

Comment thread x/evm/ante/preprocess.go
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>

@seidroid seidroid Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 — new RecoverAddressesFromAuthorization and AuthorityToPreAssociate (the latter mirrors go-ethereum's validateAuthorization).
  • 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.

@codchen
codchen added this pull request to the merge queue Jul 15, 2026
Merged via the queue into main with commit 2a3e97e Jul 15, 2026
68 checks passed
@codchen
codchen deleted the claude/nifty-jepsen-d36530 branch July 15, 2026 03:23
yzang2019 added a commit that referenced this pull request Jul 15, 2026
* 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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants