5000만 USDT가 3만 5천 달러의 AAVE로 바뀌다: 재앙은 어떻게 발생했는가? 우리는 누구를 탓해야 하는가?
- 핵심 요점: 본문은 거래 라우팅 시스템 설계 결함으로 인한 중대한 자산 손실 사건을 심층 분석하며, 핵심 문제는 하위 프로토콜 결함이나 사용자 조작 실수가 아니라 다층 시스템 검증 메커니즘이 경제적 합리성 측면에서 모두 실효되었다는 점을 지적합니다.
- 핵심 요소:
- 사건의 본질은 사용자가 Aave 인터페이스를 통해 5040만 달러 상당의 담보 교체(aEthUSDT를 aEthAAVE로)를 시작했으나, 결국 3만 5900달러 상당의 AAVE만 획득하여 막대한 손실을 입은 것입니다.
- 거래 라우팅은 막대한 자금을 약 331개의 AAVE만 보유한 SushiSwap 저유동성 풀로 유도했으며, 입력된 WETH 규모는 풀 내 준비금의 약 1017배에 달해 실행 가격이 현물 가격에서 1000배 이상 벗어나게 했습니다.
- 핵심 취약점은 CoW 프로토콜의 가격 제안 경쟁 로직에 있으며, 그 '합리성' 판단은 Gas 수수료가 양수이고 출력 금액이 0이 아닌 것에만 기반하여, 가격 편차 검증과 유동성 위험 평가가 부족합니다.
- Aave 프론트엔드 인터페이스는 가격 제안 요청 시 어댑터 전용 데이터를 비활성화하여, 제안된 가격과 최종 실행 내용이 완전히 일치하지 않게 했으며, 그 높은 가격 충격 경고는 단순 확인 체크박스일 뿐 강제 차단 장치가 아닙니다.
- 사용자가 손실한 가치는 동일 블록 내 MEV 차익 거래자들에게 포착되었으며, 거래 실행 후 즉시 백러닝 차익 거래가 발생하여, 이 비정상적인 거래 자체가 가격 왜곡을 만들어냈음을 증명합니다.
- 책임은 주로 CoW 프로토콜의 라우팅/가격 제안 시스템이 경제적 합리성에 대한 검증을 누락한 데 있으며, 부차적 책임은 Aave 프론트엔드의 위험 관리 조치가 부족한 데 있습니다.
본문 출처: @Ehsan1579
편집|Odaily (@OdailyChina); 번역| Ethan (@ethanzhang_web 3)

사건 제목만 본다면, 아마도 이는 익스플로잇 공격으로 오해할 가능성이 높다.
사건의 핵심은: 누군가가 5040만 달러 상당의 USDT를 결국 3만 5900달러 상당의 AAVE로만 교환했다는 점이다.
처음 이 소식을 들었을 때, 나는 정말 충격을 받았다. 그래서 나는 이 사건을 철저히 파헤쳤다: 트랜잭션 추적, 솔버 경로, 컨트랙트 호출, 역사적 리저브, 결산 데이터, 어댑터 프로세스, Aave 인터페이스 코드, CoW 플래시론 SDK, 그리고 인용이 "합리적인"지 판단하는 라우팅 코드까지.
이것은 해킹이 아니다. Aave 코어 프로토콜에 문제가 없었다. CoW 결산에 문제가 없었다. Uniswap에 문제가 없었다. SushiSwap에 문제가 없었다. 트랜잭션은 유효했고, 서명은 유효했으며, 모든 컨트랙트는 코드에 따라 엄격하게 실행되었다. 그러나 거의 모든 경제적 가치는 허무맹랑한 경로를 허용했기 때문에 파괴되었다.
퍼블릭 체인에 문제가 있는 것이 아니라, 라우팅에 문제가 있다.
내 생각에, 이 사건을 단순히 "사용자 실수"로 가볍게 치부하는 것은 객관적이고 엄격한 태도가 아니다. 사용자가 주문에 서명한 것은 사실이지만, 전체 소프트웨어 시스템이 약 5000만 달러에 달하는 담보 교체 작업이 인용, 서명, 경로 계획을 거쳐 최종 실행까지 허용했으며, 모든 프로세스가 약 331개의 AAVE만 보유한 낮은 유동성 풀을 가리키고 있었다는 점이다. 이는 전혀 일어날 수 없는 일이어야 하며, 적어도 결산 단계가 시작되기 전에 시스템이 강력하게 차단하고 거부했어야 했다.트랜잭션 핵심 정보 추적
이번 비정상 트랜잭션 해시는: 0x9fa9feab3c1989a33424728c23e6de07a40a26a98ff7ff5139f3492ce430801f이며, 2026년 3월 12일 이더리움 메인넷 블록 높이 24643151에서 확인되었고, 트랜잭션 인덱스는 1이며, 소모된 가스량은 3780570 단위이며, 트랜잭션 실행은 성공했다. 주문 소유 지갑 주소는 0x98b9으로 시작하며, 실제 트랜잭션을 실행한 솔버(트랜잭션 발신자) 주소는 0x3980으로 시작하며, CoW 경쟁 데이터에서 tsolver로 표시되었다.
우선 이해해야 할 점은, 이것은 단순한 지갑 수준의 USDT에서 AAVE로의 교환이 아니라는 점이다. 판매 토큰은 aEthUSDT, 즉 Aave 플랫폼에서 이자를 발생시키는 USDT 예금 증명서이다. 구매 토큰은 aEthAAVE, 즉 Aave 플랫폼에서 이자를 발생시키는 AAVE 예금 증명서이다. 따라서, 이는 실제로 CoW 프로토콜의 결산 시스템과 그 플래시론 어댑터 프로세스를 통한 Aave 담보 교체이다.
트랜잭션 전, 해당 지갑은 약 50,432,693.075254개의 aEthUSDT와 0개의 aEthAAVE를 보유하고 있었다. 트랜잭션 후, 그것은 단 4.980399개의 aEthUSDT만 남겼고, 327.241335505966487788개의 aEthAAVE를 받았다. 실제로, 해당 지갑은 거의 모든 포지션을 매도했다.
메타데이터는 더 명확하게 보여준다: 경로는 실행 전 이미 "유독성"을 띠고 있었다. 주문은 aave-v3-interface-collateral-swap 프로세스에서 왔다. CoW의 API는 이를 서명된 매도 주문으로 표시하고 있으며, 앱 메타데이터는 이를 121 베이시스 포인트 스마트 슬리피지를 사용하는 시가식 담보 교체로 표시하고 있다. 서명된 매도 금액은 50,432,688.41618개의 aEthUSDT이다. 서명된 최소 구매 금액은 324.949260918413591035개의 aEthAAVE이다. 실제 결산은 327.241335505966487788개의 aEthAAVE를 지불했다.
이는 매우 중요한 세부 사항이다. 이 주문은 수천 개의 AAVE를 기대한 후 중간에 어떤 이유로든 파괴된 것이 아니다. 그것은 처음 구성될 때부터 300여 개의 AAVE와 같은 결과를 중심으로 설계되었다.
라우팅 붕괴의 완전한 연결 고리
일단 트랜잭션 추적을 따라가면, 전체 과정은 잔혹하게도 직설적이다.
최상위 자금 흐름의 핵심은 CoW 프로토콜 0x9008으로 시작하는 GPv2Settlement 결산 컨트랙트에 의존한다. 먼저, 0x60bf로 시작하는 HooksTrampoline 컨트랙트가 aEthUSDT 승인 작업을 완료하여, CoW 금고 릴레이어가 별도의 트랜잭션 승인 없이도 사용자 자산을 인출할 수 있도록 허용한다. 그 후, 0xc92e로 시작하는 GPv2VaultRelayer 컨트랙트가 사용자 지갑에서 50432688.41618개의 aEthUSDT를 인출하여 결산 프로세스로 가져간다. 이 단계까지 모든 작업은 정상적인 논리에 부합한다.
결산 컨트랙트는 이후 aEthUSDT 운영 권한을 0xd524로 시작하는 오픈소스가 아닌 보조 컨트랙트에 부여하고, 함수 선택자 0x494b3137을 통해 호출을 시작한다. 해당 보조 컨트랙트는 실행 권한을 0x699c로 시작하는 오픈소스가 아닌 실행자 컨트랙트로 이전하며, 이 시점에서 비정상 트랜잭션 경로의 전체 모습이 완전히 드러난다.첫 번째 유효한 호출은 0x87870로 시작하는 Aave 자금 풀 컨트랙트를 가리키며, withdraw 함수(선택자 0x69328dec)를 통해 aEthUSDT를 소각하고 기저 네이티브 USDT를 상환한다. 이후 경로는 0x4e68로 시작하는 Uniswap V3 깊은 USDT/WETH 거래 풀로 점프하여, 전체 50432688.41618개의 USDT를 17957.810805702142342238개의 WETH로 교환한다.
이 단계의 거래는 완전히 정상적이다: 환율은 약 2808.4 USDT당 1 WETH로, 당시 시장 상황에 부합하며, 유동성 부족 문제나 계산 편차가 없으며, 첫 번째 점프 거래 링크에는 어떠한 이상도 존재하지 않는다.
문제는 두 번째 점프에 있다. 일단 유동성 리저브를 보면, 나머지 이야기는 피할 수 없다.
실행자가 17957.810805702142342238개의 WETH를 획득한 후, 모든 자금을 0xd75ea151a61d06868e31f8988d28dfe5e9df57b4 주소의 SushiSwap V2 AAVE/WETH 거래 풀로 이전한다.
나는 해당 거래 풀의 비정상 거래 발생 직전(블록 높이 24643150)의 역사적 유동성 리저브 데이터를 확인했고, 풀 내에는 다음만 보유하고 있었다:
331.631982538108027323 AAVE, 17.653276196397688066 WETH
이는 데이터 입력 오류가 아니라, 확고한 사실이다.
이 거래 경로는 약 17958개의 WETH 전체를 WETH 리저브가 17.65개에 불과하고, 해당 AAVE 총 재고가 단 331.63개인 소형 거래 풀에 주입했으며, 입력된 WETH 규모는 풀 내 WETH 리저브의 약 1017배에 달했다.
이는 "슬리피지가 약간 높다"거나 "유동성이 약간 얇다"는 일반적인 문제가 아니라, 극단적으로 터무니없는 시가 주문 실행 경로로, 규모가 자체를 수천 배 초과하는 거대한 거래를 체결하도록 강요하는 것과 같다.
AMM 거래 풀은 설정된 알고리즘에 따라 작업을 실행했고, 풀 내 거의 모든 AAVE 리저브를 소진했다.
SushiSwap 거래 쌍은 핵심 Swap 교환 이벤트를 트리거했다: 실행자는 17957.810805702142342238개의 WETH를 전송하고, 단 331.305315608938235428개의 AAVE만 되돌려 받았다. 거래 완료 후, 해당 풀의 남은 유동성은 약:
0.326666929169791895 AAVE, 17975.464081898540030304 WETH
간단히 말해, 풀 내 약 99.9%의 AAVE 재고가 한 번의 점프에서 고갈되었다.
거래 전 리저브에 따르면, 풀의 내재된 AAVE 가격은 약 149.50달러였다. 사용자의 실제 실행 가격은 약 154,114.66 USDT당 1 AAVE였다. 이는 거래 전 현물 가격과 1000배 이상 차이가 난다.
이어서, 이 AAVE들은 Aave 자금 풀에 다시 공급되었으며, 선택자 0x617ba037, 즉 supply(address,uint256,address,uint16)를 사용했다. 결과는 새로 발행된 aEthAAVE가 결산 컨트랙트로 돌아왔다. 결산 컨트랙트는 최종적으로 327.241335505966487788개의 aEthAAVE를 사용자에게 이전했다. 약 4.06398010297174764개의 aEthAAVE는 사용자가 지불한 금액에 대한 잉여분으로 결산 컨트랙트에 남았다.
따라서, 결산은 갑자기 좋은 실행 결과를 나쁜 결과로 왜곡한 것이 아니다. 그것은 단지 경로가 이미 생성한 결과를 최종 확정했을 뿐이다.
이것이 핵심 포인트이며, 명확히 말할 가치가 있다: 재앙적인 결과는 경로 실행 전 이미 그 안에 "사전 설정"되어 있었다.
경로에 내장된 보조 컨트랙트 호출 데이터에서, 구매 측 목표 금액은 약 331.272185078031026739개였으며, 사용자 서명으로 약정된 최소 구매 금액은 324.949260918413591035개였고, 실제 결산 금액은 327.241335505966487788개였으며, 모든 핵심 수치는 결산 전에 300여 개의 AAVE 규모로 고정되어 있었다.
이 경로는 태생부터 나빴다.
취약점은 어디에 있는가?
답은: 시스템의 각 계층 검증 메커니즘이 잘못된 차원을 검사하고 있다는 점이다.
모든 계층은 거래가 실행 가능한지, 서명이 유효한지, 금액이 0이 아닌지만 검증하며, 거래 경로가 경제적 측면에서 합리성을 갖추었는지 검증하는 핵심 계층은 거의 없다. 이것이 메커니즘이 무너진 핵심 근원이다.
Aave 인터페이스 어댑터 인용 경로의 코드 결함
첫 번째 명백한 코드 이상점은 Aave 인터페이스의 CoW 어댑터 인용 프로세스에서 나타난다: 원래 인용 요청 시 어댑터 전용 앱 데이터를 첨부하는 데 사용되던 함수가 직접 강제 비활성화되었다.

출처: rates.helpers.ts:93 및 adapters.helpers.ts:194
이는 Aave 인터페이스가 CoW에 인용을 요청할 때, 실제 주문 게시 시 첨부되는 플래시론 및 훅 메타데이터를 첨부하지 않았다는 것을 의미한다. 다시 말해, 인용된 것과 실행될 것이 완전히 동일하지 않다. 코드 주석은 심지어 이 도우미 함수의 목적이 어댑터 인용을 더 정확하게 만들기 위한 것이라고 말하지만, 이 함수는 강제로 비활성화되었다.
CoW 인용 경쟁 논리의 합리성 판단이 너무 약함 (핵심 취약점)
두 번째이자 가장 심각한 문제는 CoW 프로토콜의 인용 경쟁 논리에 있다: 그 공공 서비스 코드에서, 인용 가스 비용이 양수이고 출력 금액이 0이 아니기만 하면 "합리적인 인용"으로 판단된다.

출처: quote.rs:31
8자리 수 주문을 처리하는 라우팅 시스템에 대해, 이는 놀랍도록 약한 "합리성" 정의이다.
시스템은 오라클을 연결하여 가격 건전성 검증을 하지 않았으며, "인용이 현물 가격에서 500배 이상 벗어남" 차단 메커니즘, "경로가 유동성 풀을 완전히 고갈시킬 것" 위험 판단, "마지막 점프 유동성과 주문 규모가 심각하게 불일치함" 경고가 없다. 솔버가 실행 가능하고 0이 아닌 경로 솔루션을 반환하기만 하면 시스템에 수용된다. 이것이 이번 사건의 핵심 취약점이다.
Uniswap V2 스타일 유동성 모델링 논리의 결함
세 번째 문제는 Uniswap V2 스타일의 유동성 풀 모델링 방식에 있다: 코드는 표준 상수 곱 알고리즘만 채택하며, 0 리저브, 수치 하향 오버플로우, 리저브 오버플로우 등 수학적 불가능 상황만 거부하고, 경제적 측면의 실행 가능성 검증은 하지 않는다.



