# D20DAO developer documentation Protocol source: d7e785dda57499220bd37d73bc6fad9226872dcc SDK: @d20dao/vrf-sdk 0.1.1 Install: npm install @d20dao/vrf-sdk Agent guide: /agents.md ## Deployment snapshot Chain ID: 5042002 Coordinator proxy: 0xd20dA0fDa41f84FCfA3423ae9F96B15910587B4E Registry proxy: 0xd20Da04e4D6d97a762A5b56993d723AA7663F204 Coordinator implementation: 0xd20Da05E6bb360edA09a6a360291AB6AD7AA0c58 Registry implementation: 0xd20Da0028F2B65d8c8C8512C7029EE02F94E8BF2 Full manifest and upgrade receipts: /deployments/arc-testnet.json Confirm the current implementation onchain before using a proxy. Historical replay uses the code at each original receipt. # Getting started Route: /docs/getting-started Reference: https://github.com/d20dao/d20-sdk#getting-started Agent prompt: /prompts/getting-started.txt Install the SDK, connect your application and verify your first result. ## Work with your agents Copy the integration prompt into your coding agent to give it the SDK references, deployed contracts and implementation rules. Then follow the deployment, installation and verification steps below. ## Choose the deployment Start with the restricted Arc Testnet pilot, chain ID 5042002. Open Deployed contracts and use the coordinator proxy, not an implementation address. Check the active implementation and code hashes against the manifest. Arrange consumer allowlisting before sending live requests. The request fee is currently 0.05 native test USDC; read requestFee() at runtime. Native USDC uses 18 decimals, and transaction gas is separate. ## Install the SDK Install @d20dao/vrf-sdk in your application. Use Node 22.13 or newer, Solidity 0.8.28 and your project's npm import resolver. The package includes consumer contracts, coordinator and registry ABIs, replay helpers and an AGENTS.md integration guide. Its PROTOCOL-PROVENANCE.json records the reviewed contract source. ## Add an authenticated consumer Extend D20VRFConsumer and configure the coordinator proxy. Read requestFee(), forward that exact value, fix the refund recipient and persist the returned request ID with your application's operation. Override _fulfillRandomness to authenticate through the base, validate the expected ID and store the raw bytes32 result with minimal work. Choose raw randomness or a built-in mapping such as a range, selection or shuffle. See Integration for the Solidity example. ## Handle delivery and expiry Track proof acceptance, callback delivery and refunds separately. Accepted proofs earn the fee even if the consumer callback fails; retryCallback redelivers the same word. Unfulfilled requests become refundable strictly after their 60-second deadline. The current pilot supports optional _onRefund(requestId) after payment or backed credit; keep it within the initial 100,000-gas budget. Failed notifications retry without another payment. Application payments and assets need their own settlement rules. ## Test and verify the result Test exact-fee rejection, authenticated and duplicate callbacks, callback failure with same-word retry, expiry/refund and any application refund hook. Confirm consumer onboarding before a funded testnet request. In Explorer, verify the signed epoch packet, fixed request context, VRF, mapping and transcript, then separately confirm canonical receipts and historical code. No keeper credentials or direct keeper API are needed. # Deployed contracts Route: /docs/deployments Reference: /deployments/arc-testnet.json Agent prompt: /prompts/deployments.txt Contract addresses for the D20DAO pilot on Arc Testnet, chain ID 5042002. ## Arc Testnet addresses Use the coordinator proxy when connecting a consumer. The registry holds epoch commitments; the pilot consumer is the deployed example application. Requests currently require keeper consumer allowlisting. ## Implementation addresses These addresses follow the deployment manifest, including the confirmed refund-notification upgrade at block 62310349. Integrate through the proxies above. The manifest retains previous implementation and upgrade receipts for historical verification; check the active implementation onchain before integrating. # Integration Route: /docs/integration Reference: https://github.com/d20dao/keeper/blob/d7e785dda57499220bd37d73bc6fad9226872dcc/contracts/interfaces/ID20VRF.sol Agent prompt: /prompts/integration.txt Request general-purpose randomness and receive an authenticated callback. ## Consumer contract Extend D20VRFConsumer with the verified coordinator proxy address. Its base authenticates callbacks. The local example below tracks outstanding request IDs and stores the delivered word. Keep delivery small and apply application actions separately. Find the Arc Testnet addresses in the Deployed contracts guide and verify the active implementation before connecting a consumer. ## Request and fee Read requestFee() and send exactly that amount to requestRandomness(clientSeed, callbackGasLimit, refundAddress). The request checkpoints its epoch's canonical anchor, escrows the fee and pins its epoch ID, consumer, client seed, mapping, request block and fixed refund recipient. It can be accepted before an API packet is published. Until publication, the epoch hash and randomness target are unresolved. An absent packet or unaccepted proof can lead to expiry; there is no automatic refund or guaranteed delivery SLA. ## Result handling After publication, the target block is max(requestBlock, epochCommitBlock + 1). Its hash becomes part of the fixed VRF input, so the packet is committed before that hash is known. Track the request until proof acceptance and callback delivery are separately established. Accepted proof earns the configured keeper and treasury fee shares even if the callback fails. Retry delivery with the stored word; do not request a replacement outcome for callback failure. After expiry without accepted proof, claim the escrowed RNG fee by transaction for the fixed refund recipient. ## SDK and agent resources Install @d20dao/vrf-sdk from npm. Start with the packaged AGENTS.md and the Getting started guide, or copy the task prompt below into your agent. Additional integration skills live at github.com/d20dao/skills. Independently verify chain, proxy, registry, implementation history, public key and configuration. A stable proxy address does not guarantee unchanged behavior. # Architecture Route: /docs/architecture Reference: https://github.com/d20dao/keeper/blob/d7e785dda57499220bd37d73bc6fad9226872dcc/docs/epoch-protocol.md Agent prompt: /prompts/architecture.txt Prepare locally, publish for demand and prove against a future block. ## Local epochs and on-demand publication Epochs span 200 blocks. The first starts 200 blocks after registry initialization; each source-selection anchor is the block immediately before its epoch starts. The keeper prepares the current epoch locally with one fixed recipe and preserves its first valid snapshot. Idle epochs require no publication transaction. A live, allowlisted paid request triggers publication of that packet; the accepted packet cannot be overwritten. Unused local packets are retired after 50 epochs. Public events for used epochs remain onchain. ## Request, publication and future target A paid request checkpoints the canonical source anchor and escrows its exact fee even if no API commitment exists yet. Its epoch ID is fixed at inclusion; its epoch hash resolves from the first onchain publication. The randomness target is max(requestBlock, epochCommitBlock + 1), strictly after publication. The fixed seed binds chain, coordinator, key hash, request ID, consumer, client seed, mapping hash, request block, target block and target hash, epoch ID and epoch hash. fulfillRandomness(requestId, proof) verifies the genuine secp256k1 VRF proof. Calldata is 452 bytes and proof evidence is 416 bytes. ## Recovery and settlement API preparation runs outside request processing. There is no per-request API fetch, fallback or resampling. First valid snapshots and active transaction recovery data survive restarts. Old-epoch requests can finish after an epoch boundary while their own 60-second deadlines remain open. Only accepted proof earns the configured fee split: the keeper share goes to the configured committer, not an arbitrary proof submitter, and the remainder goes to the treasury recipient. Failed recipient transfers become backed credits. Unfulfilled-request escrow remains protected for refunds. ## Stable address, explicit upgrade authority The coordinator and registry use UUPS implementations behind ERC1967 proxies. Ownership transfers in two steps; owner, fee recipient and keeper/committer roles can rotate. Moving a keeper or rotating its transaction wallet does not rotate the VRF key. This implementation has no setter for the fixed VRF key, but the trusted upgrade owner can change implementation behavior. Replay must identify the implementation and configuration active at each historical receipt, not merely the proxy address. # Source inputs Route: /docs/sources Reference: https://github.com/d20dao/keeper/blob/d7e785dda57499220bd37d73bc6fad9226872dcc/docs/epoch-protocol.md Agent prompt: /prompts/sources.txt Four fixed recipes across three API providers. ## Fixed recipe catalog Slot 0 uses Hyperliquid metaAndAssetCtxs with dex empty, projecting BTC symbol and dayNtlVlm. Slot 1 uses ANU randomNumbers with type hex8, length 4 and size 8. Slot 2 uses TickerLayer lastTrade for crypto BTCUSD. Slot 3 uses TickerLayer lastTrade for crypto ETHUSD. Initialization pins four signer addresses in slot order; the two TickerLayer slots use the same provider signing address. Four recipes do not mean four independent providers. ## Selection and repeated data D20_EPOCH_SELECT, catalog hash, epoch ID and the start-minus-one anchor hash determine a selector modulo four. Consecutive epochs may select the same recipe. A fresh API call can return identical raw values; the protocol does not resample to force different bytes. Epoch parameters bind distinct commitments, but hashing public data does not create fresh or secret entropy. A valid local snapshot is preserved and published only for live demand. ## Exact signed record policy Canonical 65-byte low-s EIP-191 signatures bind query hash, timestamp and exact UTF-8 data. At publication an attestation cannot be future-dated or more than 120 seconds old. Hyperliquid requires the exact BTC symbol and a nonnegative decimal value. ANU requires the exact successful body with four 16-character lowercase hex values. TickerLayer retains the complete symbol, price, size and timestamp record in its exact order and bytes. Raw signed data is at most 128 bytes; malformed or oversized records are rejected, never cropped. A stale first snapshot is not silently replaced to find another outcome. # Verification Route: /docs/verification Reference: https://github.com/d20dao/keeper/blob/d7e785dda57499220bd37d73bc6fad9226872dcc/docs/epoch-protocol.md Agent prompt: /prompts/verification.txt Replay public epoch and request evidence against historical implementation context. ## Collect independent chain evidence Obtain chain ID, proxy and registry identities, canonical source anchor and randomness target blocks, request/publication/acceptance receipts and timestamps from independently trusted chain data. Resolve implementation history and configuration at those receipts: a proxy runtime hash alone is insufficient. EpochCommitted emits the complete accepted API packet once when an epoch is used. Each accepted request records abi.encode(Proof), 416 bytes. No private keeper database or keeper connection is required. ## Replay epoch and request Use replayEpochCommitment to reconstruct recipe selection, validate the exact signed packet and match the stored epoch record. Then call replayCoordinator with request context, fixed configuration, epoch evidence, proof and recorded acceptance. It checks request-block epoch membership, resolved epoch hash, the post-publication target, key and configuration, seed, VRF, mapping, transcript and acceptance time. Preserve both requestBlock and targetBlock; they need not be equal. ## Understand verification boundaries Reject altered signed bytes, noncanonical packets, mismatched commitments, invalid proofs and acceptance outside the request deadline. Establish callback delivery separately from proof acceptance. The homepage Evidence Explorer authenticates a historical Hyperliquid candle response against a pinned signer. That historical record is not a current epoch recipe, and the inspector does not prove chain inclusion or complete VRF validity. Its downloadable record preserves the original signed bytes and historical provenance. # Service rules Route: /docs/service-rules Reference: https://github.com/d20dao/keeper/blob/d7e785dda57499220bd37d73bc6fad9226872dcc/docs/epoch-protocol.md Agent prompt: /prompts/service-rules.txt Escrowed requests, earned fee shares, retries and refunds. ## Estimated completion Estimated average completion is around 8 blocks. This is a product estimate, not a measured rolling average or guaranteed block deadline. Epoch readiness and network conditions affect actual timing. Request and fulfillment blocks can be checked in the Explorer. The onchain acceptance and refund threshold remains 60 seconds. ## 60-second acceptance deadline A valid proof must be accepted onchain at or before request timestamp plus 60 seconds. This is a timestamp rule, not a guaranteed number of blocks or delivery SLA. API publication and target-block waiting consume that same window. Crossing an epoch boundary does not shorten an existing request's deadline. A request can be accepted before its epoch packet is published and remain unfulfilled if publication or proof acceptance does not complete. ## Fee settlement and callback delivery Accepted proof earns the configured keeper and treasury shares, including when the callback fails. The keeper share goes to the configured committer, not the transaction submitter; failed transfers become backed credits. The pilot currently assigns 20% to the keeper: 0.01 from the 0.05 test USDC request fee. This is configurable, not a permanent pricing promise. Administered recipients and split can change. Delivery retry uses the same stored word and does not earn another service fee. Failed callbacks do not qualify for the unfulfilled-request refund. ## Refund transactions After expiry without an accepted proof, the RNG service fee is refundable to the fixed recipient. A transaction is required; gas and application fees are excluded. Publication is not permission to spend unfulfilled-request escrow, and fees cannot be earned merely by submitting a pending proof. A rejecting refund recipient can receive a backed credit. Inspect request, refund and credit state before retrying a claim. ## Optional refund notification The current consumer source supports authenticated onRefund(requestId), after the fixed recipient has been paid or credited. Override _onRefund for a bounded application update within the initial 100,000-gas budget. Failed notification does not undo the refund; retryRefundCallback retries only notification, without another payment. Reentry into coordinator request, refund and retry paths is blocked. Verify the deployed implementation supports this hook before relying on it; a new SDK does not upgrade an existing proxy. # Security model Route: /docs/security Reference: https://github.com/d20dao/keeper/blob/d7e785dda57499220bd37d73bc6fad9226872dcc/SECURITY.md Agent prompt: /prompts/security.txt Fixed-input proofs with explicit operator and upgrade-authority trust. ## Operator, source and chain assumptions The pilot 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. 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. ## 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. 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. ## Release boundaries A restricted Arc Testnet pilot is deployed on chain 5042002. Public addresses, code hashes and deployment receipts are recorded in github.com/d20dao/keeper/blob/main/deployments/arc-testnet.json. Consumer allowlisting is required. This does not establish mainnet approval, an external cryptographic audit, or a public SLA. Monitor actual preparation, publication and request deadlines. The lab remains illustrative; the Explorer displays indexed chain evidence.