Skip to content

Repository files navigation

shellr-keeper

Keeps the seed queue full. Reveals every pack. Does nothing else.

Node viem Deploy

Two jobs, both dull on purpose.

1. Keep the seed queue full. A keccak256(secret) commitment has to be on chain before the pack that consumes it is bought. That is the entire fairness argument, so the service tops the queue up whenever it drops below SEED_FLOOR, and buy reverts rather than borrowing against an empty queue.

2. Reveal every pack. It recomputes the draw from the secret, quotes each swap through the Uniswap quoter, and sends reveal with a per-coin minimum. A stale quote reverts the whole reveal; it requotes on the next pass.

It cannot steal a pack. It can only reveal the committed seed or fail to, and failing to hands the buyer their refund once revealWindow has passed.


Running it

npm install
cp .env.example .env    # fill it in
npm run check           # the keeper's draw vs the contract's. Must pass.
npm start

npm run check needs no chain and no keys. Run it first, every time. It is the cheapest way to find out that src/draw.js and ShellrPacks.sol have drifted, and the alternative way to find out is every reveal reverting on mainnet.

The draw is mirrored, and that is a liability

src/draw.js is a line-for-line mirror of ShellrPacks._count, _pick and _payout. The keeper has to know exactly which coins a pack will land on before it sends the reveal, because it quotes each swap and passes the minimums in.

If this file and the contract ever disagree, the reveal reverts on the first slippage check and every pack stalls until its refund window. Loudly, at least - which is why the minimums are per coin rather than one number for the pack.

src/stocks.js is the stock-pack keeper and derives its own master from the one in .env - keccak256(master ++ "stocks"). Not the same value. Both contracts number their commit queues from zero, so sharing a master would make stock pack #5 and meme pack #5 share a secret, and ShellrPacks publishes its secret on reveal. See shellr-stock-packs.

Any change to the draw in the contract has to be made here in the same commit. The same mirror exists a third time in @shellr/sdk, where it is what lets anyone verify a settled pack. Three copies, one source of truth, and CI on all three.


The two things that will page you

pack N failed: ... repeating. Almost always a coin configured with a fee tier that has no pool. Run npm run pools, fix it with setCoin, and the stuck packs settle on the next pass - or refund themselves if you are slow.

npm run check failing. src/draw.js and ShellrPacks.sol have drifted. Do not restart the keeper until they agree; a mismatch means it quotes the wrong coins and every reveal reverts.


Scripts

npm start the keeper
npm run check draw vectors, no chain needed
npm run wallet a fresh keypair, printed and not saved
npm run pools which coins have a v3 pool, at which fee tier, with what depth
npm run coin -- 0x… the same question about any one token, for finding a replacement
npm run deploy compiles and deploys ShellrPacks. Dry run unless CONFIRM=1
npm run deploy:stocks the same for ShellrStockPacks
npm run configure finds each coin's deepest pool and calls addCoin. Dry run unless CONFIRM=1
npm run inspect [id] what happened to a pack: settled, delivered, or stuck
npm run bankroll fund or read the house bankroll
npm run limits -- <min> <max> [fee %] change what a pack may cost. Dry run unless CONFIRM=1
npm run tokensales the $SHELLR rate, the daily cap, and the off switch
npm run staking fund and read ShellrStaking
npm run pause / npm run pause -- off stop new buys and sell-backs

Every script that sends a transaction is a dry run by default and prints what it would do. CONFIRM=1 is the difference. Deploying needs no Foundry.


Running it on Railway

The keeper has to be up whenever packs can be bought. A pack nobody opens is a buyer waiting out a ten minute refund window, so a laptop with a terminal on it is not where this belongs.

  1. New Project → Deploy from GitHub repo, this repository. The Dockerfile is picked up automatically; the service opens no port, which is why the Dockerfile is explicit rather than left to the builder's guess.

  2. Set the variables under the service's Variables tab. None may be missing:

    PACKS_ADDRESS      the deployed contract
    KEEPER_KEY         the keeper wallet's private key
    MASTER_SECRET      the seed master - the SAME value as before, or every
                       committed seed already on chain becomes unrevealable
                       and those packs can only be refunded
    RPC_URL            one or more URLs, comma separated
    SLIPPAGE_BPS       300
    SEED_FLOOR         40
    SEED_BATCH         80
    SEED_CHUNK         20
    POLL_MS            1500
    LOG_WINDOW         400
    
  3. Watch the deploy log for the four lines it prints on start: keeper address, contract, WETH, and gas. If gas is low, top the keeper wallet up. Railway will happily keep restarting a process that has no money, and each restart re-reads the config for nothing.

Two things worth knowing before this is the only copy running.

MASTER_SECRET is not rotatable. Commitments already on chain were derived from it. Change it and those packs cannot be revealed by anyone, including you.

Only run one. Two keepers on the same contract both try to reveal the same pack; the loser's transaction reverts, which is harmless but wastes gas, and both queue seeds nobody needs. Stop the local one when Railway takes over.


No database

A single long-running process with no persistence. Every secret is derived from MASTER_SECRET and its index, so nothing has to survive a restart except that one value. State that looks like it should be stored - which pack is next, which seeds are queued - is read off the chain on every pass, because the chain is already the authoritative copy and a second one would only be a way to disagree with it.


License

MIT. See LICENSE.

About

Queues commit-reveal seeds and reveals every pack. One process, no database.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages