Vai al contenuto

Smart contract aggiornabile

Uno smart contract aggiornabile conserva indirizzo e stato di un proxy mentre soggetti autorizzati ne sostituiscono o reindirizzano l'implementazione. Questa flessibilità introduce rischi di storage, inizializzazione, governance e monitoraggio.

Aggiornato

Solo a scopo educativo; non costituisce consulenza finanziaria o di sicurezza. L’aggiornabilità può consentire a soggetti privilegiati di modificare il comportamento del contratto e può causare perdite.

Risposta diretta

Uno smart contract aggiornabile è un sistema distribuito la cui logica effettiva può cambiare senza spostare gli utenti a un nuovo indirizzo principale né perdere lo stato conservato. Sulle reti compatibili con Ethereum, un proxy mantiene lo stato e inoltra le chiamate tramite delegatecall a un contratto di implementazione. Un aggiornamento autorizzato cambia l’implementazione, mentre indirizzo, storage e saldo del proxy restano invariati.

Non viene riscritto bytecode immutabile: si inserisce un livello di indirezione. Può correggere difetti e aggiungere funzioni, ma crea anche un percorso privilegiato capace di cambiare prelievi, commissioni, permessi o contabilità. Vanno quindi valutati sia il codice attuale sia le regole per quello futuro.

Non ogni proxy è aggiornabile e non ogni sistema modificabile usa un proxy. Alcuni progetti distribuiscono nuovi contratti e migrano lo stato; altri disabilitano definitivamente gli aggiornamenti. Contano l’architettura e l’autorità effettive on-chain.

Come funziona

Il chiamante invia la transazione al proxy, che legge un indirizzo di implementazione ed esegue quel codice nel proprio contesto di storage tramite delegatecall. Il codice proviene dall’implementazione, ma letture e scritture agiscono sul proxy; mittente e valore originali restano. ERC-1967 standardizza gli slot di implementazione, beacon e amministratore.

I proxy transparent gestiscono l’aggiornamento nel proxy e separano chiamate amministrative e utente. Gli UUPS pongono la logica nell’implementazione e usano la compatibilità ERC-1822, rendendo critica l’autorizzazione. I proxy beacon ricavano l’implementazione da un beacon, il cui aggiornamento può cambiare molti proxy.

La compatibilità dello stato è il vincolo centrale. Riordinare, rimuovere o cambiare tipo alle variabili, oppure modificare l’ereditarietà, può corrompere i dati. Layout solo incrementali, spazi riservati o storage con namespace ERC-7201 aiutano, ma richiedono comunque verifica fra versioni.

I costruttori inizializzano l’implementazione, non lo storage del proxy. Il deployment chiama quindi una volta un inizializzatore come initialize. L’implementazione va bloccata contro l’inizializzazione diretta e le migrazioni successive devono usare reinizializzatori limitati. Un inizializzatore pubblico o ripetibile può trasferire il controllo.

Un processo difendibile prevede:

  1. Fissare sorgenti, compilatore, dipendenze, layout, indirizzi e bytecode atteso delle due implementazioni.
  2. Esaminare differenze, compatibilità, inizializzazione o migrazione, autorizzazione, dipendenze e rollback; provare l’intera transazione su un fork.
  3. Pubblicare proposta e indirizzo, applicando multisig, governance e timelock dichiarati senza bypass nascosti.
  4. Eseguire e verificare slot di implementazione o beacon, eventi, bytecode, stato inizializzato, ruoli e invarianti a un blocco registrato.
  5. Monitorare slot, ruoli e parametri e preparare gli incidenti senza presumere che il rollback sia sempre sicuro.

Esempio

Un protocollo di prestito necessita una nuova funzione di rimborso. Il proxy delega all’implementazione A. Il team distribuisce B, verifica che aggiunga soltanto storage e prepara la migrazione. La governance pubblica il bytecode e mette l’aggiornamento dietro un timelock di 48 ore. Poi lo stesso indirizzo delega a B e i saldi restano nel proxy.

Gli utenti devono verificare che lo slot sia passato da A a B, che la migrazione sia avvenuta una volta e che ruoli e saldi coincidano. Se un guardiano può eludere il timelock o un firmatario sostituire B con codice arbitrario, tale potere fa parte del modello di fiducia.

Rischi

  • Sostituzione privilegiata: amministratore, multisig, governatore o chiave compromessa possono installare logica dannosa o difettosa.
  • Corruzione dello storage: un layout incompatibile può reinterpretare saldi, proprietari, mapping o contabilità.
  • Errore di inizializzazione: un inizializzatore omesso, ripetuto o esposto può bloccare il sistema o trasferire il controllo.
  • Errore specifico del pattern: transparent, UUPS, beacon e proxy personalizzati falliscono diversamente; il nome non prova correttezza.
  • Governance di facciata: timelock o voto possono avere bypass d’emergenza, ritardo breve, potere concentrato o firmatari deboli.
  • Migrazione o rollback insicuri: lo stato può cambiare irreversibilmente; il vecchio codice può non ripristinarne il significato.
  • Divario di verifica: sorgente verificato non prova che il proxy lo usi né che amministratore e stato siano quelli attesi.
  • Rischio di monitoraggio e integrazione: explorer, interfacce, auditor e integrazioni possono seguire una versione obsoleta o perdere un cambio del beacon.

Idee sbagliate comuni

  • «Il contratto a questo indirizzo è immutabile». Il bytecode del proxy può esserlo mentre lo slot di implementazione o beacon cambia il comportamento.
  • «Un multisig decentralizza gli aggiornamenti». Riduce la dipendenza da una chiave solo con firmatari indipendenti, soglia, operazioni e sostituzioni solide.
  • «Un timelock impedisce aggiornamenti dannosi». Offre tempo per osservare e uscire, ma non rende sicuro il codice.
  • «Superare il controllo dello storage prova la sicurezza». Copre il layout, non logica, autorizzazione, oracoli, migrazione o economia.
  • «Rinunciare agli aggiornamenti elimina sempre il controllo». Amministratore, beacon, governatore, autorizzazione UUPS e percorsi alternativi vanno verificati on-chain.

Argomenti correlati

Fonti

Navigazione

Cerca nella wiki...