O keeper
Um worker offchain que, uma vez a cada 24 horas, aciona a conversão de cada tesouraria e, em seguida, o seu airdrop. Ele não decide nada. O seu loop faz uma passagem a cada cinco minutos por padrão e, desde 2026-10-06, ele converte o ETH de um vault uma vez por janela do airdrop, na sua primeira passagem depois que a janela fecha: veja "A cadência de conversão" abaixo. A sua etapa do airdrop está escrita desde 2026-10-05: veja abaixo.
O que ele faz
- Uma vez a cada 24 horas, depois que a janela fecha, às 13:00 UTC por padrão, antes da abertura americana o ano inteiro, identifica os vaults que detêm pelo menos o limiar de conversão, 0,1 ETH por padrão, na sua primeira passagem depois do fechamento; um vault abaixo dele espera então a janela seguinte, mesmo que trades o levem acima do limiar mais tarde naquele dia. As compras do ciclo acontecem durante o pregão seguinte, e os seus envios, por padrão, depois que esse pregão termina. O caixa que um vault ainda detém de um ciclo anterior, USDC ou USDG, segue adiante, atingido ou não o limiar: desde o sexto loop de auditoria, em 2026-10-06, o USDC de um vault uma vez depois de cada uma das suas conversões de ETH e no máximo uma vez por janela nos outros casos, o USDG de um vault espelho a cada passagem (veja "A cadência de conversão")
- Propõe rotas de swap e calcula valores mínimos a partir de uma cotação recente; desde 2026-10-05, os vaults aplicam esses mínimos ao que realmente chega. Desde 2026-10-06, cada vault no Ethereum é cotado no seu próprio router, aquele com que foi criado
- Dimensiona cada etapa, para que o local de negociação consiga executá-la dentro do limite do vault (abaixo)
- Chama a conversão, o lote da bridge e depois a compra na chain remota; desde 2026-10-05,
é o único que pode enviar o lote da bridge (
bridgeReady). No trilho canônico, ele pede a taxa do lote calculada com o dobro da taxa base mais recente (quoteBridgeAt), e o excedente lhe é devolvido. Desde o nono loop de auditoria, ele só recorre à cotação de um hub mais antigo quando o próprio hub responde que não a tem, nunca quando um nó fica em silêncio: um silêncio segura o lote por uma passagem, no trilho canônico, cuja taxa segue a taxa base, com um alerta, e no trilho do USDG só com um aviso. Desde o décimo loop de auditoria, em 2026-10-06, um lote no trilho do USDG leva no máximo o teto de mercados do adaptador, 17 por padrão, que ele lê a cada lote: os mercados que esperam há mais tempo vão primeiro, e os outros mantêm o seu USDC nos seus vaults até a sua próxima passagem, então nenhum espera para sempre (veja O trilho Robinhood). Até então, todo mercado pronto ia no único lote, cujo gas fixo de compose um lote grande podia esgotar - Pré-implanta o vault espelho de cada novo mercado na Robinhood Chain antes do seu
primeiro lote (
predeploy), o que desde 2026-10-05 só ele e o owner do StockFun podem fazer. O hub remoto passa a conhecer o keeper por meio de um lote, então, antes do primeiro, o owner do StockFun pré-implanta o vault do primeiro mercado. O keeper só pré-implanta quando a sua chave na Robinhood Chain é a que o hub remoto conhece como keeper, ou a do seu admin. Um mercado cujo vault o keeper não consegue pré-implantar (antes do primeiro lote, depois de uma mudança de keeper que o hub remoto ainda não conhece, ou quando a pré-implantação falha) fica de fora do lote, com um alerta, e os outros mercados atravessam. Um mercado cujo vault espelho ele não consegue ler naquele dia espera o próximo ciclo, já que um mercado enviado às cegas poderia fazer o lote inteiro falhar - Monitora as entregas: uma transferência que não chegou, um ticket a reexecutar, um vault
espelho ainda não implantado. Uma transferência que ele não conseguiu medir na Robinhood
Chain quando ela partiu só é confirmada pelos próprios eventos do hub remoto, nunca por
um saldo lido depois, e, no trilho canônico, desde 2026-10-06, toda transferência é
confirmada assim: o hub remoto paga os seus registros com um caixa comum, então um saldo
pode crescer com o dinheiro de outro lote. Ele lê esses eventos alguns intervalos de
cada vez, a partir de onde parou a busca de cada transferência; desde o sétimo loop de
auditoria, em 2026-10-06, só até alguns blocos abaixo do mais recente da chain, então um
evento dos blocos mais recentes é lido num ciclo posterior em vez de ser perdido atrás
de um nó um ou dois blocos atrasado. Desde o oitavo loop de auditoria, ele só acompanha
um lote da bridge depois que o bloco que o contém está a essa mesma profundidade em
blocos (
KEEPER_LOG_LAG_BLOCKS), a partir do seu recibo, lido de novo nesse momento: os identificadores de um lote na Robinhood Chain vêm desse bloco, e uma reorganização dos blocos mais recentes do Ethereum que movia o lote deixava o keeper acompanhando identificadores que nunca existem. Desde o décimo loop de auditoria, o seu alerta para uma transferência não creditada a tempo diz, no trilho do USDG, onde está a mensagem do lote no endpoint da Robinhood Chain: ainda não entregue lá; composta, com o crédito em seguida; ou armazenada, com o seu USDG no hub remoto e registrado em lugar nenhum até que alguém execute de novo à mão o último passo com mais gas, e o alerta dá o hash da mensagem armazenada. Até então, ele dava só o que o hub remoto registra, cujo zero se lia como "nada chegou" quando um último passo sem gas suficiente tinha deixado o caixa no hub - Retransmite na hora, para o seu webhook de alertas, toda transferência de emergência que
vê, em cada vault, no hub da bridge, no contrato do airdrop, no hub remoto e em cada
vault espelho. Desde o décimo loop de auditoria, ele nomeia os contratos que vigia em
grupos, uma requisição de logs por grupo, cada uma nomeando no máximo
KEEPER_LOG_MAX_SELECTORSendereços e valores de evento (1.000 por padrão), e só passa de um trecho de blocos depois que cada um dos seus grupos foi lido. Até então, uma única requisição nomeava todos: uma vez que o registro de mercados ultrapassou o que um endpoint aceita (2.000 endereços e valores de evento nos nós da Robinhood Chain, nove endereços no endpoint público da Sepolia), toda requisição era recusada e nenhuma transferência de emergência era mais retransmitida - Desde o décimo loop de auditoria, lê o que cada passagem precisa de cada mercado (o ETH de um vault, o seu USDC e a sua janela, as dívidas, o último airdrop) pelo Multicall3, cem mercados por chamada, no mesmo bloco que cada leitura usava sozinha; uma leitura que não volta é feita sozinha, como antes, nunca tomada por um zero. Até então, todo mercado já criado custava as suas leituras uma a uma a cada passagem, ocioso ou não, e 2.000 mercados ociosos faziam uma passagem durar tanto quanto o intervalo entre duas
- No trilho canônico, desde o sexto loop de auditoria, acompanha os dois tickets de cada
lote até saber que cada um foi executado, qualquer que seja o crédito da sua
transferência, a cada ciclo, haja pregão ou não, e reexecuta um que ainda esteja vivo.
Um ticket que não se sabe executado seis horas depois da partida do seu lote, por padrão
(
KEEPER_TICKET_ALERT_HOURS), é alertado uma única vez, e o mesmo vale para um que sumiu no seu prazo ou depois sem execução vista, ou cuja criação falhou. Até então, o keeper parava de acompanhar os tickets de um lote assim que os seus mercados eram creditados, o que podia deixar expirar um depósito que perdeu a sua execução automática. Desde o sétimo loop de auditoria, ele lê cada ticket na ordem em que o SDK da Arbitrum lê: primeiro o recibo da sua criação, depois a sua execução automática, depois se ele ainda existe num bloco não anterior à sua criação; desde o oitavo loop de auditoria, num bloco alguns abaixo do mais recente (KEEPER_REMOTE_LOG_LAG_BLOCKS), ou no seu bloco de criação quando este é posterior, um bloco que todo nó de um endpoint tem. Um depósito criado entre duas das suas leituras, ou visto por dois nós com um bloco de diferença, nunca é tomado por executado enquanto ainda está vivo - Emite um alerta depois de falhas repetidas num vault, contando separadamente a sua etapa no Ethereum e a sua etapa na Robinhood Chain, para que um vault que falha todos os dias num dos lados seja reportado. Desde o sétimo loop de auditoria, ele espera no máximo dez segundos pelo seu webhook de alertas e lê a sua resposta: um alerta que o webhook não aceita é guardado, cem no máximo, no seu arquivo de estado, e enviado de novo nos ciclos seguintes, então ele chega atrasado em vez de nunca. A mensagem traz os campos que o Slack e o Discord leem, cada um os seus. Desde o oitavo loop de auditoria, uma única entrada é guardada por alerta distinto: um alerta emitido de novo enquanto espera (um vault que falha a cada ciclo) é contado, não guardado duas vezes. A mensagem diz quando o alerta foi emitido pela primeira e pela última vez e quantas vezes, e um alerta entregue atrasado começa dizendo isso. Desde o nono loop de auditoria, os alertas guardados saem na ordem em que foram emitidos pela última vez: um alerta emitido de novo passa para trás dos outros, então o que é dito por último sobre um assunto é o seu estado mais recente (um monitoramento que falha, se recupera e falha de novo enquanto o webhook está fora do ar é entregue como "falhando" por último, onde antes terminava em "recuperado"). Acima de cem, só um alerta emitido a cada ciclo enquanto dura a sua causa (um vault que não consegue converter, o lote da bridge que falha) é descartado primeiro, então um alerta pontual, uma transferência de emergência por exemplo, e a última palavra de cada episódio nunca são empurrados para fora. Desde o décimo loop de auditoria, o texto de um erro, no seu log, nos seus alertas e no seu arquivo de estado, traz só o esquema e o host de um endereço de RPC, nunca o resto dele, onde os provedores põem a chave
- Desde o nono loop de auditoria, durante um minuto depois que uma das suas próprias transações é minerada, lê o que essa transação mudou no seu bloco, nunca no mais recente, e estima ali o gas do que envia em seguida. A execução em testnet mostrou por quê: um lote da bridge enviado logo depois da conversão da mesma passagem era simulado num nó de um endpoint com balanceamento de carga um bloco atrás da conversão, não via nada a passar pela bridge e emitia um falso alerta. Um nó atrás desse bloco agora responde com um erro, e o lote espera uma passagem com um aviso. Toda transação do keeper também sai com a sua estimativa de gas vezes 1,25, desde que a atualização Glamsterdam do Ethereum deixou mais pesadas as chamadas dentro das suas transações
- Desde o nono loop de auditoria, um horário lido de uma chain que nenhuma data consegue representar (o início de um feed, o fim de uma janela, o prazo de um ticket) é lido "an unknown time" em vez de fazer falhar a leitura que o encontrou
- Desde o sétimo loop de auditoria, verifica antes do seu primeiro ciclo que cada RPC serve a chain que a sua configuração indica, e se recusa a iniciar caso contrário. Descoberta depois, uma chain errada para o trabalho nessa chain com um alerta; uma chain cujo identificador não pode ser lido espera, e o trabalho na outra chain continua. Desde o oitavo loop de auditoria, os dois identificadores de chain precisam estar definidos (abaixo), e um arquivo de estado gravado para outra chain fica intocado até que o keeper tenha lido qual chain o seu RPC serve (veja "Reinícios")
- Desde o oitavo loop de auditoria, lê as duas salvaguardas dos feeds de preço do oráculo dos vaults espelho na Robinhood Chain: enquanto o oráculo retém todos os preços por causa do sequenciador, as compras remotas esperam, com um alerta, e uma ação em evento corporativo espera sozinha (veja "Quando o oráculo retém os preços")
- Paga com um sweep o caixa que espera no hub remoto, nos dois trilhos: registros cujos tokens já chegaram, e o que chegou ao hub enquanto ele estava pausado. No trilho do USDG, ele se abstém enquanto o hub remoto aguarda que o owner do StockFun acerte as contas de uma transferência de emergência, o que ele reporta uma única vez, e recomeça quando as contas são acertadas. Desde 2026-10-05, ele também faz o sweep de uma parte que um vault espelho recusou, assim que esse vault volta a aceitar o caixa; no trilho canônico, só envia esse sweep quando ele pagaria alguma coisa
- Aciona o
BuybackBurner, contando o saldo de buyback creditado no hook, que o burner retira antes de comprar - Uma vez por janela, depois do pregão americano por padrão, envia as ações de cada mercado ao contrato do airdrop, sem nunca definir a divisão: veja abaixo
- Desde 2026-10-05, a cada ciclo, qualquer que seja o pregão, paga o que o hook e o lock
de liquidez guardam para um destinatário que o recusou: o que o hook deve ao vault de um
mercado (
payTreasury), e as partes de uma coleta de taxas que o lock guarda para um vault ou um criador (payOwed). Cada pagamento é simulado primeiro e só é enviado quando paga alguma coisa. As duas chamadas são abertas a qualquer pessoa - Desde 2026-10-05, coleta as taxas de LP de um pool criado com uma (
collectFees, aberta a qualquer pessoa), no máximo uma vez por dia por pool. Os pools do StockFun não cobram taxa de LP por padrão, então por padrão não há nada a coletar
A cadência de conversão
O fundador decidiu em 2026-09-27 que o ETH de um vault é convertido uma vez por ciclo diário, logo antes do airdrop, e só se o vault detiver o limiar nessa verificação. O keeper segue essa regra desde 2026-10-06; até então, convertia o ETH de um vault a cada passagem do pregão assim que o vault detinha o limiar.
- A janela. O ciclo é a janela do airdrop: ela fecha quando o contrato do airdrop diz
(24 horas que fecham às 13:00 UTC por padrão), incluindo o mercado
$STOCKFUN; enquanto a factory não designa nenhum contrato do airdrop, nesse horário padrão - Uma verificação por janela. O loop continua fazendo uma passagem a cada cinco minutos por padrão, cada passagem terminando com um relatório do ciclo. O limiar é verificado na primeira passagem que chega ao vault depois que a janela fecha. No limiar ou acima dele, o ETH é convertido, uma única vez: o registro que o próprio vault mantém da sua última conversão de ETH, lido da chain, informa as passagens seguintes, então um reinício não muda nada. Abaixo dele, o ETH espera a janela seguinte, mesmo que trades o levem acima do limiar mais tarde naquele dia; o keeper guarda essa verificação no seu arquivo de estado. Desde 2026-10-06, ele a guarda como o fim da janela para a qual a verificação foi feita, nunca como a hora do seu próprio relógio, que um relógio um pouco desregulado em torno do fechamento podia afastar da janela da chain; uma verificação gravada por um keeper mais antigo não conta, então, na janela da atualização, um vault assim é verificado de novo. Desde o sexto loop de auditoria, a verificação lê o saldo do vault depois do fechamento da janela: uma passagem que começava antes do fechamento e terminava depois registrava o saldo que tinha lido antes dele, e um vault que tinha cruzado o limiar a tempo pulava aquela janela
- Uma conversão que não pode sair na verificação (um feed ETH/USD parado, um local de negociação que não consegue executá-la dentro do limite do vault, uma transação que falhou, uma janela que o keeper não consegue ler) é tentada de novo nas passagens seguintes da mesma janela. Uma janela que ele não consegue ler conta como uma falha da etapa do ETH, alertada depois de falhas repetidas, e o USDC do vault continua se movendo
- O USDC, desde o sexto loop de auditoria. O USDC que já está num vault segue adiante, atingido ou não o limiar, no seu próprio ritmo: a sua compra no Ethereum, ou a sua liberação num lote da bridge, sai uma vez depois de cada uma das conversões de ETH do vault, e no máximo uma vez por janela nos outros casos (uma doação, um reembolso, o que uma etapa que falhou ou foi reduzida à metade deixou). Só conta uma etapa que passou; uma que falha é tentada de novo nas passagens seguintes. A decisão do fundador de 2026-09-27 chega assim ao USDC: até então, algumas unidades de USDC enviadas a um vault antes de cada passagem faziam o keeper enviar uma compra, ou um lote inteiro da bridge com a sua taxa, a cada passagem
- O que sai a cada passagem: as compras na Robinhood Chain. 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. O ETH que uma conversão reduzida à metade deixa (o local de negociação não conseguiu executar o saldo inteiro dentro do limite) espera a janela seguinte
- As execuções locais e de testnet põem
KEEPER_CONVERT_ONCE_PER_WINDOWem false, e então convertem, compram e passam pela bridge a cada passagem; em qualquer outro lugar, ela continua ligada, o seu padrão
No resto desta página, "a cada ciclo" significa a cada passagem do loop, como no relatório do ciclo; só o ciclo diário do airdrop é a janela.
Uma falha de cada vez
Desde 2026-10-05, os contratos deixam uma perna, uma ação, um mercado ou uma entrega falhar sem parar os outros, e reportam o que falhou com um evento. O keeper lê esses eventos e alerta sobre o que persiste; o seu próprio trabalho é dividido da mesma forma.
- Uma perna de compra. A perna de cada ação é planejada isoladamente: uma perna que
não pode ser planejada é pulada, e as outras pernas seguem. Uma perna que o vault
reporta como falha (
LegFailed) mantém o seu caixa reservado para a sua ação; o keeper nunca a conta como convertida, e alerta depois de três falhas seguidas dessa ação nesse vault (KEEPER_ALERT_AFTER_FAILURES). Quando nenhuma perna de um vault pode ser planejada, o vault falha como um todo, como antes - Um mercado de um lote da bridge. Um mercado que o hub da bridge deixa fora de um
lote (
MarketSkipped) mantém o seu USDC no seu vault para um lote posterior. Deixado fora de três lotes seguidos (KEEPER_BRIDGE_ALERT_AFTER_SKIPS), ele é alertado uma única vez, com o motivo decodificado e a sua correção. Desde o décimo loop de auditoria, um mercado que o teto do adaptador deixa fora de um lote espera a passagem seguinte, o que é dito no log, e encabeça esse lote; um lote que o adaptador recusa (acima do seu teto, ou um adaptador que recebeu upgrade sem os seus parâmetros de lote) é alertado com o motivo nomeado e os próprios mercados do lote - Uma entrega recusada. Uma parte que o token da perna de caixa recusou a um vault
espelho (
DeliveryRefused) é alertada uma única vez, com a sua correção, até que o hub remoto não deva mais nada dela a esse mercado - Um vault ilegível. Um vault cujas próprias funções de leitura não respondem, depois
de um upgrade quebrado, por exemplo, fica fora daquele ciclo; os outros vaults
convertem. Ele é alertado uma única vez depois de três ciclos seguidos
(
KEEPER_ALERT_AFTER_FAILURES) - Uma dívida que persiste. Enquanto um vault, ou o hook para a parte de um criador, ainda recusar o ETH que lhe é devido, o keeper alerta uma vez por episódio que o pool aguarda o owner do StockFun (um upgrade que corrija), e registra o fim do episódio assim que a dívida é paga, pelo keeper ou por qualquer outra pessoa
O que só o owner do StockFun pode resolver fica "aguardando o admin": um alerta por episódio, nunca contado como falha, e o resto continua enquanto isso.
O relatório do ciclo passa a incluir as dívidas pagas e as ainda devidas, as pernas que
falharam, os pools cujas taxas de LP foram coletadas e, para a etapa do airdrop, os ciclos
abertos, as buscas de ações guardadas à parte executadas, os vaults que enviaram e as
entregas ainda em trânsito. Desde 2026-10-06, um envio para uma janela sem posições
elegíveis, que o contrato do airdrop guarda à parte, é contado separadamente
(airdropHeldAside), não mais com os vaults que enviaram; no trilho canônico, ele conta
as reexecuções de tickets enviadas (redeemed) e os tickets ainda acompanhados
(ticketsWatched). Desde o sétimo loop de auditoria, ele também conta os mercados cujo
envio ao airdrop espera valer o seu custo (airdropBelowCost) e os alertas guardados para
o webhook (alertsUndelivered), e diz quando o identificador de uma chain ainda não foi
verificado (deferred: chain-unverified).
Quando o oráculo retém os preços
Desde 2026-10-06, o oráculo dos vaults espelho pode reter um preço (veja O trilho Robinhood), e desde o oitavo loop de auditoria o keeper o lê antes de cotar qualquer coisa:
- O sequenciador. Uma vez por ciclo, ele pergunta ao oráculo o que diz a sua verificação do sequenciador. Enquanto o sequenciador está fora do ar, voltou há não mais que o período de carência, ou o seu feed de disponibilidade não pode ser lido, nenhuma ação pode ser precificada: a compra do vault espera, nada é cotado e nada conta como falha. Um alerta abre o episódio, guardado no arquivo de estado para que um reinício não o emita de novo, e outro diz quando as compras são retomadas. A verificação está desligada na Robinhood Chain até que a Chainlink publique um feed de disponibilidade para ela, então hoje nada disso pode acontecer
- Um evento corporativo. Uma ação cujo token pausa o seu oráculo fica fora da compra desde o início, dito no log, com o seu USDG guardado para ela; ela nunca conta para o alerta de falhas, e as outras ações do basket são compradas. Uma perna que o vault reporta como falha por esse motivo, entre o plano do keeper e a sua compra, é esperada e também não é contada
- O motivo, dito. Quando o limite de uma perna não pode ser lido porque uma
salvaguarda retém o seu preço, o keeper registra o motivo no log, em qualquer uma das
chains, em vez de um vault que não consegue precificar a perna. Uma salvaguarda que ele
não consegue ler (um oráculo de antes das salvaguardas) não retém nada: o próprio limite
de cada perna decide, como antes. Desde o nono loop de auditoria, os outros erros do
oráculo também são decodificados: um feed parado aparece como
StalePriceno log e no motivo de uma perna que falhou, onde antes aparecia um código não decodificado
A etapa do airdrop
O lado do contrato está codificado desde 2026-10-04, e a etapa do keeper desde 2026-10-05.
A cada ciclo, antes de verificar o pregão, o keeper primeiro acompanha as entregas já
enviadas. Depois, enquanto a factory designar um contrato do airdrop, ele passa por cada
mercado, um de cada vez, incluindo o mercado $STOCKFUN:
- Uma vez por janela. Um vault está concluído para a janela quando o seu último envio
(
lastAirdropAt) é igual ou posterior ao fim da janela em que um envio cairia agora (currentCycleEnd). Os dois são lidos da chain, então um reinício não muda nada. Por padrão, o keeper só envia depois que o pregão americano do dia termina, para que as compras do dia vão num único envio, para a janela que terminou naquele dia, e só quando o vault detém ações; desde o sétimo loop de auditoria, só as ações que valem o que custa enviá-las (abaixo). Desde o décimo loop de auditoria, com esse padrão, um vault lido depois do fechamento sem nada a enviar só é lido de novo quando o pregão seguinte abre, ou quando a janela avança, nos trilhos cujas compras seguem o pregão de Nova York (não o da Ondo): o que ele detém vem das suas compras, feitas em pregão. Não enquanto uma compra sua ainda aguarda o seu recibo, que pode chegar durante a noite: esse vault é lido a cada passagem, e o que a compra traz vai para a janela que terminou naquele dia - Primeiro as ações guardadas à parte, mesmo sem nada a enviar. Se o mercado guarda
ações à parte,
assignUnassigned, no máximo cinco chamadas por ciclo, até que elas sejam alocadas, o que abre o ciclo da janela que as recebe, ou não reste nenhuma janela encerrada a verificar. Desde 2026-10-06, o keeper faz essa busca tenha o vault algo a enviar ou não, e esteja o vault pausado ou não: até então ela só rodava antes de um envio, então um mercado que teve um trade e depois ficou parado mantinha o seu primeiro airdrop, guardado à parte, fora do alcance dos seus holders até um novo trade ou até alguém fazer a busca à mão. Uma busca não terminada adia para o ciclo seguinte um envio para uma janela sem posições elegíveis. Desde o sexto loop de auditoria, enquanto o vault não tem nada a enviar, uma busca que não alocaria nada (nenhuma janela pode receber as ações ainda) só é enviada quando a busca do mercado estámaxWindowsPerAssignjanelas atrás da janela mais recente, 30 por padrão: uma busca por mês em vez de uma por dia para sempre. Uma busca que aloca as ações sempre sai. Desde o sétimo loop de auditoria, "nada a enviar" significa nada que valha a pena enviar, pela mesma regra do envio: no trilho da bridge, a poeira que o OFT não consegue transportar, que todo envio deixa no vault espelho, não conta para nada, e o limite vale lá também - O ciclo, só antes de um envio.
openCycle, para que cada entrega só acrescente a ele; nunca para uma janela à qual nada é enviado, e desde o sétimo loop de auditoria só para um envio que valha o seu custo, incluída a abertura. Uma janela sem posições elegíveis não é um erro: as ações ficam então guardadas à parte - O envio. No trilho local,
sendToAirdropnoTreasuryVaultdo mercado. No trilho da bridge,sendToAirdropno vault espelho, pagando a sua taxa da LayerZero cotada (quoteSendToAirdrop) mais uma margem, 10 % por padrão; o vault devolve o excedente. Desde o nono loop de auditoria, o envio e cada cotação dele trazem o gas que as suas entregas recebem no Ethereum, que o keeper escolhe (abaixo). Antes desse envio, o keeper verifica que o hub remoto envia ao contrato do airdrop da factory, que cada ação tem um adaptador e que esse adaptador responde, e que o OFT da ação no Ethereum está registrado no contrato do airdrop. Desde o sétimo loop de auditoria, o envio só lista as ações que valem o seu custo, com a sua taxa cotada de novo para elas - As entregas. No trilho da bridge, a entrega de cada ação é acompanhada até que o endpoint da LayerZero no Ethereum tenha executado o seu último passo, que credita o contrato do airdrop. Desde o nono loop de auditoria, uma entrega presa nesse endpoint é executada de novo pelo próprio keeper (abaixo). Uma entrega não creditada em 60 minutos por padrão gera um alerta, que traz os comandos que executam os seus passos à mão; qualquer pessoa pode executá-los
Cada ação vai isoladamente: uma ação cujo saldo não pode ser lido (um congelamento do
emissor), uma sem adaptador ou cujo OFT não está registrado, uma cujo adaptador não
responde (peers(): nenhum contrato no seu endereço, ou não é um app da LayerZero; desde
2026-10-06, até então ela fazia falhar o envio inteiro do mercado), desde o oitavo loop de
auditoria uma cuja taxa da LayerZero o seu adaptador não consegue cotar (abaixo), e uma
que o vault reporta não ter conseguido enviar (AirdropSendFailed) ficam de fora, com um
alerta, e as
outras vão. Cada mercado também vai isoladamente: um que continua falhando é alertado uma
única vez depois de três falhas seguidas, e o mercado seguinte continua. Desde 2026-10-06,
uma busca de ações guardadas à parte que continua falhando tem um alerta próprio, que dá a
sua correção: qualquer pessoa pode chamar assignUnassigned para esse mercado.
"Aguardando o admin", aqui, cobre um contrato do airdrop pausado, uma ação que falta ao contrato do airdrop depois de uma transferência de emergência (essa ação espera nos vaults, as outras vão), um hub remoto que envia a outro contrato do airdrop que não o da factory e, desde o nono loop de auditoria, um hub remoto cujos limites de gas das entregas não estão definidos, ou cujo teto está abaixo do que uma entrega precisa.
O que vale a pena enviar
Desde o sétimo loop de auditoria, em 2026-10-06, o keeper só envia o que vale o que custa enviá-lo. Até então, qualquer ação acima de zero ia: um presente 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, ou um envio no Ethereum, todo dia.
- O que um envio leva. Uma ação cujo saldo pode ser lido e está acima de zero; no trilho da bridge, ela também precisa ter um adaptador e uma cotação própria acima de zero. A cotação do vault é zero tanto para a poeira que o OFT não consegue transportar quanto para uma ação cujo adaptador não consegue cotar o seu envio, então, desde o oitavo loop de auditoria, o keeper pergunta ao próprio adaptador da ação, sobre o envio que o vault montaria: a poeira nunca é enviada nem alertada; uma ação cuja cotação falha, cujo próprio envio falharia, fica de fora com um alerta que diz por quê; e uma ação que o keeper não consegue consultar vai como antes, e o seu envio decide. Até então, uma ação assim era tomada por poeira e retirada de todo envio sem uma palavra
- O seu valor. Cada ação é avaliada com o próprio oráculo do seu vault, na última resposta do seu feed de preço, parado ou não, já que isto é uma estimativa e nunca um limite; os custos, pagos em ETH, são convertidos em dólares com o feed ETH/USD do mesmo oráculo
- O seu próprio custo. Cada ação precisa valer pelo menos o seu próprio custo: a sua taxa da LayerZero no trilho da bridge, onde cada ação é uma mensagem própria, ou a sua parte do gas do envio no trilho local. Um presente que não vale a sua própria mensagem nunca vai de carona num envio real
- O envio inteiro. As ações que passam precisam valer juntas o envio inteiro, mais a
abertura da janela (
openCycle) quando o seu ciclo ainda não está aberto. No trilho local, desde o oitavo loop de auditoria, a abertura é contada uma vez: a própria estimativa do envio, feita com o ciclo fechado, já a inclui, então só o custo base da transação de abertura é somado; contada duas vezes, ela segurava por dias um envio que valia um pouco mais do que custava. Caso contrário, nenhuma vai, e o ciclo não é aberto - O que espera. O que não vai fica no vault e vai numa janela posterior, com o que se acumular. Um mercado cujo envio espera é contado no relatório do ciclo e registrado no log uma vez por janela
- O que não pode ser lido. Um preço, uma taxa ou um custo de gas que o keeper não consegue ler deixa o envio sair, como antes da regra: uma leitura que falha nunca segura um envio real
KEEPER_AIRDROP_MIN_VALUE_BPS define o múltiplo: 10.000, uma vez o custo, por padrão,
então um envio que vale pelo menos o que custa sai, qualquer que seja o seu tamanho acima
disso; um valor mais alto segura envios menores até que eles valham esse múltiplo, e 0
envia o que quer que seja levado. A mesma regra decide se um vault tem algo a enviar para
a busca de ações guardadas à parte acima. A auditoria a adotou como o seu padrão
recomendado; ela só decide quando uma ação sai, nunca quanto, o quê ou para onde.
O gas da entrega no Ethereum
Em 2026-10-06, a Sepolia ativou a atualização Glamsterdam do Ethereum, que faz um novo slot de storage custar cerca de cinco vezes o seu gas anterior, e toda entrega do airdrop do primeiro ciclo da execução em testnet com a LayerZero ficou sem gas no executor da LayerZero: um envio pagava só o gas do último passo da entrega, e o gas do seu primeiro passo era o que o owner do adaptador LayerZero da ação impõe (o emissor, na mainnet). Desde o nono loop de auditoria, por decisão do fundador do mesmo dia:
- O keeper simula cada entrega no Ethereum antes do envio: o contrato do token da ação recebendo-a, e o contrato do airdrop creditando-a, da forma como a entrega os encontrará. Ele pede a necessidade da ação mais pesada vezes 1,25, menos o gas que o adaptador LayerZero da ação já impõe para o primeiro passo
- Quando uma simulação não pode rodar, ele usa o que as últimas entregas do mercado usaram no Ethereum, e depois os padrões do hub remoto
- O hub remoto o limita. O owner do StockFun define um padrão, um piso e um teto para cada um dos dois passos (veja O trilho Robinhood); o que quer que o keeper peça é mantido entre eles. Um pedido que o teto corta abaixo da necessidade de uma entrega fica "aguardando o admin": o envio sai mesmo assim, e uma entrega que fica presa é executada de novo (seção seguinte)
- Nada muda para os holders. O keeper só decide o gas que uma entrega recebe, nunca quanto é enviado, para onde ou para quem
- Escolhido de novo só quando preciso. Um par de gas escolhido a partir da simulação de cada ação é mantido para a janela enquanto as ações, o estado do ciclo da janela e a possibilidade de uma entrega chegar depois do fim da janela seguinte continuam os mesmos; um que uma simulação não pôde dar é escolhido de novo a cada passagem. Desde o décimo loop de auditoria, um envio que leva só a poeira que a bridge não consegue levar não lê nada do ambiente da entrega, e um par simulado depois que o ciclo da janela abriu, um estado que nunca volta atrás, é reutilizado sem lê-lo de novo
Uma entrega presa no Ethereum
Uma entrega sem gas suficiente não perde nada: ela fica no endpoint da LayerZero no Ethereum, com o seu primeiro passo verificado e não executado, ou o seu último passo armazenado e não executado, até que alguém a execute de novo com mais gas. Desde o nono loop de auditoria, o próprio keeper faz isso:
- Ele lê o passo de cada entrega no endpoint a cada ciclo. Quando a vez do executor
termina (a sua falha, aceita só vinda do próprio executor da LayerZero, ou dez
minutos), ele executa de novo o passo preso a partir da sua chave no Ethereum, com a
necessidade simulada vezes 1,25, e nunca mais do que
KEEPER_AIRDROP_REEXECUTION_MAX_GAS, 4.000.000 por padrão - Uma que ele não consegue enviar (a sua simulação falha, a sua necessidade está acima do limite, falta ETH à sua chave) é alertada uma única vez, com o comando para executá-la à mão, e tentada de novo a cada ciclo
- Uma que falha de novo na chain, com o passo ainda preso, é a segunda falha: alertada,
com o comando, e nunca mais enviada pelo keeper. Ele só decide isso com uma leitura do
passo que responde, e só depois que o bloco da execução que falhou está a alguns blocos
de profundidade (
KEEPER_LOG_LAG_BLOCKS), então nem um nó um bloco atrasado nem uma reorganização desse bloco podem fazê-lo desistir - A chave do keeper no Ethereum paga essas execuções: sob a Glamsterdam, um último passo que abre um ciclo precisa de cerca de um milhão de gas
O keeper escolhe quando, e o gas de uma entrega dentro dos limites do owner, nada mais. Um envio que chega depois do horário de fechamento seguinte é medido na janela do dia seguinte.
Sete variáveis conduzem a etapa: KEEPER_AIRDROP (ligada por padrão),
KEEPER_AIRDROP_AFTER_SESSION (ligada por padrão; desligada numa testnet que ignora o
pregão), KEEPER_AIRDROP_FEE_MARGIN_BPS (1.000), KEEPER_AIRDROP_TRANSIT_MINUTES (60),
desde o sétimo loop de auditoria KEEPER_AIRDROP_MIN_VALUE_BPS (10.000), e desde o nono
KEEPER_AIRDROP_REEXECUTION_MAX_GAS (4.000.000) e KEEPER_AIRDROP_LZ_EXECUTOR (vazia: o
executor da LayerZero na chain do keeper, o único chamador cujos alertas de falha o
keeper aceita).
Reinícios: o arquivo de estado
Desde 2026-10-05, o keeper grava o que acompanha de um ciclo para o outro num arquivo de
estado (KEEPER_STATE_DIR): as entregas do airdrop e as transferências da bridge em
trânsito, as transações que aguardam um recibo, os seus episódios de alerta e as suas
sequências de falhas; desde o sexto loop de auditoria, também os tickets do trilho
canônico que ele acompanha, onde parou a busca de cada transferência e quando o USDC de
cada vault saiu pela última vez; desde o sétimo, os alertas que o seu webhook ainda não
aceitou. Um arquivo gravado por um keeper mais antigo é carregado
como está. Ele grava o arquivo depois de cada ciclo e de cada envio, e o lê uma única vez
na partida. Um reinício não esquece nada disso: uma entrega cujo último passo falha depois
de um reinício continua sendo alertada, uma transação enviada antes dele nunca é enviada
de novo, e um episódio já alertado não é alertado duas vezes. Um arquivo gravado para
outra factory é deixado de lado, e o keeper começa vazio, com um aviso. Desde o oitavo
loop de auditoria, um arquivo gravado para outra chain é primeiro deixado como está, nem
lido nem sobrescrito, até que o keeper tenha lido qual chain o seu RPC serve: se ele serve
a chain configurada, o arquivo era de outra chain e é deixado de lado nesse momento; se
não, o erro está no identificador configurado, o keeper se recusa a iniciar e, depois de
corrigido, o keeper retoma o seu arquivo, incluídos os depósitos que acompanhava. Até
então, um identificador digitado errado custava o arquivo antes de o keeper se recusar a
iniciar. Os alertas guardados são um por alerta distinto desde o mesmo loop; um arquivo
gravado por um keeper mais antigo é carregado como está. Desde o nono loop de auditoria,
o arquivo também guarda o pacote de cada entrega do airdrop e as suas execuções pelo
keeper, o gas que as últimas entregas do mercado usaram e a última reexecução que o
keeper fez de cada ticket canônico; um arquivo gravado por um keeper mais antigo continua
sendo carregado como está.
Desde 2026-10-06:
- Cada envio está em disco antes da sua espera. Toda transação sai com o nonce que a chain dá ao endereço do keeper logo antes dela, e é gravada no arquivo de estado, com o seu hash e o seu nonce, assim que o hash volta, antes de o seu recibo ser aguardado: um keeper interrompido enquanto espera a recupera pelo hash no reinício em vez de enviá-la de novo
- Uma transação perdida é abandonada. Uma que nenhum nó conhece mais quatro vezes
KEEPER_RECEIPT_ALERT_MSdepois do seu envio (duas horas por padrão) é descartada com um alerta, para que não segure mais os envios do seu tipo; o seu nonce continua livre, e a próxima transação do keeper o ocupa. O alerta de uma transação ainda não minerada diz como substituí-la - Gravado por inteiro. Um disco cheio demais para receber o arquivo é um erro, alertado, e o último arquivo bom permanece; até então, uma cópia truncada podia substituí-lo
- Um keeper por pasta. O keeper pega uma trava na sua pasta de estado (
keeper.lock): um segundo keeper na mesma pasta se recusa a iniciar e nomeia o primeiro. Uma trava cujo keeper sumiu é assumida; uma deixada por um keeper em outro host não é, e o operador a apaga quando esse keeper não roda mais. Um dry run não pega nenhuma trava
O dimensionamento de cada etapa
Desde 2026-10-01, o vault converte o valor que o keeper indica, não o seu saldo inteiro. O keeper o dimensiona:
| Etapa | Valor |
|---|---|
| ETH → USDC | O saldo inteiro, reduzido à metade enquanto a cotação ficar aquém do limite do vault, nunca abaixo do limiar de conversão; desde 2026-10-06, o resto espera a janela seguinte |
| Uma ação em pools do Uniswap no Ethereum | A reserva da ação, reduzida à metade no máximo quatro vezes; uma perna que ainda fique aquém espera o próximo ciclo, com a sua reserva intacta |
| Uma ação no trilho opcional da Ondo | A reserva da ação, com teto no limite nocional da sessão. Desde 2026-10-06, uma perna que a Ondo cota abaixo do limite do vault nunca é enviada: a cotação gratuita é lida antes de qualquer atestação e, assim que uma atestação volta abaixo do limite, nenhuma outra é pedida para essa ação até a janela seguinte |
| Uma ação na Robinhood Chain | A reserva da ação, limitada separadamente por um teto fixo e, quando o seu pool pode ser medido, por uma fração da profundidade desse pool |
O que não é gasto espera no vault o próximo ciclo (para o ETH, a janela seguinte); o caixa de uma ação continua reservado para essa ação.
Desde o pipeline de segurança de 2026-10-01, cada compra retém n−1 unidades na última ação do basket, sendo n o número de ações, em todo trilho que compra ações. Os vaults dão o resto do arredondamento dos pesos à última ação, então algumas unidades de caixa que cheguem entre a leitura do keeper e a sua transação podem baixar essa única reserva em até n−2 unidades; gastar o valor lido faria a chamada inteira reverter, e qualquer pessoa poderia provocar isso com uma transferência de poeira. O que é retido continua reservado para a próxima chamada. Qualquer outro chamador dos vaults deve manter a mesma margem. Uma correção nos contratos, que muda a regra de alocação documentada, aguarda a decisão do owner. Desde 2026-10-06, um vault que só detém essas poucas unidades de USDC (quatro no máximo, já que um basket contém no máximo cinco ações) não é mais visitado por causa delas: elas esperam o próximo USDC que o seu ETH trouxer.
O burn de $STOCKFUN é dimensionado da mesma forma: uma fatia cujo impacto de preço
ultrapassa o teto do keeper é reduzida à metade, nunca abaixo do limiar do keeper, e o
resto é queimado nos ciclos posteriores. Desde o pipeline de segurança de 2026-10-01, uma
fatia que o pool do $STOCKFUN não consegue executar por inteiro também é reduzida à
metade; antes, o burn falhava naquele ciclo. Em qualquer outra falha, não há nova
tentativa.
O que ele não pode fazer
Escolher um ativo fora do basket. Mover o caixa reservado de uma ação para outra ação. Afrouxar um limite de oráculo. Enviar um ativo para qualquer lugar além de onde o contrato o envia. Sacar qualquer coisa. Escolher quem recebe um airdrop ou quanto ele leva, ou atribuir uma parte a si mesmo.
O seu acionamento é reservado para impedir ataques sandwich, não porque se confie no keeper: toda chamada que ele faz é executada dentro dos limites dos vaults.
O ciclo
calendário da NYSE} C -->|não| W[Aguardar] C -->|sim| P{Contrato pausado?} P -->|sim| W P -->|não| A{Primeira verificação do vault
nesta janela: ≥ 0,1 ETH?} A -->|não, o ETH espera
a janela seguinte| N[Próximo mercado] A -->|sim| E[ETH → USDC, limite de 50 bps] E --> B[USDC → USDG → bridge] B --> R{Chegou na chain remota?} R -->|não| M[Monitorar, reexecutar o ticket] R -->|sim| K[Comprar as ações, limite de 200 bps] K --> AD[Enviar ao contrato do airdrop] AD --> N
O horário, o limiar e os limites do diagrama são os parâmetros padrão. O keeper faz uma passagem a cada cinco minutos; o ETH de um vault é verificado uma vez por janela, na sua primeira passagem depois do fechamento, enquanto o USDC que ele já detém segue adiante uma vez depois de cada conversão e no máximo uma vez por janela nos outros casos. O envio ao contrato do airdrop roda uma vez por janela, depois do pregão por padrão; as dívidas, as taxas de LP, as entregas e, desde o sexto loop de auditoria, os tickets do trilho canônico são tratados a cada ciclo, qualquer que seja o pregão.
A configuração
Tudo passa por variáveis de ambiente: RPCs das duas chains, a chave privada do keeper, os
endereços dos contratos, o intervalo e as alavancas de segurança — dry run, execução
única, exigir mercado aberto. Desde 2026-10-05, também: as variáveis da etapa do
airdrop, acima; a coleta das taxas de LP, KEEPER_COLLECT_FEES (ligada por padrão),
KEEPER_COLLECT_FEES_HOURS (24) e KEEPER_COLLECT_FEES_MIN_WEI (0); o alerta depois de
omissões repetidas, KEEPER_BRIDGE_ALERT_AFTER_SKIPS (3); e a pasta do arquivo de estado,
KEEPER_STATE_DIR. Desde 2026-10-06, KEEPER_CONVERT_ONCE_PER_WINDOW (ligada por
padrão): o ETH de um vault é convertido uma vez por janela e, desde o sexto loop de
auditoria, o seu USDC sai uma vez depois de cada conversão e no máximo uma vez por janela
nos outros casos; uma execução local ou de testnet a desliga e converte, compra e passa
pela bridge a cada passagem. Desde o sexto loop de auditoria, também
KEEPER_TICKET_ALERT_HOURS (6): no trilho canônico, as horas depois das quais um ticket
que não se sabe executado é alertado. KEEPER_STOCK_ROUTER, o router que a factory
designa para os novos vaults, só escolhe qual pregão de mercado condiciona um ciclo; cada
vault é cotado no seu próprio router.
Desde o sétimo loop de auditoria, os identificadores de chain, KEEPER_CHAIN_ID e
KEEPER_REMOTE_CHAIN_ID, são verificados contra os RPCs antes do primeiro ciclo: 1 com
4663 na mainnet, 11155111 com 46630 na testnet. Desde o oitavo loop de auditoria, os dois
precisam estar definidos: KEEPER_CHAIN_ID sempre, KEEPER_REMOTE_CHAIN_ID com a bridge,
e o keeper se recusa a iniciar sem eles (até então, omitidos, KEEPER_CHAIN_ID era lido
como 11155111 e KEEPER_REMOTE_CHAIN_ID como 4663). Desde o décimo loop de auditoria,
KEEPER_LOG_MAX_SELECTORS (1.000 por padrão, no mínimo 5) limita os endereços e
valores de evento que uma requisição de logs nomeia, contados como os nós da Robinhood
Chain os contam; atrás do endpoint público da Sepolia, que recusa dez endereços ou
mais, ela é definida como 10. Duas variáveis dizem quantos blocos
abaixo do mais recente as suas buscas de logs param: KEEPER_LOG_LAG_BLOCKS (2, no
Ethereum) e KEEPER_REMOTE_LOG_LAG_BLOCKS (12, na Robinhood Chain); desde o oitavo loop
de auditoria, a primeira também é a profundidade que o bloco de um lote da bridge precisa
ter antes que o keeper o acompanhe, e a segunda, quantos blocos abaixo do mais recente um
ticket é lido. As salvaguardas do oráculo não precisam de nenhuma variável: o keeper as lê
no oráculo de cada vault espelho. Uma variável de número inteiro deixada vazia assume o
seu padrão, e uma fora do seu intervalo para o keeper na partida.
A chave do keeper é uma chave quente, com fundos só para o gas, e distinta da do deployer.
Os seus limites
- No trilho do USDG, uma entrega que o token da perna de caixa recusou antes de o keeper iniciar, ou enquanto ele estava parado, aparece só como um aviso quando ele faz o sweep; o trilho canônico encontra uma parte assim no próprio estado do hub remoto
- Até o nono loop de auditoria, o keeper não executava ele mesmo o último passo de uma
entrega que falhou (
lzCompose); desde então, ele executa de novo um passo preso, com um limite, e uma segunda falha é deixada para uma pessoa, com o comando - A vigilância de emergência não guarda a sua posição entre reinícios: os eventos emitidos enquanto o keeper estava parado não são varridos
- Um keeper interrompido nos poucos milissegundos entre um envio e a sua gravação no arquivo de estado pode enviar essa transação mais uma vez no seu reinício; as próprias verificações dos contratos fazem a maioria dessas repetições falhar, ao custo do seu gas
- A busca de uma transferência pela sua chegada nunca lê um bloco duas vezes: uma reorganização que move uma chegada para um bloco já lido deixa essa transferência para o alerta de trânsito. Desde o sétimo loop de auditoria, toda busca de logs para alguns blocos abaixo do mais recente, o que atrasa um crédito, e o seu alerta de trânsito, nesses poucos blocos
- Desde o oitavo loop de auditoria, um lote da bridge é acompanhado depois que o seu bloco está a alguns blocos de profundidade, um ciclo mais tarde do que antes, e o lote seguinte espera por ele; uma reorganização mais profunda do que isso não é coberta, como nas buscas de logs. Um ticket executado nos últimos poucos blocos ainda aparece vivo ali até que o bloco mais recente esteja essa mesma quantidade de blocos além da sua execução: o ciclo seguinte numa chain movimentada, mais ciclos numa chain tranquila. Desde o nono loop de auditoria, um que a própria reexecução do keeper apagou não é nem reexecutado de novo nem alertado nesse meio-tempo, depois de um reinício também; um reexecutado por outra pessoa nesses blocos é tentado de novo, falha na simulação, e ainda pode ser alertado como vivo passadas as horas do alerta
- O minuto durante o qual o keeper lê no bloco da sua própria última transação não cobre um nó mais de um minuto atrás dos seus pares
- No trilho local, a abertura da janela é contada uma vez, sem o que a segunda transação repete (cerca de 5 % do custo): um envio pode sair valendo até esse tanto a menos do que custa
- Desde o décimo loop de auditoria, 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 keeper só volta a ler um vault sem nada a enviar no pregão seguinte. Uma compra cujo recibo o keeper leu na última passagem do pregão também poderia ser lida vazia na primeira passagem depois do fechamento a partir de um nó atrasado em relação a essa leitura, o que exige um intervalo entre passagens mais curto do que o atraso desse nó (cerca de cinco segundos na Sepolia), nunca os cinco minutos padrão
O preflight
Antes de qualquer execução real, um comando de preflight verifica, sem escrever uma única transação, que as redes respondem, que os endereços têm código, que os peers da LayerZero do OFT do USDG batem, que o USDG não está pausado pelo seu emissor, a Paxos, e que os pesos dos baskets são os que deveriam ser.
Desde o oitavo loop de auditoria, ele também verifica as salvaguardas do oráculo. O seu
manifesto precisa dizer como a verificação do sequenciador está configurada, de um jeito
ou de outro: nenhum feed de disponibilidade e nenhum período de carência (a verificação
desligada, como hoje), ou um feed com um período de carência. Ele lê esse feed quando há
um, e a pausa do oráculo do token de cada ação: um token em evento corporativo é um
aviso, que não faz a verificação falhar; um token sem o sinal falha. Depois da
implantação, ele verifica que o oráculo implantado corresponde ao manifesto, que o estado
do seu sequenciador deixa os preços passarem e que a verificação de pausa de cada ação
está ligada. O comando inspect do keeper imprime as mesmas salvaguardas: a verificação
do sequenciador e o seu estado, e a verificação de pausa de cada ação e se o seu token
está pausado agora.
Desde o nono loop de auditoria, ele também roda sobre a implantação da execução em testnet com a LayerZero (Sepolia e a testnet da Robinhood Chain), a partir dos dois arquivos dessa execução, com RPCs nomeados para esse par, então um RPC da mainnet nunca é consultado sobre a testnet; qualquer outro par de chains, uma mistura incluída, é recusado. Na testnet, ele não lê nenhum router v3 do Uniswap, que essa chain não tem, e verifica o feed ETH/USD contra o heartbeat que o oráculo da execução recebeu. Nos dois pares, ele verifica que o router remoto designa o router v3 que o manifesto diz. Executado sobre a implantação de testnet: 68 verificações, todas passando.
Ele se recusa a rodar sem RPCs em vez de reportar um falso sucesso.