Registro de decisões

O registro canônico é doc/DECISIONS.md. Esta página resume os pontos de virada.

2026-08-25 — Revisão de segurança interna

Um achado de severidade alta: execuções parciais deixavam ETH e USDC presos nos routers, integralmente taxados. Corrigido recusando execuções parciais em vez de tratá-las.

2026-08-27 — A taxa passa de 4 % para 5 %

Parte do criador dobrada, de 1 % para 2 %. Tabela do $STOCKFUN de 2 / 1,5 / 0,5 para 2 / 2,5 / 0,5. A parte da tesouraria continua em 2 %, e esse é o número que nunca se mexe.

Consequência aceita: a ida e volta passa de 7,84 % para 9,75 %. Desde 2026-10-05, a taxa e a sua divisão são parâmetros do owner, sendo estes valores os padrões.

2026-08-27 — O buyback do criador

Suspende a exclusão "nenhuma saída" num único caminho, que sempre termina no burn. O Treasury Ratio passa a poder cair a critério de um criador. Removido em 2026-09-27, substituído pelo airdrop.

2026-08-29 — Modo de emergência

O owner pode movimentar os ativos de uma tesouraria após 48 horas públicas. Substitui a promessa "ninguém pode tocar na tesouraria". O protocolo deixa de ser descrito como trustless. Imediato desde 2026-10-05: o prazo acabou.

2026-09-11 — O trilho passa para a Robinhood Chain

O bloqueio era a elegibilidade de um contrato de vault junto a um emissor de mint primário, nunca documentada publicamente. Os pools secundários da Robinhood Chain não a exigem. Preço pago: uma dependência cross-chain aceita.

2026-09-12 — A bonding curve sai de cena

Substituída por duas posições single-sided no Uniswap v4, travadas desde a criação. Sem graduação, sem migração, sem taxa de graduação.

O FDV de lançamento não muda: continua o mesmo com que a curva abria, 3,409 ETH. Um primeiro ticket de 2 ETH leva 36,06 % do supply contra 36,99 % antes — o lançamento se comporta como antes, com diferença de menos de um ponto.

Descartados no caminho: um lançamento a US$ 5.000 com teto de US$ 50.000, que dava só 3,25 ETH de profundidade e deixava o primeiro comprador de 2 ETH levar 57 % do supply. E a ideia de que um teto mais baixo acalmaria o mercado — ele passa o bastão mais cedo para a faixa ilimitada, que é rasa, e dobra o FDV atingido após 50 ETH gastos.

2026-09-12 — Anti-snipe de três blocos

Só o criador no bloco 1, 99 % para o buyback no bloco 2, exceto o criador e a whitelist do owner, normal depois disso. Substituído em 2026-09-28 pelo anti-snipe decrescente.

Decidido com pleno conhecimento da objeção: uma taxa de 99 % só produz algo se alguém perde o seu dinheiro, e fechar o bloco 2 teria tido o mesmo efeito dissuasório sem vítima. A whitelist fica no nível do protocolo e não no do criador, justamente para que não possa virar uma vantagem de insider mercado a mercado.

2026-09-12 — Sem burn nas vendas

A ideia de enviar 10 % dos tokens recebidos ao burn em cada venda foi abandonada. Paga pelo vendedor, ela levava a ida e volta a 18,78 %. Paga pela LP, tornava falso o "liquidez travada para sempre" e dava a qualquer um uma alavanca de aproximadamente 1:1 para queimar o float e pumpar a própria bag.

2026-09-27 — O airdrop substitui o buyback do criador

A tesouraria de um mercado passa a ter um único uso: 100 % das ações que ela compra são distribuídas via airdrop aos holders do seu token, pro rata, in natura, na Robinhood Chain. O buyback do criador é removido, e com ele o caminho de volta da bridge. O buyback e burn de $STOCKFUN permanece.

Descartados no caminho: manter o buyback do criador, e uma divisão que mantinha 60 % na tesouraria e distribuía 40 %, o antigo plano V2. Consequências aceitas: nenhuma tesouraria acumula mais, o Treasury Ratio perde o sentido, e o slogan e a tagline precisam ser revistos. O mecanismo foi codificado em 2026-10-04: veja O airdrop.

2026-09-27 — Um ciclo a cada 24 horas

A cadência do airdrop é definida no mesmo dia. Uma vez a cada 24 horas, para cada mercado cuja tesouraria tenha acumulado pelo menos 0,1 ETH, o keeper converte, envia pela bridge, compra as ações e depois as distribui via airdrop. Abaixo do limiar, nada acontece naquele dia; o ETH espera.

As ações só podem ser compradas enquanto a bolsa americana está aberta, então não há ciclo nos fins de semana nem nos feriados da NYSE. No código do keeper, até 2026-10-06 a conversão rodava durante o pregão, na primeira passagem em que o vault detinha o limiar; desde então ela segue esta decisão, uma vez por janela, na primeira passagem do keeper depois que a janela fecha e só se o vault detiver o limiar nesse momento (veja 2026-10-06 abaixo); desde o sexto loop de auditoria, no mesmo dia, o USDC que um vault detém também segue essa cadência. O envio ao airdrop roda uma vez por janela desde 2026-10-05, depois do pregão do dia: veja O keeper.

2026-09-27 — Fundos presos e medição das posições

As sobras de um ciclo interrompido são levadas até o fim no próximo ciclo, com ou sem o limiar atingido. Fundos de airdrop presos por 24 horas num vault espelho podem ser movimentados pelo owner sem aviso prévio: a única exceção ao prazo público de 48 horas, escolhida conscientemente. As posições são medidas como o saldo médio nas 24 horas anteriores ao ciclo, inclusive às segundas-feiras. A janela dos fundos presos passou a 48 horas em 2026-09-28, e a regra foi encerrada em 2026-10-05, sem nunca ter sido codificada.

2026-09-28 — Anti-snipe decrescente

80 % no bloco de abertura, menos 8 pontos por bloco, 5 % a partir do 11º bloco, nas compras e nas vendas. O excedente vai para a tesouraria do mercado, ou para as taxas a reivindicar da equipe no $STOCKFUN. Isentos: a compra de lançamento do criador e uma whitelist definida pelo criador na transação de criação, pública, imutável e com teto de 20 endereços; no $STOCKFUN, definida pelo owner no lançamento. Desde 2026-10-05, esses números são parâmetros do owner, sendo os valores acima os padrões.

Descartado no caminho: marcar as carteiras que compram nos primeiros blocos e taxar as suas vendas posteriores, mesmo depois de uma transferência. Um pool v4 não vê a carteira, uma taxa cobrada pelo token faz a venda falhar, e bloquear as carteiras marcadas fora do router do StockFun faria o token ser sinalizado pelos scanners. Consequência aceita: a whitelist passa do protocolo para o criador, o que a decisão de 2026-09-12 tinha descartado para impedir uma vantagem de insider.

2026-09-28 — Fundos de airdrop presos: 48 horas

Fundos de airdrop que ficaram 48 horas num vault espelho, em vez de 24, podem ser movimentados pelo owner sem aviso prévio. Com 24 horas, a janela era igual ao período do ciclo, e uma sobra comum, adiada por um único ciclo, passava a poder ser movimentada sem aviso prévio; com 48 horas, isso não acontece mais. Os fundos de uma falha de sexta-feira continuam podendo ser movimentados no domingo, antes do ciclo de segunda-feira. Decidido no mesmo dia: o relógio nunca para, nem durante uma pausa nem nos fins de semana. Regra encerrada em 2026-10-05, sem nunca ter sido codificada: a transferência de emergência é imediata em toda parte.

2026-09-28 — Posições registradas onchain

O token de cada mercado registra as posições de cada carteira ao longo do tempo, então um contrato calcula a média nas 24 horas anteriores a um ciclo e cada parte; o keeper nunca as fornece. Descartado: uma divisão calculada offchain pelo keeper e publicada com um prazo de contestação. Custo aceito: cada transferência do token paga gas extra.

2026-09-28 — O airdrop em ações wrapped, no Ethereum

As ações compradas na Robinhood Chain são travadas lá em adaptadores LayerZero implantados pelo StockFun, um por ação, e enviadas para o Ethereum como ações wrapped. A distribuição acontece no Ethereum, onde ficam o token e as suas posições, e cada holder reivindica a sua parte às suas custas. Consequências aceitas: as ações wrapped só valem o que valerem as ações travadas e a configuração da LayerZero, não têm mercado no Ethereum, e um congelamento dos Stock Tokens pelo seu emissor bloquearia as ações travadas. Decidido no mesmo dia: a configuração da LayerZero dos adaptadores fica nas mãos do owner, sem prazo e sem teto de saques, como a Paxos faz com o USDG. Descartado: uma configuração congelada após a implantação, e mudanças com aviso prévio de 48 horas.

2026-09-28 — O router oficial continua alterável

O owner pode mudar o swap router oficial a qualquer momento, e o hook reconhece a whitelist anti-snipe por meio desse router. Consequência aceita: ao designar outro router, o owner pode isentar qualquer pessoa do anti-snipe.

2026-09-28 — Uma taxa de criação de 0,001 ETH

A taxa de criação passa a 0,001 ETH, fixada no código, em vez de cerca de US$ 3: sem feed de preço, sem ajuste pelo owner. O seu valor em dólares agora acompanha o preço do ETH. Um parâmetro do owner desde 2026-10-05, 0,001 ETH por padrão.

2026-09-28 — O PoolManager fora do registro de posições

O token não registra o PoolManager do Uniswap, uma das partes de cada swap, que contém os tokens de todos os pools e nunca recebe um airdrop: o seu histórico é lido como zero, enquanto o do trader continua registrado. Economia medida: cerca de 24.000 de gas por swap, tanto nas compras quanto nas vendas.

2026-09-29 — Sem taxa de LP nos pools do StockFun

Os pools são criados com a taxa de LP do Uniswap zerada, em vez de 0,30 %: a taxa do hook é todo o custo de um trade, 5 % por sentido e 9,75 % por uma ida e volta antes do impacto de preço. Custo aceito: a tesouraria, a equipe e o criador perdem a sua parte das taxas de LP, e o burn da parte em tokens dessas taxas desaparece. Desde 2026-10-05, a taxa de LP é um parâmetro de lançamento, zero por padrão; cada pool mantém a taxa com que foi criado.

2026-10-01 — Correções da auditoria de segurança de 2026-09-29

Aplicadas em 2026-09-30 e 2026-10-01, depois de cada achado ter sido revisado e a sua correção escolhida. Cada achado corrigido tem testes de regressão que falham no código auditado.

Só o lock de liquidez pode adicionar liquidez a um pool do StockFun: uma posição de terceiros servia de contraparte a swaps taxados sem pagar a taxa nem o anti-snipe. A nova permissão do hook mudou o endereço do hook, que foi minerado de novo.

Só a parte da tesouraria é enviada durante um trade. As partes da equipe e do buyback são creditadas no hook e pagas por reivindicações que qualquer pessoa pode chamar, às carteiras atuais da factory; o escrow foi removido. O router e o lock pagam o valor de entrada antes do swap. Até então, uma carteira de taxas que fizesse uma chamada de volta ao Uniswap podia paralisar a negociação em todos os pools.

Cada etapa de conversão gasta um valor que o keeper indica, então um vault maior do que o seu local de negociação converte em fatias. O caixa é reservado por ação do basket à medida que chega, e uma ação que o keeper pula mantém a sua reserva; o vault espelho funciona da mesma forma.

Cada token registra ao longo do tempo o seu supply fora do PoolManager do Uniswap, o denominador da parte pro rata do airdrop. Das três opções da auditoria, esta custa uma escrita a mais por swap; voltar a registrar o PoolManager teria custado cerca de 24.000 de gas por swap. Consequência aceita: as janelas do airdrop começam e terminam numa hora cheia.

No trilho Robinhood, um basket recusado não bloqueia mais os outros mercados de um lote, um token remoto recebe um único identificador, uma execução parcial em v3 faz a sua rota falhar, um hub remoto pausado continua aplicando as mudanças de papéis, e os registros canônicos são pagos na ordem em que chegaram.

Medido: uma compra pelo router custa 113.529 de gas e uma venda 137.250, contra 125.862 e 150.416 antes. Ainda em aberto, à espera da decisão do owner: a rotação do adaptador da bridge (M-2, e L-8 com ela), as atestações da Ondo (M-7), e routers que aceitam a si mesmos como destinatário (L-4). Desde 2026-10-05, M-7 e L-4 estão corrigidos, e M-2 fica como está por decisão do owner, e L-8 com ele.

2026-10-01 — O pipeline de segurança completa as correções

No mesmo dia, uma segunda rodada de auditoria, por dois auditores independentes, completou várias correções. Cada uma tem testes de regressão; nenhuma muda uma decisão de design nem um parâmetro imutável.

Na Robinhood Chain, uma rota v3 é executada um pool de cada vez, e cada pool precisa consumir toda a sua entrada: a verificação anterior só via o primeiro pool, e uma execução parcial mais adiante deixava o token intermediário onde qualquer pessoa podia pegá-lo. Um ticket de contabilidade canônico paga no máximo tantos registros quantos acrescentou à fila, os mais antigos primeiro, então um acúmulo não o leva mais além do gas da sua execução automática; o sweep paga o resto.

Uma emergência executada que deixa o caixa de um vault abaixo das suas reservas zera todas elas, nos dois vaults: o que resta, e toda entrada de caixa posterior, é dividido de novo segundo os pesos. Até então, a zeragem só existia na leitura, e as reservas antigas voltavam com a entrada seguinte.

O keeper retém n−1 unidades na última ação de um basket a cada compra: o resto do arredondamento vai para essa ação, e uma transferência de poeira podia fazer a compra reverter. Ele também reduz à metade uma fatia de burn que o pool do $STOCKFUN não consegue executar por inteiro. Cada token registra a sua primeira marca horária na implantação, o que só importava num relógio que começa na hora 0, como o de uma chain de teste. O router de ações do Ethereum sincroniza antes de pagar em ETH, e a Lens recusa uma página vazia.

Medido: o primeiro swap de cada hora de um token custa cerca de 28.000 a 30.000 de gas a mais como transação à parte, e não cerca de 23.000.

À espera da decisão do owner, não decididos: uma emergência sobre o caixa registrado do hub remoto, cujos registros são então pagos com o caixa de outros mercados (R2H-1); um token da perna de caixa que recusa um vault espelho, o que paralisa a fila canônica e reverte os lotes agrupados com esse mercado (R2H-2); a margem da última ação do lado dos contratos, que muda a regra de alocação documentada (R2T-1); cobrar a taxa de compra em claims do PoolManager, para que qualquer router possa comprar (R2F-1, option b); fazer a factory implantar ela mesma o vault do $STOCKFUN (R2F-2); e três pontos informativos (R2H-4, R2H-6, R2H-7). Uma ação que nunca mais pode ser comprada continua recebendo o seu peso de cada entrada de caixa: é intencional, já que remover uma perna mudaria os pesos fixos do basket. Desde 2026-10-05, o R2H-1 está coberto pelas ferramentas de acerto das contas dos loops de auditoria daquele dia e por um procedimento, em que o owner pausa o hub remoto antes da transferência; o R2H-2 está encerrado pelas entregas não bloqueantes do quarto loop; a option b do R2F-1 foi recusada, e a taxa continua sendo cobrada como hoje; e um vault que recusa ETH não paralisa mais o seu mercado, a paralisação que o R2F-2 descrevia: veja as entradas de 2026-10-05 abaixo.

2026-10-02 — Todos os módulos upgradáveis

Até então, nenhum contrato do protocolo podia receber upgrade. Todo módulo, exceto os tokens e o lock de liquidez, passa a ser upgradável pelo owner do StockFun, com efeito imediato: sem timelock. Cada um é um proxy que recebe upgrade via UUPS, e pergunta à sua autoridade de upgrade quem pode fazer o seu upgrade: a factory no Ethereum, o hub remoto na Robinhood Chain. Os vaults, nas duas chains, são um proxy por mercado, que recebe upgrade mercado a mercado. O proxy do hook é minerado com todas as 14 permissões v4, então uma implementação posterior pode usar qualquer callback sem mover o endereço.

Os tokens não carregam nenhuma lógica própria: um ERC-20 simples com supply fixo e um único setter, setRecorder, para o owner. O registro de posições sai deles para um novo módulo, o registrador de posições, que todo token chama a cada transferência; se a chamada falhar, a transferência falha. Desde 2026-10-05, os tokens também têm rescues, para o que é enviado ao seu próprio endereço, e essa chamada bloqueante é a única exceção deliberada à regra de isolamento do fundador (veja abaixo).

O lock de liquidez continua não upgradável e ganha um modo de encerramento: o owner o anuncia, e 30 dias depois pode recuperar toda a liquidez de cada pool, inclusive a do $STOCKFUN, para qualquer endereço. O owner pode cancelar; a negociação continua durante os 30 dias, e nenhum novo mercado pode ser lançado enquanto houver um encerramento pendente. Ele existe para o caso de o projeto encerrar as suas atividades; os 30 dias são o aviso prévio dos holders. O deployer dos vaults espelho na Robinhood Chain também não é upgradável: o endereço de cada vault espelho deriva dele.

O que isso muda: um upgrade não espera as 48 horas do modo de emergência, que permanece; as regras que este livro chama de fixas, dos limites dos vaults ao burn e à taxa de 5 %, valem enquanto o owner não fizer o upgrade do módulo que as carrega; a factory é implantada primeiro e conectada pelo owner, o que muda a ordem de implantação. Um swap custa cerca de 27.000 de gas a mais, medido isoladamente: uma compra custa 237.190 de gas em vez de 210.105, uma venda 285.031 em vez de 258.278 — o preço dos proxies no seu caminho e da chamada ao registrador. Desde 2026-10-05, o modo de emergência também não tem prazo, e os limites dos vaults e a taxa de 5 % são parâmetros do owner.

2026-10-04 — O contrato do airdrop

Codificado e testado, não implantado. O AirdropDistributor, um módulo upgradável no Ethereum vinculado à factory, distribui as ações de cada mercado por ciclo diário. A janela de um ciclo fecha às 13:00 UTC, antes da abertura americana o ano inteiro; as suas compras e os seus envios acontecem no pregão seguinte. Um ciclo se abre com o seu primeiro envio, ou antes dele, e congela os seus números: o registrador de posições, a lista de exclusão em vigor quando a janela fechou e as posições elegíveis. Dois caminhos o alimentam, sendToAirdrop no vault espelho, pelo adaptador LayerZero de cada ação, e no vault do Ethereum para o trilho local; nada mais credita um ciclo.

Decidido no mesmo dia: nenhum envio pelo keeper, só o holder reivindica, às suas custas (TBD 5); nenhum teto por carteira, nenhum mínimo, nenhum prazo de validade (TBD 7); uma lista de exclusão por token, definida pelo owner, no máximo 16 endereços, com o endereço de burn sempre e o contrato de vesting no $STOCKFUN (TBD 8). Um envio para uma janela sem posições elegíveis é guardado à parte para a primeira janela que as tenha, seja quem for que chame e seja quando for, desde que, nesse meio-tempo, o horário do ciclo não mude e o registrador de posições do token não seja substituído.

Aceito e documentado: o keeper escolhe quando, então um envio que chega depois do 13:00 UTC seguinte é medido na janela do dia seguinte; mudar o horário do ciclo recorta as janelas ainda não abertas, inclusive aquelas que as ações guardadas à parte ainda vão examinar; o registrador de posições de um token recebe upgrade no lugar, nunca é substituído num token em uso. Fora desta mudança: a regra das 48 horas para fundos presos, os adaptadores de ações, a etapa do airdrop no keeper e a tela de reivindicação do dapp. Desde 2026-10-05, não há mais contrato de vesting a excluir, a regra das 48 horas está encerrada, e o horário do ciclo faz parte de um cronograma que o owner define, a duração e o horário de fechamento das janelas (setCycleSchedule); um registrador designado num token em uso parte do supply do token fora do PoolManager (veja a entrada do loop de auditoria abaixo).

2026-10-05 — Nenhuma alocação para a equipe, um modo de emergência imediato, todo número um parâmetro

Três decisões, codificadas e testadas no mesmo dia, não implantadas.

A alocação da equipe acaba. O contrato de vesting da equipe, TeamVesting, é removido, e nenhum $STOCKFUN é reservado para a equipe: todo o supply, 1.000.000.000 tokens por padrão, vai para a posição single-sided travada, como todo o supply de um mercado vai para as suas duas posições. Até então, 10 % iam para o contrato de vesting ao longo de 12 meses, e o airdrop excluía esse contrato dos ciclos do $STOCKFUN; agora só o endereço de burn é excluído, com, desde o terceiro loop de auditoria daquele dia, o operador do lançamento (veja abaixo).

O modo de emergência passa a ser imediato. emergencyTransfer movimenta um ativo de um vault, de um hub da bridge ou do contrato do airdrop, para qualquer endereço, de imediato; cada transferência tem um id sequencial e um evento público. O agendamento de 48 horas de 2026-08-29 acabou, com a sua janela de cancelamento, e o prazo não é um parâmetro: uma emergência age assim que o owner a usa, nunca depois de uma espera. A substituição do adaptador da bridge, changeAdapter, também é imediata, com as mesmas fixações. A regra dos fundos de airdrop presos, decidida em 2026-09-27 e 2026-09-28 e nunca codificada, está encerrada: a transferência imediata a cobre, em qualquer contrato, a qualquer momento.

Todo número passa a ser um parâmetro. Os números do protocolo agora são parâmetros onchain do owner, nas duas chains, sendo os valores de hoje os padrões: a taxa, a sua divisão e o anti-snipe; a taxa de criação e os limites de tamanho dos textos de um novo mercado; o formato dos novos mercados, inclusive a taxa de LP e o tick spacing, e as partes do que as posições travadas coletam; o limiar de conversão e os limites de preço dos vaults; o cronograma e os limites do airdrop; os heartbeats dos oráculos; o gas e o slippage da bridge. Cada um entra em vigor de imediato e recusa valores impossíveis. Uma mudança da taxa vale a partir do próximo swap em todos os pools, inclusive num pool ainda nos seus blocos anti-snipe; uma mudança de formato vale para os mercados criados depois, e cada pool mantém a taxa de LP e o tick spacing com que foi criado.

Mantido fixo: o aviso prévio de 30 dias do modo de encerramento, END_DELAY, no lock, que não é upgradável; as unidades e as codificações, do ponto-base à hora do registro de posições; e a conexão, dos feeds de preço aos endpoints da bridge, que só um upgrade pode apontar para outro lugar.

Consequência aceita: os valores que este livro dá para a taxa, o lançamento, os vaults e o airdrop são padrões, não garantias; o owner pode mudar cada um deles a qualquer momento, sem aviso prévio. Medido: ler os parâmetros da taxa custa a um swap cerca de 1.200 de gas a mais, com storage quente. Veja Modelo de confiança.

2026-10-05 — As correções do loop de auditoria

No mesmo dia, um loop de revisão sobre todo o código levou a correções nos contratos, cada uma com um teste de regressão, não implantadas. Quatro delas mudam o comportamento.

Depois de uma transferência de emergência, as contas são acertadas, nunca pagas por outro mercado. O contrato do airdrop e o hub remoto detêm ativos que são devidos a vários mercados. Depois de uma transferência para fora de qualquer um deles, os pagamentos que dependem do que falta esperam — as reivindicações dessa ação no airdrop, os pagamentos do hub remoto no trilho do USDG — até que os ativos voltem ou que o owner do StockFun dê baixa da perda no ciclo ou no mercado que a sofreu; no trilho canônico, o owner remove, antes que o próximo depósito chegue, o registro cujo caixa a transferência levou. Um ciclo só pode sofrer uma baixa parcial enquanto ninguém tiver reivindicado dele a ação, com todo holder perdendo então a mesma proporção; depois que alguns holders tiverem sido pagos, só pode sofrer uma baixa de todo o seu restante, que os holders ainda não pagos perdem. A transferência em si continua imediata e incondicional. Veja Modo de emergência.

Só o keeper envia pela bridge. Até então, qualquer pessoa podia enviar um lote da bridge: um terceiro podia inserir um, com o mínimo mais frouxo do adaptador, entre dois trades próprios no pool da Curve, ou fazer o lote do keeper falhar acionando antes o bridging de um dos vaults desse lote.

Só o keeper e o owner do StockFun pré-implantam um vault espelho na Robinhood Chain. Até então, qualquer pessoa podia fazê-lo, mesmo para um mercado que ainda não existia, vinculado à conexão daquele dia. Um vault pré-implantado agora adota o router de ações e o oráculo do hub remoto no seu primeiro lote.

Um registrador de posições designado num token em uso parte do supply do token fora do PoolManager, e um registrador que já registrou esse token o recusa. Até então, um registrador novo partia de zero: toda venda falhava, e as partes de airdrop dos ciclos abertos depois ficavam quebradas de vez. Agora a negociação continua, e os holders que o novo registrador não viu se mover são lidos como não tendo detido nada até o seu próximo movimento. Fazer o upgrade do registrador no lugar continua sendo a regra.

Correções menores: os vaults aplicam o próprio mínimo do keeper ao que realmente chega, não só o seu próprio limite; o ticket de contabilidade da bridge canônica paga pelo tamanho do lote; os parâmetros recusam um tick de lançamento em que nenhum pool consegue abrir, um limite de nome vazio, e um hook e um lock em PoolManagers diferentes; uma mudança para janelas de airdrop mais longas não bloqueia mais um mercado com ações guardadas à parte. Veja Modelo de confiança.

2026-10-05 — A segunda passada do loop de auditoria

No mesmo dia, um segundo loop de revisão sobre as correções levou a mais correções nos contratos, cada uma com um teste, não implantadas, e a mudanças no keeper.

As contas contabilizam o que as lastreia, nunca o saldo. O saldo do contrato do airdrop, e o do hub remoto no trilho do USDG, também inclui tokens que chegaram mas ainda não foram creditados: uma entrega cuja última etapa ainda não foi executada. Depois de uma emergência, esses tokens podiam reabrir as reivindicações de um ciclo esvaziado e pagá-las com as ações de outro mercado. Os dois contratos agora contabilizam eles mesmos o que lastreia as suas contas. Uma transferência de emergência leva primeiro do que as lastreia; o que ela leva além disso veio de tokens ainda não creditados, e as próximas entregas o quitam antes de lastrear qualquer coisa, com o hub remoto registrando esses lotes em vez de entregá-los. Os ativos voltam via restore, que qualquer pessoa pode chamar; uma transferência simples não lastreia nada, então tokens extraviados só são recuperados para serem repostos. Veja Modo de emergência.

Depois de uma baixa de todo o restante de um ciclo, que se segue a uma reivindicação, tudo o que chega a esse ciclo em seguida é dividido pro rata entre todos os seus holders, como se o valor baixado nunca tivesse estado lá; até então, ia primeiro para os holders ainda não pagos, na ordem em que reivindicaram. Uma baixa que não deixa nada guardado à parte para um mercado encerra a sua busca por uma janela.

Um token recusa um registrador de posições vinculado a outro PoolManager do Uniswap que não o do seu pool, o que contaria o pool como um holder e pagaria a cada holder uma fração da sua parte. E um registrador designado num token em uso mantém um supply registrado pelo menos igual ao total dos holders, e não igual a ele, até que todo holder tenha se movido.

Na bridge canônica, a taxa é cotada a uma taxa base que o keeper indica, o dobro da mais recente, com o excedente devolvido: uma cotação lida sem preço de gas enxergava uma taxa base nula, e um lote longo falhava. O hub remoto só passa a conhecer o keeper por meio de um lote: antes do primeiro, o owner do StockFun pré-implanta o vault espelho do primeiro mercado, e um mercado cujo vault o keeper não consegue pré-implantar fica de fora do seu lote, com um alerta. O keeper conta separadamente as falhas de um vault no Ethereum e na Robinhood Chain.

Da segunda rodada de 2026-10-01: o R2H-1 está coberto pelas ferramentas de acerto das contas e por um procedimento, em que o owner pausa o hub remoto antes da transferência; o R2H-2 está mitigado, ainda em aberto: um vault espelho congelado não paralisa mais de vez a fila canônica, e só o keeper monta um lote, mas uma entrega a esse vault ainda falha por inteiro, então o keeper precisa deixar esse mercado de fora. Veja Modelo de confiança. Encerrado no mesmo dia pela quarta passada: veja abaixo.

2026-10-05 — Uma falha nunca bloqueia o resto

A regra de design do fundador, definida no mesmo dia: quando algo faz uma função falhar, as outras funções não devem pagar por isso; tudo deve continuar funcionando, e tudo deve ter uma alavanca para recuperar fundos perdidos e receber a correção. Ela tem duas partes. 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. 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 o troca. A partir do quarto loop de auditoria, os loops contam qualquer violação como um defeito.

Uma exceção deliberada: a notificação de um token ao seu registrador de posições continua bloqueante, uma notificação que falha fazendo a transferência falhar. 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: setRecorder(0) no token, ou um upgrade do registrador no lugar, de uma transação cada.

Consequências aceitas: uma parte recusada espera pelo seu destinatário em vez de parar o resto; uma transferência de emergência não imputada a nenhum mercado faz os pagamentos desse ativo esperarem até que ela seja acertada; e, enquanto um token não tem registrador, o airdrop não abre nenhum ciclo dele e guarda as suas ações à parte. Veja Arquitetura.

2026-10-05 — A terceira passada do loop de auditoria

No mesmo dia, um terceiro loop, voltado a sequências: operações corretas isoladamente que dão errado em alguma ordem ou momento. Cada correção tem um teste, não implantada.

restore primeiro devolve o que uma transferência de emergência levou além do que lastreia as contas, no contrato do airdrop e no trilho do USDG do hub remoto, e lastreia as contas com o resto: devolver os tokens de uma entrega que espera não paga mais o mercado esvaziado com eles. Uma ação baixada por inteiro de um ciclo antes que alguém a reivindicasse sai da lista desse ciclo.

Um registrador de posições designado num token em uso começa um novo registro na troca: o airdrop não mede nenhuma janela que começou antes dela, cujas ações esperam, guardadas à parte, a primeira janela que ele cobre por inteiro, e o token notifica o saldo do endereço de burn no momento da troca. Até então, uma janela assim, medida só a partir da troca, pagava a mais quem se moveu depois dela. Procedimento: abrir primeiro os ciclos das janelas já fechadas, depois trocar logo após o fim de uma janela; fazer o upgrade do registrador no lugar continua sendo a regra.

O script de lançamento do $STOCKFUN exclui o operador do lançamento do airdrop, cujo primeiro ciclo pagava essa posição até então. Os scripts da bridge param antes de implantar quando a factory já designa outro hub, e mapeiam as ações antes de designar o hub; setBridgeHub recusa um hub que não consegue transportar um basket registrado. Offchain: uma transação cujo recibo não pode ser lido é acompanhada pelo seu hash e nunca é enviada duas vezes; a vigilância de emergência lê os seus eventos em blocos, e alerta uma vez quando falha e uma vez quando se recupera; um mercado cuja entrada no lote não pode ser montada fica de fora, com um alerta. No app, uma transação não confirmada mantém o seu hash (desde o décimo loop de auditoria, ela é acompanhada até o que é minerado no seu nonce, sem que um cancelamento na carteira jamais seja lido como feito: abaixo), e um pool que o modo de encerramento recuperou não mostra nem preço nem negociação.

2026-10-05 — A quarta passada do loop de auditoria: a regra no código

No mesmo dia, o quarto loop levou a regra do fundador ao código. Cada correção tem um teste de regressão, não implantada.

As entregas da bridge nunca bloqueiam outro mercado, a decisão do owner sobre o R2H-2: uma parte que o token da perna de caixa recusa a um vault espelho fica no hub remoto, devida ao seu mercado, e os outros são pagos; no trilho canônico, ela sai da fila, de modo que os registros atrás dela são pagos. Qualquer pessoa a paga depois com sweep. Uma transferência de emergência no hub remoto pode ser imputada a um único mercado, cujas contas são acertadas na mesma chamada. As reivindicações pagam o que podem: uma ação para a qual as contas ficam aquém, ou cuja transferência é recusada, é adiada e continua devida, e claimMany pula um ciclo que exclui quem chama. Cada perna da compra, cada ação de um envio ao airdrop e cada mercado de um lote da bridge vão isoladamente. Um vault que recusa ETH não paralisa mais o seu mercado: o hook guarda o que não conseguiu pagar como devido a esse vault, o lock guarda para o seu destinatário a parte recusada de uma coleta de taxas, e qualquer pessoa os paga; um contrato criador que não pode receber ETH reivindica para outro endereço. A Lens lê um vault de cada vez.

Alavancas em toda parte: um rescue do que um módulo detém por engano em todo módulo que não guarda nada de ninguém, no hook só para o que está extraviado, no lock nunca para as partes que ele guarda, no burner para o seu ETH só quando nenhum burn puder mais gastá-lo, e nos dois tokens; os vaults, os hubs e o contrato do airdrop mantêm o modo de emergência.

Além disso: o router da Ondo só atende os vaults da sua factory (M-7), e todo router recusa a si mesmo como destinatário (L-4); o ticket de depósito do trilho canônico é precificado à taxa base; o script de lançamento do $STOCKFUN coloca o operador na lista antes da cunhagem; a verificação do storage compara cada nível de cada struct. Decidido no mesmo dia: M-2 e R2F-1 ficam como estão. Veja Modo de emergência e Modelo de confiança.

2026-10-05 — A etapa do airdrop no keeper e a tela de reivindicação

Escritas no mesmo dia, a pedido do fundador, sem nenhuma decisão nova; não implantadas. O keeper envia as ações de cada mercado uma vez por janela, depois do pregão americano por padrão: primeiro aloca as ações guardadas à parte, depois abre o ciclo, depois faz o envio, cada ação e cada mercado isoladamente, e acompanha cada entrega da Robinhood Chain até que ela seja creditada, com um alerta que traz o comando para executar de novo uma entrega atrasada. A tela de reivindicação do dapp lista o que uma carteira pode reivindicar, janela por janela, e reivindica até dez janelas por transação, cerca de 3,4 a 3,5 milhões de gas medidos a frio. Ficou de fora: executar automaticamente o último passo de uma entrega que falhou; o alerta dá o comando em vez disso.

A passada offchain do quarto loop deu então ao keeper as suas novas tarefas: pagar as dívidas que o hook e o lock guardam, alertar sobre pernas que falharam, mercados pulados repetidamente e entregas recusadas, planejar cada perna de ação isoladamente, um arquivo de estado entre reinícios e a coleta diária das taxas de LP. O app mostra "Figures unavailable" para um vault que não consegue responder. Veja O keeper e O dapp.

2026-10-05 — A quinta passada do loop de auditoria

No mesmo dia, um quinto loop encontrou sete problemas de baixa gravidade, cada um corrigido com um teste, não implantado. A transferência do hub remoto imputada a um registro canônico serve para um registro cujo depósito já chegou: ela recusa um valor além do caixa não retido para partes recusadas, e um registro cujo depósito se perdeu recebe baixa. Uma ação cujo saldo não pode ser lido não interrompe mais um envio ao airdrop, nem a sua cotação, e um adaptador sem código também não interrompe mais a cotação. Os contratos de implementação da factory e do hub remoto, que guardam o seu admin no storage do proxy, têm o seu deployer como alavanca para o que lhes é enviado. O lock e os dois tokens ganham rescues para claims da v4 e NFTs enviados a eles por engano; o lock continua sem nenhuma chamada genérica. Um lote da bridge deixa de fora um mercado cujo vault ainda não tem código. Um comentário que descrevia errado como uma compra movimenta fundos foi corrigido. Veja Modo de emergência.

2026-10-06 — A passada offchain do quinto loop

A revisão do código offchain no quinto loop encontrou três problemas de média gravidade e dezesseis de baixa gravidade, cada um corrigido no mesmo dia com um teste, não implantado. O keeper agora segue a cadência de 2026-09-27: o ETH de um vault é convertido uma vez por janela do airdrop, se o vault detiver o limiar na primeira passagem do keeper depois que a janela fecha; abaixo dele, o ETH espera a janela seguinte. Até então, o keeper o convertia em qualquer passagem do pregão assim que o vault detinha o limiar. Toda transação que o keeper envia é gravada no seu arquivo de estado, com o seu nonce, antes de o seu recibo ser aguardado, de modo que um keeper interrompido enquanto espera não a envia de novo; uma que nenhum nó conhece mais é abandonada depois de um prazo; um keeper de cada vez usa uma pasta de estado. No trilho da Ondo, uma compra que a Ondo cota abaixo do limite do vault não é mais enviada para falhar, nem paga com uma atestação. Uma ação cujo adaptador não responde fica de fora de um envio ao airdrop sozinha.

Um basket contém no máximo cinco ações, um limite técnico que o owner do StockFun pode mudar com um upgrade: todo custo que cresce com um basket é medido até esse tamanho, e os três baskets do lançamento contêm três, três e duas. A Lens traz o estado de cada vault e o que o hook e o lock lhe devem, e o seu upgrade entra em produção antes do Worker e do app que a leem. O script de lançamento do $STOCKFUN retoma uma execução que parou antes de o mercado do protocolo ser designado, em vez de cunhar um segundo token. O app conta o ETH devido a um vault na sua tesouraria, deixa numa reivindicação espaço para uma ação creditada antes de ser minerada, lembra uma ação que o seu token recusou e nunca mostra como nada um número que não conseguiu ler. Veja O keeper, Baskets e O dapp.

2026-10-06 — O sexto loop de auditoria

O sexto loop encontrou um problema de alta gravidade e cinco de baixa gravidade, cada um corrigido no mesmo dia com um teste, não implantado. Na bridge canônica, usada na testnet e como fallback, o keeper parava de reexecutar os tickets de um lote assim que os seus mercados eram creditados, e um mercado podia ser creditado com o caixa de outro lote, de modo que um depósito que perdeu a sua execução automática podia expirar. O keeper agora acompanha cada ticket até saber que ele foi executado, qualquer que seja o crédito da sua transferência, reexecuta um que ainda esteja vivo e alerta quando não se sabe que um deles foi executado depois de seis horas por padrão, ou quando ele está perdido; ele credita uma transferência canônica só pelos próprios eventos do hub remoto, nunca por um saldo.

Uma decisão veio com as correções, tomada pela auditoria como o seu padrão recomendado: a cadência de 2026-09-27 chega ao USDC. O USDC de um vault, gasto em ações no Ethereum ou enviado pela bridge, sai uma vez depois de cada conversão do seu ETH, e no máximo uma vez por janela nos outros casos; até então, algumas unidades de USDC enviadas a um vault faziam o keeper enviar uma transação, ou um lote inteiro da bridge, a cada passagem. As compras na Robinhood Chain continuam rodando a cada passagem: o saldo de um vault espelho não distingue uma entrega de uma doação, e os tetos de cada compra distribuem de propósito uma entrega grande por várias passagens. As execuções locais e de testnet desligam as duas cadências com o mesmo interruptor.

Também corrigido: uma busca de ações guardadas à parte que não alocaria nada, para um vault sem nada a enviar, não é mais enviada todo dia; um vault abaixo do limiar é verificado com um saldo lido depois que a janela fecha; mais cedo no mesmo dia, o arquivo de implantação local passou a ser verificado contra a chain antes do uso; o app marca o preço do $STOCKFUN como "(last read)" enquanto a Lens não consegue ler a sua tesouraria, e o worker não registra nenhum preço para ele nesse meio-tempo. O loop seguinte, iniciado no mesmo dia, constatou que o keeper cotava todos os vaults num único router, enquanto cada vault mantém o router com que foi criado: cada vault agora é cotado no seu próprio. Veja O keeper.

Desde o sétimo loop, abaixo, "nada a enviar" significa nada que valha a pena enviar, e o keeper lê cada ticket a partir do recibo da sua criação primeiro.

2026-10-06 — O sétimo loop de auditoria

O sétimo loop encontrou um problema de média gravidade e catorze de baixa gravidade, cada um corrigido no mesmo dia com um teste, não implantado; os contratos estavam limpos. Na bridge canônica, o keeper lia se um ticket ainda existia antes de ler o recibo da sua criação: um depósito criado entre as duas leituras, ou visto por dois nós com um bloco de diferença, podia passar por executado enquanto ainda estava vivo, e expirar sem reexecução e sem alerta. Agora ele os lê na ordem em que o SDK da Arbitrum lê: primeiro o recibo, depois a execução automática, depois o ticket num bloco não anterior à sua criação.

Uma decisão veio com as correções, tomada pela auditoria como o seu padrão recomendado: o keeper só envia ao airdrop o que vale o que custa enviá-lo. Uma ação acima da poeira que a bridge da LayerZero não consegue transportar, avaliada com o próprio oráculo do seu vault na última resposta do seu feed de preço, precisa valer a sua própria taxa da LayerZero, ou a sua parte do gas do envio no Ethereum, e as ações que passam precisam valer juntas o envio inteiro mais a abertura do ciclo da janela quando ele ainda não está aberto; caso contrário, elas esperam no vault por uma janela posterior, com o que se acumular. Um valor que o keeper não consegue ler deixa o envio sair, como antes. O múltiplo é um parâmetro do keeper, KEEPER_AIRDROP_MIN_VALUE_BPS: uma vez o custo por padrão, e 0 desliga a regra. Ele só decide quando uma ação sai, nunca quanto, o quê ou para onde. Até então, um presente de ações logo acima da poeira ao vault de um mercado que ninguém negocia fazia o keeper abrir o ciclo dessa janela e pagar uma mensagem da LayerZero todo dia; e a mesma poeira contava como "algo a enviar", então o limite das buscas de ações guardadas à parte do sexto loop não valia na bridge.

Também corrigido: toda busca de logs do keeper para alguns blocos abaixo do bloco mais recente da chain, então um evento nunca é perdido atrás de um nó um ou dois blocos atrasado; o keeper verifica que cada RPC serve a chain que a sua configuração indica, e se recusa a iniciar caso contrário; o seu webhook de alertas tem um limite de tempo e a sua resposta é lida, e um alerta que ele não aceita é guardado e enviado de novo; um parâmetro vazio assume o seu padrão. O Worker de dados do app lê cada contrato upgradável isoladamente, então um que falha depois de um upgrade quebrado não apaga mais os números do token $STOCKFUN; ele mostra o volume de 24 horas como desconhecido enquanto as suas leituras dos logs de trades continuam falhando, verifica que cada um dos seus endpoints serve a sua chain, e o gráfico de preços coloca cada ponto no seu horário. Nem a Lens nem o esquema de dados do Worker mudam. Veja O keeper e O dapp.

Desde o oitavo loop, abaixo, uma ação cuja própria cotação é zero é consultada no seu adaptador, a abertura da janela é contada uma vez no trilho local, o ticket é lido alguns blocos abaixo do mais recente, e o keeper não supõe mais um identificador de chain quando nenhum está definido.

2026-10-06 — Proteções dos feeds de preço na Robinhood Chain

O plano de lançamento listava duas proteções que o oráculo ainda não tinha, ambas recomendadas pela documentação da Robinhood. Elas estão construídas, não implantadas, como parâmetros do owner do StockFun que começam desligados; cada uma só pode reter um preço, nunca mudá-lo.

  • Um evento corporativo. Enquanto uma ação passa por um, o seu token diz que o seu oráculo está pausado, e o seu feed de preço mantém o seu último valor, que ainda pode parecer recente enquanto o multiplicador do token muda. O oráculo agora retém o preço dessa ação: a sua perna de compra falha sozinha, com o seu caixa guardado para ela, e as outras ações do basket são compradas. A verificação está ligada para toda ação do trilho Robinhood, ação por ação, para que um token cuja resposta não pode ser usada, ou cuja flag continua ativa, possa ser desligado sozinho. Um token que não responde conta como não pausado: a Robinhood chama a flag de indicativa, e a própria verificação de defasagem do feed continua sendo a salvaguarda principal.
  • O sequenciador. A Robinhood Chain é uma chain Arbitrum com um único sequenciador. Com o feed de disponibilidade do sequenciador L2 da Chainlink, o oráculo retém todos os preços enquanto o sequenciador está fora do ar, voltou dentro do período de carência (uma hora por padrão), ou o feed não pode ser lido. Não existe nenhum feed assim para a Robinhood Chain, e a Chainlink não os acrescenta mais a novas redes: o trilho é implantado com essa verificação desligada, por uma escolha explícita que o script de implantação exige, e o owner do StockFun define o feed se um dia algum for publicado.

No Ethereum, as duas continuam desligadas. Veja O trilho Robinhood.

2026-10-06 — O oitavo loop de auditoria

O oitavo loop encontrou um problema de média gravidade e oito de baixa gravidade, cada um corrigido no mesmo dia com um teste, não implantado; os contratos e as proteções dos feeds de preço estavam limpos. Antes de o app ter lido o registro de baskets da chain, o seu formulário de lançamento oferecia os baskets configurados com os seus números configurados: numa implantação que numerasse os seus baskets de outra forma, um criador podia lançar um mercado, de forma irreversível, em outro basket que não o mostrado. O formulário agora só oferece os baskets lidos da chain, e lê de novo o escolhido na factory logo antes do envio, que ele recusa se o nome ou as ações diferirem.

Também corrigido: o keeper só acompanha um lote da bridge depois que o bloco que o contém está a alguns blocos de profundidade, então uma reorganização dos blocos mais recentes do Ethereum não pode mais deixá-lo acompanhando identificadores que nunca existem; ele distingue a poeira que a bridge não consegue transportar de uma ação cuja própria taxa da LayerZero não pode ser cotada, que agora ele deixa de fora com um alerta em vez de descartá-la em silêncio; ele guarda um único alerta em espera por alerta distinto, com quantas vezes e quando ele foi emitido, então alertas repetidos a cada ciclo não empurram mais para fora um alerta pontual; ele não deixa mais de lado um arquivo de estado gravado para outra chain antes de verificar qual chain o seu RPC serve, e exige os dois identificadores de chain; ele lê um ticket alguns blocos abaixo do mais recente, que todo nó de um endpoint tem; e no trilho local ele conta a abertura da janela uma vez. O keeper, o seu preflight e o seu inspetor passaram a conhecer as proteções dos feeds de preço: as compras na Robinhood Chain esperam enquanto o oráculo retém os preços por causa do sequenciador, com um alerta, e uma ação em evento corporativo espera sozinha, nunca contada como falha. O Worker de dados do app nunca move a sua janela de trades para trás, então um nó alguns blocos atrasado não faz mais o volume de 24 horas contar blocos duas vezes; o seu proxy RPC recusa qualquer coisa que não seja um endereço; ele publica por que falta o preço de uma ação (esquema de dados 8), o que o app mostra; e o painel de trade cobra de uma carteira da whitelist a taxa normal durante a janela anti-snipe, como o hook faz. A Lens não muda, e o Worker e o app continuam podendo ser implantados em qualquer ordem. Veja O keeper e O dapp.

2026-10-06 — O gas da entrega do airdrop sob a Glamsterdam

A Sepolia ativou a atualização Glamsterdam do Ethereum em 2026-10-06, durante a execução em testnet com a LayerZero (abaixo); a Hoodi e a mainnet ainda não tinham data. Ela reprecifica o crescimento do estado: um novo slot de storage gravado a frio custa 110.020 de gas, contra 22.100 antes. Todo número fixo de gas dos contratos e dos scripts foi medido de novo na Sepolia, e todos se mantêm, exceto um par, o gas que uma entrega do airdrop recebe no Ethereum: o envio do vault espelho levava um único número de compose, 600.000, e o lzReceive do OFT da ação só recebia o que esse OFT impõe. Toda entrega do primeiro ciclo da execução ficou sem gas no executor da LayerZero e foi executada à mão. O décimo loop de auditoria encontrou depois mais dois: o gas próprio dos scripts de implantação e o do compose da bridge para um lote (abaixo).

A decisão do fundador, no mesmo dia: o keeper simula cada entrega e escolhe o seu gas, mantido dentro de limites que o owner do StockFun define no hub remoto; uma entrega ainda presa é executada de novo pelo keeper, e alertada numa segunda falha. No código, não implantado na mainnet:

  • O hub remoto guarda duas políticas de gas, cada uma com um valor padrão, um piso e um teto: o gas do lzReceive além do que o OFT da ação impõe, 650.000 entre 200.000 e 1.500.000 (setAirdropReceiveGas), e o gas do compose, 1.250.000 entre 600.000 e 4.000.000 (setAirdropComposeGas). O sendToAirdrop(stocks, receiveGas, composeGas) do vault espelho envia o que o hub concede para o que o keeper pede, e zero assume o padrão; a chamada só com as ações assume os dois padrões. Um hub que recebeu upgrade de uma versão anterior às políticas recusa todo envio até que as duas sejam definidas
  • O keeper simula o lzReceive e o compose de cada ação no Ethereum, a partir do endereço do endpoint, e pede a necessidade mais 25 %; quando uma simulação não pode rodar, ele usa o que as últimas entregas do mercado usaram, e depois os padrões do hub. Uma entrega que continua armazenada no endpoint, depois que o executor da LayerZero a fez falhar ou depois de dez minutos, é executada de novo a partir da própria chave do keeper, com a sua necessidade simulada mais 25 %, no máximo 4.000.000 de gas por padrão; uma que não pode sair é alertada com o comando para executá-la à mão, e uma segunda falha é alertada e nunca enviada de novo
  • O app reivindica cinco janelas por transação em vez de dez, deixa 400.000 de gas por ação que uma janela ainda pode receber, e acrescentava 150.000 de gas à estimativa de toda escrita, o que o nono loop de auditoria substituiu pelo limite próprio de cada escrita (abaixo)

A correção foi aplicada por upgrade ao hub remoto e ao vault espelho da execução em testnet, e conduziu os seus ciclos posteriores. Veja O keeper e O trilho Robinhood.

2026-10-06 — A execução em testnet com a LayerZero

O protocolo foi implantado na Sepolia e na testnet da Robinhood Chain, pelos scripts de produção ou por wrappers de testnet que mantêm o seu corpo, em 167 transações, todas bem sucedidas, com ações de teste, adaptadores de teste, um USDG de teste e feeds simulados, e rodou das 13:50 às 19:07 UTC: sete janelas horárias, o ETH de cada uma convertido, enviado pela bridge via LayerZero e gasto nas ações de teste; seis ciclos do airdrop enviados de volta via LayerZero, os quatro primeiros reivindicados por inteiro por cinco holders, cada pagamento exatamente a parte calculada a partir do registrador de posições; os exercícios de incidente feitos sobre mensagens reais e recuperados como documentado, exceto duas metades. A execução prova o código do StockFun sobre os endpoints, o DVN e o executor reais da LayerZero. Ela não prova o par USDG da Paxos, as ações da Robinhood e os seus adaptadores, feeds ou liquidez reais, nem o gas, as taxas e a finalidade da mainnet: resta um teste na mainnet. O que ela encontrou no código de produção foi a reprecificação da Glamsterdam (acima) e parte do nono loop de auditoria (abaixo). Veja O trilho Robinhood.

2026-10-06 — O nono loop de auditoria, e o gate de verificação

O nono loop revisou as correções do oitavo, e incorporou os achados do operador da execução em testnet com a LayerZero. Ele encontrou dois problemas de média gravidade, o gas da entrega do airdrop (acima) e o Worker de dados do app, que reconstruía o seu failover de RPC a cada despejo do seu objeto na Cloudflare, o que, durante uma queda do RPC principal, lhe enviava 37 requisições em menos de sete minutos onde agora saem 8; e problemas de baixa gravidade no keeper, no Worker e num script de testnet, cada um corrigido no mesmo dia com um teste. Durante um minuto depois de uma das suas próprias transações, o keeper lê o que ela mudou, e estima o gas do que envia em seguida, no bloco dessa transação, então um nó um bloco atrasado não transforma mais o lote da bridge enviado logo depois de uma conversão numa falsa falha; cada uma das suas transações sai com o seu gas estimado mais 25 %; os alertas que ele não conseguiu entregar saem na ordem em que foram emitidos pela última vez; um ticket que a sua própria reexecução apagou não é mais alertado como vivo; um horário da chain que nenhuma data consegue representar é lido "an unknown time"; ele decodifica os erros do oráculo; e o seu preflight roda sobre a implantação da execução em testnet. O Worker registra o número de bloco próprio da Robinhood Chain.

Desde este loop, um segundo agente revisa a mudança de cada correção antes que ela seja enviada ao repositório, contra as classes de defeito que os loops anteriores encontraram, a maioria delas nas correções do loop anterior: o gate de verificação. O que ele encontra é corrigido como um achado de revisão, e essa correção passa de novo pelo gate. Neste loop, ele encontrou defeitos de baixa gravidade em várias correções, entre elas uma nova execução que acreditava num alerta que qualquer pessoa pode emitir, agora aceito só do executor da LayerZero, e uma que decidia uma execução que falhou no próprio bloco dessa execução, o que uma reorganização do bloco poderia ter transformado numa falsa segunda falha: agora ela espera até que o bloco esteja a alguns blocos de profundidade. Todos estão corrigidos.

A revisão do Worker e do app no mesmo loop encontrou depois mais um problema de média gravidade, os 150.000 de gas que o app acrescentava à estimativa de uma escrita, que ficavam aquém quando um trade encontra mais storage novo do que a marca de supply da hora, corrigido no mesmo dia: toda escrita agora recebe a sua estimativa mais 50.000 de gas, e um trade também o gas de cada escrita que a sua estimativa não consegue ver e que ainda pode acontecer, lido no bloco da estimativa; uma escrita cuja estimativa falha sai com um limite fixo, e um lançamento então espera. Os seus dois achados de baixa gravidade também foram corrigidos: um pote que é uma estimativa é marcado com "+" onde quer que apareça, e uma aprovação que não pode ser lida nunca é tomada por nenhuma. O loop não está limpo, e a contagem de loops limpos continua em zero. Veja O keeper e O dapp.

2026-10-06 — O décimo loop de auditoria

O décimo loop revisou as correções do nono e o trabalho sobre a atualização Glamsterdam do Ethereum, cada área sob um ângulo próprio: os contratos sob os novos preços do gas, cada mensagem cross-chain que falha no seu destino, o keeper ao longo de meses, o app com carteiras reais, e os documentos contra o código. Ele encontrou três problemas de média gravidade e seis de baixa gravidade, cada um corrigido no mesmo dia com um teste, cada correção revisada pelo gate de verificação, não implantado na mainnet. Os contratos saíram limpos no ângulo do gas sob as duas tabelas de preços.

  • O procedimento de implantação sob a Glamsterdam. A implantação documentada no Ethereum não podia ter sucesso: a ferramenta de implantação dava a cada transação o gas da sua própria simulação local, aos preços antigos, quando a criação de um contrato agora precisa de quatro a sete vezes isso. Toda transmissão agora pede ao nó o gas de cada transação depois de minerada a anterior; executado na Sepolia
  • O gas de compose de um lote da bridge. O último passo de um lote da bridge na Robinhood Chain recebia um único número fixo de gas, 1.200.000, qualquer que fosse o conteúdo do lote: quatro novos mercados de cinco ações o esgotaram, o USDG deles ficou então no hub remoto sem nenhum registro, e cada lote seguinte com os mesmos mercados falhava da mesma forma. Agora o gas é uma base mais uma parte por mercado, 200.000 e 400.000 por padrão, ambos parâmetros do owner do StockFun, e um lote leva no máximo 17 mercados, o que mantém a sua mensagem abaixo do limite de tamanho da LayerZero e o seu gas abaixo do limite por transação da Robinhood Chain; o keeper envia no máximo essa quantidade e deixa o resto para a sua próxima passagem, primeiro os mercados que esperam há mais tempo. O gas extra custa pouco: o executor da LayerZero o cobra ao preço do gas da Robinhood Chain, 0,00001 ETH por milhão de gas na testnet. O alerta do keeper para uma transferência parada agora diz onde está a mensagem do lote. O adaptador da testnet recebeu upgrade no mesmo dia e o seu lote seguinte passou com o novo gas
  • A vigilância de emergência. O keeper nomeava todos os vaults vigiados numa única requisição de logs, que um endpoint recusa além do seu limite: uma vez que o registro o tivesse ultrapassado, nenhuma transferência de emergência teria sido retransmitida de novo. Agora ele os nomeia em grupos, limitados por uma nova variável
  • Correções menores. Os textos de erro do keeper mantêm só o host de um endereço de RPC; as suas leituras de cada mercado passam pelo Multicall3, cem mercados por chamada, em vez de uma a uma a cada passagem; o app acompanha uma transação que a carteira cancela ou substitui, sem nunca mostrar um cancelamento como feito, e durante um minuto depois da sua própria transação lê num bloco não anterior ao dessa transação, então uma venda logo depois da sua aprovação não é mais recusada por um nó um bloco atrasado; e dois documentos foram alinhados ao código

Com o seu padrão de enviar depois do pregão americano, o keeper agora só volta a ler um vault sem nada a enviar depois do fechamento no pregão seguinte. Uma consequência dessa economia, e não uma regra nova: uma ação dada a um vault depois do fechamento, fora de qualquer compra, segue com o envio do pregão seguinte, para uma janela posterior; o que as próprias compras do vault trazem continua indo para a janela que terminou naquele dia.

A auditoria também avaliou uma recomendação, não um defeito: reivindicações que deixem um wei em cada um dos acúmulos de taxas do hook, para que o trade seguinte nunca pague para escrever esses slots a partir de zero. Ela não é adotada por enquanto. O gas extra recai sobre o primeiro trade depois de cada reivindicação, cerca de 104.000 por slot, e a margem do app para ele eleva o limite de um trade, não o que ele paga; a mudança tocaria código de reivindicação cujas regras formais não poderiam ser provadas de novo sem uma execução do prover; e o hook e o burner podem adotá-la mais tarde por upgrade, sem migração. O loop não está limpo, e a contagem de loops limpos continua em zero. Veja O keeper, O trilho Robinhood e O dapp.