Quando si sviluppano smart contract sulla blockchain di Ethereum, uno degli aspetti più cruciali da considerare è il consumo di gas. Il gas è una misura del lavoro computazionale su Ethereum e costa denaro reale agli utenti. Pertanto, ottimizzare i vostri smart contract per utilizzare meno gas non è solo un miglioramento delle prestazioni, ma anche una strategia di risparmio dei costi.

Il costo totale del gas viene calcolato come: Costo Totale del Gas = Gas Utilizzato × Prezzo del Gas

Il prezzo del gas fluttua in base alla congestione della rete, mentre il gas utilizzato dipende dalle operazioni del vostro smart contract. Approfondiamo le varie tecniche per ottimizzare l'uso del gas in uno smart contract Solidity.

Lo scenario

Inizieremo con un semplice smart contract Solidity che calcola la somma dei numeri pari inferiori a 99 da un array di interi. Di seguito è riportato il codice iniziale:

Codice iniziale

Gas utilizzato prima di qualsiasi ottimizzazione: 297069 (quando si usa [1,2,3,4,5,6,7,8,9,10,53,44,76,32,100,400,500] come oggetto).

1. Usare calldata invece che memory

In Solidity, calldata è una posizione dei dati più economica rispetto a memory perché è di sola lettura ed esterna al contratto intelligente. Ciò la rende adatta per i parametri delle funzioni che non devono essere modificati all'interno della funzione stessa.

Codice ottimizzato

Gas utilizzato: 59585

2. Usare Local Variables invece che State Variables

Le state variebles sono archiviate sulla blockchain, rendendole più “costose” da utilizzare rispetto alle variabili locali. Utilizzando una variabile locale, è possibile ridurre il costo del gas.

Codice ottimizzato

Gas utilizzato: 58729

3. Short-Circuit Condition Checks

Si possono combinare più condizioni in un singolo if statement per evitare controlli non necessari.

Codice ottimizzato

Quando due condizioni sono combinate con un &&, la seconda condizione non verrà valutata se la prima è falsa, a causa del comportamento di short-circuiting. Questo comportamento di short-circuiting si applica anche alle istruzioni if nidificate: se la condizione if esterna è falsa, la condizione if interna non verrà valutata. Non c'è un significativo ottimizzazione del gas da ottenere dall'uso di istruzioni if nidificate rispetto a una condizione combinata if con un operatore &&. Entrambe avranno approssimativamente lo stesso costo in gas, poiché entrambe sfruttano il comportamento di short-circuiting.

Gas utilizzato: 57450

4. Usare ++i invece che i++

L'incremento prefisso (++i) è leggermente più efficiente del postfix (i++) perché non richiede una variabile temporanea.

Codice ottimizzato

Gas utilizzato: 56400

5. Cache Array Length

Memorizzare nella cache la lunghezza dell'array può risparmiare gas, poiché evita molteplici chiamate per recuperare la lunghezza dell'array.

Codice ottimizzato

Gas utilizzaato: 55200

6. Caricare elementi di Array sulla memoria

Caricare elementi di Array sulla memoria fa risparmiare Gas quando l’elemento è utilizzato più di una volta.

Codice ottimizzato

Gas utilizzato: 54300

Altri strumenti per l’ottimizzazione:

Incremento non verificato

Poiché siamo certi che il ciclo non eseguirà più di (2^{256} - 1) volte, possiamo utilizzare il blocco unchecked per saltare i controlli di overflow, risparmiando così del gas

Utilizzare Errori Personalizzati Invece di Revert

A partire da Solidity v0.8.4, è possibile definire errori personalizzati per fornire informazioni più dettagliate sulle situazioni di fallimento in modo efficiente dal punto di vista del gas.

Spostamento dei Bit Invece di Divisione/Moltiplicazione

Lo spostamento dei bit può essere più efficiente della divisione o della moltiplicazione quando si lavora con potenze di 2

Priorità delle Funzioni

L'ordine delle funzioni in un contratto può influire sul consumo di gas a causa del modo in cui la Ethereum Virtual Machine (EVM) gestisce gli ID dei metodi. Posizionare le funzioni più utilizzate all'inizio del contratto può permettere di risparmiare gas.

Ottimizzatore del compilatore Solidity

Puoi anche utilizzare l'ottimizzatore del compilatore Solidity aggiungendo il seguente snippet al tuo truffle-config.js se stai usando Truffle:

O se stai usando Hardhat, aggiungilo al tuo hardhat.config.js:

Queste impostazioni abilitano l'ottimizzatore e lo configurano per eseguire 200 iterazioni, un numero che mira a bilanciare il costo di distribuzione rispetto ai costi di esecuzione.

Conclusione

L'ottimizzazione del gas è cruciale per l'esecuzione efficiente e l'interazione dei contratti intelligenti sulla blockchain Ethereum. Applicando queste tecniche, è possibile ridurre significativamente il costo del gas, rendendo i vostri contratti intelligenti più efficienti e user-friendly. Ricordate sempre di testare accuratamente per garantire che le ottimizzazioni non introducano bug o vulnerabilità.