Hai scritto uno smart contract in Solidity che sembra perfetto. Lo compili, lo deployi su Goerli... e la transazione fallisce con "out of gas". Oppure il gas stimato è il doppio di quello che pensavi. Succede anche a chi ha esperienza: il problema non è il codice, è la mancata comprensione di come funziona l'EVM e del gas come risorsa.
Noi, di Meteora Web, lavoriamo con la blockchain da anni. Non solo teoria: abbiamo deployato contratti in produzione, ottimizzato operazioni per ridurre i costi e visto fallire progetti perché il team non capiva la meccanica del gas. Questa guida ti porta dentro la macchina virtuale di Ethereum, ti spiega come si calcola il costo di ogni operazione e come deployare contratti efficienti. Zero lezioni accademiche: tutto quello che devi sapere per non bruciare ether inutilmente.
Come funziona l'EVM e perché il gas è il suo carburante
L'Ethereum Virtual Machine (EVM) è un computer distribuito che esegue bytecode. Ogni istruzione elementare ha un costo in gas: un'unità che misura lo sforzo computazionale. Il gas non è il prezzo in ether: è la quantità di lavoro. Il prezzo lo decidi tu (gas price) e moltiplicando ottieni il costo totale in ETH.
La struttura del bytecode e l'opcode
Il tuo contratto Solidity viene compilato in una sequenza di opcode. Ogni opcode ha un costo base definito dall'Ethereum Yellow Paper. Per esempio:
ADD(somma) costa 3 gasSLOAD(carica da storage) costa 200 gasSSTORE(scrive in storage) costa 20.000 gas se da zero a non-zero, 2.900 se aggiorna
La differenza è enorme. Scrivere in storage è l'operazione più costosa perché modifica lo stato globale della blockchain. Leggere da storage è costoso ma meno. Le operazioni aritmetiche sono economiche. Capire questo ti permette di progettare contratti che costano poco.
Il gas limit e il gas used
Quando invii una transazione, imposti un gas limit massimo che sei disposto a consumare. Se il contratto ne consuma di più, la transazione fallisce (revert) e il gas viene comunque consumato fino al punto del fallimento. Se consuma meno, paghi solo quello usato. Mai impostare un gas limit esatto: lascia un margine (es. +20%) per evitare fallimenti imprevisti.
Noi, di Meteora Web, abbiamo visto un cliente perdere 0.5 ETH in fallimenti perché usava gas limit calcolato dalla wallet senza margine. Imparare a stimare correttamente è gratis.
Gas: costi delle operazioni e come calcolarli
Ogni operazione ha un costo fisso più eventuali costi dinamici. Lo storage è il peggiore. Esempio pratico in Solidity:
// Costoso: scrive in storage a ogni chiamata
uint256 public counter;
function increment() public {
counter += 1; // SSTORE: ~20.000 gas
}Questa funzione costa circa 20.000 gas per via dello storage. Se la chiami 100 volte, sono 2 milioni di gas. Ora confronta con una variabile in memoria:
// Economico: solo operazioni in memoria
function addInMemory(uint256 a, uint256 b) public pure returns (uint256) {
return a + b; // ADD: 3 gas
}La differenza è abissale. Regola pratica: se non hai bisogno di persistenza, usa memory o calldata. Evita storage a meno che sia strettamente necessario.
Calcolare il gas con Hardhat
Usa Hardhat per stimare il gas durante lo sviluppo. Esempio:
const { ethers } = require("hardhat");
async function estimate() {
const Contract = await ethers.getContractFactory("MyContract");
const contract = await Contract.deploy();
const tx = await contract.increment();
const receipt = await tx.wait();
console.log("Gas usato:", receipt.gasUsed.toString());
}Confronta le stime prima e dopo le ottimizzazioni. Noi usiamo sempre gasUsed nei test per non avere sorprese in produzione.
Ottimizzare uno smart contract per ridurre il gas
L'ottimizzazione del gas è un'arte. Ecco le tecniche che applichiamo noi di Meteora Web nei progetti reali.
Usare uint256 invece di uint più piccoli
L'EVM lavora a 256 bit. Usare uint8 non risparmia gas: anzi, costa di più perché l'EVM deve fare conversioni. Usa sempre uint256 a meno che non hai vincoli di storage (es. array di struct).
Packing nello storage
Se hai più variabili piccole, dichiarale vicine per farle impacchettare in uno slot. Esempio:
// Male: occupa 3 slot
uint128 a;
uint128 b;
uint256 c;
// Bene: a e b condividono lo slot
uint128 a;
uint128 b;
uint256 c;Il packing automatico di Solidity funziona se le variabili sono dichiarate consecutivamente e occupano al massimo 256 bit totali. Questo riduce le operazioni di storage.
Usare mapping invece di array per lookup frequenti
Leggere un elemento da un array in storage costa SLOAD (200 gas). Un mapping ha lo stesso costo, ma l'array in più deve gestire la lunghezza. Per lookup, mapping è più efficiente.
Evitare loop lunghi non limitati
Un loop che dipende dall'input utente può far esplodere il gas. Se devi iterare, imposta un limite massimo e documentalo. Meglio ancora: sposta la logica off-chain e usa prove crittografiche (come in Uniswap o ENS).
Deploy su Ethereum: strumenti e strategie
Deployare un contratto costa gas anch'esso. Il costo di deploy è proporzionale alla dimensione del bytecode (200 gas per byte) più il costo di creazione (32.000 gas). Un contratto piccolo costa meno.
Hardhat e script di deploy
Usiamo Hardhat per deploy su testnet e mainnet. Script minimo:
async function main() {
const MyContract = await ethers.getContractFactory("MyContract");
const contract = await MyContract.deploy();
await contract.deployed();
console.log("Deployed at:", contract.address);
}Prima di deployare su mainnet, simula il costo su Hardhat local o testnet. Usa ethers.provider.getFeeData() per ottenere il gas price corrente.
Stimare il gas di deploy
Hardhat stima automaticamente, ma puoi forzare un limite. Noi consigliamo di usare il 20% in più della stima per sicurezza. Se il mercato è congestionato, considera di aspettare o usare un gas price più alto.
Verifica del contratto su Etherscan
Dopo il deploy, verifica il codice sorgente. Usa il plugin hardhat-etherscan:
npx hardhat verify --network mainnet DEPLOYED_ADDRESSLa verifica aumenta la fiducia degli utenti e permette di interagire direttamente da Etherscan. Noi lo facciamo sempre.
Errori comuni e debugging
Abbiamo visto tanti errori: ecco i più frequenti e come evitarli.
Out of gas durante il deploy
Succede se il bytecode è enorme (es. contratti con molte librerie). Soluzione: rimuovere librerie non necessarie, usare pragma experimental ABIEncoderV2 solo se serve, e compilare con ottimizzazioni attive (optimizer in Hardhat).
Revert senza messaggio
Usa require con messaggio per capire dove fallisce. Oppure usa console.log di Hardhat nei test. Non lasciare contratti muti.
Gas price troppo basso
In periodi di congestione, una transazione con gas price basso può rimanere in pending per ore. Usa ethers.provider.getFeeData() dinamicamente.
In sintesi — cosa fare adesso
- Studia l'EVM ogni volta che scrivi uno smart contract. Non dare per scontato il costo delle operazioni. Tieni aperto il documento ufficiale EVM.
- Misura sempre il gas nei tuoi test con Hardhat. Confronta versioni ottimizzate e non.
- Applica le ottimizzazioni: packing, uint256, mapping invece di array, loop limitati.
- Deploya con margine: gas limit +20% e gas price dinamico.
- Verifica il contratto su Etherscan per trasparenza e interoperabilità.
La differenza tra un buon contratto e uno eccezionale sta nei dettagli del gas. Noi di Meteora Web costruiamo contratti che non fanno piangere il portafoglio. Se vuoi approfondire, dai un'occhiata alla nostra guida alle licenze open source — anche per contratti serve saper scegliere la licenza giusta.
Sponsored Protocol