Overshoot Spardose fake balance by 1%#4362
Merged
squadgazzz merged 3 commits intomainfrom Apr 24, 2026
Merged
Conversation
Quote verification sizes the Spardose's fake balance from the trader's needed amount via `state_override`. On aTokens this sat exactly at the 1-wei boundary: if the sim's `getReserveNormalizedIncome` landed on a slightly different block than our pre-sim read, `balanceOf` rounded down to `amount - 1` and Aave's internal scaled-balance subtraction underflowed, surfacing as `trader does not have enough sell token`. Fix by giving the Spardose 1% more than requested. Spardose is a throwaway donor, overshoot has no cost, and the buffer absorbs any rounding or per-block accrual drift between our read and the sim's execution. Generic across tokens, not Aave-specific. Supersedes #4361.
Contributor
There was a problem hiding this comment.
Code Review
This pull request introduces a 1% buffer (minimum 1 wei) to the balance override amount for the 'spardose' donor in the trade verifier. This change, implemented via the new spardose_amount_with_buffer function, aims to prevent simulation failures caused by rounding or per-block accruals. The implementation includes saturating arithmetic to handle potential overflows and is supported by new unit tests. No critical issues were found, and I have no feedback to provide.
jmg-duarte
approved these changes
Apr 24, 2026
MartinquaXD
approved these changes
Apr 24, 2026
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Problem
Quote verification for small aToken sell amounts intermittently failed in prod with
execution reverted: trader does not have enough sell token: 0.1 aEthWETH quote failed, 1 aEthWETH quote minutes earlier passed.aToken does not store a balance directly. It stores a deposit and a growth factor, where
balanceOf() = deposit * growth_factor. The factor ticks up every second as interest accrues.Quote verification writes a fake deposit into the Spardose (our donor contract) so the sim can pretend the trader has funds. The old code sized the fake deposit from a pre-sim
getReserveNormalizedIncomeRPC read. The sim then re-read the growth factor inside the EVM at its own pinned block. Those two reads can disagree by one block, leaving the Spardose'sbalanceOfone wei belowamountwhen it tries to fund the trader. Aave's internal scaled-balance subtraction underflows, revert.The same kind of boundary issue could in principle hit other tokens (rebasing, tiny fee-on-transfer, future weird ones).
Fix
Bump the Spardose's fake balance by 1% before passing it to the override:
Spardose ends up slightly richer than the sim will ever transfer. Any rounding, accrual, or per-block drift is absorbed by the buffer. The Spardose is a throwaway donor, overshoot costs nothing: no gas difference, no side effects, only the trader-requested
amountactually moves.Generic by construction. Fixes aToken and covers any future token with similar near-boundary math.
Context
Supersedes #4361, which took an Aave-specific approach (scale against the stored
liquidityIndexinstead of the accrued one). Replaced with this generic overshoot per Martin's review.Changes
price-estimation/trade_verifier: 1% overshoot on the amount passed to the Spardose balance override.How to test
cargo test -p price-estimation trade_verifier. Existing tests pass plus the newspardose_amount_applies_1pct_overshoot.