ZecpassGet a pass

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

  1. On ponsfamily.com launch Zecpass / ZECPASS with the terms in Token. Creator fee recipient must be the treasury.
  2. Copy the token address.
  3. 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
    
  4. Set it everywhere else:
    fly secrets set ZECPASS_TOKEN=<TOKEN> -a zecpass-relayer
    vercel env add NEXT_PUBLIC_ZECPASS_TOKEN production && vercel --prod
    
  5. Check the stats page: curve phase, progress, both rails green.
  6. Do one real pass with 0.05 ZEC from the founders' wallet to a fresh beneficiary. Watch the eight states. Post the sweep transaction.
  7. 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 /health on the relayer: openOrders should be small; tick should be recent.
  • GET /rails: relayerArb.balanceWei and relayerHood.balanceWei above 0.0005 ETH each; top up when not.
  • The stats page: Passes delivered moves when orders complete; Hub vault is 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.