Agora, vamos brincar um pouco mais com o evento Transfer e ver como podemos enganar o Etherscan mais uma vez.
A princípio, teremos um rápido lembrete de como o Etherscan rastreia o número de tokens para todos os detentores de um contrato inteligente.
Etherscan, use o evento transfer em solidity para rastrear todas as transferências na blockchain.
Sempre que um token é transferido, o evento Transfer é acionado com o endereço _from, o endereço _to e o valor como argumentos.
O saldo exibido no Etherscan é a soma (e a diferença) de todos os eventos de transferência.
Para mais informações, você pode conferir o primeiro artigo desta série sobre como hackear o Etherscan: https://medium.com/@TrustChain/hacking-etherscan-erc20-cheating-46dc229f5f8
1. Transferência falsa no Etherscan.
E se criarmos uma função chamada fake_transfer()
e a invocarmos, o que acontecerá?
function fake_transfer(address from,address to,uint256 amount){
emit Transfer(from, to, amount);
}
Esta é exatamente a mesma função que _transfer()
em contratos inteligentes ERC20, mas apenas o evento permanece.
Após a execução da função, apenas o evento Transfer será registrado na blockchain, mas o estado do contrato inteligente (como saldos) NÃO mudará.
Se implantarmos este contrato, é claro que o Etherscan mostrará resultados ruins.
constructor() ERC20("MyToken", "MTK") {
_mint(msg.sender,100000000000000000000000000000000000000000000);
// não se esqueça de remover o evento transfer na função _mint
fake_transfer(0x0000000000000000000000000000000000000000,msg.sender,1000);
}
Resultado do contrato falso
Como os decimais ainda são 18, o Etherscan mostra 10^(-18+3) = 10^-15 tokens transferidos do endereço 0 para o proprietário. Mas nós “cunhamos” uma quantia que tem muito mais zeros…
Portanto, o valor que você vê no Etherscan PODE NÃO SER VÁLIDO.
2. Encontrando o verdadeiro saldo do dono (ou não)
Como verificar o verdadeiro valor do dono do contrato? (para garantir que o proprietário não despeje o token como uma moeda sem valor (shitcoin) e drene todo o seu dinheiro)
Uma das maneiras de fazer isso é consultar a função balanceOf()
e ver o resultado.
Pode funcionar facilmente, e podemos fazê-lo com ethers.js
, também podemos usar a Metamask ou podemos consultar o Etherscan para este endereço específico.
A boa notícia é que conseguimos recuperar o valor “verdadeiro” .(1000….000000000 tokens)
A razão é que esses métodos dependem de balanceOf() em vez do evento Transfer, que são mais precisos, mas mais difíceis de implementar.
_(Mais preciso porque, por exemplo, se quisermos classificar cada posse pelo número de tokens que eles possuem, o Etherscan precisa fazer um loop para todos os endereços possíveis, e isso é impossível na vida real, pois são cerca de 2160 endereços Ethereum possíveis no total, então o evento transfer
foi criado.)
3. Capturando a função de equilíbrio
Mas e se capturarmos a função balanceOf()
?
Quero dizer por “capturar”, modificar o valor de retorno de balanceOf()
retornando um valor falso.
Por exemplo, em vez de:
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
Escrevemos:
function balanceOf(address account) public view returns (uint256) {if (account == 0x6166f7E....) {
return 1000;
} else {
return _balances[account];
}
}
Este contrato inteligente retorna 1000
se account
for igual ao endereço 0x6166f7E...
mesmo que balances[0x6166f7E...]
seja igual a outro valor.
Portanto, 0x6166f7E
pode falsificar seu saldo para qualquer pessoa.
Além disso, no construtor, posso adicionar quantos tokens quiser para o endereço 0x6166f7E
.
constructor() ERC20("MyToken", "MTK") { _mint(msg.sender,100000000000000000000000000000000000000000000);
// não esqueça de remover o evento Transfer na função _mint()
// msg.sender = 0x6166f7E
fake_transfer(0x000000000...000000,msg.sender,1000);
// emita Transfer(0 address,msg.sender,1000)
}
Como resultado, o proprietário do contrato pode ocultar seu saldo para os detentores E para o Etherscan sem que ninguém perceba.
Vamos implantar este contrato inteligente e ver o que acontece no Etherscan & Metamask:
A Metamask e o Etherscan mostram o mesmo valor: 0,00000…1 (=10^-15 MTK)
Mas nós cunhamos uma quantidade incrível um pouco antes!
_mint(msg.sender,100000000000000000000000000000000000000000000);
Então, conseguimos enganar a Metamask e o Etherscan. (e qualquer outra carteira que dependa da função balanceOf()
)
4. Você ainda pode confiar no Etherscan?
Parece assustador, certo? Ainda existe uma maneira de confiar no Etherscan ou em qualquer projeto criptográfico que possa enganar seus detentores?
Em teoria sim.
Se o código do contrato inteligente for VERIFICADO (e o construtor também), será muito mais difícil enganar o Etherscan. Mas se uma dessas 2 condições estiver ausente, é muito mais fácil enganar o Etherscan.
A blockchain é transparente, isso significa que todos os dados, todas as transações registradas ou qualquer saldo de endereço são armazenados na blockchain e, portanto, disponíveis gratuitamente para qualquer pessoa.
Mas, na realidade, isso não é tão simples, especialmente se você não tiver habilidades técnicas.
Na verdade, a única maneira de descobrir se o contrato está "capturado" é inverter o bytecode do smart contract para entender toda a lógica do contrato e ver o que está acontecendo dentro dele.
Se você quiser entender como fazer engenharia reversa de contrato inteligente na blockchain, você pode conferir minha série sobre reversão e depuração de contrato inteligente, que ensina essa habilidade (rara): https://medium.com/@TrustChain/list/reversing-and-degugging-evm-smart-contracts-f4dd9195d07b
Qualquer outra maneira que você encontrar não é perfeita e pode ser facilmente contornada…
Artigo original publicado por TrustChain. Traduzido por Paulinho Giovannini.
Oldest comments (0)