Futuros
Aceda a centenas de contratos perpétuos
TradFi
Ouro
Plataforma de ativos tradicionais globais
Opções
Hot
Negoceie Opções Vanilla ao estilo europeu
Conta Unificada
Maximize a eficiência do seu capital
Negociação de demonstração
Introdução à negociação de futuros
Prepare-se para a sua negociação de futuros
Eventos de futuros
Participe em eventos para recompensas
Negociação de demonstração
Utilize fundos virtuais para experimentar uma negociação sem riscos
Lançamento
CandyDrop
Recolher doces para ganhar airdrops
Launchpool
Faça staking rapidamente, ganhe potenciais novos tokens
HODLer Airdrop
Detenha GT e obtenha airdrops maciços de graça
Launchpad
Chegue cedo ao próximo grande projeto de tokens
Pontos Alpha
Negoceie ativos on-chain para airdrops
Pontos de futuros
Ganhe pontos de futuros e receba recompensas de airdrop
Investimento
Simple Earn
Ganhe juros com tokens inativos
Investimento automático
Invista automaticamente de forma regular.
Investimento Duplo
Aproveite a volatilidade do mercado
Soft Staking
Ganhe recompensas com staking flexível
Empréstimo de criptomoedas
0 Fees
Dê em garantia uma criptomoeda para pedir outra emprestada
Centro de empréstimos
Centro de empréstimos integrado
Centro de Património VIP
Aumento de património premium
Gestão de património privado
Alocação de ativos premium
Fundo Quant
Estratégias quant de topo
Staking
Faça staking de criptomoedas para ganhar em produtos PoS
Alavancagem inteligente
New
Alavancagem sem liquidação
Cunhagem de GUSD
Cunhe GUSD para retornos RWA
Compreender Profundamente os Ataques de Reentrância e Estratégias de Prevenção Eficazes
## O que é um Ataque de Reentrância?
Um ataque de reentrância é uma vulnerabilidade crítica em contratos inteligentes onde uma função pode ser chamada repetidamente antes de completar sua execução inicial. O atacante explora esta janela de tempo para drenar fundos ou manipular o estado do contrato.
### Mecanismo de Ataque
1. Contrato A chama Contrato B (alvo)
2. Contrato B envia fundos para Contrato A
3. Antes de atualizar seu estado, Contrato B recebe uma chamada recursiva
4. Contrato A executa novamente a função de saque
5. Ciclo repete-se até esgotar os fundos
## Casos Históricos Notórios
**The DAO (2016)**
- Perda: 3,6 milhões de ETH (~$50 milhões)
- Conseguiu-se um hard fork para reverter a transação
**Wormhole Bridge (2022)**
- Perda: 325 milhões de dólares
- Exploração de assinatura inválida combinada com reentrância
## Técnicas de Prevenção
### 1. Padrão Checks-Effects-Interactions (CEI)
```solidity
function withdraw(uint amount) public {
// Verificação
require(balances[msg.sender] >= amount);
// Efeitos (atualizar estado)
balances[msg.sender] -= amount;
// Interações (transferir fundos)
(bool success, ) = msg.sender.call{value: amount}("");
require(success);
}
```
### 2. Mutex/ReentrancyGuard
```solidity
contract Protected {
uint private locked = 1;
modifier nonReentrant() {
require(locked == 1);
locked = 2;
_;
locked = 1;
}
function withdraw() public nonReentrant {
// Código protegido
}
}
```
### 3. Pull Pattern (Recomendado)
```solidity
mapping(address => uint) withdrawals;
function withdraw() public {
uint amount = withdrawals[msg.sender];
withdrawals[msg.sender] = 0;
(bool success, ) = msg.sender.call{value: amount}("");
require(success);
}
```
### 4. Usar OpenZeppelin ReentrancyGuard
```solidity
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract MyContract is ReentrancyGuard {
function withdraw() public nonReentrant {
// Implementação segura
}
}
```
## Tipos de Reentrância
| Tipo | Descrição | Risco |
|------|-----------|-------|
| **Simples** | Chamada recursiva direta | Alto |
| **Cross-função** | Múltiplas funções do mesmo contrato | Alto |
| **Cross-contrato** | Envolve múltiplos contratos | Crítico |
| **Read-only** | Reentrância em funções de leitura | Baixo |
## Boas Práticas de Segurança
### ✅ Fazer
- Sempre atualizar estado antes de fazer chamadas externas
- Usar bibliotecas auditadas como OpenZeppelin
- Implementar limites de taxa (rate limiting)
- Realizar auditorias de segurança
- Testar com ferramentas como Echidna e Slither
### ❌ Evitar
- Confiar em `transfer()` desatualizado
- Enviar ETH com `send()` (gás limitado)
- Assumir que contratos externos são seguros
- Ignorar warnings de ferramentas estáticas
## Ferramentas de Detecção
| Ferramenta | Função |
|-----------|--------|
| Slither | Análise estática de vulnerabilidades |
| Mythril | Verificação simbólica |
| Echidna | Testes de propriedade fuzzy |
| MythX | Análise em nuvem |
## Exemplo Completo - Antes e Depois
**❌ Vulnerável:**
```solidity
function withdraw(uint amount) public {
require(balances[msg.sender] >= amount);
msg.sender.call{value: amount}("");
balances[msg.sender] -= amount; // Tarde demais!
}
```
**✅ Seguro:**
```solidity
function withdraw(uint amount) public nonReentrant {
require(balances[msg.sender] >= amount);
balances[msg.sender] = 0;
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
}
```
## Conclusão
A reentrância permanece uma das vulnerabilidades mais perigosas em Web3. A aplicação rigorosa dos padrões CEI, uso de guard modifiers e testes abrangentes são essenciais para a segurança de contratos inteligentes.
Ataque de reentrância é uma das ameaças de segurança mais graves para contratos inteligentes. Este artigo irá ensinar-lhe não só como funciona a reentrância, mas também como proteger o seu projeto de forma abrangente.
Para uma visão completa, começaremos pelos conceitos básicos, depois analisaremos códigos de ataques reais e, por fim, exploraremos três técnicas de proteção comprovadas: desde o modifier nonReentrant() até ao GlobalReentrancyGuard() e ao padrão de checagem-efeito-interação.
O que é um tipo de ataque de reentrância?
Imagine dois contratos inteligentes a interagir entre si. ContractA e ContractB podem chamar-se mutuamente. Parece normal, mas essa é precisamente a vulnerabilidade que um atacante pode explorar.
O conceito central de reentrância é: um contrato inteligente pode chamar de volta outro contrato enquanto este ainda está a ser executado. Isto cria um ciclo infinito se não for controlado corretamente.
Para ilustrar, considere a seguinte situação: ContractA detém 10 Ether, tendo ContractB enviado 1 Ether para lá. Normalmente, quando ContractB solicita uma retirada, verifica-se (saldo > 0), envia-se Ether, e o saldo é atualizado para 0. Mas com reentrância, este processo pode ser repetido várias vezes antes de o saldo ser atualizado.
Como funciona um ataque de Reentrância
O atacante precisa de duas componentes principais: uma função attack() e uma fallback().
A fallback é uma função especial em Solidity — uma função externa sem nome, sem parâmetros e sem valor de retorno. É ativada automaticamente quando:
Agora, veja como o ataque ocorre passo a passo:
Passo 1: O atacante chama attack(), que por sua vez chama a função de retirada de ContractA.
Passo 2: ContractA verifica se o saldo de ContractB é maior que zero. Como é, envia 1 Ether para ContractB e ativa a fallback.
Passo 3: Aqui está o ponto crucial — o saldo ainda não foi atualizado para 0. ContractA ainda está a executar a função de retirada.
Passo 4: A fallback é ativada e imediatamente chama novamente a função de retirada de ContractA.
Passo 5: ContractA verifica novamente — o saldo de ContractB ainda é 1 Ether (a atualização ainda não ocorreu). Envia mais 1 Ether e ativa fallback novamente.
Este ciclo repete-se até que ContractA fique sem Ether. É por isso que a reentrância é tão perigosa.
Análise do código do ataque específico
Para entender melhor, vejamos um exemplo com o contrato EtherStore. Este contrato tem duas funções principais:
A função withdrawAll() faz: verifica (saldo > 0), envia Ether, atualiza saldo para 0.
Este é o ponto vulnerável. Como o envio de Ether ocorre antes da atualização, o atacante pode intervir.
O contrato Attack é projetado para explorar isso. Ele possui:
O processo de ataque é simples:
Três técnicas de proteção contra ataques de Reentrância
Técnica 1: Uso do Modifier nonReentrant
A forma mais simples de proteger uma única função é usar o modifier nonReentrant. Um modifier é uma função especial em Solidity que permite acrescentar condições ou funcionalidades adicionais às funções, sem reescrever toda a lógica.
Como funciona o nonReentrant:
Desvantagem: o nonReentrant protege apenas uma função, não impedindo ataques de reentrância cruzada entre funções diferentes.
Técnica 2: Padrão Check-Effect-Interaction
Este método mais avançado protege múltiplas funções. Em vez de bloquear o contrato, altera a ordem de execução do código.
Este padrão exige:
Exemplo de código vulnerável vs código seguro:
Ao atualizar o saldo logo após a verificação, mesmo que uma chamada recursiva aconteça, o saldo já estará atualizado, impedindo o ataque.
Técnica 3: GlobalReentrancyGuard para múltiplos contratos
Esta técnica é para projetos com vários contratos inteligentes interagindo. Consiste em criar um contrato central que controla o reentrancy em toda a rede.
Ao invés de cada contrato ter sua própria variável de bloqueio, todos referenciam um GlobalReentrancyGuard. Assim:
Por exemplo: se uma transferência agendada envia Ether para AttackTransfer, a fallback de AttackTransfer pode tentar chamar novamente funções em ScheduledTransfer. O guard global detecta e bloqueia isso.
Como escolher a técnica de proteção adequada
Use nonReentrant quando:
Use Check-Effect-Interaction quando:
Use GlobalReentrancyGuard quando:
A melhor abordagem é combinar as três técnicas conforme as necessidades específicas do seu projeto.
Conclusão
Ataques de reentrância não são uma ameaça difícil de prevenir, desde que compreenda seu funcionamento e aplique as técnicas corretas. Desde o simples modifier nonReentrant até ao abrangente GlobalReentrancyGuard, cada ferramenta tem seu papel na segurança dos contratos inteligentes.
Lembre-se: segurança não é uma opção, é uma obrigação. Compreendendo os ataques de reentrância e implementando as proteções adequadas, você pode criar contratos inteligentes seguros e eficientes.
Para ficar atualizado sobre segurança Web3, Solidity, auditoria de contratos e temas relacionados, siga @TheBlockChainer no Twitter.