Back to Blog

#6: Incidente Hundred Finance: Catalisando a Onda de Explorações de Precisão em Protocolos Bifurcados Vulneráveis

Code Auditing
February 16, 2024
7 min read

Em 16 de abril de 2023, o Hundred Finance, um fork do Compound V2, foi atacado, resultando em uma perda de aproximadamente US$ 7,4 milhões. O ataque envolveu dois problemas principais:

  • Um problema de perda de precisão (um problema incorreto de arredondamento);
  • Mercados vazios, que permitiram ao hacker manipular o exchangeRate.

O Compound V2, o protocolo de empréstimo mais bifurcado de acordo com a DeFiLlama, conta com mais de 100 forks. Auditado pela OpenZeppelin e comprovado em batalha, seus contratos são considerados seguros. No entanto, o ataque ao Hundred Finance destacou como a perda de precisão, especialmente em baixa liquidez, pode afetar criticamente a segurança de protocolos DeFi, desencadeando uma série de exploits semelhantes em forks notáveis como Midas e Radiant.

Para uma compreensão mais aprofundada, recomendamos consultar a análise completa. A seguir, apresentamos uma introdução sucinta a este incidente, destacando-o como um dos dez principais incidentes de segurança de 2023.

Contexto

Visão Geral do Hundred Finance

O Hundred Finance é um fork do Compound v2 que opera em múltiplas mainnets, utilizando oráculos Chainlink. Ao contrário das práticas tradicionais de empréstimo em finanças, os protocolos de empréstimo DeFi como Compound e Aave não permitem empréstimos com sobrecolateralização. Em termos simples, se você depositar US$ 100 em Token A, poderá tomar emprestado apenas ativos com valor inferior a US$ 100. De acordo com os coeficientes de controle de risco da maioria dos protocolos, essa proporção normalmente varia de 50% a 80%.

Para protocolos de empréstimo, os métodos de ataque mais comuns incluem manipulação de preço e reentrância. Curiosamente, o Hundred Finance havia sofrido anteriormente um ataque de reentrância em março de 2022, mas este incidente criou um novo vetor de ataque.

hToken

Os protocolos de empréstimo que fazem fork do Compound e do Aave criam um token contábil correspondente para cada token subjacente (colateral). Para o Hundred Finance:

  • USDC corresponde a hUSDC
  • WBTC corresponde a hWBTC

A taxa de câmbio entre o token subjacente e o hToken é referida como exchangeRate.

  • Ao depositar ativos, os usuários devem chamar o mint() do hToken.
  • Ao retirar ativos, o usuário deve chamar o redeem() do hToken.

exchangeRate

A seguir está a fórmula para calcular o exchangeRate: image

Onde:

  • getCash(): A quantidade de saldo do token subjacente pertencente a este contrato hToken. Este é um parâmetro-chave que pode ser manipulado. Por favor, lembre-se disso.
  • totalBorrows(): A quantidade de token subjacente atualmente emprestada pelo mercado, e o valor sobre o qual os juros são acumulados para os fornecedores do mercado.
  • totalReserves(): As reservas são uma entrada contábil em cada contrato hToken que representa uma parcela dos juros históricos reservados como dinheiro que pode ser retirado ou transferido pela governança do protocolo.
  • totalSupply(): O número de tokens atualmente em circulação neste mercado hToken.

Nota: O exchangeRate entre um hToken e o ativo subjacente, por exemplo (dai vs hDai ou eth vs hEth), começa em 0,020 e aumenta a uma taxa igual à taxa de juros composta do mercado.

Liquidação

Para prevenir dívidas incobráveis, os protocolos de empréstimo permitem que qualquer usuário liquide a dívida de outro usuário. Vamos usar o seguinte exemplo para ilustrar:

  1. Alice deposita BTC no valor de US$ 100 e toma emprestado ETH no valor de US$ 70.
  2. Se o preço do ETH subir ou o preço do BTC cair, os ativos de Alice podem atingir o limite de liquidação.
  3. Bob pode usar uma certa quantidade de ETH para liquidar o BTC de Alice, trazendo a dívida de Alice de volta a um nível saudável para garantir a segurança dos fundos do protocolo (o protocolo recompensa os usuários que iniciam a liquidação).

A liquidação não é o foco deste ataque, mas esteve envolvida no ataque. Aqui, precisamos apenas saber que qualquer usuário pode liquidar a dívida de outro usuário com um tipo de Token, o que reduzirá o hToken correspondente.

A Vulnerabilidade

Problema de Perda de Precisão

O hacker faz com que, quando o colateral é retirado via redeem(), o cálculo da quantidade de hToken a ser deduzida resulte em 1,99999992 (muito próximo de 2, mas menor que 2). Ao converter para um número inteiro em truncate(), o uso de arredondamento para baixo leva a um resultado final de 1.

exchangeRate

O cálculo do exchangeRate, conforme apresentado anteriormente, envolve getCash(), que se refere à quantidade de saldo subjacente pertencente ao contrato hToken. Ao transferir diretamente tokens subjacentes para o contrato (sem mint, apenas transferindo), o hacker pode manipular o exchangeRate. No entanto, é importante notar que este problema de exchangeRate por si só não compromete a segurança do protocolo; os hackers não podem lucrar com ele de forma isolada. No contexto deste ataque, foi principalmente explorado para amplificar os ganhos do hacker, permitindo-lhes esvaziar rapidamente o pool. Caso contrário, o ataque passa de um golpe único e decisivo para uma série de pequenas investidas, exigindo inúmeras iterações para ter um impacto significativo.

Para ser breve, a perda de precisão é o problema central deste ataque.

O Processo de Ataque

Aqui está a transação do ataque, e agora usaremos o Phalcon Explorer para analisar esta transação complexa.

Transação: 0x6e9ebcdebbabda04fa9f2e3bc21ea8b2e4fb4bf4f4670cb8483e2f0b2604f451

  1. Tomar emprestado 500 WBTC do Aave V3 por meio de um Flashloan.

  2. Redeem todos os hWBTC adquiridos anteriormente, redefinindo o totalSupply do hWBTC para 0.

O objetivo anterior é preparar fundos de reserva usando um flashloan e redefinir o hWBTC como um novo mercado.

  1. Criar o segundo contrato de ataque (doravante referido como Contrato de Ataque 2) e transferir todos os WBTC (500,30063816 WBTC) para o Contrato de Ataque 2.

  2. Mint() hWBTC usando 4 WBTC para produzir 200 hWBTC.

  3. Redeem() 199,99999998 hWBTC, deixando o total de hWBTC em 0,00000002 (2 wei hWBTC).

  4. Transferir todos os WBTC (500,30063816 WBTC) para o hWBTC. Observe que transferências diretas não aumentam o hWBTC; pode ser visto como doar WBTC ao pool. O principal objetivo desta etapa é manipular o exchangeRate mencionado anteriormente. Neste ponto, o totalSupply do hWBTC permanece em 2 wei hWBTC, mas agora há 500,30064194 WBTC, tornando o exchangeRate centenas de vezes o original.

  5. Tomar emprestado 1021 Ether do mercado hETH.

  6. Redeem() 50030063815 WBTC, onde, após o cálculo, 1,9999992 hBTC deveriam ser deduzidos, mas devido à perda de precisão, apenas 1 hBTC é deduzido, criando uma perda de precisão significativa (quase 50%). Neste ponto, o hacker possui 500 WBTC + 1021 Ether, lucrando com sucesso 1021 Ether.

  7. O atacante liquidate() os hWBTC restantes, redefinindo seu totalSupply para 0, em preparação para continuar os ataques a outros mercados. Dado que quase todo o WBTC dentro do hWBTC foi retirado, o hacker consegue fazer isso com apenas 0,000002 Ether.

  8. Continuar atacando outros mercados, esvaziando todo o protocolo.

  9. Reembolsar o Flashloan ao Aave.

Recomendações de Segurança

Mitigações para Protocolos de Empréstimo

Este problema é prevalente, especialmente para forks do Compound e do Aave. Uma abordagem proativa envolve, ao lançar novos mercados, cunhar alguns tokens contábeis para garantir que o totalSupply nunca chegue a 0.

Mitigações para o Problema de Perda de Precisão

Para contornar melhor a série de problemas decorrentes da perda de precisão, definir um valor mínimo é um método eficaz na prática. Esta estratégia ajuda a evitar o impacto significativo causado pela perda de precisão ao lidar com valores muito pequenos.

Leia outros artigos desta série:

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit