5천만 USDT가 3만 5천 달러의 연평균가치(AAVE)로 교환되다니: 어떻게 이런 사태가 발생했을까요? 그리고 누구를 탓해야 할까요?

이 기사는 기계로 번역되었습니다
원문 표시

이 글은 @Ehsan1579 님의 글입니다.

Odaily 오데일리 (Odaily)( @OdailyChina )에서 편집, Ethan( @ethanzhang_web3) 이 번역했습니다.

제목만 보면 누구나 이것이 취약점 악용 공격이라고 오해할 가능성이 높습니다.

이번 사건의 핵심은 누군가가 5,040만 달러 상당의 USDT를 단 35,900달러 상당의 AAVE로 교환했다는 것입니다.

처음 이 소식을 들었을 때 정말 충격을 받았습니다. 그래서 거래 추적, 해결 경로, 계약 호출, 과거 준비금, 결제 데이터, 어댑터 프로세스, Aave UI 코드, CoW 플래시 론(Flash loan) SDK, 그리고 견적이 "합리적"인지 판단하는 라우팅 코드 등 사건 전반을 철저히 검토했습니다.

这不是一次黑客攻击。​ Aave 核心协议没有出错。CoW 结算没有出错。Uniswap 没有出错。SushiSwap 没有出错。交易是有效的,签名是有效的,所有合约都严格按照代码执行。然而,几乎全部的经济价值都被摧毁了,只因为它被允许走上的路由荒谬至极。

퍼블릭 블록체인 자체는 문제가 아닙니다. 문제는 라우팅에 있습니다.

제 생각에 이 사건을 단순히 "사용자 오류" 탓으로 돌리는 것은 객관적이지도 않고 엄밀하지도 않습니다. 사용자가 주문 서명을 완료한 것은 사실이지만, 전체 소프트웨어 시스템은 약 5천만 달러에 달하는 담보 자금 회전이 관련된 거래가 견적, 서명, 라우팅 계획 및 실행에 이르는 모든 과정을 거치도록 허용했습니다. 이 모든 과정은 고작 331 AAVE 토큰만을 보유한 유동성이 낮은 풀로 진행되었습니다. 이는 완전히 불가능했어야 했으며, 최소한 결제가 시작되기 전에 시스템에서 강력하게 차단하고 거부했어야 했습니다.

거래 핵심 정보 추적성

이 비정상적인 거래의 해시는 0x9fa9feab3c1989a33424728c23e6de07a40a26a98ff7ff5139f3492ce430801f입니다. 이 거래는 2026년 3월 12일 이더 메인넷 블록 높이 24643151에서 확인되었습니다. 거래 인덱스는 1이며, 3,780,570 가스가 소모되었고, 거래는 성공적으로 실행되었습니다. 주문이 속한 지갑 주소는 0x98b9로 시작하고, 실제로 거래를 실행한 솔버(거래 발신자)의 주소는 0x3980으로 시작하며, CoW 경쟁 데이터에서 tsolver로 태그.

먼저, 이는 단순한 지갑 수준의 USDT와 AAVE 교환이 아니라는 점을 이해하는 것이 중요합니다. 판매되는 토큰은 Aave 플랫폼에서 이자를 받는 USDT 예치 증서인 aEthUSDT입니다. 구매되는 토큰은 Aave 플랫폼에서 이자를 받는 AAVE 예치 증서인 aEthAAVE입니다. 따라서 이는 실제로 CoW 프로토콜의 결제 시스템과 플래시 론(Flash loan) 어댑터 프로세스를 통해 이루어지는 Aave 담보 순환입니다.

거래 전 지갑에는 약 50,432,693.075254 aEthUSDT와 0 aEthAAVE가 보유되어 있었습니다. 거래 후에는 4.980399 aEthUSDT만 남았고 327.241335505966487788 aEthAAVE를 받았습니다. 사실상 지갑은 보유 자산의 거의 전부를 매도한 셈입니다.

메타데이터를 보면 해당 경로가 실행 전에 이미 "위험한" 상태였음을 더욱 명확히 알 수 있습니다. 주문은 aave-v3-interface-collateral-swap 프로세스에서 발생했습니다. CoW API는 이를 서명된 매도 주문으로 표시하는 반면, 애플리케이션 메타데이터는 121bp의 스마트 슬리피지를 사용하는 시장 기반 담보 스왑으로 태그. 서명된 매도 금액은 50,432,688.41618 aEthUSDT입니다. 서명된 최소 매수 금액은 324.949260918413591035 aEthAAVE입니다. 실제 결제 금액은 327.241335505966487788 aEthAAVE입니다.

이것은 매우 중요한 세부 사항입니다. 이 주문은 원래 수만 대의 AAVE를 생산하도록 설계된 것이 아니었고, 건설 도중 불가사의하게도 파괴되었습니다. 원래는 300대 남짓한 AAVE를 생산할 것으로 예상하고 설계되었습니다.

라우팅 오류의 전체 링크

무역 경로를 따라가다 보면 전체 과정이 놀라울 정도로 간단해집니다.

최상위 자금 이체의 핵심은 CoW 프로토콜의 0x9008로 시작하는 GPv2Settlement 결제 계약에 있습니다. 먼저, 0x60bf로 시작하는 HooksTrampoline 계약이 aEthUSDT 승인 작업을 완료하여 CoW 볼트 릴레이어가 별도의 거래 승인 없이 사용자 자산을 클레임 수 있도록 합니다. 그 후, 0xc92e로 시작하는 GPv2VaultRelayer 계약이 사용자 지갑에서 50,432,688.41618 aEthUSDT를 클레임 하고 결제 프로세스에 들어갑니다. 이 단계까지 모든 작업은 일반적인 논리에 따라 진행됩니다.

결제 계약은 aEthUSDT 운영 권한을 0xd524로 시작하는 비오픈소스 보조 계약에 부여하고, 함수 선택기 0x494b3137을 통해 호출을 시작합니다. 그런 다음 보조 계약은 실행 권한을 0x699c로 시작하는 비오픈소스 실행 계약으로 이전합니다. 이 시점에서 비정상적인 거래 라우팅의 전체적인 과정이 완전히 드러납니다.

첫 번째 유효한 호출은 0x87870으로 시작하는 Aave 유동성 풀 계약을 가리키며, 이 계약은 출금 기능(선택기 0x69328dec)을 통해 aEthUSDT를 소멸시키고 기초 자산인 USDT를 상환합니다. 그 후, 경로는 0x4e68로 시작하는 Uniswap V3 심층 USDT/WETH 거래 풀로 이동하여 50,432,688.41618 USDT 전체를 17,957.810805702142342238 WETH로 교환합니다.

이 단계의 거래는 완전히 정상적이었습니다. 환율은 당시 시장 상황과 일치하는 약 2808.4 USDT 대 1 WETH였습니다. 유동성 문제도, 계산 오류도, 거래 체인의 첫 번째 단계에서의 이상 징후도 없었습니다.

문제는 두 번째 도약에 있습니다. 유동성 준비금을 확인하는 순간, 나머지는 필연적으로 드러나게 됩니다.

집행자는 17957.810805702142342238 WETH를 취득한 후 모든 자금을 주소 0xd75ea151a61d06868e31f8988d28dfe5e9df57b4에 있는 SushiSwap V2 AAVE/WETH 거래 풀로 이체했습니다.

비정상적인 거래가 발생하기 직전 시점(블록 높이 24643150)의 해당 거래 풀의 과거 유동성 준비금 데이터를 확인해 본 결과, 풀에는 다음 금액만 보유되어 있었습니다.

331.631982538108027323 AAVE, 17.653276196397688066 WETH

이것은 데이터 입력 오류가 아니라 부인할 수 없는 사실입니다.

이 거래 경로는 보유량이 17.65 WETH에 불과한 마이크로 트랜잭션 풀에 거의 17,958 WETH를 투입했으며, 이는 총 AAVE 재고량이 331.63 WETH에 불과한 상황에 해당합니다. 투입된 WETH 양은 풀의 WETH 보유량의 약 1017배에 달했습니다.

이는 결코 "높은 슬리피지"나 "약간 부족한 유동성"과 같은 일반적인 문제가 아니라, 매우 작은 규모의 고정 수익률 AMM 풀이 자체 규모보다 수천 배나 큰 엄청난 거래를 처리하도록 강요하는 것과 같은 극도로 부조리한 시장 주문 체결 경로입니다.

AMM 거래 풀은 정해진 알고리즘에 따라 거래를 실행하여 풀의 AAVE 보유량을 거의 모두 소진했습니다.

SushiSwap 거래 쌍에서 핵심 스왑 이벤트가 발생했습니다. 실행자는 17957.810805702142342238 WETH를 전송하여 331.305315608938235428 AAVE로 교환했습니다. 이 거래 후 풀에 남아 있는 유동성은 대략 다음과 같습니다.

0.326666929169791895 AAVE, 17975.464081898540030304 WETH

솔직히 말해서, 전체 AAVE(아프리카계 미국인 영어) 콘텐츠의 약 99.9%가 단 한 번의 도약으로 사라졌습니다.

거래 전 준비금을 기준으로 계산했을 때, 풀 내 AAVE의 예상 가격은 약 149.50달러였습니다. 하지만 사용자의 실제 체결 가격은 1 AAVE당 약 154,114.66 USDT였습니다. 이는 거래 전 현물 가격보다 1,000배 이상 낮은 가격입니다.

다음으로, 이러한 AAVE는 셀렉터 0x617ba037, 즉 supply(address, uint256, address, uint16)를 사용하여 AAVE 풀로 다시 공급됩니다. 결과적으로 새로 민트 aEthAAVE는 정산 계약으로 다시 전송됩니다. 정산 계약은 최종적으로 327.241335505966487788 aEthAAVE를 사용자에게 전송합니다. 약 4.06398010297174764 aEthAAVE는 사용자의 지불액 대비 잉여금으로 정산 계약에 남아 있습니다.

따라서 정산은 좋은 실행 결과를 갑자기 나쁜 결과로 바꾸는 것이 아니라, 이미 경로 설정 과정에서 도출된 결과를 확정짓는 것에 불과했습니다.

이것이 핵심이며, 명확히 밝힐 가치가 있습니다. 파국적인 결과는 라우팅이 실행되기 전부터 이미 "정해져 있다"는 것입니다.

라우터에 내장된 보조 계약 호출 데이터에 따르면, 구매 목표 금액은 약 331.272185078031026739 AAVE이고, 사용자가 서명하여 동의한 최소 구매 금액은 324.949260918413591035 AAVE이며, 실제 결제 금액은 327.241335505966487788 AAVE입니다. 모든 핵심 가치는 결제 전 약 300 AAVE 수준에서 고정되었습니다.

이 경로는 근본적으로 결함이 있었다.

취약점은 어디에 있는가?

정답은 시스템 검증 메커니즘의 각 계층이 오류를 검사한다는 것입니다.

모든 단계에서는 거래 실행 가능성, 서명 유효성, 금액의 합치성만 검증할 뿐, 거래 경로의 경제적 타당성을 검증하는 핵심 단계는 거의 없습니다. 이것이 바로 해당 메커니즘의 실패를 야기하는 근본적인 원인입니다.

Aave UI 어댑터 가격 책정 경로 코드 결함

첫 번째로 눈에 띄는 코드 이상 현상은 Aave 인터페이스의 CoW 어댑터 견적 프로세스에서 나타납니다. 견적 요청 시 어댑터별 애플리케이션 데이터를 첨부하는 데 원래 사용되었던 기능이 강제로 비활성화되었습니다.

출처: rates.helpers.ts:93adapters.helpers.ts:194

这意味着Aave 界面在向CoW 请求报价时,并没有附上实际发布订单时会附加的플래시 론(Flash loan)和钩子元数据。换句话说,被报价的东西并不完全是要被执行的东西。代码注释甚至说这个助手函数的目的是为了让适配器报价更精确,然后这个函数却被硬性禁用了。

CoW 입찰 경쟁 논리의 합리성이 너무 취약합니다(핵심 취약점).

두 번째이자 가장 심각한 문제는 CoW 프로토콜의 입찰 경쟁 논리에 있습니다. 공개 서비스 코드에 따르면, 제시된 가스 요금이 양수이고 출력량이 0이 아니면 "합리적인 입찰"로 간주됩니다.

출처: quote.rs:31

수천만 원 규모의 주문을 처리하는 라우팅 시스템에 대한 "합리성"의 정의가 이렇게 허술하다니 놀랍습니다 .

해당 시스템은 가격 무결성을 위한 오라클 검증 기능이 부족하고, "현물 가격과 500배 이상 차이가 나는 견적"을 차단하는 메커니즘이 없으며, "경로가 유동성 풀을 완전히 고갈시킬 것"이라는 리스크 평가 기능도 없고, "최종 홉 유동성이 주문 규모와 심각하게 불일치하는 경우"에 대한 경고 기능도 없습니다. 이 시스템은 실행 가능한 모든 0이 아닌 경로 솔루션을 솔버가 반환하는 것을 허용하는데, 이것이 이번 사고의 핵심 취약점입니다.

유니스왑 V2와 유사한 유동성 모델링 로직의 결함

세 번째 문제는 유니스왑 V2 스타일의 유동성 풀 모델링 접근 방식에 있습니다. 해당 코드는 표준 상수 곱 알고리즘만 사용하여 경제적 타당성 검사를 수행하지 않고 준비금 0, 수치적 언더플로우, 준비금 오버플로우와 같이 수학적으로 불가능한 상황만 거부합니다.

출처: pool_fetching.rs:118pool_fetching.rs:153

이 코드 조각은 유동성 풀 규모가 해당 라우팅된 거래를 처리하기에 충분한지 여부를 판단하지 않습니다. 단지 거래 작업이 수학적으로 유효한지 여부만 확인합니다. 따라서, 단 331 AAVE의 유동성 풀조차도 17,957 WETH 매수 요청을 처리하기에 유효한 장소로 간주됩니다. 이는 상수 곱 알고리즘이 0이 아닌 결과를 계산할 수 있기 때문이며, 이로 인해 발생할 막대한 자산 손실을 완전히 무시하는 것입니다.

플래시 론(Flash loan) SDK 및 주문 검증 메커니즘의 두 번째 오류

이후 플래시 론(Flash loan) SDK는 어떠한 2차 리스크 차단 조치도 수행하지 않고 이 잘못된 견적을 주문 실행 페이로드에 직접 삽입하고 후킹했습니다.

그 다음에:

출처: index.js:484index.js:591

이것이 바로 제가 항상 이 경로가 "처음부터 잘못됐다"고 말해 온 이유입니다. 어댑터 계층은 실행 중에 새로운 잘못된 금액을 "발견"하는 것이 아닙니다 . 이미 인용된 잘못된 금액을 후크 데이터와 정의된 인스턴스 주소에 직렬화할 뿐입니다 . 잘못된 인용이 하나라도 존재하면 나머지 메커니즘은 그 내용을 그대로 전달합니다.

CoW의 주문 검증 로직조차도 이 경우에는 사용자를 제대로 보호하지 못합니다 . 왜냐하면 해당 로직은 주문 가격이 견적 시점의 시장 가격을 초과하는지 여부만 확인할 뿐, 견적 자체가 실제 유동성에 비해 터무니없이 높은지 여부는 확인하지 않기 때문입니다.

출처: order_validation.rs:694

이는 일관성 검사입니다. 견적 자체가 말이 안 되더라도 주문은 승인될 수 있습니다.

사용자 인터페이스 프런트엔드의 경고 메커니즘은 사실상 쓸모가 없습니다.

Aave 인터페이스는 가격 급등 경고를 표시하지만, 이는 거래를 완전히 차단하는 기능은 아닙니다 . 가격 손실이 20%를 초과하면 확인 체크박스가 나타납니다.

사용자가 체크박스를 선택하면 장애물이 제거됩니다.

출처: helpers.ts:24HighPriceImpactWarning.tsx:35

따라서, 이러한 거래로 인해 자산 가치가 거의 모두 소멸되더라도, 시스템은 이를 시스템이 강제로 거부해야 하는 고위험 거래가 아닌 사용자 확인이 필요한 거래로만 분류하게 됩니다. 결과적으로 경고 메커니즘은 리스크 차단하는 기능을 완전히 상실하게 됩니다.

위에서 언급한 모든 메커니즘이 실패한 상황에서 "단순히 사용자의 실수였다"는 식의 일축적인 결론에는 절대 동의할 수 없습니다. 사용자는 서명을 완료했지만, 전체 소프트웨어 시스템은 이러한 문제를 막을 수 있는 수많은 기회가 있었음에도 불구하고 각 계층에서 기본적인 검사만 수행하고 "0이 아니고 실행 가능하며 서명되었다"는 확인만으로 프로세스를 그대로 허용하여 결국 참담한 결과를 초래했습니다.

경로는 훼손되지 않았습니다.

이 단계는 대량 잘못된 추측을 직접적으로 제거하는 데 매우 중요합니다. aave-v3-interface-collateral-swap에 해당하는 공식 Aave 인터페이스 프로세스는 useSwapOrderAmounts.ts 파일의 139번째 줄에서 호가, 플래시 론(Flash loan) 수수료를 고려하여 슬리피지 조정 매수 금액을 계산합니다. 331번째 줄에서 이 금액을 buyAmountBigInt 값으로 변환하고, CollateralSwapActionsViaCoWAdapters.tsx 파일의 191번째 줄에서 해당 금액에 정확하게 서명합니다.

어댑터 계약은 서명된 주문 필드와 AaveV3BaseAdapter.sol 파일 141번째 줄에 저장된 값이 완벽하게 일치하는지 검증합니다. CoW 결제 계약은 GPv2Settlement.sol 파일 337번째 줄에 있는 서명 계약의 한도 규칙을 적용합니다. 따라서 온체인 실행 결과는 서명된 주문에서 허용된 범위를 초과하지 않았으며, 사용자가 실제로 수령한 자산은 서명 계약에 명시된 최소 한도보다 더 많았습니다.

이는 참사가 정착 과정 중이 아니라 정착 과정 이전에 발생했다는 충분한 증거입니다. 경로 설정의 치명적인 결함이 이미 참사의 운명을 결정지었던 것입니다.

손실된 가치는 어디로 갔을까요?

동일 블록 내의 다음 거래(해시 0x45388b0f부터 시작)는 손상된 SushiSwap AAVE/WETH 풀을 이용한 역추적 차익거래를 완료했습니다. 이 비정상적인 거래로 인해 풀에 대량의 WETH가 유입되고 대부분의 AAVE가 빠져나가자, 차익거래자는 즉시 AAVE를 다시 풀에 매도하여 유동성 불균형으로 발생한 초과 가치를 챙겼습니다.

이번 차익거래를 통해 약 17,929.770158685933 WETH 클레임, 이 중 약 13,087.73 ETH는 블록 생성자에게, 약 4,824.31 ETH는 차익거래 실행 주소로 지급되었습니다.

사용자가 잃는 경제적 가치 전체는 궁극적으로 거의 즉시 동일 블록 내의 MEV 차익거래 이익과 블록 건설자 이익으로 전환됩니다.

또한, 블록 수준 타임라인을 확인해 보면 다음과 같은 사실이 확인됩니다. 해당 거래 이전에 누구도 악의적으로 스시스왑 거래 풀을 조작하여 사용자를 속인 적이 없습니다. AAVE/WETH 거래쌍이 처음 거래된 시점은 바로 이 비정상적인 거래(거래 인덱스 1)였습니다. 다음 거래(거래 인덱스 2)는 이 거래로 인해 발생한 가격 왜곡을 처음으로 되돌렸습니다. 거래 인덱스 3 또한 시장 조정 과정에서 해당 거래쌍을 건드렸습니다. 타임라인은 이 비정상적인 거래가 극심한 가격 왜곡을 초래했고, 이후 거래들이 이 왜곡으로부터 직접적인 이익을 취했음을 명확히 보여줍니다.

그렇다면 누구의 잘못일까요?

Aave V3 코어 프로토콜에 문제가 발생했는지 묻는다면, 답은 '아니요' 입니다. Aave 유동성 풀은 지시된 대로 정확하게 작업을 수행하여 USDT 상환 및 AAVE 예치 프로세스를 정상적으로 완료했습니다.

CoW의 GPv2Settlement 계약이 파기되었는지 묻는다면, 답은 '아니오' 입니다. 합의는 유효하게 서명된 주문을 집행했으며 최소 서명 요건을 초과하는 금액을 지급했습니다.

유니스왑 V3나 스시스왑의 거래쌍 가격이 폭락했는지 묻는다면, 답은 역시 '아니오' 입니다. 두 거래 풀 모두 자체 알고리즘 규칙에 따라 거래 가격을 책정합니다.

진정한 시스템적 실패는 라우팅 및 위험 관리의 더 높은 수준에서 발생합니다.

주된 책임은 CoW 프로토콜의 라우팅, 가격 책정 및 해결 모듈 에 있습니다 . 전체 시스템은 "합리적인 라우팅"을 판단하는 기준이 너무 허술하여 수천만 달러에 달하는 대규모 주문이 소액 유동성 풀로 흘러 들어가도록 허용하고 있습니다. 경로가 실행 가능하고 0이 아니면 승인되므로 경제적 차원에서 극도로 비합리적인 상황을 완전히 무시하고 있습니다.

두 번째 책임 당사자는 Aave 프런트엔드 인터페이스입니다 . 어댑터 견적 요청 시, 후크와 관련된 애플리케이션 데이터를 포함하지 않고, 오류 결과를 서명 프로세스에 직접 전달했으며, 명확한 거부 메커니즘 없이 경고 메시지에만 의존했습니다. 이처럼 매우 큰 규모의 거래에서 이러한 유형의 위험 관리 조치는 리스크 예방하기에 완전히 불충분합니다.

이는 거래 경로 설정 및 위험 관리 품질 측면에서 극심한 실패였으며, 이로 인해 합법적이고 규정을 준수하는 담보 순환 작업이 막대한 자산 손실 사태로 이어졌습니다.

출처
면책조항: 상기 내용은 작자의 개인적인 의견입니다. 따라서 이는 Followin의 입장과 무관하며 Followin과 관련된 어떠한 투자 제안도 구성하지 않습니다.
라이크
60
즐겨찾기에 추가
21
코멘트
1