A recente vulnerabilidade do pool Curve é diferente dos incidentes de hacking de criptomoedas que vimos antes, porque desta vez o problema não está diretamente relacionado à vulnerabilidade do contrato inteligente em si, mas ao compilador subjacente da linguagem de programação usada pelo Vyper.

Vyper é uma linguagem de programação orientada a contratos inteligentes que adota um estilo semelhante ao Python e é projetada especificamente para interagir com a Máquina Virtual Ethereum (EVM).

O impacto desta vulnerabilidade é muito grave e enormes quantidades de perdas são noticiadas todos os dias. A situação parece estar sob controle, mas não antes de hackers roubarem mais de US$ 70 milhões. De acordo com a pós-avaliação do LlamaRisk, alguns pools de projetos DeFi também foram atacados por hackers, incluindo o pool pETH/ETH do PEGD que perdeu US$ 11 milhões, o pool msETH/ETH do Metronome que perdeu US$ 3,4 milhões e o pool alETH/ETH da Alchemix que perdeu US$ 11 milhões. 22,6 milhões de dólares americanos, enquanto o pool Curve DAO perdeu aproximadamente 24,7 milhões de dólares americanos.

Esta vulnerabilidade é chamada de erro de reentrada e aparece principalmente em algumas versões da linguagem de programação Vyper, especificamente v0.2.15, v0.2.16 e v0.3.0. Portanto, projetos que utilizam essas versões específicas do Vyper podem se tornar alvos de ataques.

O que é reentrada?​

Para entender por que essa vulnerabilidade ocorreu, vamos primeiro entender o que é reentrada e como funciona.

A chamada reentrada significa que uma função pode ser interrompida durante a execução e chamada novamente com segurança antes que a chamada anterior seja concluída. Esse mecanismo é frequentemente usado em aplicações como manipulação de interrupções de hardware e recursão.

Para que uma função seja reentrante, ela precisa atender a algumas condições:

Primeiro, não pode usar dados globais e estáticos. Esta é uma convenção, o que significa que quando a função for executada, não confie em dados globais ou variáveis ​​estáticas. Porque se uma função for interrompida durante a execução e depois chamada novamente, os dados globais e estáticos podem ser corrompidos ou as informações podem ser perdidas.

Em segundo lugar, não pode modificar o seu próprio código. Não importa quando uma função é interrompida, ela deve poder continuar a execução da mesma forma. Se uma função modificar seu próprio código durante a execução, poderá ocorrer um erro quando chamada novamente.

Finalmente, não pode chamar outras funções que não sejam reentrantes. Ou seja, dentro de uma função reentrante, você não deve chamar outras funções que possam não ser reentrantes. Porque se você fizer isso, poderá causar resultados imprevisíveis, causando falhas ou erros no programa.

É muito difícil de entender, por isso não entraremos em detalhes.

Como foi explorado?

Vamos explicar como os ataques de reentrada levaram ao roubo de fundos e à perda de US$ 70 milhões no ataque Curve.

Em primeiro lugar, sabemos que um ataque de reentrada refere-se a um método no qual um contrato malicioso chama repetidamente uma função num contrato inteligente. No ataque Curve, esta função é utilizada para retirar a liquidez do usuário no pool. Esta função tem a falha de não fazer verificações suficientes antes de atualizar o valor.

Vejamos o processo específico do ataque:

  1. Digamos que um contrato inteligente vulnerável tenha 10 éteres.

  2. O invasor chama a função de depósito e deposita 1 Ethereum.

  3. O invasor então chama a função de retirada e se prepara para retirar 1 Ethereum. Nesta função, verifica se o invasor possui 1 Ethereum em sua conta.

  4. Porém, esta função não atualiza o saldo do contrato antes de transferir 1 Ether para a conta do invasor. Isso significa que o contrato ainda considera que há 10 éteres dentro.

  5. O invasor chama a função de retirada (reentrada) novamente e se prepara para retirar 1 Ethereum novamente.

  6. Como o contrato ainda pensa que há 10 éteres dentro, ele transferirá 1 éter novamente para o atacante.

  7. Este processo se repete até que não haja mais liquidez no contrato.

Dessa forma, o invasor pode chamar repetidamente a função de saque e transferir quase toda a liquidez do contrato para sua própria conta, fazendo com que os fundos do contrato sejam roubados.

Esta vulnerabilidade é muito benéfica para o invasor porque o valor do contrato não é atualizado em tempo real, permitindo ao invasor repetir o ataque até que não haja mais fundos disponíveis para saque no contrato. #Crv