Deployment
View raw

Deploying Quiver to Robinhood Chain

This is the runbook for deploying the coordinator, registering a provider, and running Fletcher — first on testnet (46630), then mainnet (4663).

Live broadcasts require a funded key and RPC access that only you control. This repo scripts everything up to the broadcast; you supply the signer.


0. Networks

TestnetMainnet
Chain ID466304663
RPC (public, rate-limited)https://rpc.testnet.chain.robinhood.comhttps://rpc.mainnet.chain.robinhood.com
RPC (recommended)https://robinhood-testnet.g.alchemy.com/v2/KEYhttps://robinhood-mainnet.g.alchemy.com/v2/KEY
Explorerexplorer.testnet.chain.robinhood.comrobinhoodchain.blockscout.com
Gas tokenETHETH
Foundry profile namerh_testnetrh_mainnet

Robinhood Chain is an Arbitrum Orbit L2; standard Foundry tooling works unmodified.

1. Prerequisites

forge --version      # Foundry
node --version        # ≥ 20
pnpm --version
forge install && pnpm install
forge test            # green before you deploy anything

Fund your deployer address with a little ETH on the target network (bridge to testnet/mainnet per Robinhood's docs).

2. Configure environment

cp .env.example .env
# edit .env — at minimum set RH_TESTNET_RPC_URL / RH_MAINNET_RPC_URL

Use a keystore, not a raw key, especially for mainnet:

cast wallet import quiver-deployer --interactive   # paste your private key once
# deploy with `--account quiver-deployer` (Foundry prompts for the password)

3. Deploy the coordinator

Dry run (no broadcast) first:

forge script script/Deploy.s.sol --rpc-url rh_testnet

Broadcast + verify on Blockscout:

forge script script/Deploy.s.sol \
  --rpc-url rh_testnet \
  --account quiver-deployer \
  --broadcast \
  --verify --verifier blockscout \
  --verifier-url https://explorer.testnet.chain.robinhood.com/api

This writes deployments/46630.json with the coordinator address. Commit it.

Owner: defaults to the deployer. For production set QUIVER_OWNER to a multisig (QUIVER_OWNER=0xSAFE forge script ...).

4. Register a provider

Pick a chain length (random values before a rotation) and generate a seed:

pnpm --filter @quiver/fletcher exec tsx src/index.ts genseed   # → 0x… , store as FLETCHER_SEED

Set in .env: QUIVER_COORDINATOR_ADDRESS (from step 3), FLETCHER_SEED, FLETCHER_CHAIN_LENGTH (e.g. 100000), FLETCHER_FEE_WEI, FLETCHER_MAX_NUM_HASHES, PRIVATE_KEY (the provider key). Then either:

# via Fletcher (recommended — same code path the keeper uses)
FLETCHER_NETWORK=rh_testnet pnpm --filter @quiver/fletcher exec tsx src/index.ts register

# …or via Foundry
forge script script/RegisterProvider.s.sol --rpc-url rh_testnet --account quiver-deployer --broadcast

Both compute commitment = keccak256^chainLength(seed) identically.

5. Run Fletcher

FLETCHER_NETWORK=rh_testnet pnpm --filter @quiver/fletcher exec tsx src/index.ts run

For production, run it as a managed service (systemd/Docker) with restart-on-failure and a dedicated, funded operator key. See fletcher-operations.md.

6. (Optional) Deploy an example consumer

QUIVER_COORDINATOR_ADDRESS=0x… QUIVER_PROVIDER_ADDRESS=0x… \
  forge script script/DeployCoinFlip.s.sol --rpc-url rh_testnet --account quiver-deployer --broadcast

7. Smoke test on testnet

# request a flip (as any funded account)
cast send <coinflip> "flip(bytes32)" $(cast keccak $RANDOM) --account quiver-deployer --rpc-url rh_testnet
# watch Fletcher fulfill, then read the result
cast call <coinflip> "flips(uint64)(address,uint8,bool)" 1 --rpc-url rh_testnet

Or run the whole thing locally first: ./demo/local-demo.sh.

8. Promote to mainnet

Repeat steps 3–7 with --rpc-url rh_mainnet and the mainnet verifier URL (https://robinhoodchain.blockscout.com/api). Before mainnet:

  • Owner set to a multisig (ideally + timelock).
  • deployments/4663.json committed and published to integrators.
  • Fletcher running as a monitored service with alerting on low ETH and low remaining random values.
  • A fresh mainnet seed (never reuse the testnet seed).
  • Reviewed security.md; ideally an independent audit for value at scale.

9. Post-deploy checklist

  • getProviderInfo(provider) shows the expected commitment, fee, and chain length.
  • A test request is fulfilled end-to-end.
  • Contract is verified and readable on Blockscout.
  • Runbooks exist for: rotating a chain, pausing, transferring ownership, and rotating the Fletcher operator key.

Troubleshooting

SymptomLikely cause / fix
ProviderNotRegistered on requestrun step 4; check you targeted the right provider address
Fletcher: "provider … not registered"QUIVER_COORDINATOR_ADDRESS/PRIVATE_KEY mismatch, or wrong network
Reveal reverts IncorrectProviderRevelationFLETCHER_SEED/FLETCHER_CHAIN_LENGTH/FLETCHER_ANCHOR don't match what was registered
TooManyHashes on requestprovider is behind on reveals — Fletcher down or out of gas
Verification fails on Blockscoutpass --verifier blockscout and the correct --verifier-url …/api