Sumário
- Contexto
- Solidity
- Overflow e Underflow de Inteiros
- Exemplo de Código de Contrato
- Vetores de Ataque
- Tenha cuidado ao usar inteiros no código de contratos inteligentes!
Contexto
Inteiro é um número inteiro, portanto, não possui partes fracionárias. Os inteiros podem ser positivos ou negativos. Existem muitos intervalos diferentes de inteiros que podem ser usados em linguagens de programação, mas a Solidity usa o intervalo de inteiros sem sinal de 256 bits. Isso significa que os números começam em 0 e vão até 115792089237316195423570985008687907853269984665640564039457584007913129639935 (em decimal).
A Solidity lançará um erro se você tentar atribuir algo que não seja um inteiro a uma variável declarada como um. Você pode conferir o que acontece tentando definir uma variável booleana (verdadeiro/falso) igual a um inteiro.
Quando você usa inteiros com operações matemáticas, você precisa saber o que acontece quando os valores se tornam muito grandes ou pequenos para seu intervalo. O overflow ocorre quando o valor máximo é excedido e o underflow ocorre quando o valor mínimo é excedido.
Solidity
A Solidity é uma linguagem de alto nível orientada a contratos para a implementação de contratos inteligentes. Foi influenciada por C++, Python e JavaScript sendo projetada para atingir a Máquina Virtual Ethereum (EVM).
A Solidity é escrita estaticamente, suporta herança, bibliotecas e tipos complexos definidos pelo usuário, dentre outros recursos.
Overflow e Underflow de Inteiros
O overflow e o underflow de inteiros são vulnerabilidades que podem levar ao roubo de fundos ou de outras informações em um contrato inteligente. Este artigo explica quais são essas vulnerabilidades, por que é importante entendê-las e como evitá-las.
Na Solidity, os inteiros são assinados, a menos que marcados com um 'U' maiúsculo no final. Um inteiro sem sinal é do tipo uint; um inteiro com sinal é do tipo int.
O intervalo de valores para um número de 256 bits assinado (int256) é de -(2²⁵⁵) a 2²⁵⁵ — 1. O intervalo para um número de 256 bits não assinado (uint256) é de 0 a 2²⁵⁶ — 1.
Exemplo de Código de Contrato
_function deposit() public payable{_
__balance[msg.sender] = _balance[msg.sender].add(msg.value); //O método Add da biblioteca Safe Math é usado para adicionar dois números e gera um erro se o cálculo overflows/underflows um tipo_
_}_
_function withdraw(uint256 amount) public {_
_require(_balance[msg.sender] >= amount, “Insufficient balance”); //verifica se há saldo suficiente antes de sacar fundos_
__balance[msg.sender] = _balance[msg.sender].sub(amount); //O método subtract da biblioteca SafeMath é usado para subtrair dois números e gera um erro se o cálculo overflows/underflows um tipo_
_msg.sender.transfer(amount); //envia fundos de volta para o endereço do chamador_
_}_
_function withdrawAll() public {_
_uint256 amount = _balance[msg.sender]; //armazena o saldo na variável amount para que possamos usá-lo após redefinir o valor de mapeamento para 0 como parte do processo withdrawal (de retirada)_
__balance[msg.sender] = 0; //redefine o valor de mapeamento após armazenar o saldo atual em variável temporária (amount)_
_msg.sender.transfer(amount); // envia o saldo inteiro de volta para o endereço do chamador usando o método transfer no objeto msg que representa o endereço do remetente (endereço do chamador)_
_}_
Vetores de Ataque
Existem algumas maneiras de aproveitar o underflow/overflow de inteiros para obter os resultados matemáticos desejados.
- Chame a função com um grande valor. Se você der à função um valor de entrada de uint256(2)²⁵⁶ — 1, ela retornará 0. Esta é uma maneira fácil de 'zerar' o saldo!
- Chame a função com um valor negativo várias vezes. Se você chamar a função três vezes com (uint256(-1)), ela acrescentará 2⁸ — 3, resultando em 2⁸ — 1 e se fôssemos chamar isso de novo resultaria em 0! Você pode repetir isso para criar qualquer número menor que 2⁸ usando apenas 8 chamadas! A mesma ideia funciona para números de 256 bits, assim como também, se o seu contrato tiver gas suficiente.
- Chame a função com um valor negativo 101 vezes ou mais. Chamar transfer (uint (-1)) 101 vezes definirá seu saldo como MAX_UINT em vez de MIN_UINT, já que adicionar 101 * (-1) equivale a subtrair 101 do seu saldo, que terá um overflow em 255 e se torna MAX_UINT.
Tenha cuidado ao usar inteiros no código de contratos inteligentes!
A linguagem de programação Solidity foi desenvolvida para ajudar a escrever contratos inteligentes Ethereum. É a escolha mais popular para escrever contratos inteligentes hoje.
A Solidity é uma linguagem que compila até o bytecode da máquina virtual (VM) Ethereum e é armazenada na blockchain. A EVM é um ambiente de tempo de execução que executa o código de contrato inteligente e gerência seu estado, mas carece de certos recursos com os quais contamos ao trabalhar com outras linguagens de programação como JavaScript. Em particular, não há suporte integrado para inteiros não assinados na Solidity, portanto, se você não for cuidadoso ao usá-los, seu contrato pode ficar vulnerável a bugs de overflow/underflow de inteiros!
O overflow/underflow de inteiros acontece quando você tenta armazenar algo maior do que o que pode caber em uma variável inteira ou menor que 0 em uma variável inteira sem sinal. Sempre que isso acontecer, em vez de obter o resultado esperado, um valor inesperado será atribuído à variável.
Conteúdos distribuídos por Learn.Block6.tech
👉 Discord — Conversas Ao Vivo
👉 Twitter — Últimos Artigos
Esse artigo foi escrito por 0xPredator e traduzido por Fátima Lima. O original pode ser lido aqui.
Abrace a oportunidade de elevar sua jornada de desenvolvimento para um nível superior. Hacking em Solidity é apenas o começo; os builds incríveis da WEB3DEV representam a chave de entrada para o emocionante cenário web3. 🚀🧑💻
Não perca tempo, 👉inscreva-se👈 agora mesmo e comece a desbravar o universo Blockchain!
Seja também WEB3DEV!
Top comments (0)