50M USDT swapped for 35K AAVE in Aave CoW Protocol incident

iconOdaily
Share
Share IconShare IconShare IconShare IconShare IconShare IconCopy
AI summary iconSummary

expand icon
A protocol update to Aave CoW was disclosed after a user swapped 50.4 million USDT for just 35,900 AAVE on March 12, 2026. The trade depleted a low-liquidity SushiSwap pool due to an erroneous routing path. On-chain data reveals that both the CoW protocol’s routing logic and Aave’s frontend failed to prevent the trade, and no economic reasonableness checks halted the transaction.

This article is from: @Ehsan1579

Compiled by Odaily Planet Daily (@OdailyChina); Translator | Ethan (@ethanzhang_web3

Judging solely by the event title, it is likely to be mistaken for a vulnerability exploitation attack.

The core of the incident is that someone exchanged USDT worth $50.4 million for only $35,900 worth of AAVE.

When I first heard about this, I was truly shocked. So I thoroughly reviewed the entire event: transaction tracing, solver paths, contract calls, historical reserves, settlement data, adapter workflows, Aave interface code, CoW flash loan SDK, and the routing code that determines whether an offer is “reasonable.”

This was not a hack. The Aave core protocol did not fail. CoW settlement did not fail. Uniswap did not fail. SushiSwap did not fail. The transactions were valid, the signatures were valid, and all contracts executed exactly as coded. Yet, nearly all economic value was destroyed simply because an absurdly inefficient route was allowed to execute.

The public chain is fine; the issue is with the router.

In my view, dismissing this incident as merely a “user error” is not an objective or rigorous approach. True, the user completed the transaction signature, but the entire software system allowed a collateral swap involving nearly $50 million to proceed through quotation, signing, routing, and final execution—all leading to a low-liquidity pool holding only about 331 AAVE. This should have been entirely impossible; at the very least, the system should have forcefully blocked and rejected the transaction before settlement.

Traceability of core transaction information

The abnormal transaction hash is: 0x9fa9feab3c1989a33424728c23e6de07a40a26a98ff7ff5139f3492ce430801f, confirmed at block height 24643151 on the Ethereum mainnet on March 12, 2026, with transaction index 1, consuming 3,780,570 gas units, and executed successfully. The order's associated wallet address starts with 0x98b9, while the actual solver (transaction sender) address starts with 0x3980 and is marked as tsolver in CoW Competition data.

First, understand that this is not a simple wallet-level exchange of USDT for AAVE. The token being sold is aEthUSDT, which is the interest-bearing USDT deposit receipt on the Aave platform. The token being bought is aEthAAVE, which is the interest-bearing AAVE deposit receipt on the Aave platform. Therefore, this is effectively an Aave collateral swap executed through the CoW Protocol’s settlement system and its flash loan adapter workflow.

Before the transaction, the wallet held approximately 50,432,693.075254 aEthUSDT and 0 aEthAAVE. After the transaction, it retained only 4.980399 aEthUSDT and received 327.241335505966487788 aEthAAVE. In reality, the wallet sold nearly its entire position.

Metadata more clearly indicates that the route was already "toxic" before execution. The order originated from the aave-v3-interface-collateral-swap process. CoW's API displays it as a signed sell order, while the application metadata labels it as a market-style collateral swap with 121 basis points of smart slippage. The signed sell amount is 50,432,688.41618 aEthUSDT. The signed minimum buy amount is 324.949260918413591035 aEthAAVE. The actual settlement paid 327.241335505966487788 aEthAAVE.

This is an extremely important detail. This order was never intended to acquire thousands of AAVE, only to be destroyed midway for some unknown reason. From its inception, it was designed around the outcome of acquiring a few hundred AAVE.

The complete chain of the routing collapse

Once you follow the trade, the entire process is brutally straightforward.

The core of the top-level fund flow relies on the GPv2Settlement settlement contract starting with 0x9008. First, the HooksTrampoline contract starting with 0x60bf completes the aEthUSDT authorization, allowing the CoW treasury relayer to withdraw user assets without requiring separate transaction approvals; subsequently, the GPv2VaultRelayer contract starting with 0xc92e withdraws 50,432,688.41618 aEthUSDT from the user's wallet into the settlement process. Up to this point, all operations adhere to normal logic.

The settlement contract then grants operational permissions for aEthUSDT to the unsourced auxiliary contract starting with 0xd524, initiating a call via the function selector 0x494b3137; the auxiliary contract subsequently transfers execution permissions to the unsourced executor contract starting with 0x699c, fully exposing the complete path of the anomalous transaction routing.

The first valid call targets the Aave pool contract starting with 0x87870, using the withdraw function (selector 0x69328dec) to burn aEthUSDT and redeem the underlying native USDT; it then routes to the Uniswap V3 deep USDT/WETH pool starting with 0x4e68, exchanging all 50,432,688.41618 USDT for 17,957.810805702142342238 WETH.

The transaction during this phase was completely normal: the exchange rate was approximately 2808.4 USDT for 1 WETH, consistent with market conditions at the time, with no liquidity issues or calculation errors, and no anomalies in the first hop of the transaction path.

The issue lies in the second hop; once you see the liquidity reserve, the rest of the story is inevitable.

After acquiring 17957.810805702142342238 WETH, the executor transfers the full amount to the SushiSwap V2 AAVE/WETH liquidity pool at address 0xd75ea151a61d06868e31f8988d28dfe5e9df57b4.

I reviewed the historical liquidity reserve data of the pool at the moment just before the anomalous transaction occurred (block height 24643150), and the pool held only:

331.631982538108027323 AAVE and 17.653276196397688066 WETH

This is not a data entry error, but an undeniable fact.

This trade route injected nearly 17,958 WETH into a micro liquidity pool with only 17.65 WETH in reserves and a total AAVE inventory of just 331.63 WETH—the input WETH amount was approximately 1,017 times the pool’s existing WETH reserve.

This is not a routine issue of “high slippage” or “slightly low liquidity,” but an extremely absurd market order execution path, effectively forcing a tiny constant product AMM pool to absorb a trade thousands of times larger than its own size.

The AMM liquidity pool executed an operation according to its predefined algorithm, nearly depleting all AAVE reserves in the pool.

SushiSwap trading pair triggered a core Swap event: the executor transferred 17,957.810805702142342238 WETH and received only 331.305315608938235428 AAVE in return. After the transaction, the pool's remaining liquidity is approximately:

0.326666929169791895 AAVE and 17975.464081898540030304 WETH

In short, approximately 99.9% of the AAVE liquidity in the pool was drained in a single hop.

Based on the reserve prior to the trade, the pool implied AAVE price was approximately $149.50. The user’s actual execution price was approximately 154,114.66 USDT for 1 AAVE, which is over 1,000 times different from the spot price before the trade.

Next, these AAVE are supplied back to the Aave pool using the selector 0x617ba037, which is supply(address,uint256,address,uint16). As a result, the newly minted aEthAAVE is sent back to the settlement contract. The settlement contract ultimately transfers 327.241335505966487788 aEthAAVE to the user. Approximately 4.06398010297174764 aEthAAVE, representing the surplus relative to the user’s payment, remains in the settlement contract.

So, settlement didn’t suddenly turn a good execution result into a bad one—it simply finalized the result that the routing had already produced.

This is a key point worth stating clearly: catastrophic outcomes are already “pre-set” before the routing execution.

The embedded routing auxiliary contract call data shows a target purchase amount of approximately 331.272185078031026739, the user-signed minimum purchase amount is 324.949260918413591035, and the actual settled amount is 327.241335505966487788. All core values were locked at a scale of several hundred AAVE prior to settlement.

This route was bad from the start.

Where is the vulnerability?

The answer is: Each layer of the system's verification mechanism checks for errors in different dimensions.

All levels only verify whether the transaction is executable, the signature is valid, and the amount is non-zero, but almost no core-level checks assess whether the transaction routing is economically reasonable—this is the core root of the mechanism's failure.

Code defect in Aave interface adapter quote path

The first noticeable code anomaly appears in Aave's CoW adapter quote flow: the function originally used to include adapter-specific application data when requesting a quote was directly disabled.

Source: rates.helpers.ts:93 and adapters.helpers.ts:194

This means that when the Aave interface requests a quote from CoW, it does not include the flash loan and hook metadata that would be attached when the order is actually posted. In other words, what is quoted is not exactly what will be executed. The code comments even state that the purpose of this helper function is to make adapter quotes more accurate, yet this function has been hard-disabled.

The rationale for the CoW quote competition logic is too weak (critical vulnerability)

The second and more serious issue lies in the quote competition logic of the CoW protocol: its public service code considers any quote with a positive gas fee and a non-zero output amount as a "valid quote."

Source: quote.rs:31

For a routing system handling eight-digit orders, this is a shocking definition of “reasonableness.”

The system does not integrate an oracle for price sanity checks, lacks a mechanism to block quotes deviating more than 500 times from the spot price, has no risk assessment for routes that could completely drain liquidity pools, and offers no alert for severe mismatches between the final-hop liquidity and order size; it accepts any solver-provided executable, non-zero routing solution—this is the core vulnerability in this incident.

Flaws in the liquidity modeling logic of Uniswap V2

The third issue lies in the liquidity pool modeling approach of Uniswap V2: the code only implements the standard constant product algorithm and rejects only mathematically impossible scenarios such as zero reserves, numerical underflow, or reserve overflow, without performing economic feasibility checks.

Source: pool_fetching.rs:118 and pool_fetching.rs:153

This code does not evaluate whether the liquidity pool has sufficient depth to accommodate the corresponding route trade; it only checks if the swap operation is mathematically valid. Thus, even a micro pool with only 331 AAVE in reserves would be deemed capable of handling a buy request for 17,957 WETH, simply because the constant product algorithm can compute a non-zero result—completely ignoring the catastrophic asset depletion this would cause.

Second failure of the flash loan SDK and order verification mechanism

Subsequently, the flash loan SDK directly embedded this expired quote into the order and hook execution payload without performing any secondary risk interception.

Next:

Source: index.js:484 and index.js:591

That’s why I’ve always said this route is “born broken.” The adapter layer doesn’t “discover” a new bad amount at runtime—it serializes the quoted bad amount into the hook data and the determined instance address. Once a bad quote exists, the rest of the system faithfully passes it along.

Even the CoW order validation logic does not truly protect users here, as it only checks whether the order exceeds the market price at the time of the quote, not whether the quote itself is absurd relative to actual liquidity.

Source: order_validation.rs:694

This is a consistency check. If the quote itself is already nonsensical, the order will still be accepted.

The UI frontend alert mechanism is ineffective.

The Aave interface does include a high price impact warning, but it is not a hard circuit breaker. When value loss exceeds 20%, it becomes a confirmation checkbox.

Once the user checks the checkbox, the obstacle is removed:

Source: helpers.ts:24 and HighPriceImpactWarning.tsx:35

Therefore, even though this transaction would nearly deplete the entire asset value, the system only classifies it as an action requiring user confirmation, rather than a high-risk transaction that must be forcibly blocked, rendering the alert mechanism completely ineffective at intercepting risk.

Given the failure of all the above mechanisms, I cannot accept the dismissive conclusion that “this is just user stupidity.” The user did indeed sign the transaction, but the entire software system had countless opportunities to intercept this disaster—yet each layer performed only basic validation, approving the transaction as long as it was “non-zero, executable, and signed,” and then allowed it to proceed, ultimately leading to this catastrophe.

The route has not been tampered with

This step is critical and eliminates a large number of incorrect guesses: The official Aave interface flow for aave-v3-interface-collateral-swap calculates the adjusted buy amount, incorporating the quote, network fees, partner fees, and flash loan fees, at line 139 of the useSwapOrderAmounts.ts file; converts it to a buyAmountBigInt value at line 331; and then signs this amount precisely at line 191 of the CollateralSwapActionsViaCoWAdapters.tsx file.

The subsequent adapter contract will verify at line 141 of AaveV3BaseAdapter.sol that the signed order fields exactly match the stored values; the CoW settlement contract will enforce the signed order's limit rules at line 337 of GPv2Settlement.sol. Therefore, the on-chain execution result does not exceed the permitted range of the signed order, and the user actually received assets exceeding the minimum limit specified in the signature.

This is enough to prove: the disaster occurred before settlement, not during it—the fatal flaw in routing had already sealed the outcome.

Where did the lost value go?

The next transaction within the same block (hash starting with 0x45388b0f) executed a flash loan arbitrage against the compromised SushiSwap AAVE/WETH pool. After the malicious transaction flooded the pool with a massive amount of WETH and drained most of the AAVE, the arbitrageur immediately sold the AAVE back into the pool, capturing the excess value created by the liquidity imbalance.

A total of approximately 17,929.770158685933 WETH were extracted in this arbitrage run, followed by a payment of approximately 13,087.73 ETH to the block builder and approximately 4,824.31 ETH to the arbitrage execution address.

The entire economic value lost by users is almost instantly converted into MEV arbitrage profits and block builder rewards within the same block.

Additionally, verifying the chronological block-level data confirms: no malicious manipulation of the SushiSwap pool occurred prior to this transaction to trap users; the AAVE/WETH pair was first touched in this very anomalous transaction (Transaction Index 1); the very next transaction (Transaction Index 2) immediately exploited the price distortion created by this transaction; and Transaction Index 3 also interacted with this pair during the market’s recovery. The timeline clearly confirms: this anomalous transaction created an extreme price distortion, and subsequent transactions directly profited from this distortion.

So, whose fault is it?

If you're asking whether the Aave V3 core protocol has crashed, the answer is no. The Aave pools executed all operations as instructed and successfully completed the USDT redemption and AAVE deposit processes.

If you're asking whether the CoW GPv2Settlement contract crashed, the answer is no. The settlement successfully enforced a validly signed order and paid an amount exceeding the minimum specified in the signature.

If you ask whether the trading pair contracts for Uniswap V3 or SushiSwap have crashed, the answer is no again. Both types of liquidity pools execute trade pricing according to their respective algorithmic rules.

A true systemic failure occurred at the higher-level routing and risk control layers:

The primary responsibility lies with CoW Protocol’s routing, quoting, and solver modules: the system’s criteria for determining “reasonable routing” are too weak, allowing multi-million-dollar orders to be routed to micro, low-liquidity pools as long as the route is executable and non-zero, completely disregarding extreme economic irrationality.

The secondary party responsible is the Aave frontend interface: it failed to include hook-associated application data when requesting adapter quotes, directly passed erroneous results into the signing process, and relied solely on alert warnings without any hard rejection mechanism—such risk controls are entirely inadequate to mitigate risks associated with such extremely large transactions.

This was an extreme failure in trade routing quality and risk control safeguards, directly turning a legitimate and compliant collateral swap operation into a catastrophic asset loss event.

Disclaimer: The information on this page may have been obtained from third parties and does not necessarily reflect the views or opinions of KuCoin. This content is provided for general informational purposes only, without any representation or warranty of any kind, nor shall it be construed as financial or investment advice. KuCoin shall not be liable for any errors or omissions, or for any outcomes resulting from the use of this information. Investments in digital assets can be risky. Please carefully evaluate the risks of a product and your risk tolerance based on your own financial circumstances. For more information, please refer to our Terms of Use and Risk Disclosure.