SEA settlement adapter rounding error inflates redemptions
A round-accounting fault in the SEA settlement adapter let fixed USDT deposits mint more SEA value than they should have. The exploit path stayed compact: deposit a fixed lot, read the round state, redeem, then sell the output back through the SEA/USDT pair. Flash-loan funding turned that into a repeatable loop instead of a one-off mistake.
The rounding path that turned fixed deposits into excess SEA
The fault sat in the settlement adapter path, rooted at selector 0x987217bc and redeemPosition(). A fixed deposit of 3,000 USDT was treated as a settlement lot, then the round-state logic from getUserRoundInfo fed an inflated redemption calculation. That created more SEA entitlement than the deposit justified.
The attacker did not need to wait for any external state change. Each loop deposited, redeemed, and moved straight into a swap path that converted SEA back into USDT through the pool. The repeated use of the same selectors inside one transaction is the giveaway here: the adapter was happy to process the same round pattern again and again, and the accounting never caught up with reality.
The visible effect was ugly. The SEA/USDT pair lost 13,906.591068 USDT net and ended up holding 129,202,760.357336 SEA. The attacker EOA finished with 13,904.941068 USDT after repaying the loan. That is the sort of arithmetic that makes a fixed deposit look more like a printing press.
Flash-loan pacing made the adapter failure repeatable
The attack used Aave flashLoanSimple with 3,300 USDT on Arbitrum, then ran 12 SEA settlement cycles in a single transaction. The loan size was only just enough to keep the loop moving: 3,000 USDT for settlement, 300 USDT for the swap leg, and repayment approval for 3,301.65 USDT at the end. That left no room for slippage tolerance or slow cleanup, only for fast repetition.
Flash loans are a blunt fit for this kind of flaw because they compress deposit, redemption, and exit into one atomic path. If the adapter can be convinced that each loop is a fresh round, the attacker gets a new overpayment every time without needing fresh capital. The same transaction also hides the pacing issue that would usually expose broken round state across blocks.
The trace shows the pattern clearly enough. There were 24 calls each to the deposit selector 0x987217bc, round-info selector 0x49525c23, and redeemPosition() selector 0xf046d966, plus repeated router and pair helper calls. That is not incidental noise. It is the exploit mechanic.
Closing the gap with settlement caps and round-state checks
The first control is a hard settlement cap per round that cannot be crossed by same-transaction recycling. If a deposit lot is fixed, redemption should only reflect the lot once, with no path that lets a fresh redeem observe still-open round credit from the same transaction. A round marker that advances only after settlement finality would stop the loop from reusing the same state.
The second control is a round-state consistency check before redemption. The adapter should reject any redeem path where slot_7_userRounds, slot_0b_runningValue, and slot_0c_runningValue still match a pre-settlement state for the same account. If the state has not moved, the redemption amount should not move either.
The swap leg needs the same kind of boundary. If redemption output is meant to be routed into a SEA/USDT pair, the adapter should cap the redeem amount against the exact deposit lot and block same-block re-entry after payout. That closes off the easy flash-loan pacing trick and leaves the attacker with a broken loop instead of a profit loop.




