Lição: 258: Usando Tornado Cash
Tornado Cash é uma solução descentralizada de privacidade construída sobre o Ethereum que permite que os usuários enviem e recebam fundos sem revelar seu histórico de transações. Isso é alcançado através de provas de conhecimento zero que ocultam a origem e o destino dos fundos. Esta aula irá guiá-lo pelos conceitos básicos do Tornado Cash e mostrar como interagir com ele usando Solidity e JavaScript.
Entendendo o Tornado Cash
Antes de mergulharmos no código, é essencial entender como o Tornado Cash funciona:
-
Depósitos: Os usuários depositam ETH ou tokens no contrato inteligente do Tornado Cash, gerando um recibo privado. Este recibo é crucial, pois permite que os usuários retirem seus depósitos posteriormente.
-
Saques Anônimos: Para sacar fundos, os usuários devem apresentar seu recibo privado ao contrato inteligente do Tornado Cash. Essa etapa é realizada sem vincular o saque ao endereço do depósito.
-
Provas de Conhecimento Zero: O anonimato é alcançado usando zk-SNARKs (provas succincts não interativas de conhecimento), que validam a transação sem revelar qualquer informação sobre o remetente ou o destinatário.
Configurando o Ambiente
Para interagir com os contratos inteligentes do Tornado Cash, certifique-se de ter as ferramentas necessárias:
- Node.js e npm para gerenciamento de pacotes
- Hardhat para desenvolvimento local em Ethereum
- Ether.js ou Web3.js para interagir com o Ethereum
Você pode configurar um projeto Hardhat da seguinte forma:
mkdir tornado-cash-demo
cd tornado-cash-demo
npm init -y
npm install --save-dev hardhat
npx hardhat
Escolha "Criar um arquivo de configuração vazio hardhat.config.js", e seu ambiente de trabalho estará pronto.
Implantando o Contrato Inteligente Tornado Cash (Exemplo)
Para esta aula, ilustraremos uma versão simplificada de um contrato de depósito e retirada semelhante ao Tornado Cash. Abaixo está um contrato inteligente básico em Solidity.
TornadoCash.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract TornadoCash {
struct Deposit {
uint256 amount;
bytes32 commitment;
}
mapping(address => Deposit) public deposits;
event Deposited(address indexed user, bytes32 commitment);
event Withdrawn(address indexed user, uint256 amount);
function deposit(bytes32 _commitment) external payable {
require(msg.value > 0, "Envie ETH para depositar");
deposits[msg.sender] = Deposit(msg.value, _commitment);
emit Deposited(msg.sender, _commitment);
}
function withdraw(uint256 _amount) external {
Deposit storage userDeposit = deposits[msg.sender];
require(userDeposit.amount >= _amount, "Fundos insuficientes");
userDeposit.amount -= _amount;
payable(msg.sender).transfer(_amount);
emit Withdrawn(msg.sender, _amount);
}
}
Explicação:
- Estrutura de Depósito: Uma estrutura para armazenar o valor e o compromisso de cada usuário.
- Mapeamento: Armazena os depósitos correspondentes ao endereço de cada usuário.
- Eventos: Emite eventos para cada depósito e retirada para melhor transparência.
- Função de Depósito: Aceita ETH e um compromisso (hash representando o depósito).
- Função de Saque: Verifica o depósito do usuário e permite o saque de um montante especificado.
Interagindo com o Contrato Inteligente usando JavaScript
Uma vez que você tenha implantado seu contrato inteligente, pode interagir com ele usando Ether.js em um script. Abaixo está um exemplo de como depositar e retirar usando esta biblioteca.
interaction.js
const { ethers } = require("hardhat");
async function main() {
const [deployer] = await ethers.getSigners();
// Obtém o contrato implantado
const TornadoCash = await ethers.getContractFactory("TornadoCash");
const tornadoCash = await TornadoCash.deploy();
await tornadoCash.deployed();
console.log("TornadoCash implantado em:", tornadoCash.address);
// Exemplo de Depósito
const commitment = ethers.utils.formatBytes32String("Seu hash de compromisso");
const depositTx = await tornadoCash.deposit(commitment, { value: ethers.utils.parseEther("1") });
await depositTx.wait();
console.log("Depositou 1 ETH com compromisso:", commitment);
// Exemplo de Saque
const withdrawTx = await tornadoCash.withdraw(ethers.utils.parseEther("1"));
await withdrawTx.wait();
console.log("Retirou 1 ETH");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Explicação:
- Busca o endereço da carteira do deployador usando
getSigners()
. - Implanta o contrato TornadoCash.
- Chama a função
deposit
para enviar 1 ETH e fornecer um compromisso. - Por fim, demonstra como retirar o valor depositado.
Conclusão
Tornado Cash oferece uma abordagem inovadora para aprimorar a privacidade das transações no Ethereum. Ao usar contratos inteligentes e provas de conhecimento zero, os usuários podem depositar e retirar fundos de forma discreta, garantindo que suas atividades financeiras permaneçam confidenciais. Esta aula destacou uma implementação simples de um mecanismo de depósito e retirada inspirado no Tornado Cash, demonstrando os conceitos centrais por trás da privacidade nas transações em blockchain.
Experimente com o código e considere integrar zk-SNARKs para uma solução de privacidade completa! Boa codificação!