On May 17, 2026 at 2026-05-17T16:11:19Z, an attacker on Arbitrum used an Aave flashLoanSimple of 3,300 USDT to run 12 flash-loan-funded SEA settlement cycles through 0xa70f31c06f921019237fc00b1417217dae5c37c5. Each cycle deposited fixed USDT lots into the settlement adapter, redeemed a disproportionately large SEA amount through the adapter’s round logic, and sold the redeemed SEA back through the SEA/USDT pair. funds_flow.json shows the attacker EOA 0x352173fabf0e67e1cb1fcdf15474d0477d5d3674 ending the transaction with 13,904.941068 USDT, while the SEA/USDT pair 0xeeb9c6b73a9ba397fbea320d9e4cce7b8ac10513 lost 13,906.591068 USDT net and accumulated 129,202,760.357336 SEA.

Root Cause

Vulnerable Contract

SEA Settlement Adapter proxy 0xa70f31c06f921019237fc00b1417217dae5c37c5

  • Proxy: yes
  • Implementation used in this transaction: 0x13dde273b66323686bfb96cce5a2a7190b40b264
  • Source type: recovered only, confidence: low

The verified SEA token implementation is not the root cause. The verified source at SEATokenUpgradeable.sol is a fixed-supply ERC20 with one-time minting and pause or whitelist controls only. The pair implementation recovered at 0x00cf80e8... is a standard Uniswap V2 style pair. The trace places the exploit behavior inside the settlement adapter path: every profit-making cycle enters 0x987217bc, reads getUserRoundInfo, calls redeemPosition(), and then returns excess SEA to the attacker helper before that SEA is sold for USDT.

Vulnerable Functions

  • 0x987217bc(uint256,uint256) on 0xa70f31... [recovered signature unresolved]
  • redeemPosition() (0xf046d966) on 0xa70f31...

Why It’s Vulnerable

The root cause is best classified as logic_error, with flash_loan_abuse as the secondary technique.

Expected behavior: depositing 3,000 USDT into the settlement adapter and redeeming the resulting round position should return SEA consistent with the user’s actual round entitlement. The adapter should not let a caller repeatedly convert small fixed USDT lots into dramatically larger SEA amounts inside the same transaction.

Actual behavior proved by the trace:

  1. The attacker helper deposits a fixed USDT lot with selector 0x987217bc and round argument 0.
  2. The helper immediately reads getUserRoundInfo(attackerHelper, 1) and then calls redeemPosition().
  3. Inside redeemPosition(), the adapter makes multiple price-sensitive router and pair queries (0xd06ca61f, 0x1f00ca74, 0x8803dbee, plus repeated getReserves() calls through the router path), transfers SEA through the treasury-side address 0x5210525f..., burns part of that SEA to 0xdead, and returns a larger SEA amount to the attacker helper.
  4. The attacker helper then sells the redeemed SEA back to USDT through the router and repeats the same sequence.

The verified SEA token source does not expose a mint-on-redeem surface. The pair is standard. The only contract in the call flow that can explain same-transaction creation of redeemable SEA value is the settlement adapter’s round accounting and redemption formula. The recovered implementation is low confidence, so the exact formula is approximate, but the trace directly proves the economic effect: 3,000 USDT deposits repeatedly unlock SEA redemptions large enough to leave the helper with increasing USDT after each sellback.

Logic Error Checklist

  1. Incorrect behavior occurs on the settlement adapter path rooted at 0x987217bc and redeemPosition().
  2. The transaction repeatedly mixes fixed USDT deposit lots (3000, then split into intermediate 1000 and 2000 router-side actions) with much larger SEA redemption outputs, indicating a broken value-conversion or round-state formula.
  3. No verified token-side mint path or privileged access path appears in the trace.
  4. The adapter’s recovered code shows round-state reads and writes around slot_7_userRounds, slot_0b_runningValue, and slot_0c_runningValue [recovered — approximation], consistent with the observed round-based mis-accounting.

Attack Execution

High-Level Flow

  1. EOA 0x352173fabf0e67e1cb1fcdf15474d0477d5d3674 calls attacker entry contract 0x7b1de577da005a58565d6d1fbad286fdf2f269b7.
  2. The entry contract creates helper 0x32db518e84955739912b6257cc65e3e8374b60e4 and calls its owner-only flash-loan entrypoint 0x8fedc408.
  3. That call passes:
    • round contract: 0xa70f31c06f921019237fc00b1417217dae5c37c5
    • flash-loan amount: 0xc4b20100 = 3,300,000,000 raw = 3,300 USDT
    • per-loop swap amount: 0x11e1a300 = 300,000,000 raw = 300 USDT
    • per-loop settlement amount: 0xb2d05e00 = 3,000,000,000 raw = 3,000 USDT
    • iterations: 0x0c = 12
  4. The helper borrows 3,300 USDT from Aave and loops through swap -> deposit -> redeem -> swap-back logic.
  5. After 12 iterations, the helper approves Aave for 3,301.65 USDT, repays the flash loan plus premium, transfers the remaining 13,904.941068 USDT to the entry contract, and the entry contract sweeps that USDT to the attacker EOA.

Representative Settlement Cycle

One complete loop can be read directly from decoded_calls.json and funds_flow.json:

  1. The helper first sells 300 USDT into the SEA/USDT pair and receives 2,009,299.190519 SEA (funds_flow transfers 0 to 2).
  2. It deposits 3,000 USDT into the settlement adapter (funds_flow transfer 6).
  3. The adapter immediately returns 1,000 USDT and then 2,000 USDT to the pair in two router-facing actions (funds_flow transfers 7 and 13), while the pair transfers 6,543,065.087247 SEA and then 12,412,971.908597 SEA to the adapter (funds_flow transfers 8 and 14).
  4. During the same redemption path, SEA is routed through 0x5210525f..., with portions burned to 0xdead and sent to 0x7a8a47d5... (funds_flow transfers 9 to 18).
  5. The adapter then sends 13,192,657.996172 SEA back to the pair (funds_flow transfer 21) and receives 2,000 USDT from the pair (funds_flow transfer 22).
  6. The adapter returns 17,101,229.888968 SEA to the helper (funds_flow transfer 29), and the helper sells 17,915,897.432936 SEA back through the pair to receive 2,506.180666 USDT (funds_flow transfers 31 and 32).

That representative cycle shows the core exploit mechanic: a fixed 3,000 USDT settlement deposit unlocks far more SEA than the helper should be able to redeem, and the helper immediately monetizes that SEA through the pair. The same pattern repeats across the remaining cycles, with decoded_calls.json showing:

  • 24 occurrences of selector 0x987217bc
  • 24 occurrences of selector 0x49525c23
  • 24 occurrences of selector 0xf046d966
  • 48 occurrences each of 0xd06ca61f, 0xfbec6d5e, and 0x8d56dac5

The doubled counts reflect proxy + implementation entries for the adapter calls. The high-level economic pattern is stable across all 12 loops.

Detailed Call Trace

  1. Depth 0: attacker EOA 0x352173... -> entry contract 0x7b1de5..., selector 0x93a66b22.
  2. Depth 1: entry contract creates helper 0x32db51....
  3. Depth 1: entry contract -> helper 0x8fedc408(...).
  4. Depth 2: helper -> Aave Pool flashLoanSimple(address,address,uint256,bytes,uint16).
  5. Depth 5: Aave Pool -> helper callback 0x1b11d0ff(...), then helper execution begins.
  6. Per loop:
    • helper -> router 0x5c11d795 to swap 300 USDT -> SEA
    • helper -> settlement adapter 0x987217bc(3000000000, 0)
    • helper -> settlement adapter 0x49525c23(attackerHelper, 1)
    • helper -> settlement adapter redeemPosition()
    • settlement adapter -> router or pair helper functions 0xd06ca61f, 0x1f00ca74, 0x8803dbee
    • settlement adapter -> SEA token transferFrom / transfer
    • settlement adapter -> pair via router path
    • helper -> router 0x5c11d795 to swap redeemed SEA back to USDT
  7. After loop completion:
    • helper approves Aave for 3,301.65 USDT
    • Aave pulls repayment with transferFrom
    • helper transfers the remaining USDT to entry contract
    • entry contract transfers that USDT to tx.origin

Financial Impact

funds_flow.json is the primary evidence for realized impact in this transaction.

  • Attacker realized gain: 13,904.941068 USDT
  • Pair net loss: 13,906.591068 USDT
  • Aave premium paid: 1.65 USDT

The 1.65 USDT difference between pair loss and attacker profit is fully explained by the flash-loan fee retained by Aave. trace_prestateTracer.json also shows the helper contract finishing with storage slot 0x0 = 0x33ccc900c, which matches the helper’s recovered profit() slot and corresponds to the accumulated profit [recovered — approximation].

Who lost funds:

  • Primary direct victim: SEA/USDT pair 0xeeb9c6b73a9ba397fbea320d9e4cce7b8ac10513
  • Secondary affected parties: SEA-side treasury and burn accounting paths, because the redemption flow pushes very large SEA amounts through treasury and burn addresses during each cycle

Evidence

  • Transaction hash: 0x001cb16e17c4c5a5c4d02423c9e9b2f2b11ab6b2a1baf2ba53b8fcaf06167716
  • Block: 463840994
  • Timestamp: 2026-05-17T16:11:19Z
  • Status: success
  • Attacker EOA: 0x352173fabf0e67e1cb1fcdf15474d0477d5d3674
  • Flash-loan receiver / helper: 0x32db518e84955739912b6257cc65e3e8374b60e4
  • Attacker entry contract: 0x7b1de577da005a58565d6d1fbad286fdf2f269b7
  • Vulnerable contract: 0xa70f31c06f921019237fc00b1417217dae5c37c5
  • Vulnerable implementation analyzed: 0x13dde273b66323686bfb96cce5a2a7190b40b264 [recovered — approximation]
  • Pair: 0xeeb9c6b73a9ba397fbea320d9e4cce7b8ac10513
  • Verified SEA token implementation: SEATokenUpgradeable.sol
  • Recovered pair implementation: recovered.sol
  • Recovered settlement adapter implementation: recovered.sol
  • Recovered helper implementation: recovered.sol

Key trace-backed facts:

  • trace_callTracer.json top-level helper call input encodes flash-loan amount 3300 USDT, per-loop swap amount 300 USDT, per-loop settlement amount 3000 USDT, and 12 iterations.
  • decoded_calls.json shows 24 redeemPosition() entries because both the proxy and implementation calls are recorded for each of the 12 loops.
  • funds_flow.json attacker_gains records 13,904.941068 USDT.
  • funds_flow.json net_changes records the pair at -13,906.591068 USDT.