DEV Community

Edu
Edu

Posted on

Da Série Cliente Imaginário #1: Como resolvi o pedido "preciso pausar meu contrato sem novo deploy" usando Solidity + Foundry

Modo Manutenção em Solidity com Foundry

Ainda não tenho clientes reais em Web3. Mas ao invés de só fazer tutoriais soltos, decidi simular pedidos reais de clientes e resolvê-los como se fossem projetos de verdade do entendimento da dor até o deploy funcionando. Esse é o primeiro caso da série.

O pedido do Cliente (imaginário)

Imagine o seguinte cenário: CryptoMarket, um marketplace de NFTs, já está em produção com usuários reais. O dono me procura com uma dor bem específica:

"Se um bug aparecer no meio da noite, eu preciso conseguir travar as transações imediatamente, sem depender de ninguém, sem precisar rodar um novo deploy. E quando eu resolver, preciso poder destravar do mesmo jeito."

Duas alternativas ruins que ele tinha antes de me procurar:

  1. Deixar o contrato ativo mesmo sabendo do risco
  2. Fazer um novo deploy do zero (caro, quebra o endereço já divulgado, perde histórico)

O que eu vou construir

Um mecanismo de Modo Manutenção: um interruptor on-chain que só o dono do contrato pode ligar ou desligar, bloqueando funções críticas enquanto estiver ativo e permitindo que qualquer pessoa consulte o status a qualquer momento (transparência).

Arquitetura antes do código

Função Quem pode chamar O que faz
toggleMaintenance() Só o owner Liga/desliga o modo manutenção
isUnderMaintenance() Qualquer um Consulta o status atual
buyNFT() (exemplo) Usuários Só executa se não estiver em manutenção

O contrato

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract CryptoMarket {

    address public owner;
    bool public maintenanceMode;

    event MaintenanceToggled(bool novoStatus);

    constructor() {
        owner = msg.sender;
        maintenanceMode = false;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Apenas o owner pode fazer isso");
        _;
    }

    modifier notInMaintenance() {
        require(!maintenanceMode, "Contrato em manutencao no momento");
        _;
    }

    function toggleMaintenance() public onlyOwner {
        maintenanceMode = !maintenanceMode;
        emit MaintenanceToggled(maintenanceMode);
    }

    function isUnderMaintenance() public view returns (bool) {
        return maintenanceMode;
    }

    function buyNFT() public notInMaintenance {
    }
}
Enter fullscreen mode Exit fullscreen mode

Testando com Foundry

Escrevi 8 testes cobrindo os cenários principais: deploy correto, estado inicial, toggle nos dois sentidos, bloqueio de acesso pra quem não é owner, bloqueio do buyNFT() durante manutenção, e emissão do evento.

forge test -vvv
Enter fullscreen mode Exit fullscreen mode

Todos os 8 testes passaram (8 passed; 0 failed; 0 skipped).

Deploy local com Anvil

Subi uma blockchain local simulada:

anvil
Enter fullscreen mode Exit fullscreen mode

E fiz o deploy do contrato usando a primeira conta pré-financiada como owner:

forge create src/CryptoMarket.sol:CryptoMarket \
  --rpc-url http://127.0.0.1:8545 \
  --private-key <CHAVE_PRIVADA> \
  --broadcast
Enter fullscreen mode Exit fullscreen mode

Deploy feito com sucesso 🎉

  • Deployer (owner): 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
  • Endereço do contrato: 0x5FbDB2315678afecb367f032d93F642f64180aa3

Interagindo com o contrato via Cast

Com o contrato no ar, testei o fluxo completo na prática não só nos testes, mas em uma blockchain local de verdade.

1. Consultar o status (leitura, sem gastar gas)

cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "isUnderMaintenance()(bool)" --rpc-url http://127.0.0.1:8545
Enter fullscreen mode Exit fullscreen mode

Retornou false — o contrato nasce operacional, como esperado.

2. Ativar o modo manutenção (escrita, precisa da chave do owner)

cast send 0x5FbDB2315678afecb367f032d93F642f64180aa3 "toggleMaintenance()" \
  --rpc-url http://127.0.0.1:8545 \
  --private-key <CHAVE_PRIVADA_DO_OWNER>
Enter fullscreen mode Exit fullscreen mode

Transação minerada com status: 1 (success). Repare no campo logs: ali está o evento MaintenanceToggled sendo emitido on-chain — prova de auditoria, gravada permanentemente na blockchain.

3. Confirmar que mudou

cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "isUnderMaintenance()(bool)" --rpc-url http://127.0.0.1:8545
Enter fullscreen mode Exit fullscreen mode

Agora retorna true.

4. Testar o bloqueio

Tentei chamar buyNFT() enquanto o contrato está em manutenção:

cast send 0x5FbDB2315678afecb367f032d93F642f64180aa3 "buyNFT()" \
  --rpc-url http://127.0.0.1:8545 \
  --private-key <CHAVE_PRIVADA_DO_OWNER>
Enter fullscreen mode Exit fullscreen mode

Error: execution reverted: Contrato em manutencao no momento

Exatamente o comportamento esperado: o modifier notInMaintenance bloqueou a função de negócio.

5. Voltar o status para operacional (false)

cast send 0x5FbDB2315678afecb367f032d93F642f64180aa3 "toggleMaintenance()" \
  --rpc-url http://127.0.0.1:8545 \
  --private-key <CHAVE_PRIVADA_DO_OWNER>
Enter fullscreen mode Exit fullscreen mode

6. Confirmar que voltou

cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "isUnderMaintenance()(bool)" --rpc-url http://127.0.0.1:8545
Enter fullscreen mode Exit fullscreen mode

Retornou false novamente.

7. Testar buyNFT() com o contrato liberado

cast send 0x5FbDB2315678afecb367f032d93F642f64180aa3 "buyNFT()" \
  --rpc-url http://127.0.0.1:8545 \
  --private-key <CHAVE_PRIVADA_DO_OWNER>
Enter fullscreen mode Exit fullscreen mode

status: 1 (success) sem nenhum erro. O contrato voltou a funcionar normalmente assim que a manutenção foi desativada.

O que essa simulação prova

Estado buyNFT()
Em manutenção (true) ❌ Reverte com "Contrato em manutencao no momento"
Operacional (false) ✅ Executa normalmente

O ciclo completo — construção, teste, deploy e interação real — funcionou do início ao fim, exatamente como o cliente (imaginário) precisava.

Por que documentar assim

Não tenho clientes reais em Web3 ainda. Mas resolver problemas simulados com o mesmo rigor que teria com um cliente de verdade entender a dor antes de codar, testar com cobertura real, validar em ambiente local antes de qualquer coisa em produção é como estou construindo prática e portfólio ao mesmo tempo.

Código completo no GitHub: https://github.com/Eduprogrammer/solidity-maintenance-mode

Meu Linkedin: https://www.linkedin.com/in/educarlos29/

Se você é dev e tem uma dor parecida com essa (ou outra ideia de "cliente imaginário" pra próxima simulação), comenta aí 👇

#solidity #foundry #web3 #blockchain #smartcontracts #developer

Top comments (0)