Arquitetura

O protocolo vive em duas chains. O Ethereum abriga o launchpad, os pools e os vaults; a Robinhood Chain abriga as ações tokenizadas.

graph TD subgraph ETH[Ethereum] F[StockFunFactory] -->|implanta| TK[StockFunToken] F -->|implanta| V[TreasuryVault] F --> LL[LiquidityLock] TK -->|cada transferência| HR[HoldingRecorder] LL -->|duas posições travadas| PM[Uniswap v4 PoolManager] PM --> H[StockFunHook] H -->|2 %| V H -->|2 %| CR[Criador] H -->|0,5 %| TW[Carteira da equipe] H -->|0,5 %| BB[BuybackBurner] BB -->|compra + burn| SF[$STOCKFUN] V -->|ETH → USDC → USDG| BH[BridgeHub] V -->|sendToAirdrop, trilho local| AD[AirdropDistributor] AD -.consulta.-> HR AD -->|reivindicações, pro rata| HO[Holders do token] L[StockFunLens] -.consulta.-> F O[TreasuryOracle] -.limita.-> V end subgraph RH[Robinhood Chain] RH2[RemoteHub] --> MV[Vault espelho por mercado] MV -->|pools secundários| ST[Stock Tokens] end BH -->|LayerZero, OFT do USDG| RH2 ST -->|sendToAirdrop, OFTs das ações| AD K[Keeper offchain] -.aciona.-> V K -.aciona.-> BH

Os contratos

Esta tabela descreve o protocolo tal como foi decidido. A parte do lançamento está no código desde 2026-09-28, e a distribuição do airdrop desde 2026-10-04, não implantada; os adaptadores LayerZero das ações não estão no repositório. Routers e adaptadores que não sejam o swap router oficial ficam de fora: UniswapV4StockRouter no Ethereum, RobinhoodStockRouter na Robinhood Chain e o UsdgOftAdapter. Veja Status. Desde 2026-10-02, todo contrato desta tabela é upgradável, exceto os tokens, o lock de liquidez e os deployers: veja abaixo. As porcentagens do diagrama são os parâmetros padrão da taxa.

Contrato Papel Cardinalidade
StockFunFactory Cria os mercados, cobra a taxa de criação, mantém o registro e os parâmetros do owner para os novos mercados e para os vaults; a autoridade de upgrade de todo módulo do Ethereum Um
MarketDeployer · VaultDeployer Contornam o EIP-170 carregando o creation code do token e o do proxy do vault; não guardam estado, são substituídos pela factory em vez de receberem upgrade Um de cada
StockFunToken ERC-20 simples, não upgradável, sem mint e sem burn; sem lógica própria além de um único setter, setRecorder, e dos seus rescues, para o owner do protocolo; notifica cada mudança de saldo ao registrador de posições Um por mercado
HoldingRecorder Registra, para cada token, as posições de cada endereço ao longo do tempo e o supply fora do PoolManager do Uniswap; uma transferência falha se o seu registro falhar, a única exceção deliberada à regra de isolamento descrita abaixo Um
TreasuryVault Detém ETH, USDC e depois ações; conversão, cada perna da compra isoladamente, entrega das suas ações ao airdrop no trilho local (sendToAirdrop), cada ação isoladamente, e recuperação de emergência imediata Um proxy por mercado
LiquidityLock Cria o pool e deposita as duas posições, travadas, e guarda a taxa de LP e o tick spacing de cada pool; guarda para o seu destinatário a parte recusada de uma coleta de taxas; não upgradável; a sua única saída é o modo de encerramento, 30 dias depois do seu anúncio Um
StockFunHook Cobra a taxa em cada swap, aplica o anti-snipe, guarda os parâmetros da taxa e a whitelist de cada pool, recusa liquidez de qualquer um que não seja o lock, mantém os saldos dos criadores, da equipe e do buyback até serem reivindicados, e o que é devido a um vault que recusou a sua parte Um
StockFunSwapRouter O router oficial para os trades, o único pelo qual um endereço na whitelist fica isento do anti-snipe Um, substituível pelo owner
StockFunLens Somente leitura; agrega o estado de um mercado para o dapp, lendo cada vault isoladamente; desde 2026-10-06, a sua página também traz o trilho do vault, o seu estado de pausa e o USDC que ele já enviou pela bridge, o estado de travamento do pool, o registrador de posições do token, e o que o hook e o lock devem ao vault Um
TreasuryOracle Feeds da Chainlink, gravados uma única vez; os seus heartbeats são parâmetros e, desde 2026-10-06, também as suas duas salvaguardas na Robinhood Chain: a verificação do sequenciador, desligada até que a Chainlink publique um feed de disponibilidade para essa chain, e a pausa do oráculo de cada ação, que retém o preço dessa ação durante um evento corporativo Um por chain
BuybackBurner Compra $STOCKFUN e o envia para o burn. Enquanto o pool do $STOCKFUN estiver travado, não existe nenhum outro caminho Um
BridgeHub · RemoteHub · RemoteTreasuryVault O trilho cross-chain; o hub remoto é a autoridade de upgrade na Robinhood Chain e designa a rota do airdrop e o adaptador de cada ação; o vault espelho envia as suas ações ao airdrop (sendToAirdrop) Um, um, um proxy por mercado
StockFunProtocolToken $STOCKFUN, não upgradável como um token de mercado; todo o seu supply vai para a sua posição travada Um
AirdropDistributor Distribui, no Ethereum, as ações que cada tesouraria comprou aos holders do seu token, por ciclo diário; só credita os próprios vaults do mercado; cada holder reivindica, e uma reivindicação paga todas as ações que pode; vinculado à factory, que o designa Um

Proxies e upgrades

Desde 2026-10-02, todo módulo é um proxy ERC-1967 na frente de uma implementação, que recebe upgrade via UUPS. O proxy guarda o endereço e o estado; a implementação guarda o código, e um upgrade a substitui. Uma implementação nunca pode ser inicializada: cada proxy é inicializado dentro do seu próprio construtor.

Todo módulo pergunta a um único contrato quem pode fazer o seu upgrade, a sua autoridade de upgrade, fixada na sua implementação: a factory no Ethereum, que responde com o seu owner, e o hub remoto na Robinhood Chain, que responde com o seu admin de emergência, o owner do Ethereum tal como o último lote da bridge o levou. Uma transferência da propriedade da factory, portanto, move de uma só vez o poder de upgrade de todos os módulos do Ethereum, e o dos módulos da Robinhood Chain com o lote seguinte. Um upgrade é recusado se a nova implementação designar outra autoridade; as do hook e do registrador de posições também precisam manter o mesmo PoolManager.

Não upgradáveis: os tokens, o lock de liquidez e, na Robinhood Chain, o deployer dos vaults espelho, de cujo endereço é derivado o endereço de cada vault espelho. MarketDeployer e VaultDeployer não guardam estado: a factory os substitui (setDeployers) em vez de fazer o seu upgrade.

O storage só recebe acréscimos, nunca é reordenado: o layout de cada módulo é registrado em contracts/storage-layouts/, e contracts/script/check-storage-layouts.sh o compara antes de cada upgrade. Desde 2026-10-05, ele compara cada nível de cada struct, tamanhos incluídos, e recusa qualquer mudança numa struct que seja o elemento de um array de storage: só uma struct que seja o valor de um mapping, ou a última variável de estado, pode crescer, no seu final.

Um contrato de implementação nunca é usado diretamente, mas o que for enviado ao seu próprio endereço por engano também tem uma alavanca. A maioria das implementações lê a sua autoridade de um immutable, então o owner do protocolo o retira; as da factory e do hub remoto guardam o seu admin no storage do proxy, então, nas suas implementações, a alavanca é o endereço que as implantou.

Quem pode fazer upgrade, e com que rapidez: veja Modelo de confiança.

O contrato do airdrop

Desde 2026-10-04, o AirdropDistributor distribui as ações de cada tesouraria no Ethereum. É um módulo upgradável como os outros, um proxy cuja autoridade de upgrade é a factory. A factory o designa (setAirdropDistributor) e os vaults o leem em tempo real; um distribuidor substituído mantém cada ciclo reivindicável onde está. Ele lê as posições no registrador de posições, e as suas regras estão em O airdrop.

Dois caminhos chegam até ele, e nada mais credita um ciclo:

  • O trilho da bridge. O sendToAirdrop do vault espelho envia cada ação listada pelo adaptador LayerZero dessa ação, que o hub remoto designa (setStockAdapter), para o distribuidor que o hub remoto designa (setAirdrop), com o id do mercado como payload. No Ethereum, o OFT da ação cunha a ação wrapped para o distribuidor, e o endpoint da LayerZero o chama. Ele só credita a entrega vinda de um OFT de ação que o owner registrou, da Robinhood Chain, enviada pelo vault espelho que o hub da bridge deriva para esse mercado.
  • O trilho local. O sendToAirdrop do vault do Ethereum aprova os valores exatos, o distribuidor os puxa, somente do próprio vault do mercado, e credita o que recebeu; as aprovações são fechadas de novo. Um vault ligado ao hub da bridge recusa essa chamada.

O keeper aciona os dois, e só decide quando; no trilho da bridge, desde 2026-10-06, também o gas que cada entrega recebe no Ethereum, que o hub remoto mantém dentro dos limites que o owner do StockFun define lá.

Propriedades estruturais

O hook é um singleton. Um único contrato atende todos os pools, o que evita minerar um endereço por mercado — o endereço de um hook v4 codifica as suas permissões nos bits menos significativos, e encontrar um custa processamento. Desde 2026-10-02, ele é um proxy cujo endereço carrega todas as 14 permissões v4: um upgrade mantém esse endereço, e uma implementação posterior pode usar qualquer callback.

A liquidez não é um NFT. Ela fica diretamente no PoolManager, indexada pelo endereço do lock. Não há posição a transferir, nenhum approve a revogar, nenhum tokenId a perder. As únicas operações de liquidez que o contrato pode executar são um modifyLiquidity com delta exatamente zero, para coletar as taxas, e, pelo modo de encerramento, a remoção de todas as posições de um pool, 30 dias depois do anúncio do encerramento.

Só o lock adiciona liquidez. Desde 2026-10-01, o hook recusa qualquer outra posição num pool do StockFun, então todo trade é um swap contra as posições travadas, e paga a taxa.

Os vaults não têm saque. Nenhuma função permite a alguém enviar os ativos de um vault para um endereço da sua escolha. As duas saídas são o airdrop, cujo único destino é o contrato do airdrop que o protocolo designa, que paga os holders do token pro rata segundo uma regra que ninguém escolhe, e o modo de emergência, pelo qual o owner do StockFun movimenta um ativo para qualquer endereço, de imediato. Essas são as regras da implementação atual: o owner do StockFun pode fazer o upgrade de um vault, com efeito imediato.

Os limites são parâmetros, os feeds não. Os limites de preço dos vaults, 50 e 200 pontos-base por padrão, são parâmetros do owner do StockFun, lidos em tempo real por todo vault; o keeper só pode apertá-los. O registro de feeds grava cada feed uma única vez; os heartbeats dos feeds são parâmetros, e também o são, desde 2026-10-06, as suas duas salvaguardas, que só podem reter um preço, nunca mudá-lo: a verificação do sequenciador (desligada na Robinhood Chain até que a Chainlink publique um feed de disponibilidade para ela) e a pausa do oráculo de cada ação (ligada para toda ação da Robinhood Chain; veja O trilho Robinhood). O modo de emergência não toca em nenhum dos dois: movimenta ativos, não muda as regras de execução. O registro, como os vaults, pode receber upgrade do owner do StockFun.

Isolamento e alavancas

Em 2026-10-05, o fundador definiu uma regra de design: quando algo faz uma função falhar, as outras funções não devem pagar por isso; tudo deve poder continuar funcionando, e tudo deve ter uma alavanca para recuperar fundos perdidos e receber a correção. O quarto loop de auditoria daquele dia a levou ao código e, desde então, os loops de auditoria contam qualquer violação das suas duas partes como um defeito.

Isolamento. Uma falha numa função, num mercado, numa ação, num ciclo, num registro ou num destinatário nunca bloqueia os outros: o item é pulado, guardado como devido ou adiado, com um evento, e o resto continua.

  • Um lote da bridge deixa de fora um mercado cujo vault não consegue liberar o seu caixa (MarketSkipped), e os outros atravessam. Uma entrega que o token da perna de caixa recusa a um vault espelho fica no hub remoto, devida a esse mercado (DeliveryRefused), e os outros mercados são pagos
  • Uma compra executa a perna de cada ação isoladamente (LegFailed), e um envio ao airdrop, cada ação isoladamente (AirdropSendFailed)
  • Uma reivindicação paga todas as ações que pode e adia as outras (ClaimDeferred)
  • Um vault que recusa ETH não paralisa mais a negociação do seu mercado: o hook guarda o que não conseguiu pagar como devido a esse vault (treasuryOwed), e o lock guarda para o seu destinatário a parte recusada de uma coleta de taxas (vaultOwed, creatorOwed). Qualquer pessoa os paga assim que o destinatário volta a aceitar ETH (payTreasury, payOwed), e o keeper o faz a cada ciclo
  • A Lens lê cada vault na sua própria chamada, então um vault que não consegue responder deixa os outros legíveis (vaultReadable). Desde 2026-10-06, essa chamada também traz o trilho do vault, o seu estado de pausa e o USDC que ele já enviou pela bridge, e a página traz o que o hook e o lock devem ao vault: o serviço de dados do app não lê mais nada por mercado, então um vault que consome todo o seu gas só faz falhar os seus próprios números. Desde o sétimo loop de auditoria, esse serviço também lê cada módulo upgradável (o hook, o oráculo, o contrato do airdrop, os dois hubs da bridge) e o token do protocolo num grupo próprio, então um módulo que consome todo o seu gas, depois de um upgrade quebrado, só faz falhar os seus próprios números

Alavancas. Todo contrato que pode deter ETH ou tokens, mesmo de passagem ou por engano, tem uma alavanca para retirar o que ficou preso, e todo módulo pode receber uma correção: um upgrade, ou um setter que troca o módulo.

  • Os módulos que não guardam nada de ninguém entre transações — a factory, a Lens, os oráculos, o registrador de posições, os routers de ações, o router de swap oficial e os adaptadores da bridge — têm o rescue(asset, amount, to) do owner do protocolo
  • Os módulos que mantêm contas próprias — os vaults, os dois hubs e o contrato do airdrop — têm o modo de emergência
  • O rescue do hook só retira o que lhe foi enviado por engano, nunca o que ele deve. O do lock nunca retira as partes que ele guarda, nem as posições, que só o modo de encerramento alcança. O do BuybackBurner só retira o seu ETH quando nenhum burn puder mais gastá-lo. Os tokens, que não podem receber upgrade, podem retirar o que foi enviado ao seu próprio endereço
  • Sem alavanca, por design: os dois deployers no Ethereum e o deployer dos vaults espelho, que não guardam estado, não aceitam ETH e não têm owner

Detalhes em Modo de emergência.

A única exceção deliberada. A notificação de um token ao seu registrador de posições continua bloqueante: se a notificação falhar, a transferência falha. Uma notificação que pudesse falhar deixaria um holder privá-la de gas na sua própria transferência, para que o registro pulasse o movimento e a sua parte do airdrop crescesse. A alavanca é imediata, de uma transação cada: setRecorder(0) no token, que interrompe o seu registro, ou um upgrade do registrador no lugar. Veja O airdrop.

Pacotes offchain

Pacote Papel
shared/ ABIs geradas, constantes do protocolo, formatação. Uma fonte única compartilhada por todo o resto
backend/ Serviço de preços. Isola a única dependência externa do dapp
keeper/ Conversão, lotes da bridge, roteamento remoto, monitoramento de entregas e, desde 2026-10-05, a etapa do airdrop, o pagamento do que o hook e o lock guardam para um destinatário e a coleta das taxas de LP
cairn-app/ O app, um front end em Next.js, ao lado de projet/ desde 2026-10-02, quando substituiu o dapp React + Vite: veja O dapp
cairn-worker/ A camada de dados do app, na edge: lê o protocolo uma única vez para todas as páginas abertas e lhes envia as mudanças