Solo a scopo educativo; non costituisce consulenza finanziaria. Gli investimenti possono comportare perdite.
Risposta diretta
Un contratto proxy è un contratto intermediario che inoltra le chiamate a un altro contratto, solitamente chiamato contratto di implementazione o logico. In una comune architettura EVM, il proxy usa delegatecall, quindi il codice dell’implementazione viene eseguito nel contesto del proxy mentre stato e saldi restano all’indirizzo del proxy.
Questo livello indiretto consente a un sistema di conservare un indirizzo stabile per gli utenti cambiando al contempo l’implementazione. Può anche ridurre il costo di distribuzione quando molti proxy condividono il codice. Un proxy non è automaticamente aggiornabile: alcuni proxy minimi puntano in modo permanente a una sola implementazione, mentre quelli aggiornabili aggiungono un modo controllato per cambiare implementazione o beacon.
Gli utenti devono quindi valutare sia l’implementazione attiva sia l’autorità in grado di cambiarla. Il solo bytecode verificato del proxy non stabilisce quale codice verrà eseguito domani.
Come funziona
Quando una chiamata raggiunge il proxy, il percorso di fallback copia o inoltra i dati della chiamata a un’implementazione. Con delegatecall, address(this) è il proxy, le letture e scritture di memoria interessano il proxy e i valori originali di msg.sender e msg.value vengono conservati. Il proxy restituisce quindi i dati dell’implementazione oppure annulla l’operazione insieme a essa.
Poiché i metadati del proxy condividono lo spazio di memoria del proxy con lo stato dell’applicazione, gli slot standardizzati aiutano a evitare collisioni accidentali. ERC-1967 definisce slot per l’indirizzo dell’implementazione, l’indirizzo di un beacon e un amministratore facoltativo, e raccomanda eventi quando tali valori cambiano. Lo standard facilita l’ispezione dei proxy, ma da solo non rende sicuro un aggiornamento.
Le architetture comuni collocano l’autorità di aggiornamento in punti diversi:
- Proxy trasparente: il proxy distingue le chiamate amministrative da quelle ordinarie degli utenti, di solito tramite un contratto amministratore separato.
- Proxy UUPS: la logica di aggiornamento risiede nell’implementazione, che deve autorizzare le modifiche e restare compatibile con l’interfaccia di aggiornamento prevista.
- Proxy beacon: il proxy chiede al beacon quale implementazione usare; cambiare un beacon può influire su tutti i proxy che lo seguono.
- Clone minimo: molti piccoli proxy delegano a codice condiviso, spesso senza alcun percorso di aggiornamento.
Esempio
Supponiamo che un proxy di un vault conservi i saldi degli utenti e deleghi all’implementazione A. Gli utenti depositano tramite l’indirizzo del proxy e il codice di A aggiorna i saldi nella memoria del proxy.
In seguito, la governance cambia lo slot di implementazione ERC-1967 impostandolo sull’implementazione B. L’indirizzo del proxy e i saldi registrati non si spostano, ma le chiamate future eseguono il codice di B. Se B conserva la disposizione della memoria e applica le regole previste, gli utenti vedono un nuovo comportamento allo stesso indirizzo.
Se B riordina le variabili in memoria, omette un controllo delle autorizzazioni o aggiunge un percorso di prelievo controllato da chi effettua l’aggiornamento, lo stesso aggiornamento può corrompere la contabilità o esporre gli asset. La domanda operativa non è quindi soltanto se un contratto sia un proxy, ma chi possa cambiarne il percorso di esecuzione, con quale ritardo e con quale verifica.
Rischi
- Compromissione della chiave di aggiornamento: un amministratore, un multisig o un processo di governance può installare codice dannoso o difettoso.
- Incompatibilità della disposizione della memoria: modificare ordine, tipi o ereditarietà delle variabili può indurre il nuovo codice a leggere male o sovrascrivere lo stato esistente.
- Errore di inizializzazione: i costruttori non inizializzano la memoria del proxy; protezioni assenti o riutilizzabili possono consentire a un altro account di assumere ruoli privilegiati.
- Instradamento inatteso delle chiamate: collisioni tra selettori, percorsi riservati all’amministratore o un beacon inatteso possono rendere l’esecuzione diversa dall’interfaccia visibile.
- Ampio impatto degli aggiornamenti condivisi: una decisione su un beacon o un’implementazione può cambiare contemporaneamente molte istanze di contratto.
Prima di depositare asset o concedere approvazioni, occorre individuare on-chain l’implementazione o il beacon attuale, identificare l’autorità di aggiornamento e qualsiasi timelock, esaminare il codice sorgente verificato e la compatibilità della memoria e, se applicabile, controllare gli eventi recenti Upgraded, BeaconUpgraded e AdminChanged. Il monitoraggio resta necessario dopo la prima verifica perché il percorso di esecuzione può cambiare.
Idee sbagliate comuni
- «Il proxy non conserva uno stato significativo». Con
delegatecall, lo stato dell’applicazione e spesso gli asset appartengono al proxy, anche se la logica proviene da un altro indirizzo. - «Un’implementazione verificata rende il sistema privo di fiducia». Chiavi di aggiornamento, governance, beacon, inizializzazione e implementazioni future restano parte del modello di fiducia.
- «Ogni proxy può essere aggiornato». I cloni e altri proxy fissi possono delegare in modo permanente; l’aggiornabilità dipende dall’architettura specifica e dal codice di autorizzazione.
Argomenti correlati
- Rischio di memoria con Delegatecall
- Collisione della memoria del proxy
- Monitoraggio degli aggiornamenti del proxy
- Smart contract
- Contratto aggiornabile
Fonti
- Introduzione agli smart contract - Solidity Documentation (consultato: 2026-08-21)
- ERC-1967: slot di memoria dei proxy - Ethereum Improvement Proposals (consultato: 2026-08-21)
- ERC-1822: standard universale per proxy aggiornabili (UUPS) - Ethereum Improvement Proposals (consultato: 2026-08-21)
- Proxy - OpenZeppelin Documentation (consultato: 2026-08-21)