Vai al contenuto

Come leggere un audit di smart contract

Un audit di smart contract è una revisione delimitata di codice, build, deployment, ipotesi e proprietà specifici; risultati e correzioni vanno riconciliati con il sistema live.

Aggiornato

Solo a scopo educativo; non costituisce consulenza né raccomandazione d’investimento. Gli investimenti possono comportare perdite.

Risposta diretta

Un audit esamina in un periodo dichiarato requisiti, codice sorgente, input di build, logica di deployment e ipotesi di sicurezza specifici. Metodi complementari identificano difetti, dimostrano percorsi di exploit, valutano l’impatto e verificano le correzioni. La conclusione vale solo per lo snapshot e le prove descritti.

Lo snapshot fissa repository, commit o tree hash, submodule, dipendenze, compilatore, impostazioni, codice generato, script, chain, indirizzi, proxy, implementazione o beacon, dati di constructor o initializer, librerie, amministratori, timelock e blocco o ora. Le esclusioni contano: frontend, keeper, oracle, bridge, governance o firmatario off-chain possono dominare il rischio restando fuori audit.

Servono threat model e specifica: asset, attori, ruoli privilegiati, confini di fiducia, capacità, ordinamento e reorg, dipendenze, transizioni e proprietà precise di safety e liveness. Un invariante senza unità, precondizioni, quantificatori ed eccezioni può verificare perfettamente il comportamento sbagliato.

Usare quattro registri: identità di ambito, build e deployment; requisiti, minacce e invarianti; risultati, prove e retest; rischio residuo, accettazione e disclosure. Nessun critical non certifica la sicurezza, resolved non significa distribuito e una prova copre solo proprietà, modello e ipotesi codificati.

Come funziona

La revisione manuale segue architettura, fondi, stato tra funzioni e intento economico. L’analisi statica trova pattern ma produce falsi positivi e negativi. Test unitari, di integrazione, fork e differenziali confrontano casi concreti. Fuzzing stateful e test d’invariante dipendono da handler, selettori, seed, corpus, run, profondità e ambiente modellato.

Esecuzione simbolica e verifica formale dimostrano asserzioni selezionate sotto semantiche e ipotesi supportate. unknown, timeout o comportamento non supportato non sono prove. Anche una proprietà dimostrata può omettere economia dell’oracle, governance, configurazione o requisito voluto. La revisione umana governa specifica e interpretazione; un’osservazione IA non è un metodo autonomo.

Ogni risultato indica artefatto e deployment, prerequisito, prova minima, percorso, raggiungibilità, privilegi, capitale, ripetibilità, impatto, metodo di gravità e raccomandazione. Sfruttabilità o probabilità e impatto sono distinti. Massimo teorico, nome o etichetta di tool non stabiliscono una perdita eseguibile.

open, acknowledged, risk accepted, partially fixed, resolved e retested non sono standard universali. Una chiusura difendibile collega il problema al commit esatto e documenta percorsi adiacenti, chi ha ritestato cosa e quando. Il rischio accettato resta rischio; un retest limitato non amplia l’ambito.

I deployment aggiornabili richiedono riconciliazione di slot proxy, implementazione o beacon e admin; initializer/reinitializer, blocco dell’implementazione, compatibilità storage, autorizzazione, timelock o bypass, migrazione e rollback. Si riproducono bytecode creation e runtime e si confrontano librerie, parametri, ruoli e stato su ogni chain.

Il rapporto finale indica revisione, auditor, date, ambito, metodi, configurazioni, limiti, risultati, prove, stato, rischi e disclosure. Poi si monitorano hash, ruoli, parametri, dipendenze e incidenti. Ogni modifica materiale crea un nuovo delta; un badge vecchio non segue il codice futuro.

Procedura:

  1. Congelare manifesto con repository, commit, dipendenze, compilatore, impostazioni, codice generato e di deployment, chain, indirizzi, stack proxy, parametri, blocco, revisione, inclusioni ed esclusioni.
  2. Definire asset, attori, ruoli, confini, capacità, ciclo di vita, ordinamento, liveness, dipendenze e invarianti misurabili.
  3. Riprodurre la build; mappare architettura, storage, dati, fondi e controllo; riconciliare sorgente, artefatti, librerie, bytecode, initializer, ruoli e deployment.
  4. Eseguire metodi manuali, statici, unitari, integrazione, fork, differenziali, fuzz, invarianti, simbolici o formali registrando versioni, configurazioni, seed, corpus, coverage, timeout e incognite.
  5. Registrare artefatto, prerequisito, prova, sfruttabilità, impatto, gravità, esposizione, raccomandazione ed evidenza riservata senza scambiare l’etichetta per giudizio.
  6. Congelare il fix e ritestare problema, percorsi e invarianti; validare storage, inizializzazione, migrazione, rollback, build e ricevute prima dello status.
  7. Pubblicare ambito, metodi, limiti e rischi; riconciliare artefatti con ogni chain e mantenere aggiornati monitoraggio, disclosure, risposta e bug bounty.

Esempi

  • L’inflazione di un vault richiede un registro completo. L’attaccante deposita 1 asset, riceve 1 share, dona 1,000,000 assets; restano 1,000,001 assets e 1 share. La vittima deposita 500,000 assets; l’arrotondamento dà floor(500,000 * 1 / 1,000,001) = 0 shares. Se accettato, il vault ha 1,500,001 assets; l’attaccante recupera 500,000 assets oltre il proprio contributo di 1,000,001-asset. Un revert su zero shares blocca questo percorso.
  • Copertura dei file non è copertura del deployment. Manifesto: 24 source units, 4 deployment scripts, 3 keeper services, cioè 31 items. Inclusi 20 source units e 2 scripts: 22 / 31 = 70.96774194%; esclusi 9 items. Se il proxy usa un’unità esclusa, copertura live 0% nonostante 70.96774194%.
  • Il fuzzing non prova assenza. Run: 2,000 sequences * 64 calls = 128,000 calls; falliscono 3 sequences, cioè 3 / 2,000 = 0.15%. Dopo il fix: 10,000 sequences * 64 calls = 640,000 calls, zero fallimenti. Con ipotesi didattiche, limite superiore approssimativo 95%: 3 / 10,000 = 0.03% per sequenza, non una prova.
  • Chiusura e identità sono indipendenti. 12 findings: 2 critical, 3 high, 4 medium, 3 low. Chiusi 2 + 2 + 3 + 2 = 9: 9 / 12 = 75%; restano high, medium e low. Audit H1, live H2: verifica fallita. Esatto H1 più slot, initializer e ruoli prova identità solo al blocco.

Rischi

  • Repository, commit, submodule o sorgente generato sono ambigui.
  • Compilatore, optimizer, librerie o dipendenze non sono fissati.
  • Script, constructor, initializer o salt CREATE2 sono esclusi.
  • Si ispeziona chain, indirizzo, proxy, beacon o implementazione errati.
  • Sorgente, artefatto e bytecode non coincidono.
  • Il threat model omette attore, privilegio, asset o confine.
  • Specifica o invariante ha unità, precondizioni o eccezioni errate.
  • Percorsi admin, guardian, timelock, pausa, upgrade o migrazione sono omessi.
  • Falliscono ipotesi su oracle, token, bridge, keeper, governance o chain.
  • L’analisi statica produce falso positivo non valutato.
  • Revisione, test o fuzzing omettono un percorso.
  • Harness, selettore, seed, corpus, profondità o modello sono distorti.
  • Timeout, semantica non supportata o unknown sono scambiati per prova.
  • Prova corretta formalizza requisito o sistema incompleto.
  • La gravità segue il nome anziché sfruttabilità e impatto.
  • Valore teorico è confuso con perdita raggiungibile o profitto.
  • Il fix introduce regressione o rompe un invariante economico.
  • Storage, initializer, upgrade o migrazione corrompono lo stato.
  • Problema accettato, aperto o parziale è nascosto dal badge.
  • Rapporto è trattato come assicurazione, certificazione o copertura permanente.

Errori comuni

  • «Senza critical il contratto è sicuro». Descrive solo risultati entro ambito, tempo e metodi.
  • «Coverage alta o zero errori fuzz provano assenza». Misurano codice e percorsi selezionati.
  • «La verifica formale prova tutto il protocollo». Prova proprietà del modello sotto ipotesi.
  • «Resolved significa tutti i deployment corretti». Servono retest e riconciliazione di build, bytecode, proxy, parametri e ruoli.
  • «Un auditor noto garantisce risarcimento o upgrade». La responsabilità dipende dal contratto; modifiche future restano fuori.

Argomenti correlati

Fonti

Navigazione

Cerca nella wiki...