apollo_consensus_orchestrator: anchor L1 gas-price margin to local reference and harden overflow#14589
Open
asaf-sw wants to merge 1 commit into
Open
apollo_consensus_orchestrator: anchor L1 gas-price margin to local reference and harden overflow#14589asaf-sw wants to merge 1 commit into
asaf-sw wants to merge 1 commit into
Conversation
Contributor
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
…ference and harden overflow within_margin anchored the tolerance band to the proposer-supplied price (number1), so the accepted band scaled with attacker input: a proposer could inflate the L1 gas price up to ~1.111x the local reference instead of the intended 1.10x (M-17). The same line also did an unchecked u128 * u128 that can overflow on large WEI prices. Anchor the band to the locally-trusted reference and use saturating_mul. The accepted band is now the symmetric [reference*(1-m), reference*(1+m)]. Parameters renamed to proposed/reference to make the trusted argument unambiguous; call sites already pass (proposed, reference) so no call-site change is needed. Adds regression cases including the inflated-proposal exploit (1111 vs 1000 at 10% must be rejected), boundary-inclusive cases, and overflow-hardening cases with u128::MAX. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
241b4cb to
e12b551
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.

What
Fixes M-17. Rewrites
within_margininvalidate_proposal.rsso the L1 gas-price tolerance band is anchored to the validator's locally-trusted reference price instead of the proposer-supplied value, and replaces an uncheckedu128 * u128withsaturating_mul.Why
is_proposal_init_validvalidates proposer-supplied L1 gas prices against the node's own oracle read viawithin_margin(proposed, reference, margin_percent). The margin was computed as(proposed * margin_percent) / 100— anchored to the attacker-controlled value.proposed, a malicious proposer could inflate the price up to ~reference / (1 - m)≈1.111 * referenceat the default 10% margin, instead of the intended1.10 * reference. PoC:proposed=1111,reference=1000,m=10was accepted (margin = 1111*10/100 = 111,diff = 111) even though 1111 exceeds the intended 1100 ceiling. The extra ~1.1% propagates into user fees on every block the attacker proposes, and stacks with M-1.u128 * u128. Large WEI prices can makeprice * margin_percentexceedu128::MAX, panicking in debug / wrapping in release.Fix
reference(reference.0.saturating_mul(margin_percent) / 100). The accepted band becomes the symmetric[reference*(1-m), reference*(1+m)].saturating_mulremoves the overflow panic on large legitimate prices.number1/number2→proposed/referenceso the trusted argument is unambiguous in the signature (the footgun that produced the bug). Call sites already pass(proposed, reference), so no call-site change was required.Assumptions
Test coverage
Extended
test_within_marginand added a dedicated overflow test:inflated_proposed_rejected(1111, 1000, 10, false)— the M-17 exploit; verified it FAILS on the pre-fix code and passes after.upper_bound_inclusive/lower_bound_inclusive(1100 and 900 vs 1000 at 10%).deflated_proposed_rejected(889, 1000, 10, false)— symmetry.large_identical_no_overflow/large_within_no_overflow(u128::MAX) andwithin_margin_large_reference_does_not_overflow— overflow hardening.All 17 tests pass; clippy clean.
Internal analysis:
docs/security-review/M-17.md.🤖 Generated with Claude Code