Esses 200 ETH eram compostos por quatro lotes de 50 ETH que o contrato havia ganhado em leilões da MakerDAO com lances zero durante as liquidações da «Quinta-Feira Negra» em março de 2020, mas nunca havia reivindicado definitivamente.
Uma das funções desprotegidas do contrato antigo não verificava quem a estava chamando. Isso permitiu que o invasor concedesse a um contrato sob seu controle o controle total sobre a conta desse contrato no sistema da MakerDAO. Em uma única transação, o invasor liquidou os leilões antigos e retirou a garantia ali mantida.
Transações principais (horários em UTC)
| Horário | TXID | Descrição |
|---|---|---|
| 2026-10-06 05:57:23 | 0xd4c0b18a058e7f0a12855f30174f4cb1e973c15c886063deab97e1a21f048ac6 | Retirada de 0.1 ETH do Tornado Cash. Este foi o único financiamento que essa conta recebeu. |
| 2026-10-06 06:12:11 | 0x4a587af4213cc345c4c109fbf5fec46f9643183f91a9edf60305380f31ad1167 | Implantação do contrato de ataque usado para explorar a vulnerabilidade. |
| 2026-10-06 06:13:11 | 0xbb6940f7c2a1e68cafbae7bb9b94d09af9af06ec3a114f6996f2cab993f3a88c | A transação de ataque. O contrato de ataque obteve permissões delegadas por meio da função keeper 0x8804d1de, liquidou os leilões 1457-1460 e enviou 200 ETH para a conta de propriedade externa (EOA) do invasor. |
| 2026-10-06 06:19:35 | 0xb8ecff9c129d8d9331c85558eaeddff29a38c4c16b71a40986acbf8f6febefeb | O primeiro de nove depósitos de 10 ETH no roteador do Tornado Cash. |
Endereços principais
| Endereço | Função |
|---|---|
| 0x01EB957E5C7DcDDD60F3C875956cCc6fb9BdA5FA | A conta de propriedade externa (EOA) do invasor. |
| 0xEc997d2aD033277913d6002277353368E8321dcF | O contrato de ataque. |
| 0xf09a13072Ed939B79Bc25B66AA3a836ea6DCC170 | O módulo adaptador malicioso, que ainda mantém permissões delegadas sobre a conta da vítima no Vat. |
| 0x9c05a05893Ada984FC20D0DA0c046De5Cc0e8273 | O contrato vulnerável (keeper de leilão antigo, AdminUpgradeabilityProxy). |
| 0x68399ed8aa33C5b43F863EE6782de492006A5546 | A implementação do contrato vulnerável (código-fonte não verificado). |
| 0xaDC374E77b89Af0B8B39F7c47E8e0A37B6DaF073 | O proprietário e operador do keeper em março de 2020. |
| 0xd8a04F5412223F513DC55F839574430f5EC15531 | MakerDAO ETH-A Flipper, um mecanismo de leilão desativado para venda de garantias. |
| 0x35D1b3F3D7966A1DFe207aa4514C12a259A0492B | MakerDAO Vat, o módulo central de contabilidade. |
| 0x2F0b23f53734252Bda2277357e97e1517d6B042A | MakerDAO ETH-A GemJoin, o ponto de saída do ativo de garantia. |
| 0xd90e2f925DA726b50C4Ed8D0Fb90Ad053324F31b | O roteador do Tornado Cash, o endereço que recebeu os fundos roubados. |
| 0x12D66f87A04A9E220743712cE6d9bB1B5616B8Fc | O pool de 0.1 ETH do Tornado Cash, a origem do financiamento inicial do invasor. |
Como o ataque se desenrolou
Implantação do módulo
O exploit começou com o contrato de ataque criando um módulo adaptador em 0xf09a13072Ed939B79Bc25B66AA3a836ea6DCC170. Na criação, o módulo recebeu os seguintes parâmetros: o Flipper, o Vat, o ETH-A GemJoin, o tipo de garantia (ilk), o WETH, um endereço de pagamento e quatro IDs de leilão.
Transferência de permissões
O contrato do invasor chamou a função keeper 0x8804d1de e passou a ela o adaptador recém-criado em 0xf09. O keeper então chamou as funções drip() e vat() do módulo, verificou por meio de Vat.can() se as permissões já haviam sido concedidas a ele e chamou Vat.hope(). Isso deu ao módulo permissões ilimitadas para gerenciar a conta do keeper no sistema Vat.
O callback
O keeper então chamou a função join() do contrato do invasor. Isso entregou o controle ao código escrito pelo invasor em um momento em que as novas permissões já estavam em vigor.
Liquidando os leilões
Dentro do callback, o módulo chamou a função deal(id) do Flipper ETH-A desativado para os leilões 1457, 1458, 1459 e 1460. Em março de 2020, o keeper originalmente havia vencido cada um dos quatro lotes de 50 ETH com um lance zero, mas nunca havia liquidado os negócios. Uma vez que os leilões foram liquidados, 200 ETH foi creditado como colateral ETH-A na conta do keeper no Vat.
Retirando os fundos
O módulo leu o saldo de colateral do keeper e usou as permissões que havia obtido para mover todo o 200 ETH da conta do keeper no Vat para seu próprio endereço com a função flux(). Em seguida, retirou o colateral por meio do ETH-A GemJoin como 200 WETH e enviou o WETH para o contrato do invasor.
O que está no cerne da vulnerabilidade?
A causa raiz do ataque foi a falta de controle de acesso na função 0x8804d1de na implementação do keeper em 0x68399ed8aa33C5b43F863EE6782de492006A5546.
Todas as outras funções privilegiadas do contrato, incluindo os wrappers do keeper para as operações hope, flux e move, primeiro executam uma verificação ds-auth e rejeitam chamadas não autorizadas com o erro ds-auth-unauthorized.
A função 0x8804d1de, por outro lado, aceita qualquer endereço como adaptador, chama Vat.hope() para esse endereço caso o keeper ainda não tenha concedido permissões a ele, e então chama join() no mesmo endereço.
Como o keeper então chamou join(), o módulo do invasor conseguiu executar seu próprio código em um momento em que essas permissões já estavam em vigor.
Os quatro lotes não utilizados de 2020 tornaram essa vulnerabilidade lucrativa para o invasor. Qualquer pessoa pode chamar a função deal para um leilão.
DeFiTuna aprendeu a arredondar: um erro de lógica custou $570 mil em USDC20 de jul. de 2026Leia maisMovimentação dos fundos
O invasor recebeu todo o 200 ETH diretamente na transação usada para explorar a vulnerabilidade. Às 06:19:35 UTC, apenas seis minutos depois, o invasor começou a mover os fundos para o Tornado Cash, enviando-os em 20 depósitos de 10 ETH.

