fix(statedb): revert precompileCallsCounter on journal revert#1094
Open
sucloudflare wants to merge 1 commit intocosmos:mainfrom
Open
fix(statedb): revert precompileCallsCounter on journal revert#1094sucloudflare wants to merge 1 commit intocosmos:mainfrom
sucloudflare wants to merge 1 commit intocosmos:mainfrom
Conversation
5a6299f to
04aabad
Compare
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.
fix: revert
precompileCallsCounteron journal revertProblem
When a precompile call is reverted (e.g. via
RevertToSnapshot), theprecompileCallsCounterinStateDBis not decremented. Because the counter is only incremented on entry and never rolled back on revert, an attacker can craft a transaction that deliberately triggers and reverts precompile calls in a tight loop, driving the counter up to the per-tx limit without any of those calls actually succeeding.Once the limit is hit, all subsequent legitimate precompile calls within the same transaction fail unconditionally. This is a deterministic, transaction-level griefing vector that breaks any contract that relies on precompiles after an internal revert.
Affected file:
x/vm/statedb/journal.go—precompileCallChange.RevertMinimal reproduction (Solidity pseudo-code)
Fix
Decrement
precompileCallsCounterinsideprecompileCallChange.Revertso that a reverted call gives back its slot.This mirrors the invariant maintained by other journal entries (e.g. balance changes), where every mutation recorded in the journal is fully undone on revert.
Tests
Two new unit tests are added in
x/vm/statedb/journal_counter_revert_test.go:TestPrecompileCallsCounterRevertedOnRevert— asserts that a single reverted precompile call decrements the counter.TestAttackerCannotExhaustPrecompileLimitViaReverts— asserts that revertingNcalls in a loop leaves the counter at 0, so the next valid call is still allowed.Impact / Severity rationale
Although this is not a chain-wide DoS, the impact is concrete:
We believe Low–Medium severity is appropriate: the exploit is reliable and breaks expected execution flow for affected contracts, even though it is confined to a single transaction.
Checklist
Revertis modifiedCHANGELOG
fix: revert
precompileCallsCounteron journal revertProblem
When a precompile call is reverted (e.g. via
RevertToSnapshot), theprecompileCallsCounterinStateDBis not decremented. Because the counter is only incremented on entry and never rolled back on revert, an attacker can craft a transaction that deliberately triggers and reverts precompile calls in a tight loop, driving the counter up to the per-tx limit without any of those calls actually succeeding.Once the limit is hit, all subsequent legitimate precompile calls within the same transaction fail unconditionally. This is a deterministic, transaction-level griefing vector that breaks any contract that relies on precompiles after an internal revert.
Affected file:
x/vm/statedb/journal.go—precompileCallChange.RevertMinimal reproduction (Solidity pseudo-code)
Fix
Decrement
precompileCallsCounterinsideprecompileCallChange.Revertso that a reverted call gives back its slot.This mirrors the invariant maintained by other journal entries (e.g. balance changes), where every mutation recorded in the journal is fully undone on revert.
Tests
Two new unit tests are added in
x/vm/statedb/journal_counter_revert_test.go:TestPrecompileCallsCounterRevertedOnRevert— asserts that a single reverted precompile call decrements the counter.TestAttackerCannotExhaustPrecompileLimitViaReverts— asserts that revertingNcalls in a loop leaves the counter at 0, so the next valid call is still allowed.Impact / Severity rationale
Although this is not a chain-wide DoS, the impact is concrete:
We believe Low–Medium severity is appropriate: the exploit is reliable and breaks expected execution flow for affected contracts, even though it is confined to a single transaction.
Checklist
Revertis modifiedCHANGELOG