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
Acabei de querer partilhar um problema de segurança de smart contracts que muitos programadores ainda ignoram — o ataque de reentrancy. Se estiver a construir smart contracts em Solidity, isto é algo que tem de compreender bem.
De forma simples, a reentrancy acontece quando um contrato chama outro contrato, e esse contrato pode chamar novamente o contrato original enquanto ainda está a ser executado. Imagine que tem o ContractA que contém 10 Ether e o ContractB envia 1 Ether para ele. Quando o ContractB levanta dinheiro, o ContractA verifica se o saldo é maior do que 0; se for, envia Ether de volta. No entanto, se o ContractB tiver uma fallback function (função de fallback), ele pode chamar novamente a função de levantamento do ContractA enquanto esta ainda não terminou. Resultado? O saldo do ContractB continua a ser registado como 1 Ether, por isso ele recebe mais 1 Ether, e assim por diante, repetidamente, até o ContractA ficar sem fundos.
Como funciona este ataque? O atacante precisa de duas coisas: uma função attack() para começar, e uma fallback function para chamar novamente a função de levantamento. A fallback function é uma função externa especial, sem nome, sem parâmetros; qualquer pessoa a pode ativar ao chamar uma função inexistente, sem enviar dados, ou ao enviar Ether sem quaisquer dados adicionais.
Há um exemplo concreto: o contrato EtherStore tem uma função deposit() que armazena o saldo e uma função withdrawAll() que levanta tudo. O problema é que withdrawAll() verifica o saldo, envia Ether e só depois atualiza o saldo para 0. Isto cria uma brecha para que a ataque de reentrancy ocorra.
Então como se protege? Vou mostrar três formas.
Em primeiro lugar, usar o modifer noReentrant. A ideia é muito simples: bloquear o contrato enquanto a função está a ser executada. Se alguém tentar chamar novamente essa função, tem de passar na verificação do lock primeiro; mas o lock só será desbloqueado depois de a função terminar. O modifer é um tipo de função especial que permite adicionar condições a outras funções sem precisar de reescrever toda a lógica.
Em segundo lugar, aplicar o padrão Check-Effect-Interaction. Em vez de verificar a condição, enviar fundos e só depois atualizar o saldo, deve verificar primeiro, atualizar o saldo imediatamente (antes de enviar fundos), e só depois realizar a interação com a parte externa. Desta forma, mesmo que ocorra reentrancy, o saldo já terá sido atualizado para 0, por isso o atacante não conseguirá levantar mais.
Em terceiro lugar, se o seu projeto tiver muitos contratos a interagir entre si, precisa de GlobalReentrancyGuard. Em vez de bloquear apenas uma função, bloqueia todo o sistema com uma variável de estado guardada num contrato separado. Quando qualquer função de qualquer contrato é chamada, ela verifica se o sistema está bloqueado. Se estiver, a transação é rejeitada. Isto é especialmente útil quando tem contratos como ScheduledTransfer a enviar fundos para AttackTransfer — o GlobalReentrancyGuard impede que toda a cadeia do ataque de reentrancy aconteça.
O bom destas três abordagens é que pode combiná-las conforme a situação. Uma função importante? Use noReentrant. Muitas funções relacionadas? Use o Check-Effect-Interaction. Todo o projeto é complexo? Use o GlobalReentrancyGuard. Compreender a reentrancy e como preveni-la vai ajudar a construir smart contracts muito mais seguros.