Futuros
Acesse centenas de contratos perpétuos
TradFi
Ouro
Plataforma única para ativos tradicionais globais
Opções
Hot
Negocie opções vanilla no estilo europeu
Conta unificada
Maximize sua eficiência de capital
Negociação demo
Introdução à negociação de futuros
Prepare-se para sua negociação de futuros
Eventos de futuros
Participe de eventos e ganhe recompensas
Negociação demo
Use fundos virtuais para experimentar negociações sem riscos
Lançamento
CandyDrop
Colete candies para ganhar airdrops
Launchpool
Staking rápido, ganhe novos tokens em potencial
HODLer Airdrop
Possua GT em hold e ganhe airdrops massivos de graça
Launchpad
Chegue cedo para o próximo grande projeto de token
Pontos Alpha
Negocie on-chain e receba airdrops
Pontos de futuros
Ganhe pontos de futuros e colete recompensas em airdrop
Investimento
Simple Earn
Ganhe juros com tokens ociosos
Autoinvestimento
Invista automaticamente regularmente
Investimento duplo
Lucre com a volatilidade do mercado
Soft Staking
Ganhe recompensas com stakings flexíveis
Empréstimo de criptomoedas
0 Fees
Penhore uma criptomoeda para pegar outra emprestado
Centro de empréstimos
Centro de empréstimos integrado
Centro de riqueza VIP
Planos premium de crescimento de patrimônio
Gestão privada de patrimônio
Alocação premium de ativos
Fundo Quantitativo
Estratégias quant de alto nível
Apostar
Faça staking de criptomoedas para ganhar em produtos PoS
Alavancagem Inteligente
Alavancagem sem liquidação
Cunhagem de GUSD
Cunhe GUSD para retornos em RWA
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.