Do zero ao profissional em desenvolvimento Solidity | From zero to professional in Solidity development
- Introdução
- Configuração Inicial
- Primeiro Deploy
- Explorando o Contrato
- Transferências e Taxas
- Gerenciamento de Whitelist
- Configurações Administrativas
- Deploy na Testnet
- Exercícios Práticos
- Próximos Passos
Neste tutorial, você vai aprender:
- ✅ Como desenvolver um token ERC20 do zero
- ✅ Como implementar taxas de transferência
- ✅ Como gerenciar contratos inteligentes
- ✅ Como fazer deploy e interagir com contratos
- ✅ Boas práticas de segurança e otimização
In this tutorial, you will learn:
- ✅ How to develop an ERC20 token from scratch
- ✅ How to implement transfer fees
- ✅ How to manage smart contracts
- ✅ How to deploy and interact with contracts
- ✅ Security and optimization best practices
- Node.js: v22+ LTS
- npm: 10+
- Terminal: Conhecimento básico de linha de comando
- Editor: VS Code recomendado
# Verificar versão do Node.js | Check Node.js version
node --version
# Esperado: v22.22.0 ou superior | Expected: v22.22.0 or higher
# Verificar versão do npm | Check npm version
npm --version
# Esperado: 10.9.4 ou superior | Expected: 10.9.4 or higher✅ Checkpoint: Você deve ver as versões corretas do Node.js e npm.
cd .../solidity-projects/01-simple-token# Método 1: Usando Makefile (recomendado)
make install
# Método 2: Usando npm diretamente
npm installO que está sendo instalado? | What is being installed?
hardhat: Framework de desenvolvimento Ethereum@openzeppelin/contracts: Bibliotecas de contratos segurosethers.js: Biblioteca para interagir com Ethereumchai: Framework de testes
✅ Checkpoint: Você deve ver a pasta node_modules criada.
# Compilar | Compile
make compile
# Ou | Or
npx hardhat compileO que aconteceu? | What happened?
O Solidity compilou o contrato SimpleToken.sol e gerou:
- artifacts/: Código compilado
- cache/: Cache de compilação
✅ Checkpoint: Você deve ver "Compiled 1 Solidity file successfully".
# Executar todos os testes | Run all tests
make test
# Ou | Or
npx hardhat test✅ Checkpoint: Todos os 47 testes devem passar em ~2 segundos.
✔ Should set the correct token name and symbol (123ms)
✔ Should mint initial supply to deployer (45ms)
...
47 passing (2s)
Deploy é o processo de publicar seu contrato inteligente na blockchain. Depois do deploy, o contrato:
- Ganha um endereço único (exemplo:
0x5FbDB...) - Fica imutável (não pode ser alterado)
- Pode ser chamado por qualquer pessoa
Deployment is the process of publishing your smart contract to the blockchain. After deployment, the contract:
- Gets a unique address (example:
0x5FbDB...) - Becomes immutable (cannot be changed)
- Can be called by anyone
Terminal 1 (deixe aberto | keep open):
# Iniciar nó Hardhat | Start Hardhat node
make node
# Ou | Or
npx hardhat nodeO que você verá | What you will see:
Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/
Accounts
========
Account #0: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000 ETH)
Account #1: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 (10000 ETH)
...
💡 Importante: Esta rede é local e temporária. Quando você fechar o terminal, todos os dados serão perdidos.
💡 Important: This network is local and temporary. When you close the terminal, all data will be lost.
✅ Checkpoint: O servidor deve estar rodando na porta 8545.
Terminal 2 (novo terminal | new terminal):
# Fazer deploy | Deploy
make deploy-local
# Ou | Or
npx hardhat run scripts/deploy.js --network localhostO que você verá | What you will see:
🚀 Deploying SimpleToken...
📋 Deployment Parameters:
Token Name: Simple Token
Token Symbol: SMPL
Initial Supply: 1000000.0 SMPL
Fee Percent: 2%
✅ SimpleToken deployed successfully!
Contract Address: 0x5FbDB2315678afecb367f032d93F642f64180aa3
Deployer: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
Network: hardhat
# Salvar endereço | Save address
export CONTRACT_ADDRESS=0x5FbDB2315678afecb367f032d93F642f64180aa3✅ Checkpoint: Você deve ter o endereço do contrato salvo.
# Obter informações do contrato | Get contract information
npx hardhat run scripts/getInfo.js --network localhostO que você verá | What you will see:
📊 SimpleToken - Contract Information
🏷️ Token Details:
Name: Simple Token
Symbol: SMPL
Decimals: 18
💰 Supply Information:
Total Supply: 1000000.0 SMPL
Total Burned: 0.0 SMPL
Circulating Supply: 1000000.0 SMPL
⚙️ Configuration:
Fee Percentage: 2.00%
Max Transaction: 100000.0 SMPL
Paused: No
# Abrir console | Open console
make console
# Ou | Or
npx hardhat console --network localhostAgora você está no console interativo! Você pode executar comandos JavaScript.
Now you are in the interactive console! You can execute JavaScript commands.
// 1. Obter signers (contas) | Get signers (accounts)
const [owner, user1, user2] = await ethers.getSigners();
console.log("Owner:", owner.address);
console.log("User1:", user1.address);
console.log("User2:", user2.address);
// 2. Conectar ao contrato | Connect to contract
const token = await ethers.getContractAt(
"SimpleToken",
"0x5FbDB2315678afecb367f032d93F642f64180aa3" // Use seu endereço | Use your address
);
// 3. Obter informações básicas | Get basic information
await token.name(); // "Simple Token"
await token.symbol(); // "SMPL"
await token.totalSupply(); // 1000000000000000000000000
// 4. Formatar valores | Format values
const supply = await token.totalSupply();
console.log(ethers.formatEther(supply)); // "1000000.0"
// 5. Verificar saldo | Check balance
const balance = await token.balanceOf(owner.address);
console.log("Owner balance:", ethers.formatEther(balance), "SMPL");✅ Checkpoint: Você consegue ver as informações do token no console.
O SimpleToken cobra 2% de taxa em cada transferência. Essa taxa é queimada (destruída), tornando o token deflacionário.
SimpleToken charges a 2% fee on each transfer. This fee is burned (destroyed), making the token deflationary.
Exemplo | Example:
- Você transfere: 1000 SMPL
- Taxa (2%): 20 SMPL
- Destinatário recebe: 980 SMPL
- 20 SMPL são queimados (removidos do supply)
Contas na whitelist não pagam taxas. Por padrão, apenas o owner está na whitelist.
Accounts on the whitelist don't pay fees. By default, only the owner is whitelisted.
// 1. Verificar saldo inicial | Check initial balance
const ownerBalance = await token.balanceOf(owner.address);
console.log("Owner balance:", ethers.formatEther(ownerBalance));
// 2. Transferir do owner para user1 (SEM taxa - owner é whitelisted)
// Transfer from owner to user1 (NO fee - owner is whitelisted)
const amount = ethers.parseEther("1000"); // 1000 SMPL
await token.transfer(user1.address, amount);
// 3. Verificar saldo de user1 | Check user1 balance
const user1Balance = await token.balanceOf(user1.address);
console.log("User1 balance:", ethers.formatEther(user1Balance));
// Esperado: 1000 SMPL (sem taxa) | Expected: 1000 SMPL (no fee)
// 4. Transferir de user1 para user2 (COM taxa - user1 NÃO é whitelisted)
// Transfer from user1 to user2 (WITH fee - user1 is NOT whitelisted)
await token.connect(user1).transfer(user2.address, ethers.parseEther("100"));
// 5. Verificar saldo de user2 | Check user2 balance
const user2Balance = await token.balanceOf(user2.address);
console.log("User2 balance:", ethers.formatEther(user2Balance));
// Esperado: 98 SMPL (100 - 2% taxa) | Expected: 98 SMPL (100 - 2% fee)
// 6. Verificar total queimado | Check total burned
const totalBurned = await token.totalFeesBurned();
console.log("Total burned:", ethers.formatEther(totalBurned));
// Esperado: 2 SMPL | Expected: 2 SMPL✅ Checkpoint: User1 deve ter ~900 SMPL, User2 deve ter 98 SMPL.
# Script de interação completa | Complete interaction script
npx hardhat run scripts/interact.js --network localhostEste script executa automaticamente 12 operações completas, mostrando:
- Transferências com e sem taxa
- Gerenciamento de whitelist
- Mudança de configurações
- Cálculos de taxa
This script automatically executes 12 complete operations, showing:
- Transfers with and without fees
- Whitelist management
- Configuration changes
- Fee calculations
✅ Checkpoint: O script deve executar todas as operações com sucesso.
A whitelist é uma lista de endereços que não pagam taxas. Útil para:
- Exchanges
- Contratos de staking
- Pools de liquidez
- Contratos de recompensas
The whitelist is a list of addresses that don't pay fees. Useful for:
- Exchanges
- Staking contracts
- Liquidity pools
- Reward contracts
// 1. Verificar se user1 está na whitelist | Check if user1 is whitelisted
await token.isWhitelisted(user1.address);
// Esperado: false | Expected: false
// 2. Adicionar user1 à whitelist | Add user1 to whitelist
await token.addToWhitelist(user1.address);
console.log("✅ User1 added to whitelist");
// 3. Verificar novamente | Check again
await token.isWhitelisted(user1.address);
// Esperado: true | Expected: true
// 4. Testar transferência SEM taxa | Test transfer WITHOUT fee
await token.connect(user1).transfer(user2.address, ethers.parseEther("100"));
// User2 deve receber 100 SMPL completos (sem taxa)
// User2 should receive full 100 SMPL (no fee)
const user2Balance = await token.balanceOf(user2.address);
console.log("User2 balance:", ethers.formatEther(user2Balance));
// 5. Remover user1 da whitelist | Remove user1 from whitelist
await token.removeFromWhitelist(user1.address);
console.log("❌ User1 removed from whitelist");
// 6. Testar transferência COM taxa novamente | Test transfer WITH fee again
await token.connect(user1).transfer(user2.address, ethers.parseEther("100"));
// Agora user2 recebe apenas 98 SMPL (2% taxa)
// Now user2 receives only 98 SMPL (2% fee)✅ Checkpoint: User1 deve estar na whitelist e depois removido.
Apenas o owner (quem fez o deploy) pode:
- Mudar o percentual de taxa
- Gerenciar whitelist
- Pausar/despausar transferências
- Definir quantidade máxima de transação
Only the owner (who deployed) can:
- Change fee percentage
- Manage whitelist
- Pause/unpause transfers
- Set max transaction amount
// No console | In console
// Verificar taxa atual | Check current fee
const currentFee = await token.feePercent();
console.log("Current fee:", Number(currentFee) / 100, "%");
// 200 = 2.00%
// Mudar para 5% | Change to 5%
await token.setFeePercent(500);
console.log("✅ Fee changed to 5%");
// Verificar nova taxa | Verify new fee
const newFee = await token.feePercent();
console.log("New fee:", Number(newFee) / 100, "%");
// Calcular taxa para 1000 tokens | Calculate fee for 1000 tokens
const [fee, afterFee] = await token.calculateFee(ethers.parseEther("1000"));
console.log("Transfer 1000 SMPL:");
console.log(" Fee:", ethers.formatEther(fee), "SMPL");
console.log(" Recipient gets:", ethers.formatEther(afterFee), "SMPL");- Taxa deve estar entre 0% e 10%
- Não pode ser mudada por não-owners
- Emite evento
FeePercentChanged
// Verificar máximo atual | Check current max
const info = await token.getContractInfo();
console.log("Current max:", ethers.formatEther(info.maxTxAmount), "SMPL");
// Definir novo máximo | Set new maximum
await token.setMaxTransactionAmount(ethers.parseEther("5000"));
console.log("✅ Max transaction set to 5000 SMPL");
// Tentar transferir mais que o máximo | Try to transfer more than max
try {
await token.transfer(user1.address, ethers.parseEther("6000"));
} catch (error) {
console.log("❌ Transaction exceeds maximum!");
// Esperado: erro "TransactionAmountTooLarge"
// Expected: "TransactionAmountTooLarge" error
}// Pausar contrato | Pause contract
await token.pause();
console.log("⏸️ Contract paused");
// Verificar se está pausado | Check if paused
const isPaused = await token.paused();
console.log("Is paused:", isPaused); // true
// Tentar transferir (vai falhar) | Try to transfer (will fail)
try {
await token.transfer(user1.address, ethers.parseEther("100"));
} catch (error) {
console.log("❌ Cannot transfer while paused!");
}
// Despausar | Unpause
await token.unpause();
console.log("▶️ Contract unpaused");
// Agora pode transferir | Now can transfer
await token.transfer(user1.address, ethers.parseEther("100"));
console.log("✅ Transfer successful!");✅ Checkpoint: Você deve conseguir pausar, tentar transferir (falhar), despausar e transferir com sucesso.
Testnet (rede de teste) é uma blockchain pública para testes:
- ETH não tem valor real (é grátis)
- Comportamento idêntico à mainnet
- Seus contratos ficam públicos
- Pode ser explorado no Etherscan
Testnet (test network) is a public blockchain for testing:
- ETH has no real value (it's free)
- Identical behavior to mainnet
- Your contracts are public
- Can be explored on Etherscan
Vamos usar a Sepolia testnet.
-
Criar carteira MetaMask:
- Instale MetaMask: https://metamask.io/
- Crie uma conta
- GUARDE sua frase seed!
-
Mudar para Sepolia:
- Abra MetaMask
- Clique na rede (topo)
- Ative "Show test networks"
- Selecione "Sepolia"
-
Obter ETH grátis:
- Acesse: https://sepoliafaucet.com/
- Cole seu endereço
- Clique "Send Me ETH"
- Aguarde 1-2 minutos
✅ Checkpoint: Você deve ter ~0.5 ETH no MetaMask (rede Sepolia).
# Criar arquivo .env | Create .env file
touch .env
# Abrir com editor | Open with editor
code .envAdicione | Add:
# Sua chave privada do MetaMask | Your MetaMask private key
# ⚠️ NUNCA compartilhe ou faça commit disso! | NEVER share or commit this!
PRIVATE_KEY=your_private_key_here
# URL RPC da Sepolia | Sepolia RPC URL
# Obtenha gratuitamente em https://infura.io/ ou https://alchemy.com/
# Get for free at https://infura.io/ or https://alchemy.com/
SEPOLIA_RPC_URL=https://sepolia.infura.io/v3/YOUR_KEY
# API key do Etherscan (para verificação)
# Obtenha em https://etherscan.io/myapikey
# Get at https://etherscan.io/myapikey
ETHERSCAN_API_KEY=your_etherscan_key# Verificar se .env está no .gitignore | Check if .env is in .gitignore
cat .gitignore | grep .env
# Deve mostrar: .env | Should show: .env# Deploy na Sepolia | Deploy to Sepolia
make deploy-sepolia
# Ou | Or
npx hardhat run scripts/deploy.js --network sepoliaO que você verá | What you will see:
🚀 Deploying SimpleToken to Sepolia...
⏳ Waiting for confirmations...
✅ SimpleToken deployed!
Contract: 0xABC...123
Deployer: 0xYour...Address
Network: sepolia
🔍 View on Etherscan:
https://sepolia.etherscan.io/address/0xABC...123
✅ Checkpoint: Você deve ver seu contrato no Etherscan!
# Verificar no Etherscan | Verify on Etherscan
make verify-sepolia
# Quando solicitado, cole o endereço do contrato
# When prompted, paste the contract addressO que isso faz? | What does this do?
- Envia o código-fonte para Etherscan
- Permite que qualquer pessoa veja seu código
- Adiciona ícone ✅ verde no Etherscan
- Permite interação direta no site
✅ Checkpoint: Você deve ver "Contract source code verified" no Etherscan.
# Verificar informações | Check information
CONTRACT_ADDRESS=0xYourAddress npx hardhat run scripts/getInfo.js --network sepolia
# Verificar saldo | Check balance
CONTRACT_ADDRESS=0xYourAddress npx hardhat run scripts/checkBalance.js --network sepolia
# Console interativo | Interactive console
make console-sepoliaObjetivo: Fazer 3 transferências e entender as taxas.
Passos:
- Iniciar rede local
- Fazer deploy
- Transferir 1000 SMPL do owner para user1
- Transferir 500 SMPL de user1 para user2
- Transferir 250 SMPL de user2 para user3
Perguntas:
- Quanto user1 recebeu? (Resposta: 1000 - owner é whitelisted)
- Quanto user2 recebeu? (Resposta: 490 - 500 * 0.98)
- Quanto user3 recebeu? (Resposta: 245 - 250 * 0.98)
- Quanto foi queimado no total? (Resposta: 10 + 5 = 15 SMPL)
Solução:
# No console | In console
const [owner, user1, user2, user3] = await ethers.getSigners();
const token = await ethers.getContractAt("SimpleToken", "YOUR_ADDRESS");
// Transferência 1
await token.transfer(user1.address, ethers.parseEther("1000"));
// Transferência 2
await token.connect(user1).transfer(user2.address, ethers.parseEther("500"));
// Transferência 3
await token.connect(user2).transfer(user3.address, ethers.parseEther("250"));
// Verificar saldos
console.log("User1:", ethers.formatEther(await token.balanceOf(user1.address)));
console.log("User2:", ethers.formatEther(await token.balanceOf(user2.address)));
console.log("User3:", ethers.formatEther(await token.balanceOf(user3.address)));
console.log("Burned:", ethers.formatEther(await token.totalFeesBurned()));Objetivo: Entender o impacto da whitelist nas taxas.
Passos:
- Transferir 1000 SMPL do owner para user1 (sem taxa)
- Verificar saldo de user1 (deve ser 1000)
- Transferir 100 SMPL de user1 para user2 (com taxa)
- Verificar saldo de user2 (deve ser 98)
- Adicionar user1 à whitelist
- Transferir 100 SMPL de user1 para user2 (sem taxa)
- Verificar saldo de user2 (deve ser 198)
Desafio: Calcule quanto foi economizado em taxas com a whitelist.
Objetivo: Ver como mudanças de taxa afetam transferências.
Passos:
- Verificar taxa atual (2%)
- Calcular taxa para transferência de 1000 SMPL
- Mudar taxa para 5%
- Calcular novamente para mesma quantidade
- Fazer transferência real e verificar
Desafio: Crie uma tabela comparando taxas de 1% a 10% para 1000 SMPL.
Objetivo: Entender limites de transação.
Passos:
- Verificar máximo atual (100000 SMPL)
- Tentar transferir 150000 SMPL (deve falhar)
- Mudar máximo para 200000 SMPL
- Tentar transferir 150000 SMPL (deve funcionar)
Desafio: Por que esse limite é importante? Quando você usaria isso?
Objetivo: Simular situação de emergência.
Passos:
- Pausar contrato
- Tentar fazer várias operações (devem falhar)
- Despausar
- Verificar que tudo volta a funcionar
Cenário: Imagine que você descobriu um bug. Como a pausa ajuda?
Objetivo: Deploy em blockchain pública real.
Passos:
- Obter ETH de teste no faucet
- Configurar .env com suas credenciais
- Fazer deploy na Sepolia
- Verificar contrato no Etherscan
- Fazer transferências reais
Desafio: Compartilhe o link do Etherscan do seu contrato!
Objetivo: Otimizar custos de gas.
Passos:
- Executar tests com relatório de gas
- Identificar operações mais caras
- Compare transferências com/sem whitelist
- Calcule custo em USD (gas * gas price * ETH price)
# Gerar relatório | Generate report
make test-gasConsulte CHALLENGES.md para 7 desafios que levam você ao nível profissional:
- Challenge 1: Snapshot de saldo (como UNI)
- Challenge 2: Timelock para mudanças (como COMP)
- Challenge 3: Multi-sig ownership (como Yearn)
- Challenge 4: Sistema de recompensas (como RFI)
- Challenge 5: Liquidity lock
- Challenge 6: Otimização de gas
- Challenge 7: Proteção anti-bot
Estude tokens reais:
- UNI (Uniswap): https://etherscan.io/token/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984
- LINK (Chainlink): https://etherscan.io/token/0x514910771af9ca656af840dff83e8264ecf986ca
- AAVE: https://etherscan.io/token/0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9
- Tenderly: Debug de transações
- OpenZeppelin Defender: Automação de contratos
- The Graph: Indexação de dados
- Dune Analytics: Análise on-chain
Após dominar o SimpleToken, prossiga para:
- Projeto 1.2: Staking de Tokens
- Projeto 1.3: NFT Collection
- Projeto 2.1: DEX (Decentralized Exchange)
- Consensys Academy: Blockchain Developer
- Chainlink Academy: Smart Contract Development
- Secureum: Security Bootcamp
- OpenZeppelin: Defender Workshops
- Solidity: https://docs.soliditylang.org/
- Hardhat: https://hardhat.org/docs
- OpenZeppelin: https://docs.openzeppelin.com/
- Ethers.js: https://docs.ethers.org/
- Ethereum Stack Exchange: https://ethereum.stackexchange.com/
- r/ethdev: https://reddit.com/r/ethdev
- Hardhat Discord: https://hardhat.org/discord
- OpenZeppelin Forum: https://forum.openzeppelin.com/
- Remix IDE: https://remix.ethereum.org/
- Etherscan: https://etherscan.io/
- Sepolia Faucet: https://sepoliafaucet.com/
- Gas Tracker: https://etherscan.io/gastracker
Você completou o tutorial quando conseguir:
- ✅ Compilar e testar o contrato localmente
- ✅ Fazer deploy na rede local
- ✅ Interagir via console
- ✅ Fazer transferências com e sem taxas
- ✅ Gerenciar whitelist
- ✅ Mudar configurações administrativas
- ✅ Fazer deploy na Sepolia
- ✅ Verificar contrato no Etherscan
- ✅ Completar pelo menos 3 exercícios
- ✅ Entender todos os conceitos principais
Encontrou algum problema? Tem sugestões?
- Abra uma issue no GitHub
- Contribua com melhorias
- Compartilhe seu aprendizado
Parabéns! 🎉 Você completou o tutorial do SimpleToken!
Congratulations! 🎉 You completed the SimpleToken tutorial!
Continue praticando e explorando o mundo blockchain!
Tutorial Version: 1.0
Last Updated: February 2026
Level: Beginner to Professional