Calculated from recorded token losses using historical USD prices at the incident time.
0x4281343f5869e1dc03265b2db628f012c98913c9b80c420e10f517ebb317f98a0x80012bf784b83baaf28f5549a9f233cae5f70be7afcd8f594dc757d431ed93c40x62e6b906bb5aafdc57c72cd13e20a18d2de3a4a757cd2f24fde6003ce5c9f2c60xdfdcdbc789b56f99b0d0692d14dbc61906d9deedBlast0x92f32553cc465583d432846955198f0ddcbcafa1BlastOn Blast, an unprivileged attacker bought a small SSS position, repeatedly called transfer(attacker, amount) against the SSS token at 0xdfdcdbc789b56f99b0d0692d14dbc61906d9deed, and used the resulting inflated balance to drain the public Thruster SSS/WETH pair at 0x92f32553cc465583d432846955198f0ddcbcafa1. The attack realized 1310.040494988573740722 WETH of proceeds, which were withdrawn to attacker recipient 0x786c8f95c17bb990a040dc4d6539b01fc1b72842.
The root cause is a balance-accounting bug in SSS::_update: when from == to, the function first debits _balances[from] and then overwrites the same storage slot with a value computed from the pre-transfer balance plus the transfer amount. Instead of leaving the balance unchanged on a self-transfer, the token increases the sender balance and lets any holder mint spendable SSS without minting new total supply.
SSS is a custom ERC20 that overrides OpenZeppelin transfer accounting with tax, anti-bot, and transaction-limit logic. The relevant market was the public Thruster router at 0x98994a9a7a2570367554589189dc9772241650f6 and the SSS/WETH pair at 0x92f32553cc465583d432846955198f0ddcbcafa1.
The exploit required no privileged role, no flash loan, and no private order flow. Any address that could buy or otherwise obtain a positive SSS balance could trigger the bug by sending SSS to itself and then sell the inflated balance into the public pool, subject only to the token's per-transaction sell cap.
0xac3400e3d536ac23c10fdd2c06e1faf8d5de5b797df8433e9b5ab74b102a4e35The incident is an ATTACK-class ACT opportunity caused by incorrect ERC20 state updates on self-transfer. In a correct ERC20 implementation, transferring tokens from an account to itself must not increase that account's balance. SSS breaks that invariant in its custom _update path by computing the recipient balance from the old balance before it writes the sender debit. Because both writes target the same storage slot when from == to, the recipient write wins and leaves the account with fromBalanceBeforeTransfer + amountAfterTax.
The vulnerable code path is visible in the collected SSS source:
function _update(address from, address to, uint256 amount) internal override virtual {
uint256 fromBalanceBeforeTransfer = _preCheck(from, to, amount);
uint256 amountAfterTax = amount - _taxApply(from, to, amount);
uint256 toBalance = _postCheck(from, to, amountAfterTax);
_balances[from] = fromBalanceBeforeTransfer - amount;
_balances[to] = toBalance;
}
For self-transfer, _taxApply returns zero because the transfer is neither a buy nor a sell, _postCheck computes toBalance = _balances[to] + amount, and the second assignment overwrites the first. Repeating the operation geometrically expands the attacker's SSS balance until it is large enough to extract WETH from the pool in successive capped sells.
The ACT opportunity exists in Blast pre-state sigma_B at block 1111414, immediately before tx 0x80012bf784b83baaf28f5549a9f233cae5f70be7afcd8f594dc757d431ed93c4. At that point, SSS and the Thruster pair are already deployed and liquid, and the attacker helper already holds an initial SSS seed balance obtained from the preceding buy.
The exploit sequence is:
0x4281343f5869e1dc03265b2db628f012c98913c9b80c420e10f517ebb317f98a: buy a positive SSS balance through the public Thruster router.0x80012bf784b83baaf28f5549a9f233cae5f70be7afcd8f594dc757d431ed93c4: repeatedly self-transfer SSS to inflate the helper balance.0x62e6b906bb5aafdc57c72cd13e20a18d2de3a4a757cd2f24fde6003ce5c9f2c6: sell the inflated SSS back into the public SSS/WETH pair in max-size chunks.0xac3400e3d536ac23c10fdd2c06e1faf8d5de5b797df8433e9b5ab74b102a4e35: withdraw WETH proceeds from the helper to the profit address.The code-level breakpoint is the aliased storage write inside _update. The invariant is: for any transfer where sender and recipient are the same address, user balances must not increase absent an intentional mint. SSS violates that invariant because it separately computes debit and credit from the pre-transfer state and then writes both values into the same mapping slot.
Collected on-chain evidence confirms the monetization step. The balance diff for the sell transaction shows the pair losing WETH and the helper gaining it:
{
"token": "0x4300000000000000000000000000000000000004",
"holder": "0x92f32553cc465583d432846955198f0ddcbcafa1",
"before": "1337311470863",
"after": "29782190460",
"delta": "-1307529280403"
}
{
"token": "0x4300000000000000000000000000000000000004",
"holder": "0xded85d83bf06069c0bd5aa792234b5015d5410a9",
"before": "0",
"after": "1307529280403",
"delta": "1307529280403"
}
The validator-reviewed PoC trace independently reproduces the inflation primitive: after buying SSS on a fork at block 1111414, each self-transfer doubles the attacker's SSS balance and later drains WETH from the pair. That behavior is consistent with the source-level breakpoint above and confirms the exploit is deterministic, permissionless, and reproducible from public state.
The adversary cluster identified in the analysis consists of:
0x6a89a8c67b5066d59bf4d81d59f70c3976facd0a, which funded and sent the exploit transactions.0xded85d83bf06069c0bd5aa792234b5015d5410a9, which held SSS, executed the inflation loop, sold into Thruster, and held interim WETH proceeds.0x786c8f95c17bb990a040dc4d6539b01fc1b72842, which received the final WETH withdrawal.The operational flow is straightforward. First, the attacker acquires a seed SSS position from the public market. Second, the attacker uses self-transfers on SSS to expand its balance without needing any special contract callback or privileged function. Third, the attacker sells the inflated balance in repeated chunks sized to fit maxAmountPerTx, converting fake SSS into real WETH from the pair reserve. Finally, the attacker withdraws the WETH proceeds to a recipient EOA.
The validator-reviewed PoC shows the same structure in simplified form:
_buySeedPosition();
_inflateBalance();
sss.approve(ROUTER, type(uint256).max);
_dumpInflatedBalance();
assertLt(weth.balanceOf(PAIR), pairWethBefore);
assertGt(weth.balanceOf(attacker), 100 ether);
This is the same end-to-end ACT path described in root_cause.json: public acquisition, permissionless balance inflation, public pool drain, and profit realization.
The measurable loss recorded in the analysis is 1310040494988573740722 raw WETH units, or 1310.040494988573740722 WETH, drained from the public SSS/WETH pair. The exploit also breaks a core ERC20 accounting invariant because user balances can increase without a mint and without a corresponding decrease elsewhere.
Affected public components are:
0xdfdcdbc789b56f99b0d0692d14dbc61906d9deed0x92f32553cc465583d432846955198f0ddcbcafa1_update implementation: 0xdfdcdbc789b56f99b0d0692d14dbc61906d9deed0x62e6b906bb5aafdc57c72cd13e20a18d2de3a4a757cd2f24fde6003ce5c9f2c60x4281343f5869e1dc03265b2db628f012c98913c9b80c420e10f517ebb317f98a0x80012bf784b83baaf28f5549a9f233cae5f70be7afcd8f594dc757d431ed93c40x62e6b906bb5aafdc57c72cd13e20a18d2de3a4a757cd2f24fde6003ce5c9f2c60xac3400e3d536ac23c10fdd2c06e1faf8d5de5b797df8433e9b5ab74b102a4e35