Operations
Everything the person running Zecpass does, in order. Commands assume the repository root, Foundry in ~/.foundry/bin, and the Fly and Vercel CLIs logged in.
Addresses to fund
| Address | Chain | Amount | For |
|---|---|---|---|
Deployer 0x4B8275dac94AA7c4231a4e5e719426Aa7456F550 |
Robinhood Chain | 0.002 ETH | deploying the hub (and PonsMarket if fresh) |
Relayer 0x5C9A100eC739Bd7d80F1502e97Be9f549986951F |
Robinhood Chain | 0.001 ETH | sweep, deliver, setToken gas; a sweep is about 0.00003 ETH |
Relayer 0x5C9A100eC739Bd7d80F1502e97Be9f549986951F |
Arbitrum One | 0.002 ETH | Relay deposit gas; a deposit is about 0.00002 ETH |
Hub 0x2d2F1e1c7B90272728a627605dD07FC46eF79232 |
Robinhood Chain | optional | the vault for instant mode; 0.5 to 2 ETH is a reasonable first size |
1. Deploy the hub
cd contracts
export PATH=$HOME/.foundry/bin:$PATH
export PK=$(cat .deployer.txt)
PONS_MARKET=0xd03917Cd2FE890B1Fd85A409994b2A17f8a65bA0 \
forge script script/Deploy.s.sol:Deploy --rpc-url robinhood --private-key $PK \
--broadcast --slow --gas-estimate-multiplier 150 --legacy --with-gas-price 90000000
forge verify-contract <HUB> src/Zecpass.sol:Zecpass --chain-id 4663 \
--verifier blockscout --verifier-url https://robinhoodchain.blockscout.com/api \
--constructor-args $(cast abi-encode "constructor(address,address,address,address)" <OWNER> <RELAYER> <TREASURY> <MARKET>)
Write the hub address into: web env NEXT_PUBLIC_ZECPASS_HUB, relayer secret ZECPASS_HUB, and SPEC.md.
2. Deploy the relayer
cd relayer
fly launch --no-deploy --copy-config --name zecpass-relayer
fly volumes create zecpass_data --size 1 --region cdg
fly secrets set RELAYER_PK=$(cat .relayer.txt) ZECPASS_HUB=<HUB>
fly deploy
curl https://zecpass-relayer.fly.dev/health
curl https://zecpass-relayer.fly.dev/rails
3. Connect the site
cd web
vercel env add NEXT_PUBLIC_ZECPASS_HUB production
vercel env add NEXT_PUBLIC_RELAYER_URL production # https://zecpass-relayer.fly.dev
vercel --prod
The status band at the bottom of every page turns from amber to green for the hub. The token dot stays amber until launch.
4. Launch day
- On ponsfamily.com launch Zecpass / ZECPASS with the terms in Token. Creator fee recipient must be the treasury.
- Copy the token address.
- Set it on the hub:
cast send <HUB> "setToken(address)" <TOKEN> --rpc-url https://rpc.mainnet.chain.robinhood.com \ --private-key $(cat relayer/.relayer.txt) --legacy --gas-price 90000000 - Set it everywhere else:
fly secrets set ZECPASS_TOKEN=<TOKEN> -a zecpass-relayer vercel env add NEXT_PUBLIC_ZECPASS_TOKEN production && vercel --prod - Check the stats page: curve phase, progress, both rails green.
- Do one real pass with 0.05 ZEC from the founders' wallet to a fresh beneficiary. Watch the eight states. Post the sweep transaction.
- Once the address is confirmed on Pons for a day, lock it from the treasury:
cast send <HUB> "lockToken()".
5. Fund the vault
Send ETH to the hub address from the treasury. Instant mode turns on by itself for orders the balance covers. To change the caps:
cast send <HUB> "setCaps(uint256,uint256)" 500000000000000000 5000000000000000000 …
Monitoring
GET /healthon the relayer:openOrdersshould be small;tickshould be recent.GET /rails:relayerArb.balanceWeiandrelayerHood.balanceWeiabove 0.0005 ETH each; top up when not.- The stats page:
Passes deliveredmoves when orders complete;Hub vaultis what instant mode has to spend. fly logs -a zecpass-relayer: one line per state change, prefixed with the order id.
Manual interventions
| Need | Command |
|---|---|
| Pause everything but withdrawals | cast send <HUB> "pause(bool)" true from the treasury |
| Rotate the relayer key | cast wallet new, cast send <HUB> "setRelayer(address)" <NEW>, fly secrets set RELAYER_PK=… |
| Change the fee | cast send <HUB> "setFee(uint16)" 50 (max 200) |
| Take ETH out of the vault | cast send <HUB> "withdrawVault(uint256,address)" <wei> <to> |
| Sweep a pass by hand | cast send <HUB> "sweep(address,uint256)" <beneficiary> 0 from any funded key |
| Help a user recover ETH from a pass | they call withdraw(address) with their own key; the site's stats page links the hub on the explorer |
| Claim creator fees from Pons | from the treasury: cast send <FEE_ESCROW> "claim()"; the escrow address is factory.feeEscrow() |
| Bridge Arbitrum ETH by hand | the Arbitrum bridge portal to Robinhood Chain, or pnpm probe to get a Relay quote and send it with the relayer key |
Backups
fly ssh console -a zecpass-relayer -C "cat /data/orders.json" > backups/orders-$(date +%F).json once a day is enough; every fact in that file is also on chain or at 1Click.