Interagindo com contratos inteligentes
Você nem sempre precisa escrever e implantar seu próprio contrato inteligente. Na maioria das vezes, como desenvolvedor, você vai querer interagir com contratos inteligentes que outras pessoas já implantaram na rede Ethereum.
Esta página aborda as duas maneiras fundamentais de interagir com um contrato inteligente — lendo dados e escrevendo dados — e as ferramentas necessárias para fazer ambos.
Pré-requisitos
Você deve entender:
- Como funcionam os contratos inteligentes
- Contas Ethereum e como elas assinam transações
- O que é uma transação
Duas maneiras de interagir com um contrato inteligente
A interação com um contrato inteligente se divide em duas categorias:
Lendo de um contrato
A leitura é uma operação gratuita que não cria uma transação e não altera nenhum estado na blockchain.
Quando você lê de um contrato, está simplesmente consultando dados que já existem. Por exemplo:
- Verificar o saldo de um token ERC-20
- Ler o preço atual de uma corretora descentralizada
- Obter o proprietário de um NFT
Como as leituras não modificam o estado, elas não custam gás e podem ser realizadas por qualquer pessoa sem a necessidade de ETH.
Escrevendo em um contrato
A escrita é uma operação de mudança de estado que requer uma transação e custa gás.
Quando você escreve em um contrato, está acionando uma função que modifica o estado da blockchain. Por exemplo:
- Transferir tokens
- Trocar tokens em uma corretora descentralizada
- Cunhar um NFT
A escrita sempre requer:
- Uma Conta de Propriedade Externa (EOA) com ETH suficiente para o gás
- Uma transação assinada pela chave privada da conta
- Que a transação seja minerada e incluída em um bloco
Com a abstração de conta, uma conta de contrato inteligente também pode iniciar escritas, e um pagador pode cobrir o gás em nome do usuário — portanto, uma EOA com ETH não é estritamente necessária.
Entendendo as ABIs de contratos
Para interagir com um contrato inteligente, seu aplicativo precisa saber o que o contrato pode fazer. É aqui que entra a Interface Binária de Aplicação (ABI).
Uma ABI é um documento JSON que descreve:
- Cada função que o contrato expõe (nome, entradas, saídas)
- Cada evento que o contrato pode emitir
- Como codificar e decodificar dados ao se comunicar com o contrato
Pense na ABI como o manual de instruções do contrato — sem ela, seu aplicativo não sabe quais funções existem ou quais parâmetros elas esperam.
Onde encontrar a ABI de um contrato
- Contratos verificados no Etherscan - O Etherscan (abre em uma nova aba) expõe automaticamente a ABI para código-fonte verificado
- Do desenvolvedor - muitos projetos publicam suas ABIs em suas documentações ou pacotes npm
- Gerar a partir do código-fonte - se você tiver o código-fonte em Solidity, pode compilá-lo para produzir a ABI
Ferramentas e bibliotecas para interagir com contratos
Os desenvolvedores geralmente usam uma biblioteca JavaScript/TypeScript para interagir com contratos a partir de um aplicativo web, backend ou script.
Bibliotecas de cliente (JavaScript/TypeScript)
- Viem (abre em uma nova aba) - Interface TypeScript moderna e leve para Ethereum com segurança de tipo de primeira classe
- ethers.js (abre em uma nova aba) - Biblioteca testada em batalha para interagir com a blockchain Ethereum
- Web3.js (abre em uma nova aba) - A API JavaScript original da Ethereum
Bibliotecas de backend
- ethers.js (abre em uma nova aba) - Também funciona em Node.js para scripts do lado do servidor e bots
- Web3.py (abre em uma nova aba) - Biblioteca Python para interação com a Ethereum
- go-ethereum (abre em uma nova aba) - Biblioteca oficial em Go da equipe do Geth
Exemplo: lendo o saldo de um token com Viem
import { createPublicClient, http, formatUnits } from 'viem'
import { mainnet } from 'viem/chains'
// Endereço do contrato USDC e ABI (parcial, para balanceOf)
const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
const abi = [{
name: 'balanceOf',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'account', type: 'address' }],
outputs: [{ name: '', type: 'uint256' }],
}] as const
const client = createPublicClient({ chain: mainnet, transport: http() })
const balance = await client.readContract({
address: USDC,
abi,
functionName: 'balanceOf',
args: ['0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'], // vitalik.eth
})
console.log(formatUnits(balance, 6)) // USDC tem 6 decimais
Exemplo: enviando uma transação com ethers.js
const { ethers } = require('ethers')
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL)
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider)
// ABI de transferência ERC-20
const abi = ['function transfer(address to, uint256 amount) returns (bool)']
const contract = new ethers.Contract(tokenAddress, abi, wallet)
const tx = await contract.transfer(recipient, ethers.parseUnits('10', 18))
await tx.wait() // aguardar a transação ser minerada
console.log(`Transferred! TX: ${tx.hash}`)
Eventos e logs
Contratos inteligentes podem emitir eventos para sinalizar que algo aconteceu. Seu aplicativo pode escutar esses eventos para reagir em tempo real.
import { createPublicClient, http, parseAbiItem } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({ chain: mainnet, transport: http() })
// Observar eventos de transferência de USDC
const unwatch = client.watchEvent({
event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
onLogs: (logs) => console.log(logs),
})
Simulando transações
Antes de enviar uma transação, você pode simulá-la para verificar se ela seria bem-sucedida — e para ver seu valor de retorno — sem gastar gás. Isso é útil para detectar erros precocemente e para visualizar os resultados.
A maioria das bibliotecas de cliente suporta isso através de eth_call:
// Com Viem
const result = await client.simulateContract({
address: contractAddress,
abi,
functionName: 'swap',
args: [amountIn],
account: userAddress,
})
Carteiras e assinatura
Em um dapp, a carteira do usuário (como MetaMask, Rainbow ou WalletConnect) lida com a assinatura. Você não gerencia chaves privadas diretamente.
Bibliotecas de carteira e ferramentas de conexão abstraem isso para que você possa se concentrar na construção da lógica do seu aplicativo.
Tutoriais relacionados
- Chamando um contrato inteligente a partir do JavaScript
- Enviando transações usando Web3.js e Alchemy
- Como visualizar seu NFT na sua carteira
Leitura adicional
- Documentação do Viem: Lendo e escrevendo em contratos (abre em uma nova aba)
- Documentação do ethers.js: Contratos (abre em uma nova aba)
- Especificação da ABI do Solidity (abre em uma nova aba)
- O que é uma ABI? - Alchemy (abre em uma nova aba)