Introdução
A integração de tokens em contratos inteligentes pode ser um processo complexo e arriscado. Para garantir a segurança e a confiabilidade do seu contrato, é importante estar atento às ocorrências comuns e aos possíveis problemas que podem surgir durante o processo de integração. Neste artigo, forneceremos uma lista de verificação dessas ocorrências comuns, bem como uma explicação dos problemas potenciais que eles podem causar e como corrigi-los.
Nota:
Essas informações foram compiladas usando o workshop OpenZeppelin sobre desenvolvimento seguro e o repositório “weird-erc20” no GitHub. Muitos dos exemplos mostrados aqui são dessa fonte.
Links:
- https://blog.openzeppelin.com/workshop-recap-secure-development-workshop-1/
- https://github.com/d-xo/weird-erc20
Capacidade de bloquear endereços
A capacidade de bloquear endereços é um recurso de segurança incluído em alguns contratos de token, como o USDC e o USDT. Esse recurso permite que contas privilegiadas evitem que determinados endereços transfiram tokens, o que pode ser útil em determinadas situações, como quando um proprietário de contrato precisa congelar os ativos de um usuário específico ou quando uma ação regulatória exige que certas contas sejam bloqueadas de interagir com o contrato.
Possível problema
A capacidade de bloquear endereços também pode ser utilizada por proprietários mal-intencionados ou comprometidos. Os proprietários podem reter fundos adicionando os endereços à lista de bloqueio.
Consideração
Para se proteger contra esses tipos de ataques, é importante revisar cuidadosamente os privilégios e permissões concedidos a contas privilegiadas em contratos com os quais você está interagindo.
Capacidade de pausar contratos de token
A capacidade de pausar contratos de token é um recurso incluído em alguns contratos de token, como o USDC, o USDT e o BNT. Esse recurso permite que contas privilegiadas desativem determinadas funções do contrato, como transferir, aprovar e sacar, dependendo da implementação específica.
Possível problema
Embora esse recurso possa ser útil em determinadas situações, também pode causar problemas para contratos que usam o token pausado. Por exemplo, se um contrato de token for pausado enquanto seu contrato está tentando usá-lo, a chamada de função pode falhar ou resultar em comportamento não intencional. Isso pode potencialmente interromper ou quebrar seu contrato.
Consideração
Para se proteger contra esse risco, é importante considerar o cenário em que um contrato de token é pausado ao redigir seu contrato. Também é recomendável testar esse recurso e quaisquer cenários relacionados para garantir que seu contrato possa lidar com a funcionalidade de pausa corretamente.
Por exemplo, você pode incluir um modificador whenNotPaused
em seu contrato para garantir que determinadas funções sejam executadas apenas quando o contrato de token não for pausado.
modifier whenNotPaused {
require(!paused);
_;
}
function transfer(address _to, uint256 _value) public whenNotPaused {
// codigo para transferir tokens
}
Tokens que executam código arbitrário em emissores/receptores usando ganchos
Ganchos (hooks), de acordo com o OpenZeppelin, são apenas funções que são chamadas antes ou depois que uma ação ocorre. Eles servem como um ponto centralizado a partir do qual se conectam e estendem o comportamento original.
Em um contrato inteligente, ganchos “enviar” e “receber” referem-se a funções que são chamadas automaticamente quando um contrato envia ou recebe uma mensagem (ou seja, chama outro contrato ou envia fundos para outra conta). Esses ganchos podem ser usados para executar ações adicionais ou modificar o comportamento do contrato quando determinadas condições forem atendidas.
Possível problema
Se esses ganchos não forem implementados com segurança, é possível que um invasor os use para obter acesso não autorizado ao contrato ou para explorar vulnerabilidades no código do contrato.
Por exemplo, um invasor pode usar o gancho “enviar” para executar um código malicioso ou roubar fundos do contrato ao enviar uma mensagem para outro contrato ou conta.
Da mesma forma, um invasor pode usar o gancho “receber” para executar ações não autorizadas ou roubar fundos quando o contrato recebe uma mensagem de outro contrato ou conta.
A maioria dos padrões de token implementa esses ganchos na conta do remetente, no destinatário ou em ambas.
Exemplos:
- ERC777 → ganchos no emissor e no receptor.
- ERC721 → ganchos no receptor.
- ERC1363 → ganchos no gastador e no receptor.
Consideração
Para se proteger contra ataques que usam ganchos de envio e recebimento, é recomendável usar o padrão de design “Checks-Effects-Interactions” para evitar ataques de reentrância. Isso envolve a verificação de condições, a execução de efeitos e a interação com outros contratos ou recursos externos. Seguindo esse padrão, você pode ajudar a garantir que o estado do contrato não seja modificado por um invasor durante a execução de uma função.
Além disso, pode ser necessário usar bloqueios mutex ou outros mecanismos de sincronização para impedir a execução simultânea de funções críticas.
Tokens que impedem determinadas operações de transferência
Alguns tokens podem incluir restrições em certas operações de transferência para ajudar a proteger contra vulnerabilidades de segurança comuns. Por exemplo, um token pode impedir transferências para o próprio contrato de token, para o endereço zero, para o endereço do chamador ou de valor zero.
Consideração
Recomenda-se incluir verificações em seu contrato para garantir que esses tipos de transferências não sejam permitidas.
Por exemplo, você pode usar a palavra-chave require
para verificar as condições que devem ser verdadeiras antes de executar uma função de transferência.
function transfer(address _to, uint256 _value) public {
require(_to != address(0), "Não pode ser transferido para o endereço zero");
require(_to != address(this), "Não pode ser transferido para o contrato em si");
require(_to != msg.sender, "Não pode ser transferido para o endereço do chamador");
require(_value != 0, "Não é possível transferir um valor zero");
// código para transferir tokens
}
Ao incorporar essas verificações em seu contrato, você pode ajudar a diminuir a probabilidade de comportamento não intencional que pode levar a uma vulnerabilidade.
Tokens que cobram taxas nas transferências
Alguns tokens podem cobrar taxas em transferências ou ter um recurso de taxa que ainda não foi ativado, mas pode ser no futuro. Por exemplo, o token USDT é um token que pode receber taxas em transferências (embora esse recurso não esteja ativado no momento).
Possível problema
Se um contrato interagir com tokens que tenham taxas habilitadas, é importante contabilizar essas taxas para evitar corrupção interna na contabilidade. Se o valor transferido não for ajustado pelas taxas, o destinatário pode receber um número de tokens diferente do esperado, o que pode causar corrupção de dados e levar a problemas maiores.
Consideração
Existem várias maneiras de prevenir esse problema.
Por exemplo, o protocolo Compound atualiza seus registros:
- Verificando o saldo pré-transferência;
- Executando a transferência;
- Verificando o saldo pós-transferência;
- Em seguida, contabilizando a diferença entre os dois saldos.
Isso garante que quaisquer taxas sejam contabilizadas.
O contrato Uniswap V2 usa um método ligeiramente diferente, contabilizando o número real de tokens recebidos. Isso pode ser feito usando um código semelhante ao seguinte:
uint balance0 = IERC20(token0).balanceof(address(this));
Desta forma, quaisquer taxas extras são sempre contabilizadas.
Tokens que possuem diferentes formas de sinalizar sucesso e falha
Existem várias maneiras pelas quais os tokens podem sinalizar sucesso ou falha durante as operações de transferência e aprovação. Alguns tokens revertem em caso de falha, enquanto outros retornam sinalizadores booleanos ou apresentam comportamentos mistos.
- No caso do USDT, a função de transferência não retorna nenhum valor.
Possível problema
Isso pode ser problemático se o seu contrato depender de um valor de retorno específico após uma transferência, pois nem todos os tokens retornam a mesma coisa.
Consideração
Uma solução para esse problema é usar wrappers (são conhecidos na linguagem Java como classes especiais que possuem métodos capazes de fazer conversões em variáveis primitivas e também de encapsular tipos primitivos para serem trabalhados como objetos, ou seja, é feito um embrulho de streams, que são fluxo de dados através de canais) para um comportamento mais consistente.
A biblioteca SafeERC20 do OpenZeppelin Contracts fornece um conjunto de operações seguras que podem ser usadas para lidar com comportamentos inconsistentes em diferentes tokens.
- Para usar esta biblioteca, você pode adicionar uma instrução de instrução do SafeERC20 para o IERC20 ao seu contrato, que permite chamar as operações seguras.
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
Contract ...{
using SafeERC20 for IERC20;
}
Tokens que podem ser emprestados através de empréstimos relâmpago ou ter grande oferta total
É importante estar ciente de que os tokens podem ser de empréstimos ou cunhagens relâmpago, permitindo que qualquer pessoa possua temporariamente uma grande quantidade de tokens, mesmo que normalmente não tenham um saldo significativo.
Possível problema
Isso pode causar problemas se o seu contrato não for projetado para lidar com grandes saldos, pois pode quebrar em determinados cenários ou ser explorado.
Consideração
Para evitar problemas, é importante testar valores extremos em operações como trocas, depósitos e outras. Isso pode ajudar a garantir que seu contrato seja capaz de lidar com grandes saldos e funcionar adequadamente em todas as circunstâncias.
Tokens que modificam saldos fora das operações de transferência
Alguns tokens são capazes de modificar saldos fora das operações de transferência, o que pode causar problemas se o seu contrato não estiver preparado para esse comportamento. Exemplos de tokens que podem modificar saldos fora das operações de transferência incluem o UBI, AMPL e aTokens da AAVE.
Possível problema
Se o seu contrato estiver interagindo com um token que modifica saldos fora das operações de transferência, é importante estar ciente desse comportamento. O saldo desses tokens pode mudar em várias chamadas, mesmo que a conta não tenha enviado ou recebido nenhum token, o que pode causar problemas.
Consideração
Para evitar problemas com esses tipos de tokens, certifique-se de que seu contrato considere essas alterações de saldo e use a lógica adequada. Você pode, por exemplo, utilizar a função balanceOf
para manter sua contabilidade atualizada.
Tokens que possuem um mecanismo de aprovação “infinito”
Alguns tokens permitem que os usuários aprovem uma quantidade ilimitada de tokens para outros. Isso significa que sempre que ocorre uma operação transferFrom
, a quantidade aprovada de tokens não é diminuída. Esse tipo de comportamento pode ser encontrado em muitos tokens populares, como DAI, e é projetado para melhorar a experiência do usuário.
Possível problema
É importante estar ciente desse comportamento e documentá-lo claramente para os usuários do seu protocolo. Se não for devidamente contabilizado, esse tipo de mecanismo de aprovação “infinito” pode levar a possíveis exploits (programas ou códigos projetados para abusar de vulnerabilidades de software ou hardware).
Consideração
Para se proteger contra isso, é recomendável comunicar claramente aos usuários como funciona a função de aprovação e estar atento a esse comportamento ao elaborar seu contrato.
Tokens que não expõem decimais, funções de nome e símbolo
Se você já leu o padrão ERC20, deve ter percebido que as funções decimais, nome e símbolo não são obrigatórias para que um token cumpra a interface. Na prática, essas funções geralmente são apenas consideradas como implementadas.
Possível problema
Se o seu contrato incorporar qualquer uma delas em sua lógica e um token não as implementar, isso poderá resultar em problemas.
Consideração
Alguns projetos que podem se integrar com tokens arbitrários foram vistos usando a estrutura try/catch para consultar essas funções.
Exemplo:
- Como o contrato da UMA lida com isso?
// IERC20Standard. decimais) reverterá se o contrato de garantia não tiver implementado o método decimal
// o que é possível uma vez que o método é apenas um método OPTATIVO no padrão ERC20:
// https://eips.ethereum.org/EIPS/eip-20#methods
function getSyntheticDecimals(address collateralAddress) public view returns (uint8 decimals)
{
try IERC20Standard(collateralAddress).decimals) returns (uint8 _decimals)
{
return decimals;
}
catch
{
return 18;
}
}
Tokens que não possuem 18 casas decimais
Embora tokens com 18 decimais sejam a norma, não assuma cegamente que isso se aplica a todos os tokens. O USDC tem 6 casas decimais, os cTokens da Compound e o WBTC tem 8.
Possível problema
Se o seu contrato manusear tokens com números variados de casas decimais sem considerar esse fato, isso pode levar a cálculos incorretos e potencialmente comprometer a integridade do seu contrato.
Correção
Para lidar adequadamente com tokens com precisão decimal fora do padrão, você precisará levar em conta essas diferenças no código do seu contrato. Isso pode envolver o ajuste de seus cálculos ou o uso de uma função decimals()
fornecida pelo contrato do token para converter adequadamente entre as unidades de base e de exibição.
É importante testar completamente seu contrato com uma variedade de tokens diferentes para garantir que ele possa lidar corretamente com tokens com precisão decimal variável.
Condição de corrida ERC20
Alguns tokens podem não mitigar a conhecida condição de corrida ERC20. Essa vulnerabilidade permite que invasores potencialmente roubem tokens, explorando a condição de corrida no padrão ERC20.
Possível problema
Se um token não mitigar a condição de corrida ERC20, ele é potencialmente vulnerável a ataques.
Consideração
Certifique-se de que o contrato de token mitiga adequadamente a condição de corrida ERC20 para proteger contra possíveis ataques. Considere o uso de uma biblioteca como a OpenZeppelin Contracts, que fornece uma implementação testada e segura do padrão ERC20.
Tokens que não protegem contra o ataque de front-running de permissão ERC20, ou que o fazem de maneira não padrão
O “ataque de front-running de permissão” nos tokens ERC20 é uma fraqueza bem conhecida no padrão. Alguns tokens, como aqueles implementados usando a biblioteca OpenZeppelin Contracts, fornecem funcionalidade adicional em sua interface para ajudar a mitigar os riscos associados. Outros tokens adotam uma abordagem diferente, como o USDT, que não permite a aprovação de tokens quando o valor da aprovação já é positivo.
Possível problema
Diferentes métodos introduzem um desvio que pode causar problemas de interoperabilidade se não for considerado.
Consideração
Revise minuciosamente o código do contrato de token antes de integrá-lo ao seu próprio contrato para garantir que você entenda como ele está lidando com o ataque front-running de permissão.
Tokens que não emitem eventos esperados
Os serviços off-chain podem contar com eventos registrados para rastrear operações de token.
Possível problema
Nem todos os tokens emitem eventos ou os mesmos eventos. Se essas sutilezas não forem levadas em consideração, sua contabilidade off-chain pode ser imprecisa e introduzir erros inesperados em seus sistemas.
Consideração
Antes de integrar um token em seu contrato ou serviço off-chain, certifique-se de revisar completamente seu comportamento de emissão de eventos e garantir que ele esteja alinhado com suas expectativas.
Tokens que podem ser atualizados
As atualizações de token podem introduzir alterações inesperadas no comportamento de um token e podem causar problemas de interoperabilidade se não forem devidamente consideradas. Alguns tokens, como o USDC, TUSD e o UBI, são projetados para serem atualizáveis, o que significa que seu comportamento pode mudar a qualquer momento.
Possível problema
Por exemplo, o contrato MakerDAO tem um mapeamento de implementações conhecidas que revisou e sabe que é seguro interagir. Se um token for atualizado, a implementação salva pode não corresponder mais à versão atualizada, causando problemas.
- Contrato MakerDao:
require(implementations[gem.implementation())]==1,"GemJoin6/implementation-invalid");
Consideração
Para evitar esses problemas, é importante monitorar consistentemente os processos de atualização e estar preparado para reagir rapidamente a qualquer atualização suspeita ou incompatível ao integrar com tokens atualizáveis.
Além disso, os desenvolvedores devem considerar a introdução de lógica para congelar as interações com o token em questão se uma atualização for detectada.
Chamadas Reentrantes
Alguns tokens, como os ERC777, permitem chamadas reentrantes em sua função de transferência. Isso significa que um contrato pode chamar a função de transferência no contrato de token de dentro do próprio contrato, potencialmente levando à chamadas reentrantes e comportamento inesperado.
Possível problema
Se um contrato não estiver devidamente protegido contra chamadas reentrantes, ele pode ser explorado de várias maneiras.
Consideração
Para mitigar o risco de ataques reentrantes, as funções devem ser projetadas com base no padrão check-effects-interactions. Isso significa que as funções devem primeiro realizar todas as verificações necessárias, depois executar quaisquer alterações de estado necessárias e, finalmente, interagir com contratos externos. Isso pode ajudar a evitar que chamadas reentrantes sejam feitas antes que a função tenha concluído sua execução.
Além disso, é importante testar possíveis ataques de reentrância durante a fase de desenvolvimento e teste do contrato. Isso pode ajudar a garantir que o contrato esteja devidamente protegido contra esses tipos de ataques.
NOTA: Estas são apenas algumas estratégias para reduzir o risco de ataques reentrantes; outras soluções também devem ser consideradas.
Tokens de Cunhagem Relâmpago
Alguns tokens, como o DAI, permitem um recurso chamado “flash minting” (cunhagem relâmpago), que permite que os tokens sejam cunhados durante apenas uma transação, desde que sejam devolvidos ao contrato de token ao final da transação.
Possível problema
Um token que pode ser cunhado de forma relâmpago pode potencialmente ter um suprimento total do valor máximo de um tipo de dados **uint256
, que é 2^256-1. Isso pode causar problemas se o seu contrato não estiver preparado para lidar com valores tão grandes.
Consideração
Considere esses cenários ao criar/testar seus contratos.
Reverter na aprovação para endereço zero
Ao trabalhar com determinados tokens, como os implementados com o OpenZeppelin, é importante estar ciente do comportamento da função approve quando chamada com endereço zero como gastador. Especificamente, esses tokens serão revertidos se for feita uma tentativa de aprovar o endereço zero para gastar tokens (ou seja, uma chamada para **approve(address(0),amt)
).
Possível problema
Se o seu contrato depende da capacidade de aprovar o endereço zero, esse comportamento pode causar problemas inesperados. Além disso, uma reversão imprevista pode criar um comportamento inesperado em seu contrato, resultando potencialmente em problemas ou vulnerabilidades.
Consideração
Para resolver esse problema, é necessário incluir lógica de caso especial em seu contrato para lidar com esse comportamento. Isso pode envolver o uso de um bloco try-catch ou a adição de verificações adicionais para garantir que o endereço zero não seja passado como um argumento para a função de aprovação.
Reverter em Transferências de Valor Zero
Ao trabalhar com determinados tokens, como o LEND, é importante considerar a possibilidade de reversão de uma transferência ao tentar transferir uma quantia de valor zero.
Possível problema
Uma reversão em uma transferência de valor zero pode levar a um comportamento inesperado em seu contrato e potencialmente causar erros ou exploits.
Consideração
Para evitar esse problema, é importante adicionar casos especiais à lógica do seu contrato para lidar com a possibilidade de uma reversão de transferência de valor zero ao trabalhar com tokens que exibem esse comportamento. Isso pode ser feito implementando verificações apropriadas e manipulando a lógica em seu código de contrato.
Vários endereços de token
Alguns tokens de proxy têm vários endereços, o que pode levar a possíveis problemas se não forem contabilizados.
Possível problema
Se um contrato assumir um único endereço por token e não for projetado para lidar com vários endereços, ele pode ficar vulnerável a possíveis problemas.
Um exemplo disso é a função rescueFunds
mostrada abaixo, que permite ao proprietário do contrato devolver tokens não pertencentes ao pool a que foram acidentalmente enviados para o contrato, mas assume um único endereço por token. Como resultado, essa função pode permitir que o proprietário roube todos os fundos do pool.
mapping isPoolToken(address => bool);
constructor(address tokenA, address tokenB) public {
isPoolToken[tokenA] = true;
isPoolToken[tokenB] = true;
}
function rescueFunds(address token, uint amount) external nonReentrant onlyOwner {
require(!isPoolToken[token], "acesso negado");
token.transfer(msg.sender, amount);
}
Consideração
Ao integrar com tokens de proxy, é importante considerar a possibilidade de vários endereços e garantir que o contrato seja projetado para lidar com esse cenário. Isso pode incluir a adição de verificações adicionais ou modificações nas funções.
Decimais baixos
Alguns tokens têm decimais baixos (por exemplo, o USDC tem 6). Ainda mais extremo, alguns tokens como o Gemini USD têm apenas 2 casas decimais.
Possível problema
Isso pode resultar em perda de precisão maior do que o esperado ao realizar cálculos ou exibir saldos para os usuários.
Consideração
Certifique-se de levar em consideração o número de decimais de um token ao realizar cálculos e exibir saldos para os usuários. Considere o uso de uma biblioteca ou função de utilidade para lidar corretamente com divisão e multiplicação com tokens decimais baixos.
Decimais altos
Alguns tokens têm mais de 18 decimais (por exemplo, o YAM-V2 tem 24).
Possível problema
Isso pode desencadear reversões inesperadas devido ao estouro de número inteiro, representando um risco de vitalidade para o contrato.
Consideração
Ao integrar com tokens que possuem um alto número de decimais, esteja atento aos estouros de número inteiro. Certifique-se de manipular e testar adequadamente esses cenários em seu código de contrato. Isso pode ser obtido por meio do uso de bibliotecas SafeMath ou por meio de verificação manual cuidadosa de operações aritméticas.
Além disso, considere o uso de aritmética de ponto fixo ou outras abordagens alternativas para evitar possíveis estouros.
transferFrom
com src == msg.sender
Existem diferentes implementações da função transferFrom
em tokens ERC20. Alguns, como o DSToken, não tentarão diminuir a permissão do chamador se o remetente for o mesmo que o chamador. Isso dá à transferFrom
a mesma semântica que transfer,
neste caso. Outras implementações, como o OpenZeppelin e a Uniswap-v2, tentarão diminuir a permissão do chamador do remetente em transferFrom
, mesmo que o chamador e o remetente tenham o mesmo endereço, dandoa transfer(dst, amt)
e transferFrom(address(this),dst,amt)
semânticas diferentes neste caso.
Exemplos de ambas as semânticas são fornecidas:
- ERC20.sol: não tenta diminuir o subsídio.
- TransferFromSelf.sol: sempre tenta diminuir o subsídio.
Possível problema
Esse desvio do comportamento padrão pode causar problemas de interoperabilidade.
Consideração
Ao trabalhar com tokens ERC20, é importante revisar cuidadosamente a implementação da função transferFrom
para garantir que ela se comporte conforme o esperado. Nos casos em que o comportamento não é padrão, pode ser necessário adicionar tratamento ou documentação especial para garantir que os desenvolvedores estejam cientes das possíveis diferenças de comportamento.
Metadados sem string
Alguns tokens, como o MKR, codificam seus campos de metadados (por exemplo, nome e símbolo) como bytes32 em vez do tipo de string padrão específico na especificação ERC20.
Possível problema
Esse desvio do padrão pode causar problemas ao tentar consumir metadados desses tokens, pois pode não ser compatível com código ou bibliotecas existentes que esperam o tipo de string padrão.
Consideração
Ao trabalhar com esses tokens, é importante levar em consideração essa codificação não padrão de metadados. Isso pode envolver a modificação de código ou bibliotecas existentes para lidar com o tipo bytes32 ou converter os valores bytes32 em string antes do uso. Também é importante testar minuciosamente qualquer código que interaja com esses tokens para garantir que ele seja capaz de lidar corretamente com os metadados não padrão.
Reverter na Transferência para o Endereço Zero
Alguns tokens, como aqueles implementados usando a biblioteca OpenZeppelin, serão revertidos ao tentar transferir para o endereço zero (address(0)).
Possível problema
Isso pode representar um problema para sistemas que esperam poder gravar tokens transferindo-os para o endereço zero. Se um contrato ou sistema tentar gravar tokens transferindo-os para o endereço zero e o contrato de token reverter essa ação, isso poderá resultar em erros inesperados e potencialmente até mesmo em vulnerabilidades de segurança.
Considerações
Para resolver esse problema, os desenvolvedores devem garantir que seu contrato ou sistema seja capaz de lidar com tokens que não permitem a transferência para o endereço zero. Isso pode envolver a adição de lógica adicional ou manipulação de exceção para explicar esse comportamento. Também é importante revisar minuciosamente o código de quaisquer contratos de token integrados para confirmar se eles permitem ou não a transferência para o endereço zero.
Sem reversão em caso de falha
Alguns tokens, como o ZRX, não são revertidos em caso de falha, mas retornam false (falso) quando uma transferência falha.
Embora isso seja tecnicamente compatível com o padrão ERC20, ele vai contra as práticas comuns de codificação do Solidity e pode ser ignorado pelos desenvolvedores que se esquecem de agrupar suas chamadas para transferência em uma requisição.
Possível problema
Isso pode levar a vulnerabilidades potenciais se não for devidamente contabilizado na lógica do contrato.
Consideração
Certifique-se de agrupar as chamadas para transferência em um solicitação para garantir que uma falha seja tratada adequadamente. Como alternativa, considere o uso de uma implementação de token que reverta adequadamente em caso de falha.
Reverter em Grandes Aprovações e Transferências
Alguns tokens, como o UNI e o COMP, serão revertidos se o valor passado para aprovar ou transferir for maior que uint96. Esses tokens também têm lógica de caso especial na aprovação que define a permissão como type(uint96).max se o valor da aprovação for uint256(-1).
Possível problema
Esse desvio do comportamento padrão do ERC20 pode causar problemas nos sistemas.
Consideração
Para evitar esse problema, certifique-se de testar completamente as interações do seu contrato com esses tokens e considere adicionar lógica de caso especial para lidar com esses tipos de desvios.
Injeção de código via nome do token
Alguns tokens maliciosos foram observados para incluir Javascript malicioso em seu atributo de nome, permitindo que invasores extraiam chaves privadas de usuários que optam por interagir com esses tokens por meio de front-ends vulneráveis.
Isso foi usado para explorar usuários etherdelta em estado selvagem (referência: https://hackernoon.com/how-one-hacker-stole-thousands-of-dollars-worth-of-cryptocurrency-with-a-classic-code- injeção-a3aba5d2bff0).
Possível problema
A interação com esses tokens maliciosos pode resultar em sérias vulnerabilidades de segurança para seus usuários.
Consideração
Verifique a autenticidade dos tokens antes de permitir que os usuários interajam com eles.
Implemente proteções em seu front-end para impedir que os usuários interajam com tokens não confiáveis.
Considere a implementação de um sistema de lista de permissões para permitir que apenas tokens confiáveis sejam usados em seu aplicativo.
Função de Permissão Incomum
Alguns tokens (DAI, RAI, GLM, STAKE, CHAI, HAKKA, USDFL, HNY) têm uma implementação de permissão que não segue o padrão EIP2612.
Possível problema
Isso pode levar a um comportamento inesperado ao interagir com esses tokens, pois a função de permissão pode não se comportar conforme o esperado.
Consideração
Ao trabalhar com tokens que possuem uma função de permissão incomum, é importante testar minuciosamente o comportamento dessa função para garantir que ela não introduza vulnerabilidades ou consequências não intencionais em seu contrato.
Artigo escrito por ciphky e traduzido por Marcelo Panegali.
Top comments (0)