Architettura
Il protocollo vive su due chain. Ethereum ospita il launchpad, i pool e i vault; Robinhood Chain ospita le azioni tokenizzate.
I contratti
Questa tabella descrive il protocollo come è stato deciso. La parte del lancio è nel codice
dal 2026-09-28, e la distribuzione dell'airdrop dal 2026-10-04, non deployata; gli adapter
LayerZero delle azioni non sono nel repository. Router e adapter diversi dallo swap router
ufficiale non vi figurano: UniswapV4StockRouter su Ethereum, RobinhoodStockRouter su
Robinhood Chain e l'UsdgOftAdapter. Vedi Stato di avanzamento. Dal
2026-10-02 ogni contratto della tabella è upgradabile, tranne i token, il lock della
liquidità e i deployer: vedi sotto. Le percentuali del diagramma sono le impostazioni di
default della tassa.
| Contratto | Ruolo | Cardinalità |
|---|---|---|
StockFunFactory |
Crea i mercati, preleva la commissione di creazione, tiene il registro e le impostazioni dell'owner per i nuovi mercati e per i vault; l'autorità di upgrade di ogni modulo Ethereum | Uno |
MarketDeployer · VaultDeployer |
Aggirano EIP-170 trasportando il creation code del token e quello del proxy del vault; non detengono alcuno stato, vengono sostituiti tramite la factory anziché ricevere un upgrade | Uno ciascuno |
StockFunToken |
ERC-20 semplice, non upgradabile, senza mint e senza burn; nessuna logica propria oltre a un solo setter, setRecorder, e ai suoi rescue, per l'owner del protocollo; notifica ogni variazione di saldo al registratore della detenzione |
Uno per mercato |
HoldingRecorder |
Registra nel tempo, per ogni token, la detenzione di ogni indirizzo e la supply al di fuori del PoolManager di Uniswap; un trasferimento fallisce se la sua registrazione fallisce, l'unica eccezione voluta alla regola di isolamento descritta più avanti |
Uno |
TreasuryVault |
Detiene ETH, USDC e poi azioni; conversione, ogni tratta d'acquisto a sé, consegna delle sue azioni all'airdrop sul rail locale (sendToAirdrop), ogni azione a sé, e recupero di emergenza immediato |
Un proxy per mercato |
LiquidityLock |
Crea il pool e deposita entrambe le posizioni, bloccate, e conserva la commissione LP e il tick spacing di ogni pool; conserva per il suo destinatario la quota rifiutata di un incasso di commissioni; non upgradabile; la sua unica uscita è la modalità di chiusura, 30 giorni dopo il suo annuncio | Uno |
StockFunHook |
Preleva la commissione su ogni swap, applica l'anti-snipe, tiene le impostazioni della tassa e la whitelist di ogni pool, rifiuta la liquidità di chiunque non sia il lock, detiene i saldi dei creatori, del team e del buyback finché non vengono riscossi, e ciò che è dovuto a un vault che ha rifiutato la sua quota | Uno |
StockFunSwapRouter |
Il router ufficiale per i trade, l'unico attraverso cui un indirizzo in whitelist è esente dall'anti-snipe | Uno, sostituibile dall'owner |
StockFunLens |
Sola lettura; aggrega lo stato di un mercato per la dapp, leggendo ogni vault a sé; dal 2026-10-06 la sua pagina riporta anche il rail del vault, il suo stato di pausa e l'USDC che ha inviato attraverso il bridge, lo stato di blocco del pool, il registratore della detenzione del token, e ciò che l'hook e il lock devono al vault | Uno |
TreasuryOracle |
Feed Chainlink, scritti una sola volta; i loro heartbeat sono impostazioni e, dal 2026-10-06, le sue due protezioni su Robinhood Chain: il controllo del sequencer, disattivato finché Chainlink non pubblica un feed di uptime per quella chain, e la pausa dell'oracolo di ogni azione, che trattiene il prezzo di quell'azione durante un'operazione societaria | Uno per chain |
BuybackBurner |
Compra $STOCKFUN e lo invia al burn. Finché il pool di $STOCKFUN è bloccato, non esiste nessun altro percorso |
Uno |
BridgeHub · RemoteHub · RemoteTreasuryVault |
Il rail cross-chain; l'hub remoto è l'autorità di upgrade su Robinhood Chain e indica la rotta dell'airdrop e l'adapter di ogni azione; il vault speculare invia le sue azioni all'airdrop (sendToAirdrop) |
Uno, uno, un proxy per mercato |
StockFunProtocolToken |
$STOCKFUN, non upgradabile come un token di mercato; la sua intera supply va nella sua posizione bloccata |
Uno |
AirdropDistributor |
Distribuisce, su Ethereum, le azioni comprate da ogni tesoreria agli holder del suo token, per ciclo giornaliero; accredita solo i vault del mercato stesso; ogni holder riscuote, e una riscossione paga ogni azione che può; legato alla factory, che lo indica | Uno |
Proxy e upgrade
Dal 2026-10-02 ogni modulo è un proxy ERC-1967 davanti a un'implementazione, con upgrade tramite UUPS. Il proxy detiene l'indirizzo e lo stato; l'implementazione detiene il codice, e un upgrade la sostituisce. Un'implementazione non può mai essere inizializzata: ogni proxy viene inizializzato all'interno del proprio costruttore.
Ogni modulo chiede a un unico contratto chi può farne l'upgrade, la sua autorità di
upgrade, fissata nella sua implementazione: la factory su Ethereum, che risponde con il
proprio owner, e l'hub remoto su Robinhood Chain, che risponde con il proprio admin di
emergenza, l'owner di Ethereum così come l'ha trasportato l'ultimo batch del bridge. Un
trasferimento della proprietà della factory sposta quindi in un colpo solo il potere di
upgrade di ogni modulo Ethereum, e quello dei moduli di Robinhood Chain con il batch
successivo. Un upgrade viene rifiutato se la nuova implementazione indica un'altra
autorità; quelle dell'hook e del registratore della detenzione devono inoltre mantenere lo
stesso PoolManager.
Non upgradabili: i token, il lock della liquidità e, su Robinhood Chain, il deployer dei
vault speculari, dal cui indirizzo deriva l'indirizzo di ogni vault speculare.
MarketDeployer e VaultDeployer non detengono alcuno stato: la factory li sostituisce
(setDeployers) anziché farne l'upgrade.
Lo storage viene solo esteso in coda, mai riordinato: il layout di ogni modulo è registrato
in contracts/storage-layouts/, e contracts/script/check-storage-layouts.sh lo confronta
prima di ogni upgrade. Dal 2026-10-05 confronta ogni livello di ogni struct, dimensioni
comprese, e rifiuta qualsiasi modifica a una struct che sia l'elemento di un array dello
storage: solo una struct che sia il valore di un mapping, o l'ultima variabile di stato,
può crescere, in coda.
Un contratto di implementazione non viene mai usato direttamente, ma anche ciò che viene inviato per errore al suo stesso indirizzo ha una leva. La maggior parte delle implementazioni legge la propria autorità da un immutable, quindi l'owner del protocollo lo porta fuori; quelle della factory e dell'hub remoto tengono il loro admin nello storage del proxy, per cui sulle loro implementazioni la leva è l'indirizzo che ne ha fatto il deploy.
Chi può fare l'upgrade, e con quale rapidità: vedi Modello di fiducia.
Il contratto dell'airdrop
Dal 2026-10-04, AirdropDistributor distribuisce su Ethereum le azioni di ogni tesoreria.
È un modulo upgradabile come gli altri, un proxy la cui autorità di upgrade è la factory.
La factory lo indica (setAirdropDistributor) e i vault lo leggono in tempo reale; un
distributore sostituito mantiene ogni ciclo riscuotibile dove si trova. Legge la detenzione
dal registratore della detenzione, e le sue regole sono in L'airdrop.
Due percorsi lo raggiungono, e nient'altro accredita un ciclo:
- Il rail del bridge.
sendToAirdropdel vault speculare invia ogni azione in lista attraverso l'adapter LayerZero di quell'azione, indicato dall'hub remoto (setStockAdapter), verso il distributore indicato dall'hub remoto (setAirdrop), con l'id del mercato come payload. Su Ethereum l'OFT dell'azione conia l'azione wrapped a favore del distributore, e l'endpoint di LayerZero lo chiama. Il distributore accredita la consegna solo da un OFT di azione registrato dall'owner, da Robinhood Chain, inviata dal vault speculare che il bridge hub deriva per quel mercato. - Il rail locale.
sendToAirdropdel vault Ethereum approva gli importi esatti, il distributore li preleva, solo dal vault del mercato stesso, e accredita ciò che ha ricevuto; le approvazioni vengono poi chiuse. Un vault collegato al bridge hub rifiuta questa chiamata.
Il keeper attiva entrambi, e decide solo quando; sul rail del bridge, dal 2026-10-06, anche il gas che ogni consegna riceve su Ethereum, che l'hub remoto mantiene entro i limiti che l'owner di StockFun vi fissa.
Proprietà strutturali
L'hook è un singleton. Un solo contratto serve tutti i pool, il che evita di minare un indirizzo per mercato — l'indirizzo di un hook v4 codifica i suoi permessi nei bit meno significativi, e trovarne uno costa potenza di calcolo. Dal 2026-10-02 è un proxy il cui indirizzo porta tutti i 14 permessi v4: un upgrade mantiene quell'indirizzo, e un'implementazione successiva può usare qualsiasi callback.
La liquidità non è un NFT. È detenuta direttamente nel PoolManager, indicizzata
dall'indirizzo del lock. Non c'è alcuna posizione da trasferire, nessun approve da
revocare, nessun tokenId da perdere. Le uniche operazioni di liquidità che il contratto
può eseguire sono un modifyLiquidity con un delta esattamente pari a zero, per incassare
le commissioni, e, tramite la modalità di chiusura, la rimozione di tutte le posizioni di
un pool, 30 giorni dopo l'annuncio della chiusura.
Solo il lock aggiunge liquidità. Dal 2026-10-01 l'hook rifiuta qualsiasi altra posizione su un pool StockFun, quindi ogni trade è uno swap contro le posizioni bloccate, e paga la tassa.
I vault non hanno prelievo. Nessuna funzione permette a qualcuno di inviare gli asset di un vault a un indirizzo di sua scelta. Le due uscite sono l'airdrop, la cui unica destinazione è il contratto dell'airdrop indicato dal protocollo, che paga gli holder del token pro rata secondo una regola che nessuno sceglie, e la modalità di emergenza, con cui l'owner di StockFun sposta un asset verso qualsiasi indirizzo, subito. Queste sono le regole dell'implementazione attuale: l'owner di StockFun può fare l'upgrade di un vault, con effetto immediato.
I limiti sono impostazioni, i feed no. I limiti di prezzo dei vault, 50 e 200 punti base di default, sono impostazioni dell'owner di StockFun, lette in tempo reale da ogni vault; il keeper può solo restringerli. Il registro dei feed scrive ogni feed una sola volta; gli heartbeat dei feed sono impostazioni, e lo sono anche, dal 2026-10-06, le sue due protezioni, che possono solo trattenere un prezzo, mai cambiarlo: il controllo del sequencer (disattivato su Robinhood Chain finché Chainlink non vi pubblica un feed di uptime) e la pausa dell'oracolo di ogni azione (attiva per ogni azione di Robinhood Chain; vedi Il rail Robinhood). La modalità di emergenza non tocca né gli uni né gli altri: sposta asset, non cambia le regole di esecuzione. Il registro, come i vault, è upgradabile dall'owner di StockFun.
Isolamento e leve
Il 2026-10-05 il fondatore ha fissato una regola di progettazione: quando qualcosa fa fallire una funzione, le altre funzioni non devono farne le spese; tutto deve poter continuare a funzionare, e tutto deve avere una leva per recuperare i fondi persi e ricevere la correzione. Il quarto ciclo di audit di quel giorno l'ha portata nel codice, e da allora i cicli di audit contano come un difetto qualsiasi violazione delle sue due parti.
Isolamento. Un guasto in una funzione, un mercato, un'azione, un ciclo, una registrazione o un destinatario non blocca mai gli altri: l'elemento viene saltato, conservato come dovuto o differito, con un evento, e il resto prosegue.
- Un batch del bridge lascia fuori un mercato il cui vault non può rilasciare il proprio
cash (
MarketSkipped), e gli altri attraversano. Una consegna che il token cash rifiuta a un vault speculare resta sull'hub remoto, dovuta a quel mercato (DeliveryRefused), e gli altri mercati vengono pagati - Un acquisto esegue la tratta di ogni azione a sé (
LegFailed), e un invio all'airdrop ogni azione a sé (AirdropSendFailed) - Una riscossione paga ogni azione che può e differisce le altre (
ClaimDeferred) - Un vault che rifiuta ETH non ferma più il trading del suo mercato: l'hook conserva ciò
che non ha potuto pagare come dovuto a quel vault (
treasuryOwed), e il lock conserva per il suo destinatario la quota rifiutata di un incasso di commissioni (vaultOwed,creatorOwed). Chiunque li paga non appena il destinatario accetta di nuovo ETH (payTreasury,payOwed), e il keeper lo fa a ogni ciclo - La Lens legge ogni vault in una chiamata a sé, così un vault che non può rispondere
lascia leggibili gli altri (
vaultReadable). Dal 2026-10-06 quella chiamata riporta anche il rail del vault, il suo stato di pausa e l'USDC che ha inviato attraverso il bridge, e la pagina riporta ciò che l'hook e il lock devono al vault: il servizio dati dell'app non legge nient'altro per mercato, così un vault che consuma tutto il suo gas fa fallire solo i propri numeri. Dal settimo ciclo di audit quel servizio legge anche ogni modulo upgradabile (l'hook, l'oracolo, il contratto dell'airdrop, i due hub del bridge) e il token del protocollo in un gruppo a sé, così un modulo che consuma tutto il suo gas, dopo un upgrade difettoso, fa fallire solo i propri numeri
Leve. Ogni contratto che può detenere ETH o token, anche di passaggio o per errore, ha una leva per portare fuori ciò che resta bloccato, e ogni modulo può ricevere una correzione: un upgrade, o un setter che sostituisce il modulo.
- I moduli che non conservano nulla di nessuno tra una transazione e l'altra — la factory,
la Lens, gli oracoli, il registratore della detenzione, gli stock router, il router di
swap ufficiale e gli adapter del bridge — hanno il
rescue(asset, amount, to)dell'owner del protocollo - I moduli che tengono conti propri — i vault, i due hub e il contratto dell'airdrop — hanno la modalità di emergenza
- Il
rescuedell'hook prende solo ciò che gli è stato inviato per errore, mai ciò che deve. Quello del lock non prende mai le quote che conserva, né le posizioni, che solo la modalità di chiusura raggiunge. Quello delBuybackBurnerprende il suo ETH solo quando nessun burn potrebbe più spenderlo. I token, che non sono upgradabili, possono portare fuori ciò che è stato inviato al loro stesso indirizzo - Senza leva, per progettazione: i due deployer su Ethereum e il deployer dei vault speculari, che non detengono stato, non accettano ETH e non hanno owner
Dettagli in Modalità di emergenza.
L'unica eccezione voluta. La notifica di un token al suo registratore della detenzione
resta bloccante: se la notifica fallisce, il trasferimento fallisce. Una notifica a cui
fosse permesso fallire lascerebbe che un holder la privasse del gas nel proprio
trasferimento, così che il registro salti il movimento e la sua quota dell'airdrop cresca.
La leva è immediata, di una transazione ciascuna: setRecorder(0) sul token, che ne ferma
la registrazione, o un upgrade sul posto del registratore. Vedi L'airdrop.
Pacchetti offchain
| Pacchetto | Ruolo |
|---|---|
shared/ |
ABI generate, costanti del protocollo, formattazione. Un'unica fonte condivisa da tutto il resto |
backend/ |
Servizio prezzi. Isola l'unica dipendenza esterna della dapp |
keeper/ |
Conversione, batch del bridge, routing remoto, monitoraggio delle consegne e, dal 2026-10-05, il passaggio dell'airdrop, il pagamento di ciò che l'hook e il lock conservano per un destinatario, e l'incasso delle commissioni LP |
cairn-app/ |
L'app, un front end Next.js, accanto a projet/ dal 2026-10-02, quando ha sostituito la dapp React + Vite: vedi La dapp |
cairn-worker/ |
Lo strato dati dell'app, sull'edge: legge il protocollo una sola volta per tutte le pagine aperte e invia loro le modifiche |