Skip to content
D20DAODocs
Keeper LabExplorerStatusGitHub

REFERENCE / GUIDE

Security model

Fixed-input proofs with explicit operator, beacon and upgrade-authority trust.

Read the repository reference
01

Operator, source and chain assumptions

The service uses a single operator and a genuine fixed secp256k1 VRF key. A proof establishes the output for its fixed input; it does not force operator availability or establish source truthfulness, independence or lack of bias. The operator can withhold preparation, publication or fulfillment. On Arc, publication must precede the randomness target block so the final block hash is unknown when the packet is chosen. Independent chain context remains necessary for replay.

02

Arc: drand assumptions

Each epoch's source is the drand evmnet beacon. A drand signature shows what the beacon's key signed for that round, not that the beacon is unbiased or independent of its operators. The committer chooses which round, among those scheduled within the last 240 seconds, an epoch commits, and one round can serve several consecutive epochs. The registry trusts the yes or no that a registered verifier gives. It does not check that the chain hash names the network of the key or that the verifier's code is the reviewed D20BeaconVerifier: the owner vouches for each registration, which BeaconRegistered publishes. D20BeaconVerifier is stateless, has no owner and is not behind a proxy, so its behavior cannot change after registration. The drand catalog has one source and no fallback, so drand is a single point of failure for publication: while no fresh round can be obtained no epoch is published, affected requests expire and their escrowed fee is refundable. Another source needs a catalog the owner schedules at least two epochs ahead.

03

Robinhood Chain: how a result is made

When a request is made, the contract binds it to a future round of drand's evmnet beacon: the first round scheduled at least 3 seconds after the request. Until that round is published, nobody can know or choose the result: not the requester, the operator, the sequencer or drand. The keeper then delivers the operator's VRF output over the request's fixed fields and the round's randomness. The contract verifies the round's BLS signature and the VRF proof before accepting it, and anyone can replay the result from public chain data.

04

Robinhood Chain: assumptions

What a Robinhood result rests on.

  1. Shared with every Robinhood Chain application: D20DAO relies on the chain's sequencer for ordering and confirmation.
  2. Shared with other verifiable-randomness services: results assume the operator's VRF key and the sequencer act independently.
  3. drand: evmnet is run by the League of Entropy, and its signatures rest on a threshold of independent operators.
05

Robinhood Chain: finality

Results are confirmed by the sequencer within seconds. Settlement on Ethereum follows in about 15–20 minutes.

06

Robinhood Chain: delivery and refunds

A typical delivery takes 5–8 seconds. If a request is not fulfilled within 60 seconds, its fee can be refunded to the request's refund address. As with any randomness service, design applications so that a party cannot cancel a request and retry for a better outcome.

07

Robinhood Chain: upgrades

The coordinator is upgradeable (UUPS) by its owner; read `owner()` from the chain. Beacon changes are scheduled on chain at least 10 minutes ahead.

08

Arc: upgrade and role authority

Both stable proxy addresses have trusted upgrade authority. The current implementation fixes the VRF key without a setter, but an owner-authorized implementation upgrade can change behavior. Ownership uses a two-step transfer; fee recipients and keeper/committer addresses are configurable, and the registry owner can allow backup committers, register recipes and beacons and schedule catalogs for future epochs. Verify historical implementation code and configuration when replaying earlier receipts, and review upgrades before trusting new requests. Do not describe the service as immutable merely because its proxy address is stable.

09

Release boundaries

D20DAO VRF is live on Arc Mainnet (chain 5042), owned by the DAO treasury Safe, and on Robinhood Chain (chain 4663). Public test services run on Arc Testnet (chain 5042002) and Robinhood Chain Testnet (chain 46630). Public addresses, code hashes and deployment receipts are recorded in https://d20dao.org/deployments/arc-mainnet.json, https://d20dao.org/deployments/arc-testnet.json, https://d20dao.org/deployments/robinhood-mainnet.json, https://d20dao.org/deployments/robinhood-testnet.json. Any consumer contract can request service by paying the quoted fee; no allowlist is required. This does not establish an external cryptographic audit or a public SLA. Monitor actual preparation, publication and request deadlines. The lab remains illustrative; the Explorer displays indexed Arc evidence and reads Robinhood requests from the chain.

Work with your agents

Copy a task-specific prompt with the protocol references and integration rules.

 

View prompt
Review my D20DAO integration for callback authentication, fee quoting and overpayment credit, request association, duplicate handling, reentry, selective outcome cancellation and refund accounting. Check historical proxy implementations and explicit operator/source/upgrade trust assumptions. Report findings with code evidence.

Read these public references first; do not guess signatures, addresses or limits:
- This guide: https://d20dao.org/docs/security (full text of every guide: https://d20dao.org/llms-full.txt, agent guide: https://d20dao.org/agents.md)
- SDK README and AGENTS.md: https://github.com/d20dao/d20-sdk (also inside the installed package). It lists the randomness options, callback gas bounds, how to wait for results, compiler setup and gas needs for refunds and retries.
- Protocol source (contracts and replay library): https://github.com/d20dao/d20-sdk/tree/main/protocol, pinned to commit 98e537fb249dd0d3365b8d78e6040a9323a65a88 by PROTOCOL-PROVENANCE.json
- Deployment manifests: https://d20dao.org/deployments/arc-mainnet.json, https://d20dao.org/deployments/arc-testnet.json, https://d20dao.org/deployments/robinhood-mainnet.json, https://d20dao.org/deployments/robinhood-testnet.json
- Integration skills and templates: https://github.com/d20dao/skills (d20-consumer: methods.md, RandomnessConsumer.sol, mappings.mjs)
- Explorer for checking requests: https://d20dao.org/explorer (arc.d20dao.org for Arc Mainnet, arc-testnet.d20dao.org for Arc Testnet; Robinhood requests are read from the chain)
- Agent API, for agents and services without a contract: https://d20dao.org/docs/agents (0.05 USDC per call over x402)
If a link is unavailable, use the installed package's README, AGENTS.md, ABIs and protocol sources.

Networks: Arc Mainnet chain 5042 (live, USDC; RPC https://rpc.mainnet.arc.io; explorer https://explorer.arc.io); Arc Testnet chain 5042002 (build and test here first, USDC; RPC https://rpc.testnet.arc.io; explorer https://testnet.arcscan.app); Robinhood Chain chain 4663 (live, ETH; RPC https://rpc.mainnet.chain.robinhood.com; explorer https://robinhoodchain.blockscout.com); Robinhood Chain Testnet chain 46630 (build and test here first, ETH; RPC https://rpc.testnet.chain.robinhood.com; explorer https://explorer.testnet.chain.robinhood.com). Native USDC on Arc and ETH on Robinhood Chain have 18 decimals. The consumer interface is the same on both; Arc serves requests through epochs, Robinhood Chain binds each request to a future drand round. Compile with Solidity 0.8.28 and EVM version cancun, importing contracts from the installed @d20dao/vrf-sdk package. Take the coordinator proxy address from the manifest of the network you target and check that its implementation matches the manifest. Any consumer contract can request; there is no allowlist, and EOAs cannot request.

Requests and fees: use the D20VRFRequests helpers from the SDK for every randomness option (raw word, dice, custom dice, coin flip, ranges, choose one or many, shuffle). Never hardcode the fee. In a contract, quote with quoteFee(callbackGasLimit) inside the requesting transaction. Off chain, quote with quoteFeeAt(callbackGasLimit, latest block baseFeePerGas) plus a buffer, or the SDK's quoteRequestFee with an ethers v6 provider, because eth_call reports a base fee of 0. Choose one payment pattern deliberately: collect a buffered quote from the user, pay the exact fee from the contract and return the change; or forward msg.value and accept that the excess becomes refund credit of the refund address.

Results: store the delivered word or mapped result in your consumer when the authenticated callback arrives, keyed by request ID, and have the application read that state. Off chain, wait for the coordinator's fulfillment events or poll getRequest (getRoundRequest on Robinhood Chain); the SDK documents the fields and mapped-result readers. A browser app must bundle the ESM package. Delivery usually takes a few seconds; measured Arc Testnet completion times, including under burst load, are at https://d20dao.org/benchmarks (observations of the testnet keepers, not an SLA). On Robinhood Chain a typical delivery takes 5–8 seconds. An unserved request can be refunded strictly after its 60-second deadline at the refund ratio fixed when it was requested. Give refund and callback-retry transactions explicit gas limits as documented.

Keep callbacks small and authenticated through D20VRFConsumer, and never request randomness from inside a callback. An accepted proof with a failed callback is paid service: retry the same stored result, never reroll. Optional _onRefund(requestId) means the refund recipient was paid or credited, not that the consumer received funds, and notification retries must not pay twice. Keep application assets and settlement separate from RNG fees.

For verification, keep the original epoch packet, request and target context and accepted proof evidence. Mathematical replay alone does not prove chain inclusion; check receipts and the implementation history too.

Implement only the requested changes. Do not ask for keeper, VRF, deployer or bot secrets, and do not send funded or mainnet transactions without my explicit authorization. Compile, run lifecycle tests on a local chain or a testnet, then report changed files, results, anything unverified, and any documentation that was unclear or missing.