Apostila completa de Web3, Blockchain & Smart Contracts
Blockchain é uma ferramenta específica para um problema específico: coordenar sem um intermediário confiável. Esta apostila cobre o que ela resolve e o que não, como funciona por baixo, o Ethereum e a EVM, escrever smart contracts em Solidity, a segurança (onde um bug custa milhões), construir a interface de um dApp, os padrões de DeFi/NFT/DAO, a escala com L2s, e a produção — custódia de chaves, regulação e ética — sempre com ceticismo honesto sobre quando não usar.
O que blockchain resolve (e o que não)
Objetivo: entender o problema real (coordenação sem intermediário confiável), quando isso vale, e por que na maioria dos casos um banco de dados é melhor.
1.1 A ideia central
Uma blockchain é um ledger (livro-razão) replicado em muitos computadores independentes, que concordam sobre o seu conteúdo por um protocolo de consenso, sem ninguém no comando. O valor não é "ser um banco de dados" — é minimizar a confiança: você não precisa confiar numa empresa para que as regras sejam seguidas, o registro não seja alterado, e o acesso não seja censurado.
1.2 Quando faz sentido
- Não há (ou não se quer) um intermediário confiável e as partes não confiam umas nas outras.
- Resistência à censura e a apreensão importa (dinheiro, publicação, propriedade).
- Ativos digitais escassos e transferíveis sem um emissor central (a "propriedade" verificável).
- Composabilidade sem permissão: qualquer um pode construir sobre os contratos de outro ("money legos" de DeFi).
- Regras aplicadas por código que ninguém pode mudar unilateralmente (um cofre, um leilão, uma distribuição).
1.3 Quando um banco de dados é melhor (quase sempre)
- Existe uma entidade que legitimamente controla os dados e as regras → um Postgres é mais rápido, mais barato, mais flexível e mutável.
- Você precisa de privacidade por padrão (blockchain pública é transparente).
- Você precisa de alto throughput e baixa latência.
- Os dados mudam, precisam de correção, ou há um "botão de desfazer" legítimo.
- "Colocar na blockchain" não muda o problema de garbage in — o oráculo/pessoa que insere o dado continua sendo o ponto de confiança.
Para a maioria dos projetos, a resposta é "não use blockchain". Ela custa performance, dinheiro (gas), complexidade e uma superfície de risco enorme, e só se paga quando a minimização de confiança ou a resistência à censura é o requisito central. Esta apostila ensina a construir bem quando a resposta for "sim" — e a reconhecer honestamente quando for "não".
Perguntas de abertura: "O que uma blockchain resolve que um banco de dados não?" (coordenação sem intermediário confiável, resistência à censura, ativos sem emissor central, composabilidade sem permissão — não velocidade nem "dado seguro"), "Quando você não usaria blockchain?" (há um controlador legítimo dos dados, precisa de privacidade/throughput/correção — quase sempre), "Blockchain resolve o problema do dado errado na entrada?" (não — o oráculo continua sendo o ponto de confiança).
✏️ Exercício 1 — Blockchain ou banco de dados
Para cada caso, decida e justifique: (a) o cadastro de clientes de um e-commerce; (b) um sistema de pagamentos entre pessoas sem banco, em um país com hiperinflação e controle de capital; (c) o rastreamento de lotes de café da fazenda ao consumidor; (d) um leilão automático de um ativo onde ninguém pode "mudar as regras no meio"; (e) prontuário médico compartilhado entre hospitais.
Gabarito (uma boa resposta): (a) banco de dados — o e-commerce controla os dados; blockchain só adiciona custo e expõe PII. (b) blockchain (uma stablecoin numa L2) — o requisito é justamente "sem banco, resistente a censura/controle". (c) banco de dados quase certamente — a blockchain não impede alguém de escanear a etiqueta errada ou mentir na entrada; o "problema do oráculo" domina; só faz sentido se muitos atores que não confiam entre si precisam de um registro comum e nenhum pode ser o dono — e mesmo assim há alternativas. (d) smart contract — "regras imutáveis aplicadas por código, sem intermediário" é o caso de uso canônico. (e) não é blockchain — precisa de privacidade forte (dado de saúde), correção, e há entidades reguladas que devem controlar; um sistema federado com padrões de interoperabilidade resolve melhor.
Como uma blockchain funciona
Objetivo: blocos, hashes, Merkle trees, transações, contas, chaves, mempool, consenso (PoW vs PoS) e finalidade, e gas.
2.1 Blocos e hashes
- Um bloco contém um lote de transações + um hash do bloco anterior. Alterar um bloco antigo mudaria seu hash e quebraria a cadeia de todos os seguintes — daí a "imutabilidade".
- As transações de um bloco são resumidas numa Merkle tree (uma raiz de hash) — permite provar que uma transação está num bloco sem baixar o bloco inteiro.
- Hash = função one-way; qualquer mudança no input muda o output de forma imprevisível.
2.2 Contas, chaves e assinaturas
- Uma chave privada gera uma chave pública, que gera um endereço. Quem tem a chave privada é a conta — não há "recuperar senha".
- Uma transação é assinada com a chave privada; a rede verifica a assinatura contra o endereço. Ninguém precisa confiar em ninguém para validar quem enviou.
- No Ethereum: EOA (externally owned account — uma chave) vs contract account (código; "age" quando chamado).
2.3 Mempool e mineração/validação
- Você envia a transação → ela entra na mempool (fila pública de pendentes) → um produtor de bloco (minerador no PoW, validador no PoS) a inclui num bloco → o bloco propaga e é validado pelos nós.
- A mempool ser pública abre a porta para front-running / MEV (Módulo 5).
2.4 Consenso e finalidade
| Proof of Work (PoW) | Proof of Stake (PoS) | |
|---|---|---|
| Como | gastar energia computacional para achar um hash válido | validadores depositam ("stake") um valor; são escolhidos para propor/atestar; perdem o stake se trapaceiam (slashing) |
| Custo | alto consumo de energia (Bitcoin) | muito menor (Ethereum migrou em 2022) |
| Finalidade | probabilística — quanto mais blocos por cima, menos provável reverter | o Ethereum PoS atinge finalidade "econômica" em ~2 épocas (~13 min) |
- Fork: dois blocos concorrentes; a regra de escolha de cadeia decide o vencedor. Reorg: a ponta da cadeia muda — por isso se espera N confirmações antes de considerar uma tx "final".
2.5 Gas
- Cada operação custa gas; você paga
gas usado × preço do gasem ETH. Isso remunera os validadores e limita o que uma transação pode fazer (evita loop infinito). - O preço do gas varia com a demanda — em picos, uma transação simples pode custar caro (na L1). L2s (Módulo 3) reduzem isso em ordens de magnitude.
Perguntas: "Por que uma blockchain é 'imutável'?" (cada bloco referencia o hash do anterior; alterar um quebra a cadeia), "O que é uma Merkle tree e para que serve?" (resumir transações numa raiz; provar inclusão sem o bloco todo), "PoW vs PoS?" (energia vs stake + slashing; Ethereum migrou), "O que é gas e por que existe?" (paga os validadores e limita o custo de uma tx), "Por que esperar confirmações?" (reorgs — a ponta da cadeia pode mudar).
✏️ Exercício 2 — Explique a um leigo
Explique, sem jargão, por que (a) você não pode "recuperar a senha" de uma carteira, (b) uma transação enviada pode demorar e às vezes "falhar" custando gas mesmo assim, e (c) por que a mesma transação custa preços diferentes em momentos diferentes.
Gabarito (uma boa resposta): (a) a "carteira" é apenas um par de chaves matemáticas; não há servidor com o seu cadastro nem um "esqueci a senha" — quem tem a chave privada controla os fundos, e se ela se perde, os fundos ficam inacessíveis para sempre (por isso backup e custódia são tudo — Módulo 9). (b) a transação entra numa fila pública; um produtor de bloco decide incluí-la, e isso pode demorar se a rede está congestionada ou se você ofereceu um preço de gas baixo; e se a transação reverte (uma condição do contrato falhou), o trabalho computacional já foi feito, então o gas gasto até ali não volta. (c) o gas é um "leilão" de espaço no bloco — quando muita gente quer transacionar ao mesmo tempo, o preço sobe; em horários calmos, cai.
Ethereum, EVM, L1 e L2
Objetivo: a EVM como "computador mundial", o modelo de contas e estado, por que L2s existem (rollups optimistic vs zk), e o panorama de chains e carteiras.
3.1 A EVM
- A Ethereum Virtual Machine é uma máquina de estados: cada transação é uma entrada que transforma o world state (saldos + o storage de cada contrato) de forma determinística, executada por todos os nós.
- Contratos são bytecode na EVM; você escreve em Solidity (ou Vyper) e compila. A ABI descreve as funções para que clientes possam chamá-las.
- Eventos/logs: os contratos emitem eventos (baratos, não ficam no storage) que aplicações e indexadores leem.
- A EVM virou um padrão: muitas chains ("EVM-compatible") rodam o mesmo bytecode.
3.2 Por que L2
- A L1 (Ethereum mainnet) é segura e descentralizada, mas cara e lenta (poucas dezenas de transações por segundo).
- Rollups (L2): executam as transações fora da L1, publicam os dados (e uma prova) na L1, herdando a segurança dela a uma fração do custo.
- Optimistic rollups (Arbitrum, Optimism, Base): assumem que os lotes são válidos; há uma janela (~7 dias) para alguém provar fraude → saques para a L1 demoram.
- ZK rollups (zkSync, Starknet, Linea, Scroll): publicam uma prova de validade (zero-knowledge) — matematicamente correta, saída mais rápida; tecnologia mais nova/complexa.
- Hoje a maior parte da atividade "de usuário" acontece em L2.
3.3 O panorama de chains
- Bitcoin: foco em ser dinheiro/reserva de valor; script limitado, sem "smart contracts" ricos (mudando devagar com camadas).
- Ethereum + L2s: o maior ecossistema de contratos, DeFi, NFTs.
- Outras L1 EVM (Polygon PoS, BNB Chain, Avalanche): trade-offs de descentralização por custo/velocidade.
- Não-EVM: Solana (alta performance, modelo próprio, Rust), outras — em uma frase, ecossistemas paralelos.
3.4 Carteiras e acesso
- EOA (MetaMask, Rabby): a chave está no navegador/hardware do usuário.
- Smart accounts / account abstraction (ERC-4337): a "conta" é um contrato — permite recuperação social, patrocínio de gas, limites, chaves de sessão. Melhora muito o UX (Módulo 6, 8).
- Embedded wallets (Privy, Dynamic, etc.): a chave é gerenciada para o usuário (login por e-mail/social), reduzindo a fricção.
- RPC providers (Alchemy, Infura, ou seu nó): o "gateway" pelo qual apps falam com a chain.
Perguntas: "O que é a EVM?" (máquina de estados determinística que todos os nós executam; contratos são bytecode), "Por que L2s existem e qual a diferença entre optimistic e zk?" (custo/escala herdando a segurança da L1; optimistic assume validade com janela de fraude — saque lento; zk publica prova de validade — saída mais rápida), "O que é account abstraction?" (a conta vira um contrato — recuperação social, gas patrocinado, chaves de sessão), "EOA vs contract account?".
✏️ Exercício 3 — Escolha a camada
Você vai lançar um app de "gorjetas para criadores de conteúdo" — micro-pagamentos frequentes de valores pequenos, público não-técnico. Que chain/camada e que tipo de carteira, e por quê? O que você não faria?
Gabarito (uma boa resposta): uma L2 (Base/Arbitrum/Optimism) — micro-pagamentos na L1 seriam inviáveis pelo gas. Uma stablecoin como unidade (o criador não quer volatilidade). Embedded wallet com login por e-mail/social + account abstraction com paymaster para o app patrocinar o gas — o usuário não-técnico não deveria precisar comprar ETH nem entender "gas". Confirmações rápidas da L2 dão um UX aceitável. O que não faria: exigir MetaMask e que o usuário tenha ETH para gas; usar a L1 mainnet; pedir ao usuário para guardar uma seed phrase de 12 palavras como pré-requisito para dar uma gorjeta de R$ 2; lançar um "token do app" com tokenomics sem necessidade (Módulo 7).
Smart contracts com Solidity
Objetivo: a estrutura de um contrato, storage/memory/calldata, funções e modifiers, eventos, os padrões ERC, upgradeabilidade, e o ferramental (Foundry).
4.1 Anatomia
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; contract Cofre { address public immutable dono; mapping(address => uint256) public saldo; event Deposito(address indexed de, uint256 valor); error SaldoInsuficiente(uint256 pedido, uint256 disponivel); constructor() { dono = msg.sender; } modifier apenasDono() { require(msg.sender == dono, "nao autorizado"); _; } function depositar() external payable { saldo[msg.sender] += msg.value; emit Deposito(msg.sender, msg.value); } function sacar(uint256 valor) external { uint256 s = saldo[msg.sender]; if (valor > s) revert SaldoInsuficiente(valor, s); saldo[msg.sender] = s - valor; // EFFECTS antes da interação (bool ok, ) = msg.sender.call{value: valor}(""); // INTERACTION require(ok, "transferencia falhou"); } }
4.2 Storage, memory, calldata
- storage: persistente na chain, caro — cada slot escrito custa gas significativo. Minimize o que guarda.
- memory: temporário, durante a execução da função.
- calldata: os argumentos da chamada, read-only, o mais barato — use para parâmetros que você só lê.
4.3 Funções e visibilidade
- external / public / internal / private; view (lê, não escreve) / pure (nem lê) / payable (recebe ETH).
- msg.sender (quem chamou), msg.value (ETH enviado), block.timestamp (com cuidado — manipulável em pequena margem).
- modifiers para pré-condições reutilizáveis (
apenasDono,quandoNaoPausado). - Erros:
require(cond, "msg"),revert CustomError(...)(mais barato e informativo),assert(invariantes que nunca devem falhar).
4.4 Os padrões ERC
| Padrão | É |
|---|---|
| ERC-20 | token fungível (moedas, pontos, governança) |
| ERC-721 | token não-fungível (NFT — cada um único) |
| ERC-1155 | multi-token (fungíveis e não-fungíveis no mesmo contrato — jogos, edições) |
| ERC-4626 | vault tokenizado (padrão para cofres de rendimento) |
| ERC-4337 | account abstraction (smart accounts sem mudar o protocolo) |
Use as implementações auditadas da OpenZeppelin (ou Solady) em vez de reescrever — reinventar um ERC-20 é uma fonte clássica de bug.
4.5 Upgradeabilidade
- Contratos são imutáveis por padrão. Para poder corrigir/evoluir, usa-se um proxy: um contrato "casca" que guarda o estado e delega a lógica (via
delegatecall) a um contrato de implementação que você pode trocar. - Padrões: UUPS, Transparent Proxy, Diamond.
- Perigos: quem controla a chave de upgrade controla os fundos (centralização — mitigar com timelock + multisig); colisão de storage entre versões;
delegatecallmal usado; a "imutabilidade" que os usuários esperam some.
4.6 Ferramental
- Foundry (
forge,cast,anvil): compilar, testar (em Solidity!), fuzzing, simular na rede real (fork), deploy. O padrão moderno. - Hardhat: baseado em JS/TS, ecossistema de plugins.
- Testes: unitários, invariantes, fuzz, fork tests contra estado real — cobertura alta não é opcional aqui (Módulo 5). Ver Testing Moderno & Automação.
Perguntas: "Diferença entre storage, memory e calldata?" (persistente e caro / temporário / argumentos read-only baratos), "Por que usar as libs da OpenZeppelin?" (implementações auditadas dos ERCs; reescrever é fonte de bug), "Como se faz um contrato 'atualizável' e quais os riscos?" (proxy + delegatecall; centralização da chave de upgrade, colisão de storage, perda da imutabilidade), "Foundry ou Hardhat?".
✏️ Exercício 4 — Revise o contrato
Um contrato de "vesting" (liberação gradual de tokens) tem: function claim() external { token.transfer(msg.sender, disponivel()); claimed += disponivel(); }. Aponte os problemas e reescreva.
Gabarito (uma boa resposta): problemas: (1) disponivel() é chamado duas vezes — se ele depende de claimed, a segunda chamada retorna um valor diferente da primeira (o usuário pode receber a mais); (2) a ordem viola checks-effects-interactions: a interação externa (token.transfer) acontece antes de atualizar o estado (claimed) — janela para reentrância se o token for malicioso/com hook (ERC-777); (3) não verifica se há algo a reclamar (poderia emitir um transfer de 0). Reescrito: function claim() external { uint256 amount = disponivel(); require(amount > 0, "nada a reclamar"); claimed += amount; emit Claimed(msg.sender, amount); token.safeTransfer(msg.sender, amount); } — calcula uma vez, atualiza o estado antes da transferência, usa safeTransfer, checa > 0 e emite evento. Idealmente também um nonReentrant guard.
Segurança de smart contracts
Objetivo: as classes de vulnerabilidade (reentrancy, access control, oracle, MEV, delegatecall), as ferramentas, e por que auditoria é obrigatória.
5.1 Por que a barra é outra
Um contrato em produção é imutável (ou upgradeável por uma chave que também é um risco), guarda dinheiro real, é público (qualquer um lê o código e tenta explorá-lo), e não tem "rollback". Bugs que numa web app seriam um incidente aqui são milhões perdidos em minutos. O site rekt.news é um cemitério de exemplos.
5.2 As classes clássicas
| Vulnerabilidade | O que é / mitigação |
|---|---|
| Reentrancy | um contrato externo, chamado no meio da sua função, "chama de volta" antes de você atualizar o estado, drenando fundos. → checks-effects-interactions, guard nonReentrant, pull-payments |
| Access control | função sensível sem onlyOwner/role; initialize de proxy chamável por qualquer um. → modifiers, Ownable/AccessControl, inicialização protegida |
| Integer overflow/underflow | resolvido por padrão no Solidity ≥ 0.8 (reverte); cuidado com unchecked e com casts |
| Oracle manipulation | usar o preço de um pool AMM (manipulável com flash loan) como fonte de verdade. → oráculos robustos (Chainlink), TWAP, checagem de sanidade |
| Front-running / MEV | a mempool é pública; bots reordenam/inserem transações para lucrar (sandwich, liquidação). → commit-reveal, slippage limits, private mempools |
| delegatecall perigoso | executar código de outro contrato no seu contexto de storage — se o alvo é controlável, é game over. → nunca delegatecall para endereço não confiável |
| Timestamp / block dependence | usar block.timestamp ou blockhash como aleatoriedade ou trava fina. → não use para randomness (use VRF); tolere margem de segundos |
| Unchecked external call | ignorar o retorno de um call/transfer. → checar sempre; usar SafeERC20 |
| Precisão / rounding | divisões que arredondam a favor do usuário; ordem de operações. → arredondar contra o usuário, testar bordas |
5.3 Ferramentas e processo
- Análise estática: Slither, Aderyn — pega padrões conhecidos rápido.
- Fuzzing / invariantes: Foundry (
forge testcom fuzz einvariant), Echidna — testa milhares de sequências aleatórias contra propriedades ("o total de shares nunca excede os ativos"). - Verificação formal (noção): provar propriedades matematicamente (Certora, Halmos, o SMT do Solidity).
- Auditoria por uma firma reconhecida antes de mainnet — não é opcional para qualquer coisa que segura valor.
- Bug bounty (Immunefi) contínuo; monitoramento on-chain (Forta) e um plano de pausar (circuit breaker) — mesmo que você "não possa reverter", pode parar o sangramento.
- Deploy gradual: limites de valor no começo, timelock em funções administrativas, multisig no owner.
Interação externa antes de atualizar o estado (reentrancy). Função de admin sem modifier. initialize de proxy sem proteção. Preço de spot de um AMM como oráculo + flash loan. Aritmética de shares/assets que arredonda a favor do atacante. delegatecall para um endereço que o atacante controla. "Aleatoriedade" com block.timestamp. Deploy em mainnet sem auditoria porque "está com pressa". Chave de upgrade numa EOA.
Perguntas: "O que é reentrancy e como preveni-la?" (chamada externa reentra antes da atualização de estado; checks-effects-interactions + nonReentrant), "Por que não usar o preço de um pool AMM como oráculo?" (manipulável com flash loan; usar Chainlink/TWAP), "O que é MEV / front-running?" (mempool pública; bots reordenam para lucrar), "Como você garante segurança antes de ir para mainnet?" (Slither + fuzzing/invariantes no Foundry + auditoria + bug bounty + monitoramento + circuit breaker + timelock/multisig).
✏️ Exercício 5 — Ache o bug
Um pool de recompensas tem: function withdraw() external { uint256 r = rewards[msg.sender]; (bool ok,) = msg.sender.call{value: r}(""); require(ok); rewards[msg.sender] = 0; }. Descreva o ataque passo a passo e o conserto.
Gabarito (uma boa resposta): Ataque (reentrancy): o atacante é um contrato cuja função receive()/fallback() chama withdraw() de novo. Passos: (1) o atacante deposita e acumula rewards[atacante] = X; (2) chama withdraw(); (3) o contrato lê r = X e faz msg.sender.call{value: X}(""); (4) isso invoca o fallback do atacante, que chama withdraw() de novo — como rewards[atacante] ainda é X (só é zerado depois do call), o contrato envia mais X; (5) repete até drenar o pool; (6) só então a pilha de chamadas desenrola e cada rewards[msg.sender] = 0 roda (tarde demais). Conserto: aplicar checks-effects-interactions — zerar rewards[msg.sender] antes do call; adicionar um modifier nonReentrant; e checar r > 0. Idealmente, padrão pull com SafeTransfer e limites.
Interagir com contratos (dApp)
Objetivo: conectar carteira, ler e escrever, assinar mensagens, indexar eventos, e melhorar o UX notoriamente ruim de web3.
6.1 As bibliotecas
- viem: cliente TypeScript moderno, tipado, para ler/escrever/assinar; substituiu o ethers.js em muitos projetos.
- wagmi: hooks React sobre o viem (
useAccount,useReadContract,useWriteContract,useWaitForTransactionReceipt). - ethers.js: ainda muito usado; API estável.
- RainbowKit / ConnectKit / Web3Modal: UI pronta de "conectar carteira".
6.2 Conectar e o EIP-1193
- A carteira injeta um provider (
window.ethereum, padrão EIP-1193); WalletConnect conecta carteiras de celular por QR. - Peça a conexão só quando necessário; trate troca de conta e troca de rede (o usuário pode estar na chain errada — ofereça "trocar para X").
6.3 Ler vs escrever
- Ler (
call): grátis, instantâneo, não precisa de carteira (pode ir por um RPC público). - Escrever (transação): custa gas, precisa de assinatura da carteira, é assíncrona — você envia, recebe um hash, e espera a confirmação (que pode demorar ou falhar).
- UX: mostrar cada estado ("aguardando assinatura na carteira", "transação enviada", "confirmando…", "confirmada" / "revertida"), estimar o gas, permitir acompanhar num explorer, e nunca assumir sucesso antes da confirmação (ver Design de Produtos com IA para padrões de estado assíncrono e otimista).
6.4 Assinar mensagens (EIP-712)
- Assinar dados estruturados off-chain (grátis, sem gas) prova identidade/intenção — usado em "Sign-In with Ethereum", permits de token (
permit— aprovar sem uma tx separada), ordens de marketplace. - Mostre ao usuário o que ele está assinando de forma legível — assinaturas cegas são vetor de golpe.
6.5 Eventos e indexação
- Contratos emitem eventos; para exibir histórico e agregações, você indexa os logs:
- The Graph (subgraphs), Ponder, envio, ou seu próprio indexer lendo os logs via RPC → um Postgres → sua API (ver API Design, Engenharia de Dados).
- Não tente "consultar a chain" para telas ricas — indexe.
6.6 Melhorar o UX
- Account abstraction (ERC-4337) + paymaster: o app patrocina o gas; o usuário não precisa de ETH.
- Embedded wallets (login por e-mail/social/passkey): sem seed phrase, sem extensão.
- Batching: várias ações numa transação (aprovar + depositar).
- Session keys: autorizar ações limitadas por um tempo sem assinar cada uma.
- Comece na testnet (Sepolia + faucet) e num fork local (anvil).
Perguntas de front-end web3: "Diferença entre ler e escrever num contrato?" (call grátis e síncrono vs transação com gas, assinatura e confirmação assíncrona), "Como você exibe o histórico de um contrato numa tela?" (indexar os eventos — The Graph/Ponder → banco → API; não consultar a chain direto), "O que é EIP-712 e por que assinar off-chain?" (dados estruturados assinados sem gas — SIWE, permit, ordens), "Como melhorar o UX de web3?" (account abstraction + paymaster, embedded wallets, batching, session keys).
✏️ Exercício 6 — Fluxo de "depositar num cofre"
Descreva o fluxo completo de front-end (viem/wagmi) para um usuário depositar um token ERC-20 num cofre: conexão, aprovação, depósito, estados de UI, e o que fazer se a transação falhar.
Gabarito (uma boa resposta): (1) Conectar a carteira (RainbowKit); checar a rede — se errada, botão "trocar para Base". (2) Ler o saldo do token e a allowance atual do cofre (call, grátis). (3) Se a allowance < valor: aprovar — useWriteContract chamando token.approve(cofre, valor); estados: "assine na carteira" → "enviada (hash, link pro explorer)" → useWaitForTransactionReceipt → "aprovada". (Alternativa melhor: permit via EIP-712 — assinatura sem tx — e depositar em uma transação só.) (4) Depositar: cofre.deposit(valor); mesmos estados. (5) Ao confirmar: atualizar os saldos (re-ler), mostrar sucesso, e o novo balanço de shares do cofre. Falha: se a tx reverte (ex.: cofre pausado, valor acima do limite), mostrar a razão em linguagem simples (decodificar o custom error), preservar o input, e oferecer "tentar de novo"; se o usuário rejeita a assinatura, voltar ao estado anterior sem erro alarmante; se demora demais, permitir "acelerar" (bump de gas) ou cancelar. Nunca marcar como depositado antes da confirmação.
DeFi, NFTs, DAOs e os padrões
Objetivo: AMMs, lending, stablecoins, oráculos, NFTs além da arte, governança on-chain e multisig, e os red flags de tokenomics.
7.1 DeFi
- AMM (Uniswap-style): em vez de um order book, um pool de dois ativos com uma fórmula (ex.:
x·y=k) define o preço; quem provê liquidez ganha taxas e sofre impermanent loss (perda relativa a só segurar os ativos quando o preço se move). - Lending (Aave-style): deposita colateral, toma emprestado até um LTV; se o colateral cai, você é liquidado (com penalidade). Juros variam com utilização.
- Stablecoins: lastreadas em fiat (USDC), sobre-colateralizadas em cripto (DAI), ou algorítmicas (histórico ruim — Terra). Saber o tipo é saber o risco.
- Flash loans: empréstimo sem colateral que deve ser pago na mesma transação — legítimo para arbitragem, e ferramenta de ataque (manipular um oráculo — Módulo 5).
- Composabilidade: o token de um protocolo vira colateral em outro, que vira liquidez em outro — poder e risco sistêmico.
7.2 Oráculos
- Contratos não podem chamar APIs; um oráculo traz dados de fora (preço, resultado, aleatoriedade).
- Chainlink (price feeds, VRF para randomness, Automation); TWAP (média de preço no tempo, mais difícil de manipular).
- O oráculo é um ponto de confiança — o "descentralizado" do seu app depende de quão descentralizado é o oráculo.
7.3 NFTs além da arte
- Credenciais e certificados (diplomas, participação — "POAP"), ingressos (transferíveis com regras), identidade, tokenização de ativos reais (RWA) (imóveis, títulos — com toda a camada legal por trás), itens de jogo, domínios (ENS).
- O metadata e a imagem geralmente ficam off-chain (IPFS/Arweave) — se o link quebra, o NFT "some"; prefira armazenamento persistente.
7.4 DAOs e governança
- DAO: uma organização cujas decisões e o tesouro são governados por regras on-chain — normalmente votos ponderados por um token de governança.
- Stack: um contrato de Governor (propostas, votação), um Timelock (atraso obrigatório entre aprovação e execução — janela de segurança), e um multisig (Gnosis/Safe) para execução e custódia.
- Problemas reais: baixa participação, concentração de tokens ("plutocracia"), compra de votos, e a lentidão da governança on-chain.
7.5 Tokenomics — os red flags
- Grande parte da oferta pré-alocada para o time/investidores com pouco lock; emissão alta e inflacionária; "utilidade" vaga do token; incentivos que só funcionam com entrada de dinheiro novo (Ponzi-like); "APY" absurdo pago em token do próprio protocolo; chave de mint sem limite; ausência de auditoria; equipe anônima sem accountability.
- Um projeto não precisa de um token — muitos lançam um só para captar, e isso é um sinal.
Perguntas: "Como um AMM define preço e o que é impermanent loss?" (fórmula de produto constante sobre um pool; a perda de LP relativa a segurar quando o preço se move), "O que é um oráculo e por que é um ponto de confiança?", "O stack de uma DAO?" (token de governança + Governor + Timelock + multisig), "Cite red flags de tokenomics" (pré-alocação alta sem lock, emissão inflacionária, utilidade vaga, APY insustentável em token próprio, mint sem limite, sem auditoria).
✏️ Exercício 7 — Avalie o projeto
Um projeto oferece "35% de APY" para quem faz stake do token nativo, a maior parte do supply está com o time (lock de 3 meses), o preço do oráculo vem do próprio pool de liquidez do token, e não há auditoria pública. Liste os riscos.
Gabarito (uma boa resposta): (1) APY de 35% pago no token próprio → não é rendimento real; é diluição/emissão; sustentável só com entrada contínua de capital novo (dinâmica de esquema). (2) Supply concentrado no time com lock curto (3 meses) → risco enorme de dump quando destravar; o preço pode colapsar. (3) Oráculo = preço do próprio pool → manipulável (flash loan): um atacante move o preço, aciona liquidações/mints/empréstimos indevidos, e reverte — o vetor de ataque de DeFi mais comum. (4) Sem auditoria → não há evidência de que o contrato não tem os bugs do Módulo 5; a chave de mint/upgrade pode ser irrestrita. (5) Provavelmente chave de upgrade/mint numa EOA (rug pull possível). Conclusão: o conjunto é o retrato de um projeto de altíssimo risco / possível golpe; um engenheiro responsável não constrói nem promove isso (Módulo 9).
Escala, L2s e o resto do stack
Objetivo: rollups a fundo, bridges e por que são o elo mais hackeado, account abstraction, storage e identidade descentralizados, e a infra de produção.
8.1 Rollups a fundo
- Um rollup precisa: um sequencer (ordena as transações — hoje frequentemente centralizado, um risco), publicar os dados na L1 (data availability — para qualquer um poder reconstruir o estado), e um mecanismo de verificação (prova de fraude no optimistic; prova de validade/ZK no zk).
- EIP-4844 (blobs) baratearam a publicação de dados dos rollups na L1.
- App-chains / L3s: uma chain dedicada a um app (com frameworks como OP Stack, Arbitrum Orbit, ZK Stack) — mais controle, menos "vizinhos", à custa de segurança/liquidez fragmentada.
8.2 Bridges — o elo mais hackeado
- Mover um ativo entre chains: você tranca na origem e emite um representante no destino (ou queima e libera).
- Os contratos de bridge concentram muito valor e dependem de validadores/relayers — foram responsáveis por alguns dos maiores roubos da história do setor.
- Prefira bridges canônicas (a oficial da L2), com auditoria e histórico; entenda o modelo de confiança de qualquer bridge antes de usar.
8.3 Account abstraction (ERC-4337)
- Uma infra (bundlers, EntryPoint, paymasters) que permite smart accounts sem mudar o protocolo Ethereum: recuperação social, patrocínio de gas, chaves de sessão, limites de gasto, batching, verificação customizada (passkeys).
- É a maior alavanca de UX de web3 (Módulo 6).
8.4 Storage e identidade descentralizados
- IPFS (endereçado por conteúdo — o CID é o hash; precisa de "pinning" para persistir) e Arweave (pagamento único para armazenamento "permanente") — para metadata de NFT, frontends, arquivos.
- ENS: nomes legíveis (
alice.eth) para endereços; Sign-In with Ethereum (EIP-4361): login com a carteira; verifiable credentials e "attestations" (EAS).
8.5 Infra de produção
- RPC: nó próprio ou provedor (Alchemy/Infura/QuickNode) — rate limits, custo, e o risco de depender de um provedor centralizado.
- Indexação: The Graph / Ponder / indexer próprio (Módulo 6).
- Monitoramento: Tenderly (simular/debugar tx), Forta (alertas on-chain), dashboards de saldo/atividade dos contratos.
- CI/CD de contratos: testes + Slither no pipeline, deploy scripts versionados, verificação do código no explorer (Etherscan) para transparência.
Perguntas: "O que é data availability num rollup e por que importa?" (publicar os dados na L1 para qualquer um reconstruir o estado — sem isso o rollup não herda a segurança), "Por que bridges são tão hackeadas?" (concentram muito valor e dependem de validadores/relayers — enorme superfície), "O que o ERC-4337 possibilita?" (smart accounts: recuperação social, gas patrocinado, chaves de sessão, batching), "Como você indexa e monitora contratos em produção?".
✏️ Exercício 8 — Arquitetura de um dApp em produção
Você vai lançar um marketplace de ingressos como NFT numa L2. Descreva a arquitetura: contratos, storage do metadata, carteira/UX, indexação, e monitoramento. Aponte os pontos de centralização/risco.
Gabarito (uma boa resposta): Contratos: um ERC-721 (ou 1155 para lotes) com regras de transferência (revenda com teto de preço, royalties, "burn" na entrada), usando OpenZeppelin, auditado, com owner em multisig + timelock e um pause de emergência. Deploy numa L2 (Base/Arbitrum) pelo gas. Metadata: JSON + imagem em Arweave (ou IPFS com pinning pago) — persistência importa para um ingresso; o tokenURI aponta para lá. Carteira/UX: embedded wallet com login social + account abstraction com paymaster (o comprador não precisa de ETH nem seed phrase); comprar com stablecoin ou cartão via on-ramp. Indexação: um subgraph/Ponder lendo os eventos de mint/transfer/uso → Postgres → API para as telas "meus ingressos", "revendas", "check-in". Monitoramento: Forta/Tenderly alertando sobre transferências anômalas, mint fora do previsto, e chamadas às funções de admin; dashboard de vendas. Centralização/risco: o sequencer da L2 (censura/downtime), o multisig (quem controla), o paymaster (o app banca o gas — pode ser alvo de abuso, precisa de limites), o provedor de RPC, o on-ramp, e o "check-in" (se um servidor central valida a entrada, a descentralização do resto é parcial). Deixar isso explícito para o time e para os usuários.
Produção, regulação e ética
Objetivo: custódia de chaves, monitoramento e resposta a incidente, regulação (sem aconselhamento jurídico), impacto ambiental, e o dever de não facilitar golpes.
9.1 A chave privada é tudo
- Não há "esqueci a senha". Quem controla a chave controla os fundos — para sempre.
- Custódia: hardware wallets para pessoas; para tesouros e funções de admin, multisig (Safe) com signatários distribuídos e/ou HSM/MPC; key management com rotação, backups geograficamente separados, e um plano para "e se um signatário sumir".
- "Not your keys, not your coins": deixar cripto numa exchange é confiar na exchange (várias quebraram).
- Nunca coloque a chave de upgrade/mint de um contrato de valor numa EOA — é o vetor de rug pull.
9.2 Monitoramento e resposta a incidente
- Você não pode reverter uma transação. A resposta a incidente é: detectar rápido (Forta, alertas de anomalia), pausar (se houver circuit breaker), comunicar, e — se um exploit está em andamento — às vezes um "white-hat rescue" (mover os fundos antes do atacante) coordenado.
- Tenha um runbook: quem pode pausar, como, e o processo de comunicação (o histórico de hacks mostra que a comunicação lenta piora tudo).
- Bug bounty ativo (Immunefi) reduz a chance de o bug virar exploit.
9.3 Regulação
- Um token pode ser considerado um valor mobiliário (com todas as obrigações que isso traz), dependendo de como é vendido e do país; KYC/AML se aplica a on-ramps, exchanges e, cada vez mais, a protocolos; a MiCA (UE) trouxe um regime; no Brasil e nos EUA o cenário evolui e tem incerteza.
- Atividades como stablecoins, custódia, e "yield" para o público têm atenção regulatória crescente.
Esta seção é uma noção geral, não aconselhamento jurídico nem financeiro. A classificação de tokens, as obrigações de KYC/AML, tributação e licenciamento variam muito por país e mudam rápido. Para qualquer projeto real que lide com valores ou com o público, envolva advogados especializados desde o início.
9.4 Impacto ambiental
- O PoW (Bitcoin) tem consumo de energia alto e legítimo motivo de crítica.
- O PoS (Ethereum desde 2022) reduziu o consumo do Ethereum em ~99,95%. A maioria das chains de contrato hoje é PoS ou similar.
- Avalie a chain que você usa; comunique honestamente.
9.5 Ética e o dever de não facilitar golpes
- O setor tem uma proporção alta de golpes: rug pulls, tokens com honeypot (você compra e não consegue vender), esquemas de "yield" insustentável, "airdrops" que drenam a carteira ao assinar.
- Um engenheiro tem responsabilidade: não construir mecanismos de rug pull (mint infinito, chave de upgrade escondida, taxa de venda de 100%), não promover APYs insustentáveis, alertar sobre riscos, e recusar trabalhos cujo modelo é predatório.
- Transparência: código verificado, contratos sem "trapdoors", comunicação clara dos riscos e da centralização.
9.6 Quando NÃO usar blockchain (de novo)
Fechando o círculo do Módulo 1: a maioria dos problemas de negócio se resolve melhor sem blockchain. Só use quando a minimização de confiança ou a resistência à censura for o requisito central, o time entende a barra de segurança, e há orçamento para auditoria e operação. "Porque é inovador" não é um motivo.
Perguntas: "Como você custodia as chaves de admin de um protocolo?" (multisig com signatários distribuídos + timelock; nunca uma EOA; HSM/MPC; plano para signatário ausente), "O que você faz num exploit em andamento?" (não dá para reverter — detectar, pausar via circuit breaker, comunicar, possível white-hat rescue; ter runbook), "O Ethereum ainda gasta muita energia?" (não desde a migração para PoS em 2022), "O que é um rug pull e como o design de contrato pode habilitá-lo?" (mint infinito, chave de upgrade oculta, taxa de venda proibitiva — o engenheiro não deve construir isso).
✏️ Exercício 9 — Plano de custódia e incidente
Um protocolo de lending que você vai lançar terá um tesouro e funções administrativas (ajustar taxas, pausar, atualizar oráculo). Descreva a custódia das chaves, os controles, e o plano para um exploit.
Gabarito (uma boa resposta): Custódia: nenhuma função de admin numa EOA. Um Safe multisig (ex.: 5 de 9) com signatários de perfis e locais diferentes (fundadores, um investidor, um membro da comunidade, uma firma de segurança), cada um em hardware wallet; documentado quem, e um processo para substituir um signatário. Ações administrativas passam por um Timelock (ex.: 48h) — dá tempo de a comunidade ver e reagir a uma proposta maliciosa; exceção: o pause de emergência pode ter um caminho mais rápido (um "guardian" 2 de 3 que só pode pausar, nunca mover fundos). Controles: limites nos parâmetros (a taxa não pode ser setada acima de X por uma única tx), oráculo com checagem de sanidade e fallback, auditoria + bug bounty ativo, código verificado no explorer. Plano de exploit: monitoramento (Forta) com alertas de: grandes retiradas, mudança de parâmetro fora de faixa, chamadas à função de mint, divergência de oráculo. Runbook: o guardian pausa imediatamente; o time se reúne num canal predefinido; avaliar white-hat rescue (mover fundos vulneráveis para o Safe) se possível; comunicado público em até 1h dizendo o que se sabe; post-mortem público depois. Nada de esconder.
Mercado de trabalho: roadmap, entrevistas e portfólio
Objetivo: converter o conteúdo dos módulos em contratação — onde a habilidade é usada, um plano de estudo, um banco de perguntas e projetos que geram entrevista.
10.1 Onde web3 pesa
- Smart contract / protocol engineer: Solidity, segurança, DeFi/infra — o cargo mais valorizado e escasso.
- Security auditor: revisar e quebrar contratos; firmas e programas de bounty.
- Web3 frontend engineer: dApps com viem/wagmi, UX de carteira, indexação.
- Infra / node / indexing engineer: RPC, subgraphs, monitoramento.
- DevRel / integrações.
- Realidade do mercado: cíclico (segue o preço dos ativos), com muito projeto de baixa qualidade — priorize equipes sérias, com contratos auditados e produto real.
10.2 Roadmap de estudo (6–8 semanas)
| Semanas | Foco | Prática |
|---|---|---|
| 1 | Fundamentos e ceticismo (Módulos 1–3) | Explicar por escrito 5 casos "blockchain vs banco de dados"; mapear EVM, L1/L2, carteiras |
| 2–3 | Solidity + Foundry (Módulo 4) | Escrever e testar (Foundry) um ERC-20, um ERC-721 e um cofre; deploy em Sepolia |
| 4 | Segurança (Módulo 5) | Resolver desafios (Ethernaut, Damn Vulnerable DeFi); rodar Slither + fuzz nos seus contratos |
| 5 | dApp frontend (Módulo 6) | Um front-end viem/wagmi que lê e escreve num contrato seu, com estados de tx e um indexer simples |
| 6 | DeFi e padrões (Módulo 7) | Implementar um mini-AMM ou um vault ERC-4626 com testes de invariante |
| 7 | Escala, produção, ética (Módulos 8–9) | Deploy numa L2; multisig no owner; escrever um plano de incidente e um "blockchain: sim ou não" honesto |
| 8 | Portfólio | Publicar os contratos verificados, o dApp, e um relatório de auditoria de um contrato vulnerável |
10.3 Banco de perguntas (com a resposta que aprova)
Júnior/pleno — "Quando blockchain e quando banco de dados?"
Blockchain quando o requisito central é coordenar sem um intermediário confiável, resistir à censura, ou ter ativos sem emissor central, e as partes não confiam umas nas outras. Banco de dados em quase todo o resto — quando existe um controlador legítimo, precisa de privacidade, throughput, correção. E blockchain não resolve o problema do dado errado na entrada.
Pleno — "storage, memory, calldata em Solidity?"
storage: persistente na chain, caro (cada escrita custa muito gas) — minimize. memory: temporário durante a execução. calldata: os argumentos da chamada, read-only, o mais barato — use para parâmetros que só lê. Escolher errado infla o gas.
Pleno — "O que é reentrancy e como você previne?"
Um contrato externo chamado no meio da sua função "chama de volta" antes de você atualizar o estado, permitindo drenar fundos (o hack do The DAO). Prevenção: padrão checks-effects-interactions (atualize o estado antes de qualquer chamada externa), um guard nonReentrant, e pull-payments. Rodar fuzz/invariantes para pegar variações.
Pleno — "Por que não usar o preço de um pool AMM como oráculo?"
O preço spot de um pool é manipulável numa única transação com um flash loan: o atacante distorce o preço, aciona uma liquidação/empréstimo/mint indevido no seu contrato, e desfaz — tudo antes do bloco fechar. Use oráculos robustos (Chainlink), TWAP (média no tempo), e checagens de sanidade.
Pleno/front-end — "Ler vs escrever num contrato, do ponto de vista de UX?"
Ler (call) é grátis, síncrono e não precisa de carteira. Escrever é uma transação: custa gas, precisa de assinatura, e é assíncrona — você recebe um hash e espera a confirmação, que pode demorar ou reverter (gastando gas mesmo assim). A UI precisa de estados explícitos (assinar → enviada → confirmando → confirmada/revertida), decodificar o erro, e nunca assumir sucesso antes da confirmação.
Sénior — "Como você leva um protocolo a mainnet com segurança?"
Testes de unidade + invariantes + fuzz (Foundry) + fork tests; Slither no CI; auditoria por uma firma reconhecida; bug bounty ativo; deploy gradual com limites de valor; funções de admin em multisig + timelock; um circuit breaker (pause); monitoramento on-chain (Forta/Tenderly) e um runbook de incidente. Código verificado no explorer.
Sénior — "Por que bridges são o alvo mais comum de grandes hacks?"
Concentram muito valor num só contrato e o modelo de segurança depende de validadores/relayers/multisigs que podem ser comprometidos ou ter bugs de verificação de mensagem. Prefira bridges canônicas auditadas e entenda o modelo de confiança antes de mover valor.
Armadilha — "Nosso produto seria muito melhor 'na blockchain'"
Quase nunca. Blockchain custa performance, gas, complexidade e uma superfície de risco onde um bug é irreversível e público. Só compensa quando a minimização de confiança ou a resistência à censura é o requisito central. "É inovador" não é um requisito. Um engenheiro sênior diz isso ao time.
10.4 Projetos de portfólio que geram entrevista
- Contratos testados e deployados (âncora): um ERC-20 e um ERC-721 seus, com suíte Foundry completa (unit + fuzz + invariantes), Slither limpo, verificados numa testnet/L2, com README das decisões.
- Vault ERC-4626 ou mini-AMM: com testes de invariante ("shares nunca valem mais que os ativos"), e um estudo dos vetores de ataque considerados.
- dApp full-stack: front-end viem/wagmi que lê e escreve, com estados de transação bem feitos, um indexer (Ponder/subgraph) e uma tela de histórico.
- Relatório de auditoria: pegue um contrato vulnerável (dos desafios ou um real pós-hack), escreva o relatório: descrição, severidade, PoC, correção.
- Ensaio honesto: "quando blockchain, quando não" aplicado a 3 casos reais, com a arquitetura alternativa.
10.5 Fontes para continuar
- Fundamentos: ethereum.org (docs); Mastering Ethereum (Antonopoulos & Wood); a documentação do Solidity; o Foundry Book.
- Cursos: Cyfrin Updraft / Patrick Collins (Solidity + segurança, gratuito e muito completo); Secureum.
- Segurança: Ethernaut e Damn Vulnerable DeFi (desafios); os checklists e blogs de Trail of Bits, OpenZeppelin, Consensys Diligence; rekt.news (pós-mortems); Solodit (agregador de achados de auditoria).
- Ferramentas: viem/wagmi docs, The Graph/Ponder, Tenderly, Foundry.
- Nesta trilha: Arquitetura de Software & System Design, API Design: REST, GraphQL & gRPC, Cibersegurança Prática & DevSecOps, Testing Moderno & Automação, Full Stack com TypeScript & Next.js, JavaScript Fullstack, Rust: Sistemas, CLI & WebAssembly, Investimentos Financeiros com Controlo de Risco.
Cinco ideias sustentam web3: (1) blockchain é uma ferramenta de minimização de confiança — para a maioria dos casos, um banco de dados é melhor, e dizer isso é parte do trabalho; (2) o código é imutável, público e move dinheiro real — a barra de segurança é outra: checks-effects-interactions, oráculos robustos, fuzzing, auditoria obrigatória; (3) o UX de web3 é ruim por padrão — account abstraction, paymasters e embedded wallets são a saída; (4) a atividade real vive em L2s, e bridges são o elo mais frágil; (5) a chave privada é tudo (multisig + timelock, nunca uma EOA no admin), você não pode reverter um exploit, e há um dever ético de não construir mecanismos de golpe.