Fix int256 overflow in token imbalances from spam transfer amounts - #380
Closed
data-cowwboy wants to merge 1 commit into
Closed
Fix int256 overflow in token imbalances from spam transfer amounts#380data-cowwboy wants to merge 1 commit into
data-cowwboy wants to merge 1 commit into
Conversation
A spam token on BNB emitted a fake Transfer event of 2^256 - 1 atoms to the settlement contract (tx 0xf06378e10b27ccc35de3c8c2ba53fc6da2a5c837d9be5b10a584ab24dfa8a710, 2026-08-22). Casting that amount to int256 overflows and makes the raw slippage query fail for any time window containing the event. Amounts of 2^255 and larger cannot come from real trades and are now ignored. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bram-vdberg
reviewed
Aug 24, 2026
| from "query_4021257(blockchain='{{blockchain}}',start_time='{{start_time}}',end_time='{{end_time}}')" | ||
| -- Spam tokens emit fake Transfer events with amounts of up to 2^256 - 1, which do not fit into | ||
| -- int256. Amounts of 2^255 and larger cannot come from real trades and are ignored. | ||
| where amount < uint256 '57896044618658097711785492504343953926634992332820282019728792003956564819968' --noqa: PRS, LT02 |
Contributor
There was a problem hiding this comment.
Why not use POWER(2, 255) instead?
Contributor
Author
There was a problem hiding this comment.
Tested it, power() is not safe here because it works in doubles:
power(2, 255)returns a double, soamount < power(2, 255)coerces the uint256 amount to double before comparing. Near 2^255 adjacent doubles are 2^202 apart, so the comparison is only approximate at the boundary (e.g.uint256 '2^255 - 1' < power(2, 255)evaluates to false even though that value fits int256).- The precise-looking variant
cast(power(2, 255) as uint256)actually evaluates to 578960446186581000...0, which is about 2.3e60 larger than the real 2^255. Amounts in that gap would pass the filter and still crash the int256 cast.
Verification of both: https://dune.com/queries/8427355
An exact alternative would be bitwise_left_shift(uint256 '1', 255) (verified bit-identical to the literal in https://dune.com/queries/8427357), but that seemed harder to read than the plain constant, so I kept the literal with the comment explaining it.
Contributor
|
Haven't read the PR but my first reaction would be the following. Wouldn't it be better if we just exclude that particular tx hash, so as to not silently fail on potential other instances of this? |
Contributor
|
Addressed by #381 |
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.
Problem
The raw slippage query (4059683) fails with
Overflow in INT256 cast of UINT256: 115792089237316...639935for any BNB time window containing 2026-08-22 (reported in Slack).Root cause: a spam token (
0xf0e8fc6211feb9a1ea9f94609c245bc39973e4d7on BNB) emitted a fakeTransferevent of 2^256 − 1 atoms to the settlement contract in tx0xf06378e10b27ccc35de3c8c2ba53fc6da2a5c837d9be5b10a584ab24dfa8a710— a direct EOA→token call, not a settlement; there is no corresponding row incow_protocol_bnb.trades. The token imbalances query (4021644) doescast(amount as int256)on every transfer amount, and max-uint256 does not fit into int256.Fix
Ignore transfer amounts ≥ 2^255 in the imbalances query. Such amounts cannot come from real trades (no token supply comes anywhere near 2^255), so this only drops spam events that would otherwise crash the query. Filtering is preferred over
try_cast, which would silently turn the amount into NULL inside thesum.Testing
Tested on Dune with copies of the production queries:
raw_slippage_per_transaction): original vs fixed produce identical tx sets (11,292), allslippage_weivalues identical,slippage_usddiffers only by float summation-order noise (max 2.8e-14).The two
noqa: PRSmarkers cover sqlfluff parse errors from the non-standardint256/uint256types (same convention as classified_fees_4058574.sql and balance_changes_4021257.sql);sqlfluff lintnow passes on the file, whereas it already failed onmainfor the pre-existingint256cast block.🤖 Generated with Claude Code