PROTOCOL / GUIDE
Architecture
Prepare locally, publish for demand and prove against a future block.
Read the repository referenceLocal 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.
Work with your agent
Copy a task-specific prompt with the protocol references and integration rules.
View prompt
Explain how D20DAO fits my application's architecture. Trace a request through epoch publication, the future target block, fixed-input VRF proof, callback and settlement. Identify the public contracts and the evidence my app needs. Read these references before choosing APIs: - Agent guide: https://github.com/d20dao/web/blob/main/public/agents.md - Full text docs: https://github.com/d20dao/web/blob/main/public/llms-full.txt - This guide: https://github.com/d20dao/keeper/blob/d7e785dda57499220bd37d73bc6fad9226872dcc/docs/epoch-protocol.md - Current deployment and upgrade history: https://github.com/d20dao/keeper/blob/main/deployments/arc-testnet.json - SDK and packaging instructions: https://github.com/d20dao/d20-sdk - Integration skills: https://github.com/d20dao/skills - Reviewed protocol source: https://github.com/d20dao/keeper/tree/d7e785dda57499220bd37d73bc6fad9226872dcc If a reference needs repository access, use the installed package's AGENTS.md and provenance or request the reviewed files. Do not invent signatures or addresses. Use the existing project toolchain. Install @d20dao/vrf-sdk from npm and read its AGENTS.md and PROTOCOL-PROVENANCE.json. Use Solidity 0.8.28. Configure the actual chain and coordinator proxy; Arc Testnet is 5042002 and requires consumer allowlisting. Read requestFee() instead of hardcoding the fee. Keep callbacks small and authenticated through D20VRFConsumer. Mapped requests still deliver a raw bytes32 word. Accepted proof with a failed callback is paid service; retry the same stored result, never reroll it. Unfulfilled requests are refundable strictly after 60 seconds. Optional _onRefund(requestId) means the fixed recipient was paid or credited, not that the consumer received funds; notification retries must not pay twice. Do not request randomness from inside a callback. Separate application assets and settlement rules. For verification, retain original epoch packets, request/target context and accepted proof evidence. Mathematical replay alone does not establish chain inclusion. An implementation upgrade inside a relevant block requires transaction-ordered evidence; block-end storage alone cannot prove which code ran. Implement only the requested application changes. Do not request keeper, VRF, deployer or bot secrets. Respect my authorization for any deployment or funded transaction. Run relevant compilation and lifecycle tests; report changed files, results, missing inputs and any remaining onboarding step.