Aprenda a evitar ataques de negação de serviço (DOS) em contratos inteligentes, garantindo que as filas sejam seguras, lidando com baixos tokens decimais e gerenciando com segurança chamadas externas.
Bem -vindo de volta à série Solodit Checklist Resolution Series. Continuaremos a explorar as listas de verificação de auditoria do Solodit Smart Contract , concentrando -se em estratégias práticas para escrever contratos inteligentes seguros e resilientes.
Esta lista de verificação ajuda a identificar possíveis vulnerabilidades e implementar medidas proativas de segurança. Na seção anterior " Resolução da Lista de Verificação Solodit (1) ", examinamos três listas de verificação ( padrão de extração, quantidade mínima de transação e lista negra ) relacionadas a um ataque de negação de serviço (DOS) e forneceu soluções para desenvolvedores. Se você ainda não leu, recomendo verificar o artigo antes de continuar.
Neste artigo, discutiremos outros três itens na lista de verificação, concentrando -se novamente nos ataques do DOS. Vamos mergulhar nas vulnerabilidades de manuseio da fila , os desafios colocados por baixos tokens decimais e a importância de lidar com chamadas de contrato externas com segurança .
Para obter a melhor experiência, abra uma tag Solodit Checklist para referência.
Aqui está o que discutiremos hoje:
SOL-AM-DOSA-4: Bloqueio de manuseio da fila : esse problema ocorre quando um invasor manipula a fila para pausar ou interromper suas operações, resultando em DOS. Veremos como os atacantes podem destruir filas de processamento.
SOL-AM-DOSA-5: Baixo tokens decimais : problemas que ocorrem ao lidar com tokens com casas decimais baixas. O cálculo, especialmente a divisão, pode ser truncado a zero, resultando em comportamento inesperado e prejudicial. Esses tokens de baixa precisão podem causar problemas com a divisão inteira, interferindo assim nas principais funções.
SOL-AM-DOSA-6: Chamadas externas inseguras : exploraremos como confiar em contratos externos sem tratamento adequado de erros para criar vulnerabilidades. Quando a falha de uma chamada externa não é tratada corretamente, pode fazer com que todo o contrato recue .
Os ataques do mundo real provam o potencial dano que essas vulnerabilidades podem causar. O projeto sofreu grandes perdas devido a negligência aparentemente menor.
As listas de verificação de solodit são baseadas em descobertas de auditoria, relatórios de recompensas de vulnerabilidades e eventos do mundo real. Ao estudar essas listas de verificação, você pode aprender com os erros do passado e melhorar a segurança do seu código .
Agora, vejamos cada item de verificação um por um através do código de amostra. Esses exemplos foram simplificados para destacar as principais vulnerabilidades.
Problema : se seu contrato inteligente depende de uma fila para processamento de tarefas, um invasor poderá manipular um estado específico na fila para evitar o processamento correto.
Pergunta da lista de verificação : "Um bloqueio de invasor pode impedir o processamento da fila para causar interrupções no serviço?"
Solução : Seu mecanismo de manuseio da fila requer poderosos mecanismos de manuseio de erros e fallback para garantir que os problemas possam continuar sendo processados, mesmo que ocorram.
Exemplo :
Considere um exemplo de extração de uma fila:
O usuário solicita a extração e alguns sinalizadores indicam que a solicitação está ativa.
O invasor pode usar a função resetUserStatus
após a extração ser criada para impedir a mesma operação de outros usuários.
// 易受攻击的函数:可以被利用function resetUserStatus() external { // 任何人在仍然处于队列中的情况下都可以重置他们的状态withdrawalRequested[msg.sender] = false; // 注意:用户没有被移出队列! } // 处理队列中的下一次提取function processNextWithdrawal() external { require(withdrawalQueue.length > currentIndex, "没有可处理的提取"); // 获取下一次提取Withdrawal memory withdrawal = withdrawalQueue[currentIndex]; // 可被攻击者利用:此检查可能会被重置状态所攻击require(withdrawalRequested[withdrawal.user], "提取请求不再有效"); // 处理提取uint256 amount = withdrawal.amount; require(balances[withdrawal.user] >= amount, "余额不足"); // 更新余额balances[withdrawal.user] -= amount; // 重置提取请求withdrawalRequested[withdrawal.user] = false; // 发送资金(bool success, ) = payable(withdrawal.user).call{value:amount}(""); require(success, "资金发送失败"); // 移动到队列中的下一个currentIndex++; }
Para aproveitar isso, um invasor pode fazer o seguinte:
resetUserStatus
.processNextWithdrawal
recairá, causando um ataque contínuo do DOS.Remédios :
withdrawalRequested
ao administrador.Problema : Tokens com baixos casas decimais podem causar problemas de divisão inteira, arredondando para zero .
Imagine um contrato de streaming de token alocando tokens por um período de tempo. Se tokensPerSecond
rodadas zero devido à divisão inteira com baixos tokens decimais, a função de alocação será bloqueada. Pergunta da lista de verificação : "Os baixos tokens decimais levam ao DOS?" Solução : Implemente a lógica para lidar com baixos pontos decimais para evitar a interrupção dos processos de negociação devido a erros de arredondamento. Exemplo :
Considere um contrato TokenStream
que transmite regularmente um certo número de tokens para os usuários, onde:
total_tokens
precisa ser transferido para o contratotoken_per_second
pode ser arredondado para zero porque estamos usando tokens com um ponto decimal de 1distributeTokens
voltará contract TokenStream { IERC20 public token; uint256 public streamDuration; uint256 public tokensPerSecond; constructor(IERC20 _token, uint256 _streamDuration, uint256 _tokensPerSecond) { token = _token; streamDuration = _streamDuration; tokensPerSecond = _tokensPerSecond; } function distributeTokens(address recipient) external { uint256 balance = token.balanceOf(address(this)); uint256 amount = tokensPerSecond * streamDuration; uint256 tokensToSend = amount > balance ? balance : amount; require(tokensToSend > 0, "没有足够的代币进行流送"); token.transfer(recipient, tokensToSend); } } contract LowDecimalToken is ERC20 { constructor() ERC20("LowDecimalToken", "LDT") { _mint(msg.sender, 100000 * (10 ** decimals())); } function decimals() public view virtual override returns (uint8) { return 1; // 模拟小数点为低的代币} }
Nesse caso, o teste testDOSWithLowDecimalTokens
no TokenStreamTest
será revertido.
Solução : Certifique -se de que o contrato lida com os baixos tokens decimais corretamente, aliviando os problemas causados pelo arredondamento dos números inteiros durante o processo de cálculo, dimensionando as fórmulas matemáticas .
Problema : Muitos contratos inteligentes dependem de contratos externos para interagir. O comportamento inesperado de contratos externos pode fazer com que todo o sistema recue . A falha em lidar com esses erros externos pode levar a vulnerabilidades do DOS.
Pergunta da lista de verificação : "O protocolo lida com as interações de contrato externo com segurança?"
Solução : Garanta um forte tratamento de erros para interações de contrato externas para proteger a integridade do protocolo, independentemente do desempenho de contratos externos.
Exemplo : considere um contrato que interage com uma fonte de dados de preços de cadeia externa. Se você não usar o Try/Catch para obter um manuseio de erro adequado, quaisquer reversão de fontes de dados externas se propagam para o superior e farão com que o contrato seja revertido.
getPrice
recupera dados de preço.calculateSomethingImportant
a função é importante depende do getPrice
e também reverterá. contract PriceDependentContract { AggregatorV3Interface public priceFeed; constructor(address _priceFeed) { priceFeed = AggregatorV3Interface(_priceFeed); } // 易受攻击的函数,在没有处理可能的Chainlink 回滚的情况下获取价格function getPrice() public view returns (uint256) { (, int256 price, , , ) = priceFeed.latestRoundData(); // 易受攻击的行:没有错误处理require(price > 0, "价格必须为正"); return uint256(price); } function calculateSomethingImportant() public view returns (uint256) { uint256 price = getPrice(); // ... 使用价格的一些重要计算return price * 2; }
Solução : envolva chamadas de contrato externo em um bloco de tentativa/captura para lidar com erros de reversão e implementar valores de reversão ou cache.
Nota : Há um caso de borda em que o contrato externo consome intencionalmente gás , que também pode falhar no bloco de captura! Discutiremos isso mais tarde.
Exploramos três verificações importantes projetadas para aprimorar a capacidade do seu contrato inteligente de resistir aos ataques do DOS: vulnerabilidades de manuseio de filas , desafios associados a baixos tokens decimais e a importância de lidar com as interações externas do contrato com segurança .
Lembre -se de que os exemplos fornecidos têm como objetivo ilustrar as vulnerabilidades principais. É muito importante entender os princípios básicos e adaptar esses conceitos aos seus casos de uso específicos.
Ao implementar essas sugestões, você pode melhorar significativamente a segurança e a resiliência de seus contratos inteligentes.
Fique atento para a próxima parte da série Solodit Checklist Resolution.
- Link original: cyfrin.io/blog/solodit-c ...
- A Comunidade Dengliana Assistente de IA traduz excelentes artigos em inglês para todos. Se houver alguma área em que a tradução não seja compreensível, por favor me perdoe ~