Interagire con gli smart contract
Non è sempre necessario scrivere e distribuire il proprio smart contract. La maggior parte delle volte, come sviluppatore, vorrai interagire con gli smart contract che altri hanno già distribuito sulla rete Ethereum.
Questa pagina illustra i due modi fondamentali per interagire con uno smart contract — leggere i dati e scrivere i dati — e gli strumenti necessari per fare entrambe le cose.
Prerequisiti
Dovresti comprendere:
- Come funzionano gli smart contract
- Gli account Ethereum e come firmano le transazioni
- Cos'è una transazione
Due modi per interagire con uno smart contract
L'interazione con uno smart contract si divide in due categorie:
Leggere da un contratto
La lettura è un'operazione gratuita che non crea una transazione e non modifica alcuno stato sulla blockchain.
Quando leggi da un contratto, stai semplicemente interrogando dati che esistono già. Ad esempio:
- Controllare il saldo di un token ERC-20
- Leggere il prezzo attuale da un exchange decentralizzato
- Ottenere il proprietario di un NFT
Poiché le letture non modificano lo stato, non costano gas e possono essere eseguite da chiunque senza bisogno di ETH.
Scrivere su un contratto
La scrittura è un'operazione che modifica lo stato, richiede una transazione e costa gas.
Quando scrivi su un contratto, stai attivando una funzione che modifica lo stato della blockchain. Ad esempio:
- Trasferire token
- Scambiare token su un exchange decentralizzato
- Il conio di un NFT
La scrittura richiede sempre:
- Un Account di Proprietà Esterna (EOA) con abbastanza ETH per il gas
- Una transazione firmata dalla chiave privata dell'account
- Che la transazione venga minata e inclusa in un blocco
Con l'astrazione dell'account, anche un account smart contract può avviare scritture, e un paymaster può coprire il gas per conto dell'utente, quindi un EOA che detiene ETH non è strettamente necessario.
Comprendere le ABI dei contratti
Per interagire con uno smart contract, la tua applicazione deve sapere cosa può fare il contratto. È qui che entra in gioco l'Application Binary Interface (ABI).
Un'ABI è un documento JSON che descrive:
- Ogni funzione esposta dal contratto (nome, input, output)
- Ogni evento che il contratto può emettere
- Come codificare e decodificare i dati quando si comunica con il contratto
Pensa all'ABI come al manuale di istruzioni del contratto: senza di essa, la tua applicazione non sa quali funzioni esistono o quali parametri si aspettano.
Dove trovare l'ABI di un contratto
- Contratti verificati su Etherscan - Etherscan (si apre in una nuova scheda) espone automaticamente l'ABI per il codice sorgente verificato
- Dallo sviluppatore - molti progetti pubblicano le loro ABI nella loro documentazione o nei pacchetti npm
- Generare dal sorgente - se hai il codice sorgente Solidity, puoi compilarlo per produrre l'ABI
Strumenti e librerie per interagire con i contratti
Gli sviluppatori in genere utilizzano una libreria JavaScript/TypeScript per interagire con i contratti da un'app web, un backend o uno script.
Librerie client (JavaScript/TypeScript)
- Viem (si apre in una nuova scheda) - Interfaccia TypeScript moderna e leggera per Ethereum con sicurezza dei tipi di prim'ordine
- Ethers.js (si apre in una nuova scheda) - Libreria collaudata sul campo per interagire con la blockchain di Ethereum
- Web3.js (si apre in una nuova scheda) - L'API JavaScript originale di Ethereum
Librerie backend
- Ethers.js (si apre in una nuova scheda) - Funziona anche in Node.js per script lato server e bot
- Web3.py (si apre in una nuova scheda) - Libreria Python per l'interazione con Ethereum
- go-ethereum (si apre in una nuova scheda) - Libreria Go ufficiale del team di Geth
Esempio: leggere il saldo di un token con Viem
import { createPublicClient, http, formatUnits } from 'viem'
import { mainnet } from 'viem/chains'
// Indirizzo del contratto USDC e ABI (parziale, per 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 ha 6 decimali
Esempio: inviare una transazione con 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 di trasferimento 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() // attendi che la transazione venga minata
console.log(`Transferred! TX: ${tx.hash}`)
Eventi e log
Gli smart contract possono emettere eventi per segnalare che è successo qualcosa. La tua applicazione può ascoltare questi eventi per reagire in tempo reale.
import { createPublicClient, http, parseAbiItem } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({ chain: mainnet, transport: http() })
// Monitora gli eventi di trasferimento USDC
const unwatch = client.watchEvent({
event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
onLogs: (logs) => console.log(logs),
})
Simulare le transazioni
Prima di inviare una transazione, puoi simularla per verificare se andrebbe a buon fine — e per vedere il suo valore di ritorno — senza spendere gas. Questo è utile per individuare tempestivamente gli errori e per visualizzare in anteprima i risultati.
La maggior parte delle librerie client supporta questa funzionalità tramite eth_call:
// Con Viem
const result = await client.simulateContract({
address: contractAddress,
abi,
functionName: 'swap',
args: [amountIn],
account: userAddress,
})
Portafogli e firma
In un'applicazione decentralizzata (dapp), il portafoglio dell'utente (come MetaMask, Rainbow o WalletConnect) gestisce la firma. Non gestisci direttamente le chiavi private.
Le librerie per portafogli e gli strumenti di connessione astraggono questo processo in modo che tu possa concentrarti sulla costruzione della logica della tua applicazione.
Tutorial correlati
- Chiamare uno smart contract da JavaScript
- Inviare transazioni usando Web3.js e Alchemy
- Come visualizzare il tuo NFT nel tuo portafoglio
Letture di approfondimento
- Documentazione di Viem: Leggere e scrivere sui contratti (si apre in una nuova scheda)
- Documentazione di Ethers.js: Contratti (si apre in una nuova scheda)
- Specifica dell'ABI di Solidity (si apre in una nuova scheda)
- Cos'è un'ABI? - Alchemy (si apre in una nuova scheda)