@d20dao/vrf-sdk 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +31 -15
- package/API.md +2190 -0
- package/BUILD-MANIFEST.json +18 -16
- package/CHANGELOG.md +44 -0
- package/PROTOCOL-PROVENANCE.json +9 -8
- package/README.md +157 -97
- package/abi/EpochEntropy.json +372 -26
- package/dist/abi.d.ts +292 -24
- package/dist/abi.js +1 -1
- package/dist/epoch.d.ts +42 -78
- package/dist/epoch.js +121 -27
- package/dist/index.d.ts +4 -2
- package/dist/index.js +2 -1
- package/dist/sources.js +2 -0
- package/dist/templates.d.ts +22 -0
- package/dist/templates.js +220 -0
- package/examples/DiceConsumer.sol +37 -29
- package/examples/LootDropConsumer.sol +60 -0
- package/examples/RaffleConsumer.sol +71 -0
- package/package.json +6 -2
- package/contracts/examples/MiningRandomnessConsumer.sol +0 -59
package/API.md
ADDED
|
@@ -0,0 +1,2190 @@
|
|
|
1
|
+
# D20DAO coordinator API reference
|
|
2
|
+
|
|
3
|
+
<!-- Generated by scripts/api-reference.mjs from abi/*.json and scripts/api-descriptions.mjs. Do not edit by hand. -->
|
|
4
|
+
|
|
5
|
+
Every function, event and error of `D20VRFCoordinator` and `EpochEntropy`, generated from the ABIs of `@d20dao/vrf-sdk` 0.4.0. Regenerate with `npm run build && npm run api-reference`; `npm test` fails when this file is out of date.
|
|
6
|
+
|
|
7
|
+
- Package: `@d20dao/vrf-sdk` 0.4.0
|
|
8
|
+
- Protocol source: commit `de5f82eb9fc749c80e83270f57cde9908ddcf1f3`, copied to [`protocol/contracts/`](protocol/contracts/) (hashes in `PROTOCOL-PROVENANCE.json`)
|
|
9
|
+
- Compiler: solc 0.8.28+commit.7893614a.Emscripten.clang, EVM version `cancun`
|
|
10
|
+
- `abi/D20VRFCoordinator.json` SHA-256: `4764ba62745e109f3b968b21ed23e88da739a4a26906fc2ed3192fa23b8d79c1`
|
|
11
|
+
- `abi/EpochEntropy.json` SHA-256: `684ee3dfe0745f141831aee896db6436d490d5e9715e61661c86b044d1c3260e`
|
|
12
|
+
|
|
13
|
+
This reference describes that source. A deployment runs it only while the implementation behind each proxy is the one the deployment manifest records for that commit: check when you integrate and whenever a proxy emits `Upgraded` (README [Security and trust](README.md#security-and-trust)).
|
|
14
|
+
|
|
15
|
+
## Conventions
|
|
16
|
+
|
|
17
|
+
- **Addresses.** Call the proxies listed in README [Deployments](README.md#deployments). The ABIs are those of the implementations; `D20Proxy` adds no functions of its own.
|
|
18
|
+
- **Units.** Fees and credits are wei of native USDC, which has 18 decimals (`1e18` is 1 USDC). Deadlines and timestamps are Unix seconds. Ratios are basis points (10000 is 100%).
|
|
19
|
+
- **Callers.** "Anyone" means any account or contract; "Any contract" means `msg.sender` must have code. Owner-only functions revert `OwnableUnauthorizedAccount` for other callers.
|
|
20
|
+
- **Selectors.** Functions and errors show their 4-byte selector, events their topic 0, so revert data and logs can be matched by hand.
|
|
21
|
+
- **Decoding errors.** `coordinatorAbi` and `epochEntropyAbi` (`@d20dao/vrf-sdk/abi`) contain every custom error below. When your consumer calls the coordinator with an ordinary Solidity call, a coordinator revert is passed through unchanged, so a wallet sending a transaction to your consumer sees the coordinator's selector. Decode with `coordinator.interface.parseError(data)` in ethers or `decodeErrorResult({ abi: coordinatorAbi, data })` in viem, or build your consumer's contract object from its ABI plus the coordinator's error entries. Your consumer's own errors, such as `OnlyCoordinator` and `InvalidCoordinator` from `D20VRFConsumer`, are only in your consumer's ABI. Arithmetic overflow reverts with `Panic(uint256)`.
|
|
22
|
+
- **ethers v6 results.** Structs and multiple return values arrive as `Result` objects, which are arrays. A named value is also a property unless its name collides with an `Array` or `Result` member, such as `length`, `values`, `keys`, `map` or `filter`; read such a value with `result.getValue(name)`, by position, or from `result.toObject()`. Unnamed outputs, such as those of `pricing()`, are positional only.
|
|
23
|
+
- **Consumer contracts.** `D20VRFConsumer` implements `rawFulfillRandomness(requestId, randomness)` and `onRefund(requestId)`; both revert `OnlyCoordinator` unless called by the coordinator proxy given to its constructor, which reverts `InvalidCoordinator` for an address without code.
|
|
24
|
+
|
|
25
|
+
## Contents
|
|
26
|
+
|
|
27
|
+
- [D20VRFCoordinator](#coordinator)
|
|
28
|
+
- [Types](#coordinator-types)
|
|
29
|
+
- [Requesting](#coordinator-requesting)
|
|
30
|
+
- [Pricing and refund settings](#coordinator-pricing-and-refund-settings)
|
|
31
|
+
- [Reading request state and results](#coordinator-reading-request-state-and-results)
|
|
32
|
+
- [Settlement, refunds and credits](#coordinator-settlement-refunds-and-credits)
|
|
33
|
+
- [Settlement balances](#coordinator-settlement-balances)
|
|
34
|
+
- [Keeper and proof functions](#coordinator-keeper-and-proof-functions)
|
|
35
|
+
- [Keeper, key and configuration reads](#coordinator-keeper-key-and-configuration-reads)
|
|
36
|
+
- [Owner administration](#coordinator-owner-administration)
|
|
37
|
+
- [Constants](#coordinator-constants)
|
|
38
|
+
- [Events](#coordinator-events)
|
|
39
|
+
- [Errors](#coordinator-errors)
|
|
40
|
+
- [EpochEntropy](#registry)
|
|
41
|
+
- [Types](#registry-types)
|
|
42
|
+
- [Epoch state for consumers and verifiers](#registry-epoch-state-for-consumers-and-verifiers)
|
|
43
|
+
- [Registry reads](#registry-registry-reads)
|
|
44
|
+
- [Source selection and publication](#registry-source-selection-and-publication)
|
|
45
|
+
- [Recipes and catalogs](#registry-recipes-and-catalogs)
|
|
46
|
+
- [Owner administration](#registry-owner-administration)
|
|
47
|
+
- [Constants](#registry-constants)
|
|
48
|
+
- [Events](#registry-events)
|
|
49
|
+
- [Errors](#registry-errors)
|
|
50
|
+
|
|
51
|
+
## <a id="coordinator"></a>D20VRFCoordinator
|
|
52
|
+
|
|
53
|
+
The consumer entry point. Call the coordinator proxy for your chain (README [Deployments](README.md#deployments)). `ID20VRF` in `contracts/interfaces/ID20VRF.sol` declares the five functions a consumer contract needs (`quoteFee`, `quoteFeeAt`, `requestRandomness`, `requestMappedRandomness`, `getMappedResult`); `coordinatorAbi` from `@d20dao/vrf-sdk/abi` carries everything below. In Solidity, declare a local interface for any other function you call.
|
|
54
|
+
|
|
55
|
+
Requests, fulfillment, `storeBlockHash`, retries, `refundRequest` and withdrawals are `nonReentrant`. A consumer callback (`rawFulfillRandomness`, `onRefund`) that calls one of them fails with `ReentrancyGuardReentrantCall`, and the coordinator records the callback as failed. Views stay callable from callbacks.
|
|
56
|
+
|
|
57
|
+
### <a id="coordinator-types"></a>Types
|
|
58
|
+
|
|
59
|
+
#### <a id="coordinator-type-d20vrfcoordinator-request"></a>`D20VRFCoordinator.Request`
|
|
60
|
+
|
|
61
|
+
Returned by `getRequest`. It does not contain the escrowed fee or the refund ratio; read `requestFeePaid` and `requestRefundBps`.
|
|
62
|
+
|
|
63
|
+
Source: `D20VRFCoordinator.sol` lines 59–77
|
|
64
|
+
|
|
65
|
+
| Field | Type | Meaning |
|
|
66
|
+
| --- | --- | --- |
|
|
67
|
+
| `consumer` | `address` | Contract that made the request; receives `rawFulfillRandomness` and `onRefund`. |
|
|
68
|
+
| `callbackGasLimit` | `uint32` | Gas forwarded to `rawFulfillRandomness` at fulfillment, and the lowest `gasLimit` that `retryCallback` accepts. |
|
|
69
|
+
| `requestBlock` | `uint64` | Block of the request transaction. |
|
|
70
|
+
| `targetBlock` | `uint64` | Block whose hash enters the seed: `max(requestBlock, committedBlock + 1)` of the epoch. 0 until the epoch packet is published. |
|
|
71
|
+
| `deadline` | `uint64` | Request block timestamp plus `RESPONSE_TIMEOUT` (60 seconds), in Unix seconds. A proof accepted in a block with timestamp at or before `deadline` serves the request; `refundRequest` needs a block timestamp after it. |
|
|
72
|
+
| `refundAddress` | `address` | Fixed recipient of the expiry refund and of any overpayment credit. |
|
|
73
|
+
| `clientSeed` | `bytes32` | Value supplied by the consumer, bound into the seed and emitted in `RandomnessRequested`. |
|
|
74
|
+
| `mappingHash` | `bytes32` | `keccak256(abi.encode(operation, lower, upper, count, population))` of the stored spec; `hashMapping(spec)` in TypeScript. |
|
|
75
|
+
| `blockHash` | `bytes32` | Target block hash once `storeBlockHash` or fulfillment stored it; zero before. |
|
|
76
|
+
| `randomness` | `bytes32` | Accepted VRF output. Zero until `fulfilled`. |
|
|
77
|
+
| `proofHash` | `bytes32` | `keccak256(abi.encode(proof))` of the accepted proof. Zero until `fulfilled`. |
|
|
78
|
+
| `transcriptHash` | `bytes32` | `keccak256(abi.encode(TRANSCRIPT_DOMAIN, chainId, coordinator, requestId, protocolConfigurationHash, blockHash, proofHash, randomness, mappingHash, epochId, epochHash))`. Zero until `fulfilled`. |
|
|
79
|
+
| `fulfilled` | `bool` | A proof was accepted. Final: the word can no longer change. |
|
|
80
|
+
| `delivered` | `bool` | A callback attempt succeeded. Stays false after a failed callback until `retryCallback` succeeds; it says nothing about acceptance. |
|
|
81
|
+
| `refunded` | `bool` | `refundRequest` settled the request. Never true together with `fulfilled`. |
|
|
82
|
+
| `epochId` | `uint64` | Epoch of `requestBlock`, fixed at creation; never zero for an existing request. |
|
|
83
|
+
| `epochHash` | `bytes32` | Commitment of the published epoch packet. Zero until the packet is published. |
|
|
84
|
+
|
|
85
|
+
#### <a id="coordinator-type-randomnessmapping-spec"></a>`RandomnessMapping.Spec`
|
|
86
|
+
|
|
87
|
+
A randomness mapping stored with a request ("mapping" here is not a Solidity `mapping`). The TypeScript `MappingSpec` returned by `builtins` has the same five fields in the same order, with `lower` and `upper` as `bigint`, and ethers encodes it for this struct unchanged. Valid combinations: README [Randomness options](README.md#randomness-options).
|
|
88
|
+
|
|
89
|
+
Source: `libraries/RandomnessMapping.sol` lines 7–14
|
|
90
|
+
|
|
91
|
+
| Field | Type | Meaning |
|
|
92
|
+
| --- | --- | --- |
|
|
93
|
+
| `operation` | `RandomnessMapping.Operation` | Enum encoded as uint8: 0 Raw, 1 DiceRoll, 2 CoinFlip, 3 NumberRange, 4 ChooseOne, 5 ChooseMany, 6 Shuffle. |
|
|
94
|
+
| `lower` | `uint256` | NumberRange minimum; zero for every other operation. |
|
|
95
|
+
| `upper` | `uint256` | DiceRoll sides or NumberRange maximum; zero otherwise. |
|
|
96
|
+
| `count` | `uint32` | Values returned: the dice count; 1 for CoinFlip, NumberRange and ChooseOne; the number of choices for ChooseMany; the population for Shuffle; 0 for Raw. |
|
|
97
|
+
| `population` | `uint32` | Number of items (1 to 256) for ChooseOne, ChooseMany and Shuffle; zero otherwise. |
|
|
98
|
+
|
|
99
|
+
#### <a id="coordinator-type-vrf-proof"></a>`VRF.Proof`
|
|
100
|
+
|
|
101
|
+
Chainlink secp256k1 VRF proof, verified by the unmodified vendored `VRF.sol`. ABI-encoded it is 416 bytes: the `FulfillmentEvidence` packet.
|
|
102
|
+
|
|
103
|
+
Source: `vendor/VRF.sol` lines 570–580
|
|
104
|
+
|
|
105
|
+
| Field | Type | Meaning |
|
|
106
|
+
| --- | --- | --- |
|
|
107
|
+
| `pk` | `uint256[2]` | VRF public key; must equal `(publicKeyX, publicKeyY)`. |
|
|
108
|
+
| `gamma` | `uint256[2]` | Proof point. The accepted word is `keccak256(abi.encode(3, gamma))`. |
|
|
109
|
+
| `c` | `uint256` | Proof challenge scalar. |
|
|
110
|
+
| `s` | `uint256` | Proof response scalar. |
|
|
111
|
+
| `seed` | `uint256` | Must equal `requestSeed(requestId)`. |
|
|
112
|
+
| `uWitness` | `address` | Address of `c·pk + s·G`, checked by the verifier. |
|
|
113
|
+
| `cGammaWitness` | `uint256[2]` | Precomputed `c·gamma`, checked by the verifier. |
|
|
114
|
+
| `sHashWitness` | `uint256[2]` | Precomputed `s·hashToCurve(pk, seed)`, checked by the verifier. |
|
|
115
|
+
| `zInv` | `uint256` | Inverse of the projective z coordinate of `cGammaWitness + sHashWitness`. |
|
|
116
|
+
|
|
117
|
+
### <a id="coordinator-requesting"></a>Requesting
|
|
118
|
+
|
|
119
|
+
Requests must come from a contract and pay at least the fee computed in their own transaction; see README [Paying for a request](README.md#paying-for-a-request). The registry call a request makes (`checkpointEpoch` for the current epoch) cannot fail in practice, so requests revert only with the errors listed.
|
|
120
|
+
|
|
121
|
+
#### <a id="coordinator-fn-quotefee"></a>`quoteFee`
|
|
122
|
+
|
|
123
|
+
```solidity
|
|
124
|
+
function quoteFee(uint32 callbackGasLimit) external view returns (uint256)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Selector `0xc9caa0c3` · Caller: Anyone (view) · Source: `D20VRFCoordinator.sol` lines 228–233
|
|
128
|
+
|
|
129
|
+
Fee for a request with this `callbackGasLimit` priced at `block.basefee`, that is `quoteFeeAt(callbackGasLimit, block.basefee)`. Exact inside the requesting transaction, which is how `D20VRFRequests` helpers pay. Through `eth_call` the base fee is commonly reported as 0 (observed on Arc), so the answer collapses to `minFee` and a transaction sent with it reverts `IncorrectFee`. Off-chain, quote with `quoteFeeAt` and the latest header base fee plus a buffer, as `quoteRequestFee` does. It does not check the gas limit range.
|
|
130
|
+
|
|
131
|
+
**Errors:** [`FeeOverflow`](#coordinator-error-feeoverflow).
|
|
132
|
+
|
|
133
|
+
#### <a id="coordinator-fn-quotefeeat"></a>`quoteFeeAt`
|
|
134
|
+
|
|
135
|
+
```solidity
|
|
136
|
+
function quoteFeeAt(uint32 callbackGasLimit, uint256 baseFee) external view returns (uint256)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Selector `0x26fa8481` · Caller: Anyone (view) · Source: `D20VRFCoordinator.sol` lines 220–227
|
|
140
|
+
|
|
141
|
+
`max(minFee, feeMultiplier × baseFee × (fulfillGasOverhead + callbackGasLimit))` over the live pricing for a base fee in wei that you supply; with `feeMultiplier` 0 it returns `minFee`. A quote, not a reservation: pricing can change before your transaction. A `baseFee` large enough to overflow uint256 reverts with `Panic(0x11)` instead of `FeeOverflow`.
|
|
142
|
+
|
|
143
|
+
**Errors:** [`FeeOverflow`](#coordinator-error-feeoverflow).
|
|
144
|
+
|
|
145
|
+
#### <a id="coordinator-fn-requestrandomness"></a>`requestRandomness`
|
|
146
|
+
|
|
147
|
+
```solidity
|
|
148
|
+
function requestRandomness(bytes32 clientSeed, uint32 callbackGasLimit, address _refundAddress) external payable returns (uint256 requestId)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Selector `0x9849d1e5` · Caller: Any contract · Source: `D20VRFCoordinator.sol` lines 235–240, 248–287
|
|
152
|
+
|
|
153
|
+
Creates a raw request (spec all zero) with `msg.sender` as consumer and returns its ID. Needs `msg.value` at least the fee computed in this transaction; escrows exactly that fee and credits any excess to `_refundAddress` as refund credit. Fixes the request block, epoch, client seed, refund address, fee, refund ratio (`refundBps`) and a deadline of `block.timestamp + RESPONSE_TIMEOUT`. After acceptance the consumer receives `rawFulfillRandomness(requestId, randomness)` with exactly `callbackGasLimit` gas. Checks run in this order: caller has code, refund address non-zero, gas limit in range, fee, mapping, epoch started.
|
|
154
|
+
|
|
155
|
+
**Emits:** [`FeeOverpaymentCredited`](#coordinator-event-feeoverpaymentcredited), [`RandomnessRequested`](#coordinator-event-randomnessrequested), [`MappingRequested`](#coordinator-event-mappingrequested).
|
|
156
|
+
|
|
157
|
+
**Errors:** [`ContractConsumerRequired`](#coordinator-error-contractconsumerrequired), [`InvalidRefundAddress`](#coordinator-error-invalidrefundaddress), [`InvalidCallbackGas`](#coordinator-error-invalidcallbackgas), [`FeeOverflow`](#coordinator-error-feeoverflow), [`IncorrectFee`](#coordinator-error-incorrectfee), [`EpochUnavailable`](#coordinator-error-epochunavailable).
|
|
158
|
+
|
|
159
|
+
#### <a id="coordinator-fn-requestmappedrandomness"></a>`requestMappedRandomness`
|
|
160
|
+
|
|
161
|
+
```solidity
|
|
162
|
+
function requestMappedRandomness(bytes32 clientSeed, uint32 callbackGasLimit, address _refundAddress, RandomnessMapping.Spec spec) external payable returns (uint256 requestId)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Selector `0xe6b41a8c` · Caller: Any contract · Source: `D20VRFCoordinator.sol` lines 242–246, 248–287
|
|
166
|
+
|
|
167
|
+
Same as `requestRandomness`, storing `spec` with the request (`getMapping`, `mappingHash`). The callback still carries the raw word; read the mapped values with `getMappedResult`. `D20VRFRequests` helpers call this function and pay `quoteFee` from the calling contract balance.
|
|
168
|
+
|
|
169
|
+
**Emits:** [`FeeOverpaymentCredited`](#coordinator-event-feeoverpaymentcredited), [`RandomnessRequested`](#coordinator-event-randomnessrequested), [`MappingRequested`](#coordinator-event-mappingrequested).
|
|
170
|
+
|
|
171
|
+
**Errors:** [`ContractConsumerRequired`](#coordinator-error-contractconsumerrequired), [`InvalidRefundAddress`](#coordinator-error-invalidrefundaddress), [`InvalidCallbackGas`](#coordinator-error-invalidcallbackgas), [`FeeOverflow`](#coordinator-error-feeoverflow), [`IncorrectFee`](#coordinator-error-incorrectfee), [`InvalidMapping`](#coordinator-error-invalidmapping), [`EpochUnavailable`](#coordinator-error-epochunavailable).
|
|
172
|
+
|
|
173
|
+
### <a id="coordinator-pricing-and-refund-settings"></a>Pricing and refund settings
|
|
174
|
+
|
|
175
|
+
Views, callable by anyone. They describe requests created from now on; an existing request settles from its own snapshots (`requestFeePaid`, `requestRefundBps`).
|
|
176
|
+
|
|
177
|
+
| Function | Selector | Meaning | Source |
|
|
178
|
+
| --- | --- | --- | --- |
|
|
179
|
+
| <a id="coordinator-fn-pricing"></a>`pricing() returns (uint256, uint16, uint32)` | `0x7ce91411` | Live `(minFee, feeMultiplier, fulfillGasOverhead)`. The outputs are unnamed, so read them by position. | lines 211–213 |
|
|
180
|
+
| <a id="coordinator-fn-minfee"></a>`minFee() returns (uint256)` | `0x24ec7590` | Minimum fee in wei, at most `MAX_MIN_FEE` (10 USDC). | line 44 |
|
|
181
|
+
| <a id="coordinator-fn-feemultiplier"></a>`feeMultiplier() returns (uint16)` | `0xe5a70ef7` | Base-fee multiplier, 0 to `MAX_FEE_MULTIPLIER` (20); 0 makes every fee `minFee`. | lines 46–47 |
|
|
182
|
+
| <a id="coordinator-fn-fulfillgasoverhead"></a>`fulfillGasOverhead() returns (uint32)` | `0x19d40839` | Gas added to `callbackGasLimit` in the fee formula, `MIN_FULFILL_GAS_OVERHEAD` to `MAX_FULFILL_GAS_OVERHEAD`. | line 48 |
|
|
183
|
+
| <a id="coordinator-fn-refundbps"></a>`refundBps() returns (uint16)` | `0xec8c9a0b` | Current refund ratio in basis points (5000 to 10000), copied into each new request. Not the ratio of an existing request: use `requestRefundBps(requestId)`. | lines 49–50 |
|
|
184
|
+
|
|
185
|
+
### <a id="coordinator-reading-request-state-and-results"></a>Reading request state and results
|
|
186
|
+
|
|
187
|
+
Views, callable by anyone, including from a callback. Request IDs start at 1 and increase by one; functions taking a `requestId` revert `UnknownRequest` for an ID that was never issued. README [Reading results](README.md#reading-results) shows a polling loop.
|
|
188
|
+
|
|
189
|
+
#### <a id="coordinator-fn-getrequest"></a>`getRequest`
|
|
190
|
+
|
|
191
|
+
```solidity
|
|
192
|
+
function getRequest(uint256 requestId) external view returns (D20VRFCoordinator.Request result)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Selector `0xc58343ef` · Caller: Anyone (view) · Source: `D20VRFCoordinator.sol` lines 289–308, 558–563
|
|
196
|
+
|
|
197
|
+
Full state of a request, see [`D20VRFCoordinator.Request`](#coordinator-type-d20vrfcoordinator-request). `targetBlock` and `epochHash` are resolved from the registry, so they become non-zero as soon as the epoch packet is published. `fulfilled` means the word is final; `delivered` only reports that a callback succeeded. A request that is not `fulfilled` in a block whose timestamp is after `deadline` has expired and can only be refunded. When polling, read the latest block before `getRequest`, so that a proof included up to that block is visible.
|
|
198
|
+
|
|
199
|
+
**Errors:** [`UnknownRequest`](#coordinator-error-unknownrequest).
|
|
200
|
+
|
|
201
|
+
#### <a id="coordinator-fn-getmapping"></a>`getMapping`
|
|
202
|
+
|
|
203
|
+
```solidity
|
|
204
|
+
function getMapping(uint256 requestId) external view returns (RandomnessMapping.Spec)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Selector `0xede9ba8b` · Caller: Anyone (view) · Source: `D20VRFCoordinator.sol` lines 340–343
|
|
208
|
+
|
|
209
|
+
The stored [`RandomnessMapping.Spec`](#coordinator-type-randomnessmapping-spec); all fields zero (Raw) for `requestRandomness`.
|
|
210
|
+
|
|
211
|
+
**Errors:** [`UnknownRequest`](#coordinator-error-unknownrequest).
|
|
212
|
+
|
|
213
|
+
#### <a id="coordinator-fn-getmappedresult"></a>`getMappedResult`
|
|
214
|
+
|
|
215
|
+
```solidity
|
|
216
|
+
function getMappedResult(uint256 requestId) external view returns (uint256[])
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Selector `0x8f09a3e6` · Caller: Anyone (view) · Source: `D20VRFCoordinator.sol` lines 345–349
|
|
220
|
+
|
|
221
|
+
The accepted word mapped with the stored spec: `[uint256(word)]` for a raw request, otherwise the values in README [Randomness options](README.md#randomness-options). Part of `ID20VRF`. Reverts `NotFulfilled` until a proof is accepted, so an expired or refunded request never has a result. Gas grows with the mapping; a 256-item shuffle is expensive onchain.
|
|
222
|
+
|
|
223
|
+
**Errors:** [`UnknownRequest`](#coordinator-error-unknownrequest), [`NotFulfilled`](#coordinator-error-notfulfilled).
|
|
224
|
+
|
|
225
|
+
#### <a id="coordinator-fn-maprandomness"></a>`mapRandomness`
|
|
226
|
+
|
|
227
|
+
```solidity
|
|
228
|
+
function mapRandomness(bytes32 randomness, RandomnessMapping.Spec spec) external pure returns (uint256[])
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Selector `0x41c2a199` · Caller: Anyone (pure) · Source: `D20VRFCoordinator.sol` lines 351–356
|
|
232
|
+
|
|
233
|
+
Maps any word with any valid spec, like the SDK `mapRandomness(word, spec)` off-chain. It does not show that a request was fulfilled.
|
|
234
|
+
|
|
235
|
+
**Errors:** [`InvalidMapping`](#coordinator-error-invalidmapping).
|
|
236
|
+
|
|
237
|
+
#### <a id="coordinator-fn-requestfeepaid"></a>`requestFeePaid`
|
|
238
|
+
|
|
239
|
+
```solidity
|
|
240
|
+
function requestFeePaid(uint256 requestId) external view returns (uint256)
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Selector `0xef7cc992` · Caller: Anyone (view) · Source: `D20VRFCoordinator.sol` lines 331–334
|
|
244
|
+
|
|
245
|
+
Fee escrowed by the request (`feePaid` in `RandomnessRequested`), excluding any overpayment. The keeper share, the protocol share and the refund are computed from it.
|
|
246
|
+
|
|
247
|
+
**Errors:** [`UnknownRequest`](#coordinator-error-unknownrequest).
|
|
248
|
+
|
|
249
|
+
#### <a id="coordinator-fn-requestrefundbps"></a>`requestRefundBps`
|
|
250
|
+
|
|
251
|
+
```solidity
|
|
252
|
+
function requestRefundBps(uint256 requestId) external view returns (uint16)
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Selector `0x5d170fd7` · Caller: Anyone (view) · Source: `D20VRFCoordinator.sol` lines 335–338
|
|
256
|
+
|
|
257
|
+
Refund ratio the request copied from `refundBps` at creation. An expiry refund pays `requestFeePaid × requestRefundBps / 10000`; a later `setRefundBps` does not change it.
|
|
258
|
+
|
|
259
|
+
**Errors:** [`UnknownRequest`](#coordinator-error-unknownrequest).
|
|
260
|
+
|
|
261
|
+
#### <a id="coordinator-fn-refundcallbackdelivered"></a>`refundCallbackDelivered`
|
|
262
|
+
|
|
263
|
+
```solidity
|
|
264
|
+
function refundCallbackDelivered(uint256) external view returns (bool)
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Selector `0x281d3157` · Caller: Anyone (view) · Source: `D20VRFCoordinator.sol` lines 103, 511
|
|
268
|
+
|
|
269
|
+
True once an `onRefund` notification for the request succeeded, at `refundRequest` or `retryRefundCallback`. Returns false for unknown IDs instead of reverting.
|
|
270
|
+
|
|
271
|
+
#### <a id="coordinator-fn-nextrequestid"></a>`nextRequestId`
|
|
272
|
+
|
|
273
|
+
```solidity
|
|
274
|
+
function nextRequestId() external view returns (uint256)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Selector `0x6a84a985` · Caller: Anyone (view) · Source: `D20VRFCoordinator.sol` lines 51, 173, 261
|
|
278
|
+
|
|
279
|
+
ID the next request will receive. Issued IDs are 1 to `nextRequestId() - 1`.
|
|
280
|
+
|
|
281
|
+
### <a id="coordinator-settlement-refunds-and-credits"></a>Settlement, refunds and credits
|
|
282
|
+
|
|
283
|
+
Recovery calls need no value or role. They forward gas to the consumer and revert `InsufficientCallbackGas` rather than forward less, so the transaction gas limit must cover it (README [Gas for refund and retry calls](README.md#gas-for-refund-and-retry-calls)). Refund credit and keeper credit are pull balances: only the holder withdraws them.
|
|
284
|
+
|
|
285
|
+
#### <a id="coordinator-fn-refundrequest"></a>`refundRequest`
|
|
286
|
+
|
|
287
|
+
```solidity
|
|
288
|
+
function refundRequest(uint256 requestId) external
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Selector `0x7411484e` · Caller: Anyone · Source: `D20VRFCoordinator.sol` lines 466–490, 502–513
|
|
292
|
+
|
|
293
|
+
Refunds an unfulfilled request once a block timestamp is after its deadline. Marks it refunded, sends `feePaid × requestRefundBps / 10000` to the fixed refund address with a 30,000-gas transfer, or adds it to that address's refund credit if the transfer fails, and adds the rest of the fee to `earnedFees`. Then calls `onRefund(requestId)` on the consumer with 100,000 gas; a failed notification does not undo the refund. The caller receives nothing. Measured minimum transaction gas limit 302,558 to 357,517; use 400,000.
|
|
294
|
+
|
|
295
|
+
**Emits:** [`RequestRefundedTo`](#coordinator-event-requestrefundedto), [`RefundCallbackAttempted`](#coordinator-event-refundcallbackattempted).
|
|
296
|
+
|
|
297
|
+
**Errors:** [`UnknownRequest`](#coordinator-error-unknownrequest), [`RefundNotAvailable`](#coordinator-error-refundnotavailable), [`InsufficientCallbackGas`](#coordinator-error-insufficientcallbackgas).
|
|
298
|
+
|
|
299
|
+
#### <a id="coordinator-fn-retrycallback"></a>`retryCallback`
|
|
300
|
+
|
|
301
|
+
```solidity
|
|
302
|
+
function retryCallback(uint256 requestId, uint32 gasLimit) external
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Selector `0xdd11c275` · Caller: Anyone · Source: `D20VRFCoordinator.sol` lines 456–464, 613–630
|
|
306
|
+
|
|
307
|
+
Calls `rawFulfillRandomness` again with the same accepted word after a failed callback, forwarding `gasLimit` (30,000 to 1,000,000 and not below the request's `callbackGasLimit`). Sets `delivered` on success. Pays nobody and never changes the word. Transaction gas limit: about `gasLimit + 250,000`.
|
|
308
|
+
|
|
309
|
+
**Emits:** [`CallbackAttempted`](#coordinator-event-callbackattempted).
|
|
310
|
+
|
|
311
|
+
**Errors:** [`UnknownRequest`](#coordinator-error-unknownrequest), [`NotFulfilled`](#coordinator-error-notfulfilled), [`AlreadyDelivered`](#coordinator-error-alreadydelivered), [`InvalidCallbackGas`](#coordinator-error-invalidcallbackgas), [`InsufficientCallbackGas`](#coordinator-error-insufficientcallbackgas).
|
|
312
|
+
|
|
313
|
+
#### <a id="coordinator-fn-retryrefundcallback"></a>`retryRefundCallback`
|
|
314
|
+
|
|
315
|
+
```solidity
|
|
316
|
+
function retryRefundCallback(uint256 requestId, uint32 gasLimit) external
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Selector `0x054f6962` · Caller: Anyone · Source: `D20VRFCoordinator.sol` lines 492–500, 502–513
|
|
320
|
+
|
|
321
|
+
Repeats a failed `onRefund` notification for a refunded request with `gasLimit` (100,000 to 1,000,000). Never transfers funds again. Transaction gas limit: about `gasLimit + 150,000`.
|
|
322
|
+
|
|
323
|
+
**Emits:** [`RefundCallbackAttempted`](#coordinator-event-refundcallbackattempted).
|
|
324
|
+
|
|
325
|
+
**Errors:** [`UnknownRequest`](#coordinator-error-unknownrequest), [`NotRefunded`](#coordinator-error-notrefunded), [`RefundCallbackAlreadyDelivered`](#coordinator-error-refundcallbackalreadydelivered), [`InvalidCallbackGas`](#coordinator-error-invalidcallbackgas), [`InsufficientCallbackGas`](#coordinator-error-insufficientcallbackgas).
|
|
326
|
+
|
|
327
|
+
#### <a id="coordinator-fn-withdrawrefundcredit"></a>`withdrawRefundCredit`
|
|
328
|
+
|
|
329
|
+
```solidity
|
|
330
|
+
function withdrawRefundCredit(address recipient) external
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
Selector `0x445071f2` · Caller: Refund-credit holder · Source: `D20VRFCoordinator.sol` lines 515–525
|
|
334
|
+
|
|
335
|
+
Sends all of the caller's refund credit, `refundCredits(msg.sender)`, to `recipient` with all remaining gas. Credit comes from overpayment and from refund transfers that failed, and belongs to the request's refund address, so that address must make the call. If `recipient` rejects the transfer the call reverts and the credit stays.
|
|
336
|
+
|
|
337
|
+
**Emits:** [`RefundCreditWithdrawn`](#coordinator-event-refundcreditwithdrawn).
|
|
338
|
+
|
|
339
|
+
**Errors:** [`InvalidRefundAddress`](#coordinator-error-invalidrefundaddress), [`NoRefundCredit`](#coordinator-error-norefundcredit), [`TransferFailed`](#coordinator-error-transferfailed).
|
|
340
|
+
|
|
341
|
+
#### <a id="coordinator-fn-withdrawfees"></a>`withdrawFees`
|
|
342
|
+
|
|
343
|
+
```solidity
|
|
344
|
+
function withdrawFees(address recipient) external
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Selector `0x164e68de` · Caller: Fee recipient · Source: `D20VRFCoordinator.sol` lines 527–536
|
|
348
|
+
|
|
349
|
+
Sends all `earnedFees` to `recipient`. Fees accrue at acceptance (fee minus keeper share) and from the part of a refunded fee that is not returned; open escrow is never included. With nothing earned it sends zero without reverting.
|
|
350
|
+
|
|
351
|
+
**Emits:** [`FeesWithdrawn`](#coordinator-event-feeswithdrawn).
|
|
352
|
+
|
|
353
|
+
**Errors:** [`OnlyFeeRecipient`](#coordinator-error-onlyfeerecipient), [`InvalidConfig`](#coordinator-error-invalidconfig), [`TransferFailed`](#coordinator-error-transferfailed).
|
|
354
|
+
|
|
355
|
+
#### <a id="coordinator-fn-withdrawkeepercredit"></a>`withdrawKeeperCredit`
|
|
356
|
+
|
|
357
|
+
```solidity
|
|
358
|
+
function withdrawKeeperCredit(address recipient) external
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Selector `0xf62c546b` · Caller: Keeper-credit holder · Source: `D20VRFCoordinator.sol` lines 538–547
|
|
362
|
+
|
|
363
|
+
Sends all of the caller's keeper credit (keeper-share transfers that failed) to `recipient`.
|
|
364
|
+
|
|
365
|
+
**Emits:** [`KeeperCreditWithdrawn`](#coordinator-event-keepercreditwithdrawn).
|
|
366
|
+
|
|
367
|
+
**Errors:** [`InvalidConfig`](#coordinator-error-invalidconfig), [`NoKeeperCredit`](#coordinator-error-nokeepercredit), [`TransferFailed`](#coordinator-error-transferfailed).
|
|
368
|
+
|
|
369
|
+
### <a id="coordinator-settlement-balances"></a>Settlement balances
|
|
370
|
+
|
|
371
|
+
Views, callable by anyone. Amounts are in wei of native USDC.
|
|
372
|
+
|
|
373
|
+
| Function | Selector | Meaning | Source |
|
|
374
|
+
| --- | --- | --- | --- |
|
|
375
|
+
| <a id="coordinator-fn-refundcredits"></a>`refundCredits(address) returns (uint256)` | `0x61137e40` | Refund credit that an address can withdraw with `withdrawRefundCredit`. | line 57 |
|
|
376
|
+
| <a id="coordinator-fn-totalrefundcredits"></a>`totalRefundCredits() returns (uint256)` | `0x6e0842e1` | Sum of all refund credit held by the coordinator. | line 56 |
|
|
377
|
+
| <a id="coordinator-fn-earnedfees"></a>`earnedFees() returns (uint256)` | `0xb1b3ffd9` | Protocol fees that the fee recipient can withdraw. | line 52 |
|
|
378
|
+
| <a id="coordinator-fn-feerecipient"></a>`feeRecipient() returns (address)` | `0x46904840` | Address allowed to call `withdrawFees`; changed with `setFeeRecipient`. | line 40 |
|
|
379
|
+
| <a id="coordinator-fn-keeperfeebps"></a>`keeperFeeBps() returns (uint16)` | `0x0eab7d63` | Keeper share of each accepted fee in basis points (0 to 10000). Read at acceptance, not snapshotted: a change applies to open requests accepted afterwards. It only splits the escrowed fee; what the consumer paid and can be refunded does not change. | lines 41, 433 |
|
|
380
|
+
| <a id="coordinator-fn-keepercredits"></a>`keeperCredits(address) returns (uint256)` | `0xf5c764f6` | Keeper credit that an address can withdraw with `withdrawKeeperCredit`. | line 42 |
|
|
381
|
+
| <a id="coordinator-fn-totalkeepercredits"></a>`totalKeeperCredits() returns (uint256)` | `0xc7281b7a` | Sum of all keeper credit held by the coordinator. | line 43 |
|
|
382
|
+
|
|
383
|
+
### <a id="coordinator-keeper-and-proof-functions"></a>Keeper and proof functions
|
|
384
|
+
|
|
385
|
+
Proof submission is permissionless: anyone holding a valid proof may submit it, and the keeper share goes to the submitting wallet when the registry authorizes it as its committer or a backup committer, and to `committer()` otherwise. Consumers normally only read `getRequest`. Besides the custom errors listed, proof functions can revert with `Error(string)` messages from the vendored VRF verifier, such as `invalid proof`, which are not in the ABI.
|
|
386
|
+
|
|
387
|
+
#### <a id="coordinator-fn-fulfillrandomness"></a>`fulfillRandomness`
|
|
388
|
+
|
|
389
|
+
```solidity
|
|
390
|
+
function fulfillRandomness(uint256 requestId, VRF.Proof proof) external
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
Selector `0xef7c2b19` · Caller: Anyone · Source: `D20VRFCoordinator.sol` lines 389–397, 413–448
|
|
394
|
+
|
|
395
|
+
Accepts a proof for a request that is not fulfilled, not refunded and not past its deadline; acceptance in a block with timestamp equal to `deadline` is timely. Stores the target block hash if needed, verifies the proof against `requestSeed(requestId)`, stores the word, proof hash and transcript hash, sets `fulfilled`, adds `feePaid` minus the keeper share to `earnedFees` and calls the consumer with `callbackGasLimit` gas. It then sends the keeper share (`keeperFeeBps` of `feePaid`) with 30,000 gas to the submitting wallet when the registry answers `isAuthorizedCommitter` true for it (the committer or an allowed backup committer) and to `committer()` otherwise, or records it as that wallet's keeper credit; a registry call that reverts also pays `committer()`. A failing callback does not revert the fulfillment.
|
|
396
|
+
|
|
397
|
+
**Emits:** [`BlockHashStored`](#coordinator-event-blockhashstored), [`RequestServed`](#coordinator-event-requestserved), [`ProofVerified`](#coordinator-event-proofverified), [`RandomnessFulfilled`](#coordinator-event-randomnessfulfilled), [`FulfillmentEvidence`](#coordinator-event-fulfillmentevidence), [`CallbackAttempted`](#coordinator-event-callbackattempted), [`KeeperFeePaid`](#coordinator-event-keeperfeepaid).
|
|
398
|
+
|
|
399
|
+
**Errors:** [`UnknownRequest`](#coordinator-error-unknownrequest), [`AlreadyFulfilled`](#coordinator-error-alreadyfulfilled), [`RequestRefunded`](#coordinator-error-requestrefunded), [`RequestExpired`](#coordinator-error-requestexpired), [`NotReady`](#coordinator-error-notready), [`BlockHashUnavailable`](#coordinator-error-blockhashunavailable), [`WrongPublicKey`](#coordinator-error-wrongpublickey), [`WrongSeed`](#coordinator-error-wrongseed), [`EvidencePacketTooLarge`](#coordinator-error-evidencepackettoolarge), [`InsufficientCallbackGas`](#coordinator-error-insufficientcallbackgas).
|
|
400
|
+
|
|
401
|
+
#### <a id="coordinator-fn-fulfillrandomnessbatch"></a>`fulfillRandomnessBatch`
|
|
402
|
+
|
|
403
|
+
```solidity
|
|
404
|
+
function fulfillRandomnessBatch(uint256[] ids, VRF.Proof[] proofs) external
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
Selector `0x9497b180` · Caller: Anyone · Source: `D20VRFCoordinator.sol` lines 399–411
|
|
408
|
+
|
|
409
|
+
Fulfills up to `MAX_FULFILL_BATCH` (16) requests, one proof each. Members already fulfilled, refunded or past their deadline, including an ID repeated in the batch, are skipped with `FulfillmentSkipped`; every other member runs exactly like `fulfillRandomness` and emits the same events, so an unknown ID, an unready member or an invalid proof reverts the whole batch.
|
|
410
|
+
|
|
411
|
+
**Emits:** [`FulfillmentSkipped`](#coordinator-event-fulfillmentskipped), [`BlockHashStored`](#coordinator-event-blockhashstored), [`RequestServed`](#coordinator-event-requestserved), [`ProofVerified`](#coordinator-event-proofverified), [`RandomnessFulfilled`](#coordinator-event-randomnessfulfilled), [`FulfillmentEvidence`](#coordinator-event-fulfillmentevidence), [`CallbackAttempted`](#coordinator-event-callbackattempted), [`KeeperFeePaid`](#coordinator-event-keeperfeepaid).
|
|
412
|
+
|
|
413
|
+
**Errors:** [`InvalidBatch`](#coordinator-error-invalidbatch), [`UnknownRequest`](#coordinator-error-unknownrequest), [`NotReady`](#coordinator-error-notready), [`BlockHashUnavailable`](#coordinator-error-blockhashunavailable), [`WrongPublicKey`](#coordinator-error-wrongpublickey), [`WrongSeed`](#coordinator-error-wrongseed), [`EvidencePacketTooLarge`](#coordinator-error-evidencepackettoolarge), [`InsufficientCallbackGas`](#coordinator-error-insufficientcallbackgas).
|
|
414
|
+
|
|
415
|
+
#### <a id="coordinator-fn-storeblockhash"></a>`storeBlockHash`
|
|
416
|
+
|
|
417
|
+
```solidity
|
|
418
|
+
function storeBlockHash(uint256 requestId) external returns (bytes32)
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
Selector `0x262fd733` · Caller: Anyone · Source: `D20VRFCoordinator.sol` lines 368–372, 564–579
|
|
422
|
+
|
|
423
|
+
Resolves the target block from the published epoch, stores its hash if not stored yet and returns it. Fulfillment does this automatically; calling it earlier keeps a request provable after its target leaves the 256-block `BLOCKHASH` window. Needs `block.number` at least `targetBlock + confirmationBlocks`. Works on any request, whatever its status.
|
|
424
|
+
|
|
425
|
+
**Emits:** [`BlockHashStored`](#coordinator-event-blockhashstored).
|
|
426
|
+
|
|
427
|
+
**Errors:** [`UnknownRequest`](#coordinator-error-unknownrequest), [`NotReady`](#coordinator-error-notready), [`BlockHashUnavailable`](#coordinator-error-blockhashunavailable).
|
|
428
|
+
|
|
429
|
+
#### <a id="coordinator-fn-verifyrequestproof"></a>`verifyRequestProof`
|
|
430
|
+
|
|
431
|
+
```solidity
|
|
432
|
+
function verifyRequestProof(uint256 requestId, VRF.Proof proof) external view returns (bytes32)
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
Selector `0x0846de99` · Caller: Anyone (view) · Source: `D20VRFCoordinator.sol` lines 358–366
|
|
436
|
+
|
|
437
|
+
Returns the word a proof yields for the request's seed, without changing state. A valid proof is not acceptance: check `getRequest(requestId).fulfilled`.
|
|
438
|
+
|
|
439
|
+
**Errors:** [`UnknownRequest`](#coordinator-error-unknownrequest), [`NotReady`](#coordinator-error-notready), [`BlockHashUnavailable`](#coordinator-error-blockhashunavailable), [`WrongPublicKey`](#coordinator-error-wrongpublickey), [`WrongSeed`](#coordinator-error-wrongseed).
|
|
440
|
+
|
|
441
|
+
#### <a id="coordinator-fn-requestseed"></a>`requestSeed`
|
|
442
|
+
|
|
443
|
+
```solidity
|
|
444
|
+
function requestSeed(uint256 requestId) external view returns (uint256)
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
Selector `0xa9df851a` · Caller: Anyone (view) · Source: `D20VRFCoordinator.sol` lines 374–379, 581–589
|
|
448
|
+
|
|
449
|
+
Seed the proof must use: `keccak256(abi.encode(SEED_DOMAIN, chainId, coordinator, keyHash, requestId, consumer, clientSeed, mappingHash, requestBlock, targetBlock, blockHash, epochId, epochHash))` as uint256. Available only after publication and `confirmationBlocks` confirmations of the target block.
|
|
450
|
+
|
|
451
|
+
**Errors:** [`UnknownRequest`](#coordinator-error-unknownrequest), [`NotReady`](#coordinator-error-notready), [`BlockHashUnavailable`](#coordinator-error-blockhashunavailable).
|
|
452
|
+
|
|
453
|
+
#### <a id="coordinator-fn-getproofcontext"></a>`getProofContext`
|
|
454
|
+
|
|
455
|
+
```solidity
|
|
456
|
+
function getProofContext(uint256 requestId) external view returns (uint256 seed, uint64 deadline, bool fulfilled, bool refunded)
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
Selector `0xcf14de9d` · Caller: Anyone (view) · Source: `D20VRFCoordinator.sol` lines 381–387
|
|
460
|
+
|
|
461
|
+
`requestSeed` together with `deadline`, `fulfilled` and `refunded`. It reverts `NotReady` like `requestSeed`, so it is not a status read for waiting requests; use `getRequest`.
|
|
462
|
+
|
|
463
|
+
**Errors:** [`UnknownRequest`](#coordinator-error-unknownrequest), [`NotReady`](#coordinator-error-notready), [`BlockHashUnavailable`](#coordinator-error-blockhashunavailable).
|
|
464
|
+
|
|
465
|
+
#### <a id="coordinator-fn-getpendingrequestids"></a>`getPendingRequestIds`
|
|
466
|
+
|
|
467
|
+
```solidity
|
|
468
|
+
function getPendingRequestIds(uint256 fromId, uint256 limit) external view returns (uint256[] ids, uint256 nextCursor)
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
Selector `0xfdfe72e6` · Caller: Anyone (view) · Source: `D20VRFCoordinator.sol` lines 310–329
|
|
472
|
+
|
|
473
|
+
Scans `limit` (1 to 256) request IDs from `fromId` (at least 1) and returns those not fulfilled, not refunded and not past their deadline, with the ID to continue from. Continue with `nextCursor` until it equals `nextRequestId()`. The answer can be stale by the time a transaction lands.
|
|
474
|
+
|
|
475
|
+
**Errors:** [`InvalidScan`](#coordinator-error-invalidscan).
|
|
476
|
+
|
|
477
|
+
### <a id="coordinator-keeper-key-and-configuration-reads"></a>Keeper, key and configuration reads
|
|
478
|
+
|
|
479
|
+
Views, callable by anyone. Nothing here has a setter except through an upgrade.
|
|
480
|
+
|
|
481
|
+
| Function | Selector | Meaning | Source |
|
|
482
|
+
| --- | --- | --- | --- |
|
|
483
|
+
| <a id="coordinator-fn-lastservedrequestid"></a>`lastServedRequestId() returns (uint256)` | `0xef54e226` | ID of the most recently accepted request; 0 before the first. | lines 53, 435 |
|
|
484
|
+
| <a id="coordinator-fn-lastservedindex"></a>`lastServedIndex() returns (uint256)` | `0x7e176eed` | Number of accepted requests so far: the `serveIndex` of the latest `RequestServed`. | lines 54, 436 |
|
|
485
|
+
| <a id="coordinator-fn-servedrequestat"></a>`servedRequestAt(uint256) returns (uint256)` | `0xf9a4acc6` | Request ID accepted at a serve index (from 1); 0 for an index not used yet. | lines 55, 436 |
|
|
486
|
+
| <a id="coordinator-fn-keyhash"></a>`keyHash() returns (bytes32)` | `0x61728f39` | `keccak256(abi.encode(publicKey))` of the VRF key; indexed in `RandomnessRequested` and `ProofVerified`. | lines 37, 180 |
|
|
487
|
+
| <a id="coordinator-fn-publickeyx"></a>`publicKeyX() returns (uint256)` | `0xfa6df55d` | x coordinate of the VRF public key. | line 35 |
|
|
488
|
+
| <a id="coordinator-fn-publickeyy"></a>`publicKeyY() returns (uint256)` | `0xd7a6f6e8` | y coordinate of the VRF public key. | line 36 |
|
|
489
|
+
| <a id="coordinator-fn-confirmationblocks"></a>`confirmationBlocks() returns (uint16)` | `0x460a58aa` | Blocks after the target block before the seed and proofs become available (1 to 64, set at initialization). | lines 45, 566 |
|
|
490
|
+
| <a id="coordinator-fn-epochregistry"></a>`epochRegistry() returns (address)` | `0x2b12cb69` | The `EpochEntropy` proxy that supplies epochs and the keeper-share recipient. | line 33 |
|
|
491
|
+
| <a id="coordinator-fn-protocolconfigurationhash"></a>`protocolConfigurationHash() returns (bytes32)` | `0x155cf49b` | Hash of the initialized configuration (public key, initial fee recipient, initial minimum fee, confirmations, registry, initial catalog hash, first epoch start, epoch length 200) under `CONFIG_DOMAIN`. Bound into every transcript hash. | lines 32, 190 |
|
|
492
|
+
| <a id="coordinator-fn-initialfeerecipient"></a>`initialFeeRecipient() returns (address)` | `0x308c2d6b` | Fee recipient given to `initialize`, used by replay. The live payout address is `feeRecipient()`. | lines 39, 182 |
|
|
493
|
+
| <a id="coordinator-fn-initialminfee"></a>`initialMinFee() returns (uint256)` | `0xb3839295` | Minimum fee given to `initialize`, used by replay. The live minimum is `minFee()`. | lines 105, 185 |
|
|
494
|
+
|
|
495
|
+
### <a id="coordinator-owner-administration"></a>Owner administration
|
|
496
|
+
|
|
497
|
+
Owner-only functions revert `OwnableUnauthorizedAccount` for anyone else. No setter can change an existing request, the VRF key, the registry or the confirmations.
|
|
498
|
+
|
|
499
|
+
#### <a id="coordinator-fn-setpricing"></a>`setPricing`
|
|
500
|
+
|
|
501
|
+
```solidity
|
|
502
|
+
function setPricing(uint256 nextMinFee, uint16 multiplier, uint32 overhead) external
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
Selector `0x4c729ce6` · Caller: Owner · Source: `D20VRFCoordinator.sol` lines 205–210
|
|
506
|
+
|
|
507
|
+
Sets `minFee` (at most `MAX_MIN_FEE`, 10 USDC), `feeMultiplier` (at most `MAX_FEE_MULTIPLIER`, 20) and `fulfillGasOverhead` (`MIN_FULFILL_GAS_OVERHEAD` to `MAX_FULFILL_GAS_OVERHEAD`, 100,000 to 2,000,000 gas). Affects requests created afterwards; open requests keep their escrowed fee.
|
|
508
|
+
|
|
509
|
+
**Emits:** [`PricingChanged`](#coordinator-event-pricingchanged).
|
|
510
|
+
|
|
511
|
+
**Errors:** [`OwnableUnauthorizedAccount`](#coordinator-error-ownableunauthorizedaccount), [`InvalidConfig`](#coordinator-error-invalidconfig).
|
|
512
|
+
|
|
513
|
+
#### <a id="coordinator-fn-setrefundbps"></a>`setRefundBps`
|
|
514
|
+
|
|
515
|
+
```solidity
|
|
516
|
+
function setRefundBps(uint16 next) external
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
Selector `0x55a94d1b` · Caller: Owner · Source: `D20VRFCoordinator.sol` lines 214–218
|
|
520
|
+
|
|
521
|
+
Sets the refund ratio for requests created afterwards, `MIN_REFUND_BPS` (5000) to 10000.
|
|
522
|
+
|
|
523
|
+
**Emits:** [`RefundBpsChanged`](#coordinator-event-refundbpschanged).
|
|
524
|
+
|
|
525
|
+
**Errors:** [`OwnableUnauthorizedAccount`](#coordinator-error-ownableunauthorizedaccount), [`InvalidConfig`](#coordinator-error-invalidconfig).
|
|
526
|
+
|
|
527
|
+
#### <a id="coordinator-fn-setkeeperfeebps"></a>`setKeeperFeeBps`
|
|
528
|
+
|
|
529
|
+
```solidity
|
|
530
|
+
function setKeeperFeeBps(uint16 next) external
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
Selector `0xe140f0ca` · Caller: Owner · Source: `D20VRFCoordinator.sol` lines 201–204
|
|
534
|
+
|
|
535
|
+
Sets the keeper share, 0 to 10000 basis points. Read at each acceptance, so it also applies to open requests accepted later.
|
|
536
|
+
|
|
537
|
+
**Emits:** [`KeeperFeeBpsChanged`](#coordinator-event-keeperfeebpschanged).
|
|
538
|
+
|
|
539
|
+
**Errors:** [`OwnableUnauthorizedAccount`](#coordinator-error-ownableunauthorizedaccount), [`InvalidConfig`](#coordinator-error-invalidconfig).
|
|
540
|
+
|
|
541
|
+
#### <a id="coordinator-fn-setfeerecipient"></a>`setFeeRecipient`
|
|
542
|
+
|
|
543
|
+
```solidity
|
|
544
|
+
function setFeeRecipient(address next) external
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
Selector `0xe74b981b` · Caller: Owner · Source: `D20VRFCoordinator.sol` lines 197–200
|
|
548
|
+
|
|
549
|
+
Sets the address allowed to withdraw `earnedFees`, including fees earned before the change. The zero address is rejected.
|
|
550
|
+
|
|
551
|
+
**Emits:** [`FeeRecipientChanged`](#coordinator-event-feerecipientchanged).
|
|
552
|
+
|
|
553
|
+
**Errors:** [`OwnableUnauthorizedAccount`](#coordinator-error-ownableunauthorizedaccount), [`InvalidConfig`](#coordinator-error-invalidconfig).
|
|
554
|
+
|
|
555
|
+
#### <a id="coordinator-fn-owner"></a>`owner`
|
|
556
|
+
|
|
557
|
+
```solidity
|
|
558
|
+
function owner() external view returns (address)
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
Selector `0x8da5cb5b` · Caller: Anyone (view)
|
|
562
|
+
|
|
563
|
+
Current owner: upgrade authority and the only account that can call the setters.
|
|
564
|
+
|
|
565
|
+
#### <a id="coordinator-fn-pendingowner"></a>`pendingOwner`
|
|
566
|
+
|
|
567
|
+
```solidity
|
|
568
|
+
function pendingOwner() external view returns (address)
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
Selector `0xe30c3978` · Caller: Anyone (view)
|
|
572
|
+
|
|
573
|
+
Account nominated by `transferOwnership` that has not accepted yet; zero when none.
|
|
574
|
+
|
|
575
|
+
#### <a id="coordinator-fn-transferownership"></a>`transferOwnership`
|
|
576
|
+
|
|
577
|
+
```solidity
|
|
578
|
+
function transferOwnership(address newOwner) external
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
Selector `0xf2fde38b` · Caller: Owner
|
|
582
|
+
|
|
583
|
+
Starts a two-step transfer by nominating `newOwner`; ownership moves only when that account calls `acceptOwnership`. A new call replaces the nomination, and the zero address cancels it.
|
|
584
|
+
|
|
585
|
+
**Emits:** [`OwnershipTransferStarted`](#coordinator-event-ownershiptransferstarted).
|
|
586
|
+
|
|
587
|
+
**Errors:** [`OwnableUnauthorizedAccount`](#coordinator-error-ownableunauthorizedaccount).
|
|
588
|
+
|
|
589
|
+
#### <a id="coordinator-fn-acceptownership"></a>`acceptOwnership`
|
|
590
|
+
|
|
591
|
+
```solidity
|
|
592
|
+
function acceptOwnership() external
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
Selector `0x79ba5097` · Caller: Pending owner
|
|
596
|
+
|
|
597
|
+
Completes the transfer to the caller and clears the nomination.
|
|
598
|
+
|
|
599
|
+
**Emits:** [`OwnershipTransferred`](#coordinator-event-ownershiptransferred).
|
|
600
|
+
|
|
601
|
+
**Errors:** [`OwnableUnauthorizedAccount`](#coordinator-error-ownableunauthorizedaccount).
|
|
602
|
+
|
|
603
|
+
#### <a id="coordinator-fn-renounceownership"></a>`renounceOwnership`
|
|
604
|
+
|
|
605
|
+
```solidity
|
|
606
|
+
function renounceOwnership() external view
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
Selector `0x715018a6` · Caller: Owner · Source: `D20VRFCoordinator.sol` lines 194–195
|
|
610
|
+
|
|
611
|
+
Disabled and declared `view`: the owner gets `RenounceDisabled` and anyone else `OwnableUnauthorizedAccount`, so the contract always has an owner and upgrade authority can only move through an accepted transfer.
|
|
612
|
+
|
|
613
|
+
**Errors:** [`OwnableUnauthorizedAccount`](#coordinator-error-ownableunauthorizedaccount), [`RenounceDisabled`](#coordinator-error-renouncedisabled).
|
|
614
|
+
|
|
615
|
+
#### <a id="coordinator-fn-upgradetoandcall"></a>`upgradeToAndCall`
|
|
616
|
+
|
|
617
|
+
```solidity
|
|
618
|
+
function upgradeToAndCall(address newImplementation, bytes data) external payable
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
Selector `0x4f1ef286` · Caller: Owner, through the proxy
|
|
622
|
+
|
|
623
|
+
UUPS upgrade: points the proxy at `newImplementation`, which must report the ERC-1967 slot from `proxiableUUID`, and delegatecalls `data` when it is non-empty. An upgrade can change any behavior described here. Integrators check the implementation when they integrate and again whenever a proxy emits `Upgraded` or the deployment manifest records an upgrade (README [Security and trust](README.md#security-and-trust)).
|
|
624
|
+
|
|
625
|
+
**Emits:** [`Upgraded`](#coordinator-event-upgraded).
|
|
626
|
+
|
|
627
|
+
**Errors:** [`UUPSUnauthorizedCallContext`](#coordinator-error-uupsunauthorizedcallcontext), [`OwnableUnauthorizedAccount`](#coordinator-error-ownableunauthorizedaccount), [`ERC1967InvalidImplementation`](#coordinator-error-erc1967invalidimplementation), [`UUPSUnsupportedProxiableUUID`](#coordinator-error-uupsunsupportedproxiableuuid), [`ERC1967NonPayable`](#coordinator-error-erc1967nonpayable), [`AddressEmptyCode`](#coordinator-error-addressemptycode), [`FailedCall`](#coordinator-error-failedcall).
|
|
628
|
+
|
|
629
|
+
#### <a id="coordinator-fn-proxiableuuid"></a>`proxiableUUID`
|
|
630
|
+
|
|
631
|
+
```solidity
|
|
632
|
+
function proxiableUUID() external view returns (bytes32)
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
Selector `0x52d1902d` · Caller: Anyone (view)
|
|
636
|
+
|
|
637
|
+
ERC-1822 check used by `upgradeToAndCall`. Returns the ERC-1967 implementation slot when called on an implementation contract directly and reverts through the proxy.
|
|
638
|
+
|
|
639
|
+
**Errors:** [`UUPSUnauthorizedCallContext`](#coordinator-error-uupsunauthorizedcallcontext).
|
|
640
|
+
|
|
641
|
+
#### <a id="coordinator-fn-initialize"></a>`initialize`
|
|
642
|
+
|
|
643
|
+
```solidity
|
|
644
|
+
function initialize(uint256[2] publicKey, address initialOwner, address recipient, uint256 fee, uint16 confirmations, address registry, uint16 keeperBps) external
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
Selector `0x56b95b47` · Caller: Once, by `D20Proxy` at deployment · Source: `D20VRFCoordinator.sol` lines 170–191
|
|
648
|
+
|
|
649
|
+
Sets owner, VRF public key, fee recipient, minimum fee, confirmations, registry and keeper share, with `feeMultiplier` 5, `fulfillGasOverhead` 300,000 and `refundBps` 10000. A public key that is not on the curve can also revert with an `Error(string)` from the verifier.
|
|
650
|
+
|
|
651
|
+
**Emits:** [`OwnershipTransferred`](#coordinator-event-ownershiptransferred), [`Initialized`](#coordinator-event-initialized).
|
|
652
|
+
|
|
653
|
+
**Errors:** [`InvalidInitialization`](#coordinator-error-invalidinitialization), [`OwnableInvalidOwner`](#coordinator-error-ownableinvalidowner), [`InvalidConfig`](#coordinator-error-invalidconfig), [`InvalidPublicKey`](#coordinator-error-invalidpublickey).
|
|
654
|
+
|
|
655
|
+
### <a id="coordinator-constants"></a>Constants
|
|
656
|
+
|
|
657
|
+
Views returning values fixed in the implementation code.
|
|
658
|
+
|
|
659
|
+
| Constant | Returns | Value | Selector | Meaning |
|
|
660
|
+
| --- | --- | --- | --- | --- |
|
|
661
|
+
| <a id="coordinator-fn-min_callback_gas"></a>`MIN_CALLBACK_GAS` | `uint32` | `30_000` | `0x4374e10c` | Lowest `callbackGasLimit` and `retryCallback` gas limit. |
|
|
662
|
+
| <a id="coordinator-fn-max_callback_gas"></a>`MAX_CALLBACK_GAS` | `uint32` | `1_000_000` | `0x6d9809a0` | Highest callback or notification gas limit. |
|
|
663
|
+
| <a id="coordinator-fn-response_timeout"></a>`RESPONSE_TIMEOUT` | `uint64` | `60 seconds` | `0x11e219d7` | Seconds from the request block timestamp to `deadline`. |
|
|
664
|
+
| <a id="coordinator-fn-refund_callback_gas"></a>`REFUND_CALLBACK_GAS` | `uint32` | `100_000` | `0x8a8ae284` | Gas for the first `onRefund` notification, and the lowest `retryRefundCallback` gas limit. |
|
|
665
|
+
| <a id="coordinator-fn-max_fulfill_batch"></a>`MAX_FULFILL_BATCH` | `uint256` | `16` | `0x1d7e0cc4` | Most requests per `fulfillRandomnessBatch`. |
|
|
666
|
+
| <a id="coordinator-fn-max_evidence_packet_bytes"></a>`MAX_EVIDENCE_PACKET_BYTES` | `uint256` | `512` | `0x7fcf2f33` | Upper bound on the `FulfillmentEvidence` packet (actual size 416 bytes). |
|
|
667
|
+
| <a id="coordinator-fn-max_min_fee"></a>`MAX_MIN_FEE` | `uint256` | `10e18` | `0x8483d43e` | Highest `minFee`: 10 USDC in 18-decimal native units. |
|
|
668
|
+
| <a id="coordinator-fn-max_fee_multiplier"></a>`MAX_FEE_MULTIPLIER` | `uint16` | `20` | `0xb6994144` | Highest `feeMultiplier`. |
|
|
669
|
+
| <a id="coordinator-fn-min_fulfill_gas_overhead"></a>`MIN_FULFILL_GAS_OVERHEAD` | `uint32` | `100_000` | `0x35ccd0b4` | Lowest `fulfillGasOverhead`. |
|
|
670
|
+
| <a id="coordinator-fn-max_fulfill_gas_overhead"></a>`MAX_FULFILL_GAS_OVERHEAD` | `uint32` | `2_000_000` | `0x2a06b47d` | Highest `fulfillGasOverhead`. |
|
|
671
|
+
| <a id="coordinator-fn-min_refund_bps"></a>`MIN_REFUND_BPS` | `uint16` | `5000` | `0xaf7718f1` | Lowest `refundBps` (50%). |
|
|
672
|
+
| <a id="coordinator-fn-seed_domain"></a>`SEED_DOMAIN` | `bytes32` | `keccak256("D20_VRF_SEED")` | `0x6000054d` | Domain tag of `requestSeed`. |
|
|
673
|
+
| <a id="coordinator-fn-transcript_domain"></a>`TRANSCRIPT_DOMAIN` | `bytes32` | `keccak256("D20_VRF_TRANSCRIPT")` | `0xab2fde00` | Domain tag of the transcript hash. |
|
|
674
|
+
| <a id="coordinator-fn-config_domain"></a>`CONFIG_DOMAIN` | `bytes32` | `keccak256("D20_VRF_CONFIG")` | `0x3624ffed` | Domain tag of `protocolConfigurationHash`. |
|
|
675
|
+
| <a id="coordinator-fn-upgrade_interface_version"></a>`UPGRADE_INTERFACE_VERSION` | `string` | `"5.0.0"` | `0xad3cb1cc` | OpenZeppelin UUPS interface version: upgrades go through `upgradeToAndCall` only. |
|
|
676
|
+
|
|
677
|
+
### <a id="coordinator-events"></a>Events
|
|
678
|
+
|
|
679
|
+
**Request lifecycle**
|
|
680
|
+
|
|
681
|
+
#### <a id="coordinator-event-randomnessrequested"></a>`RandomnessRequested`
|
|
682
|
+
|
|
683
|
+
```solidity
|
|
684
|
+
event RandomnessRequested(uint256 indexed requestId, address indexed consumer, bytes32 indexed keyHash, bytes32 clientSeed, uint64 requestBlock, uint32 callbackGasLimit, uint256 feePaid, address refundAddress, uint64 deadline)
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
Topic 0 `0xaf91b17376114a36689aa115062983bda7b43263a891fb8de0cc69d30d4240ad` · Emitted by: [`requestRandomness`](#coordinator-fn-requestrandomness), [`requestMappedRandomness`](#coordinator-fn-requestmappedrandomness) · Source: `D20VRFCoordinator.sol` lines 139–143, 284–285
|
|
688
|
+
|
|
689
|
+
A request was created. `feePaid` is the escrowed fee, not `msg.value`; `deadline` is the block timestamp plus 60 seconds. Read `requestId` from this log in the request receipt, filtering by the coordinator address and event name: with an overpayment, `FeeOverpaymentCredited` comes first.
|
|
690
|
+
|
|
691
|
+
#### <a id="coordinator-event-mappingrequested"></a>`MappingRequested`
|
|
692
|
+
|
|
693
|
+
```solidity
|
|
694
|
+
event MappingRequested(uint256 indexed requestId, bytes32 indexed mappingHash, RandomnessMapping.Spec spec)
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
Topic 0 `0xbe1c93f40bd74ff9acd22dc40818e36d04e0b8a49b8238d0537c63219c2336dd` · Emitted by: [`requestRandomness`](#coordinator-fn-requestrandomness), [`requestMappedRandomness`](#coordinator-fn-requestmappedrandomness) · Source: `D20VRFCoordinator.sol` lines 158, 286
|
|
698
|
+
|
|
699
|
+
Emitted right after `RandomnessRequested` with the stored spec (all zero for a raw request) and its hash.
|
|
700
|
+
|
|
701
|
+
#### <a id="coordinator-event-feeoverpaymentcredited"></a>`FeeOverpaymentCredited`
|
|
702
|
+
|
|
703
|
+
```solidity
|
|
704
|
+
event FeeOverpaymentCredited(uint256 indexed requestId, address indexed refundAddress, uint256 amount)
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
Topic 0 `0x8ae693db98f043f48e8f427375449ed5576aba97575e4f7f93ff2c1f6c75dcb5` · Emitted by: [`requestRandomness`](#coordinator-fn-requestrandomness), [`requestMappedRandomness`](#coordinator-fn-requestmappedrandomness) · Source: `D20VRFCoordinator.sol` lines 152, 278–283
|
|
708
|
+
|
|
709
|
+
`msg.value` exceeded the fee and `amount` was added to `refundCredits(refundAddress)`, independently of what happens to the request. Emitted before `RandomnessRequested`.
|
|
710
|
+
|
|
711
|
+
#### <a id="coordinator-event-blockhashstored"></a>`BlockHashStored`
|
|
712
|
+
|
|
713
|
+
```solidity
|
|
714
|
+
event BlockHashStored(uint256 indexed requestId, uint64 targetBlock, bytes32 blockHash)
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
Topic 0 `0x81bc3b4ec75af0fb9ed3521d7c766d8f995d04b0735c17d61ff9d468b0f04911` · Emitted by: [`fulfillRandomness`](#coordinator-fn-fulfillrandomness), [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch), [`storeBlockHash`](#coordinator-fn-storeblockhash) · Source: `D20VRFCoordinator.sol` lines 144, 572–579
|
|
718
|
+
|
|
719
|
+
The target block hash of the request was stored. Emitted once per request: by `storeBlockHash`, or by fulfillment if the hash was not stored before.
|
|
720
|
+
|
|
721
|
+
#### <a id="coordinator-event-requestserved"></a>`RequestServed`
|
|
722
|
+
|
|
723
|
+
```solidity
|
|
724
|
+
event RequestServed(uint256 indexed requestId, uint256 indexed serveIndex)
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
Topic 0 `0x2012511e6cebd578bcabff1ef3346edb032cbab8622e9f23d9f15d7d1037267f` · Emitted by: [`fulfillRandomness`](#coordinator-fn-fulfillrandomness), [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch) · Source: `D20VRFCoordinator.sol` lines 160, 435–437
|
|
728
|
+
|
|
729
|
+
A proof was accepted. `serveIndex` counts accepted requests from 1 (`lastServedIndex`, `servedRequestAt`).
|
|
730
|
+
|
|
731
|
+
#### <a id="coordinator-event-proofverified"></a>`ProofVerified`
|
|
732
|
+
|
|
733
|
+
```solidity
|
|
734
|
+
event ProofVerified(uint256 indexed requestId, bytes32 indexed keyHash, uint256 seed, bytes32 proofHash)
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
Topic 0 `0x55bb25be3ecd9f68ceae7cdabf4eabe2e0940bd8fc1c26c0d68ad5f7c5d08d22` · Emitted by: [`fulfillRandomness`](#coordinator-fn-fulfillrandomness), [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch) · Source: `D20VRFCoordinator.sol` lines 159, 438
|
|
738
|
+
|
|
739
|
+
Seed and hash of the accepted proof.
|
|
740
|
+
|
|
741
|
+
#### <a id="coordinator-event-randomnessfulfilled"></a>`RandomnessFulfilled`
|
|
742
|
+
|
|
743
|
+
```solidity
|
|
744
|
+
event RandomnessFulfilled(uint256 indexed requestId, bytes32 randomness, address indexed submitter)
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
Topic 0 `0x9c82683ee7932041c254d206bcce4241d66a811d53ee7191799cc120777b2b87` · Emitted by: [`fulfillRandomness`](#coordinator-fn-fulfillrandomness), [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch) · Source: `D20VRFCoordinator.sol` lines 145, 439
|
|
748
|
+
|
|
749
|
+
A proof was accepted and `randomness` is final. `submitter` sent the transaction; `KeeperFeePaid` names the wallet that received the keeper share, which is `submitter` only when the registry authorizes it.
|
|
750
|
+
|
|
751
|
+
#### <a id="coordinator-event-fulfillmentevidence"></a>`FulfillmentEvidence`
|
|
752
|
+
|
|
753
|
+
```solidity
|
|
754
|
+
event FulfillmentEvidence(uint256 indexed requestId, bytes32 indexed transcriptHash, bytes packet)
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
Topic 0 `0xa121bbea897439460dfb08c3e6d6af064bc1f31e9477471828a87c5596b92e77` · Emitted by: [`fulfillRandomness`](#coordinator-fn-fulfillrandomness), [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch) · Source: `D20VRFCoordinator.sol` lines 163–164, 450–454
|
|
758
|
+
|
|
759
|
+
The accepted proof as a 416-byte ABI-encoded packet, indexed by `transcriptHash`. Decode it with `decodeEvidencePacket`; take evidence from this log, not from calldata, since a batch carries several proofs.
|
|
760
|
+
|
|
761
|
+
#### <a id="coordinator-event-callbackattempted"></a>`CallbackAttempted`
|
|
762
|
+
|
|
763
|
+
```solidity
|
|
764
|
+
event CallbackAttempted(uint256 indexed requestId, bool success, uint32 gasLimit)
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
Topic 0 `0x70f64c0739e827900ae6f2e1317601653f4080bc857f423671fc58d5822f1f4a` · Emitted by: [`retryCallback`](#coordinator-fn-retrycallback), [`fulfillRandomness`](#coordinator-fn-fulfillrandomness), [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch) · Source: `D20VRFCoordinator.sol` lines 146, 613–630
|
|
768
|
+
|
|
769
|
+
Result of calling `rawFulfillRandomness` with `gasLimit` gas, at fulfillment and at each `retryCallback`. `success` false means the consumer reverted, ran out of gas or has no code; the word is accepted either way.
|
|
770
|
+
|
|
771
|
+
#### <a id="coordinator-event-keeperfeepaid"></a>`KeeperFeePaid`
|
|
772
|
+
|
|
773
|
+
```solidity
|
|
774
|
+
event KeeperFeePaid(uint256 indexed requestId, address indexed keeper, uint256 amount, bool paid)
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
Topic 0 `0x7605929b04963e0365f647d9ab12e7ac4aeba5474bb80f1e1554fccad0584683` · Emitted by: [`fulfillRandomness`](#coordinator-fn-fulfillrandomness), [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch) · Source: `D20VRFCoordinator.sol` lines 153, 442–447
|
|
778
|
+
|
|
779
|
+
At acceptance, when the keeper share is non-zero: `amount` went to `keeper`, the submitter when the registry authorizes it and `committer()` otherwise, by a 30,000-gas transfer (`paid` true) or was added to `keeperCredits(keeper)` (`paid` false). Emitted after `CallbackAttempted`.
|
|
780
|
+
|
|
781
|
+
#### <a id="coordinator-event-fulfillmentskipped"></a>`FulfillmentSkipped`
|
|
782
|
+
|
|
783
|
+
```solidity
|
|
784
|
+
event FulfillmentSkipped(uint256 indexed requestId, uint8 reason)
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
Topic 0 `0x45d96bda73a91db41bdeab56114e5d7b9f42c9f38add9e2d2c6d6f5761203ca3` · Emitted by: [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch) · Source: `D20VRFCoordinator.sol` lines 161–162, 407–408
|
|
788
|
+
|
|
789
|
+
A batch member was left untouched: `reason` 1 already fulfilled, 2 refunded, 3 past its deadline.
|
|
790
|
+
|
|
791
|
+
#### <a id="coordinator-event-requestrefundedto"></a>`RequestRefundedTo`
|
|
792
|
+
|
|
793
|
+
```solidity
|
|
794
|
+
event RequestRefundedTo(uint256 indexed requestId, address indexed refundAddress, uint256 amount, bool paid)
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
Topic 0 `0x0f6107d218fea62a20553f3700dba7c94dcf653bd2027c0bf1ebe0832f42a506` · Emitted by: [`refundRequest`](#coordinator-fn-refundrequest) · Source: `D20VRFCoordinator.sol` lines 155, 488
|
|
798
|
+
|
|
799
|
+
An expired request was refunded: `amount` (`feePaid × requestRefundBps / 10000`) was sent to `refundAddress` (`paid` true) or added to its refund credit (`paid` false).
|
|
800
|
+
|
|
801
|
+
#### <a id="coordinator-event-refundcallbackattempted"></a>`RefundCallbackAttempted`
|
|
802
|
+
|
|
803
|
+
```solidity
|
|
804
|
+
event RefundCallbackAttempted(uint256 indexed requestId, address indexed consumer, bool success, uint32 gasLimit)
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
Topic 0 `0x88448c9fbcfc67f28f0266e82766e402ccd28115fbb84edb6e5b2597effe83d8` · Emitted by: [`refundRequest`](#coordinator-fn-refundrequest), [`retryRefundCallback`](#coordinator-fn-retryrefundcallback) · Source: `D20VRFCoordinator.sol` lines 157, 502–513
|
|
808
|
+
|
|
809
|
+
Result of calling `onRefund(requestId)` on `consumer` with `gasLimit` gas: 100,000 at `refundRequest`, the caller's limit at `retryRefundCallback`.
|
|
810
|
+
|
|
811
|
+
**Credits and withdrawals**
|
|
812
|
+
|
|
813
|
+
#### <a id="coordinator-event-refundcreditwithdrawn"></a>`RefundCreditWithdrawn`
|
|
814
|
+
|
|
815
|
+
```solidity
|
|
816
|
+
event RefundCreditWithdrawn(address indexed owner, address indexed recipient, uint256 amount)
|
|
817
|
+
```
|
|
818
|
+
|
|
819
|
+
Topic 0 `0x9d520065b24fda0469128acd3f3078de7e43d70ab762aeea8c741bde25070192` · Emitted by: [`withdrawRefundCredit`](#coordinator-fn-withdrawrefundcredit) · Source: `D20VRFCoordinator.sol` lines 156, 524
|
|
820
|
+
|
|
821
|
+
`owner`, the credit holder (not the contract owner), withdrew `amount` of refund credit to `recipient`.
|
|
822
|
+
|
|
823
|
+
#### <a id="coordinator-event-keepercreditwithdrawn"></a>`KeeperCreditWithdrawn`
|
|
824
|
+
|
|
825
|
+
```solidity
|
|
826
|
+
event KeeperCreditWithdrawn(address indexed keeper, address indexed recipient, uint256 amount)
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
Topic 0 `0x22f05c41968705c032a86a65f8fda7e64483ea5e6b6b27a920d1fbfab94267ba` · Emitted by: [`withdrawKeeperCredit`](#coordinator-fn-withdrawkeepercredit) · Source: `D20VRFCoordinator.sol` lines 154, 546
|
|
830
|
+
|
|
831
|
+
`keeper` withdrew `amount` of keeper credit to `recipient`.
|
|
832
|
+
|
|
833
|
+
#### <a id="coordinator-event-feeswithdrawn"></a>`FeesWithdrawn`
|
|
834
|
+
|
|
835
|
+
```solidity
|
|
836
|
+
event FeesWithdrawn(address indexed recipient, uint256 amount)
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
Topic 0 `0xc0819c13be868895eb93e40eaceb96de976442fa1d404e5c55f14bb65a8c489a` · Emitted by: [`withdrawFees`](#coordinator-fn-withdrawfees) · Source: `D20VRFCoordinator.sol` lines 147, 535
|
|
840
|
+
|
|
841
|
+
The fee recipient withdrew `amount` of earned fees to `recipient`.
|
|
842
|
+
|
|
843
|
+
**Administration and upgrades**
|
|
844
|
+
|
|
845
|
+
#### <a id="coordinator-event-pricingchanged"></a>`PricingChanged`
|
|
846
|
+
|
|
847
|
+
```solidity
|
|
848
|
+
event PricingChanged(uint256 minFee, uint16 feeMultiplier, uint32 fulfillGasOverhead)
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
Topic 0 `0x32806eb5e21ac2f5fb7d11f898c2995e19fdf203c8a5aeed8b824506cd0d44ff` · Emitted by: [`setPricing`](#coordinator-fn-setpricing) · Source: `D20VRFCoordinator.sol` lines 150, 209
|
|
852
|
+
|
|
853
|
+
New `minFee`, `feeMultiplier` and `fulfillGasOverhead` for requests created afterwards.
|
|
854
|
+
|
|
855
|
+
#### <a id="coordinator-event-refundbpschanged"></a>`RefundBpsChanged`
|
|
856
|
+
|
|
857
|
+
```solidity
|
|
858
|
+
event RefundBpsChanged(uint16 previousBps, uint16 newBps)
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
Topic 0 `0x21e3c4cf3007c4ee385a3936593ff4cfa23fc17bca1175b6350c546f9810e0d8` · Emitted by: [`setRefundBps`](#coordinator-fn-setrefundbps) · Source: `D20VRFCoordinator.sol` lines 151, 217
|
|
862
|
+
|
|
863
|
+
New refund ratio for requests created afterwards.
|
|
864
|
+
|
|
865
|
+
#### <a id="coordinator-event-keeperfeebpschanged"></a>`KeeperFeeBpsChanged`
|
|
866
|
+
|
|
867
|
+
```solidity
|
|
868
|
+
event KeeperFeeBpsChanged(uint16 previousBps, uint16 newBps)
|
|
869
|
+
```
|
|
870
|
+
|
|
871
|
+
Topic 0 `0xa648a60f1d22511c1cc898ca69b633d1a1114079e83734b9ab9a13e0e28c68b7` · Emitted by: [`setKeeperFeeBps`](#coordinator-fn-setkeeperfeebps) · Source: `D20VRFCoordinator.sol` lines 149, 203
|
|
872
|
+
|
|
873
|
+
New keeper share, applied at later acceptances, including of requests already open.
|
|
874
|
+
|
|
875
|
+
#### <a id="coordinator-event-feerecipientchanged"></a>`FeeRecipientChanged`
|
|
876
|
+
|
|
877
|
+
```solidity
|
|
878
|
+
event FeeRecipientChanged(address indexed previousRecipient, address indexed newRecipient)
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
Topic 0 `0x0bc21fe5c3ab742ff1d15b5c4477ffbacf1167e618228078fa625edebe7f331d` · Emitted by: [`setFeeRecipient`](#coordinator-fn-setfeerecipient) · Source: `D20VRFCoordinator.sol` lines 148, 199
|
|
882
|
+
|
|
883
|
+
New address allowed to withdraw earned fees.
|
|
884
|
+
|
|
885
|
+
#### <a id="coordinator-event-ownershiptransferstarted"></a>`OwnershipTransferStarted`
|
|
886
|
+
|
|
887
|
+
```solidity
|
|
888
|
+
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner)
|
|
889
|
+
```
|
|
890
|
+
|
|
891
|
+
Topic 0 `0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700` · Emitted by: [`transferOwnership`](#coordinator-fn-transferownership)
|
|
892
|
+
|
|
893
|
+
`transferOwnership` nominated `newOwner`; the zero address means a nomination was cancelled.
|
|
894
|
+
|
|
895
|
+
#### <a id="coordinator-event-ownershiptransferred"></a>`OwnershipTransferred`
|
|
896
|
+
|
|
897
|
+
```solidity
|
|
898
|
+
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
Topic 0 `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` · Emitted by: [`acceptOwnership`](#coordinator-fn-acceptownership), [`initialize`](#coordinator-fn-initialize)
|
|
902
|
+
|
|
903
|
+
Ownership moved: from the zero address at initialization, and at each `acceptOwnership`.
|
|
904
|
+
|
|
905
|
+
#### <a id="coordinator-event-upgraded"></a>`Upgraded`
|
|
906
|
+
|
|
907
|
+
```solidity
|
|
908
|
+
event Upgraded(address indexed implementation)
|
|
909
|
+
```
|
|
910
|
+
|
|
911
|
+
Topic 0 `0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b` · Emitted by: [`upgradeToAndCall`](#coordinator-fn-upgradetoandcall), proxy deployment
|
|
912
|
+
|
|
913
|
+
The proxy now runs `implementation`. Emitted by the proxy at deployment and at every `upgradeToAndCall`. Compare the address with the deployment manifest; an implementation you have not reviewed means stop and review before sending more requests.
|
|
914
|
+
|
|
915
|
+
#### <a id="coordinator-event-initialized"></a>`Initialized`
|
|
916
|
+
|
|
917
|
+
```solidity
|
|
918
|
+
event Initialized(uint64 version)
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
Topic 0 `0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2` · Emitted by: [`initialize`](#coordinator-fn-initialize)
|
|
922
|
+
|
|
923
|
+
`initialize` ran on the proxy (`version` 1). Each implementation contract also emitted it once at construction with `version` 2^64 − 1, which locks the implementation against initialization.
|
|
924
|
+
|
|
925
|
+
### <a id="coordinator-errors"></a>Errors
|
|
926
|
+
|
|
927
|
+
**Requesting**
|
|
928
|
+
|
|
929
|
+
#### <a id="coordinator-error-contractconsumerrequired"></a>`ContractConsumerRequired`
|
|
930
|
+
|
|
931
|
+
`error ContractConsumerRequired()` · Selector `0x2b99db1e` · Source: `D20VRFCoordinator.sol` lines 111, 251
|
|
932
|
+
|
|
933
|
+
**Raised by:** [`requestRandomness`](#coordinator-fn-requestrandomness), [`requestMappedRandomness`](#coordinator-fn-requestmappedrandomness).
|
|
934
|
+
|
|
935
|
+
The caller of a request function has no code: an externally owned account, or a contract still running its constructor.
|
|
936
|
+
|
|
937
|
+
**What to do:** Send the request through a deployed consumer contract (README [Integrate a consumer](README.md#integrate-a-consumer)), and not from its constructor.
|
|
938
|
+
|
|
939
|
+
#### <a id="coordinator-error-invalidrefundaddress"></a>`InvalidRefundAddress`
|
|
940
|
+
|
|
941
|
+
`error InvalidRefundAddress()` · Selector `0xe2fe2726` · Source: `D20VRFCoordinator.sol` lines 125, 252, 517
|
|
942
|
+
|
|
943
|
+
**Raised by:** [`requestRandomness`](#coordinator-fn-requestrandomness), [`requestMappedRandomness`](#coordinator-fn-requestmappedrandomness), [`withdrawRefundCredit`](#coordinator-fn-withdrawrefundcredit).
|
|
944
|
+
|
|
945
|
+
A request named the zero address as refund address, or `withdrawRefundCredit` named the zero address as recipient.
|
|
946
|
+
|
|
947
|
+
**What to do:** Pass a non-zero address that can receive a plain native transfer or call `withdrawRefundCredit`.
|
|
948
|
+
|
|
949
|
+
#### <a id="coordinator-error-invalidcallbackgas"></a>`InvalidCallbackGas`
|
|
950
|
+
|
|
951
|
+
`error InvalidCallbackGas()` · Selector `0x35883c54` · Source: `D20VRFCoordinator.sol` lines 113, 462, 498, 609–611
|
|
952
|
+
|
|
953
|
+
**Raised by:** [`requestRandomness`](#coordinator-fn-requestrandomness), [`requestMappedRandomness`](#coordinator-fn-requestmappedrandomness), [`retryCallback`](#coordinator-fn-retrycallback), [`retryRefundCallback`](#coordinator-fn-retryrefundcallback).
|
|
954
|
+
|
|
955
|
+
A gas limit is out of range: a request `callbackGasLimit` outside 30,000 to 1,000,000; a `retryCallback` limit outside that range or below the request's `callbackGasLimit`; a `retryRefundCallback` limit outside 100,000 to 1,000,000.
|
|
956
|
+
|
|
957
|
+
**What to do:** Use a limit inside the range; retry with at least the original limit.
|
|
958
|
+
|
|
959
|
+
#### <a id="coordinator-error-incorrectfee"></a>`IncorrectFee`
|
|
960
|
+
|
|
961
|
+
`error IncorrectFee(uint256 expected, uint256 actual)` · Selector `0xdcf6afcb` · Source: `D20VRFCoordinator.sol` lines 112, 255
|
|
962
|
+
|
|
963
|
+
**Raised by:** [`requestRandomness`](#coordinator-fn-requestrandomness), [`requestMappedRandomness`](#coordinator-fn-requestmappedrandomness).
|
|
964
|
+
|
|
965
|
+
`actual` (`msg.value`) is below `expected`, the fee computed in the request transaction. No request was created.
|
|
966
|
+
|
|
967
|
+
**What to do:** Quote again with `quoteFeeAt(callbackGasLimit, latestBlock.baseFeePerGas)` plus a buffer (`quoteRequestFee`) and resend. A contract paying in the same transaction sends `quoteFee(callbackGasLimit)`. Never quote with `quoteFee` through `eth_call`.
|
|
968
|
+
|
|
969
|
+
#### <a id="coordinator-error-feeoverflow"></a>`FeeOverflow`
|
|
970
|
+
|
|
971
|
+
`error FeeOverflow()` · Selector `0x8181adca` · Source: `D20VRFCoordinator.sol` lines 136, 225
|
|
972
|
+
|
|
973
|
+
**Raised by:** [`quoteFee`](#coordinator-fn-quotefee), [`quoteFeeAt`](#coordinator-fn-quotefeeat), [`requestRandomness`](#coordinator-fn-requestrandomness), [`requestMappedRandomness`](#coordinator-fn-requestmappedrandomness).
|
|
974
|
+
|
|
975
|
+
The dynamic fee exceeds the uint96 escrow limit. Within the pricing bounds that needs a base fee above about 1.3e21 wei.
|
|
976
|
+
|
|
977
|
+
**What to do:** Not expected on a live chain. For `quoteFeeAt`, check that `baseFee` is in wei.
|
|
978
|
+
|
|
979
|
+
#### <a id="coordinator-error-invalidmapping"></a>`InvalidMapping`
|
|
980
|
+
|
|
981
|
+
`error InvalidMapping()` · Selector `0x07a966e0` · Source: `libraries/RandomnessMapping.sol` lines 19, 21–39
|
|
982
|
+
|
|
983
|
+
**Raised by:** [`requestMappedRandomness`](#coordinator-fn-requestmappedrandomness), [`mapRandomness`](#coordinator-fn-maprandomness).
|
|
984
|
+
|
|
985
|
+
The spec breaks the rules for its operation (README [Randomness options](README.md#randomness-options)). Declared in `RandomnessMapping`.
|
|
986
|
+
|
|
987
|
+
**What to do:** Build specs with the `D20VRFRequests` helpers or TypeScript `builtins`, which enforce the same bounds.
|
|
988
|
+
|
|
989
|
+
#### <a id="coordinator-error-epochunavailable"></a>`EpochUnavailable`
|
|
990
|
+
|
|
991
|
+
`error EpochUnavailable()` · Selector `0x0b3487b8` · Source: `D20VRFCoordinator.sol` lines 109, 259
|
|
992
|
+
|
|
993
|
+
**Raised by:** [`requestRandomness`](#coordinator-fn-requestrandomness), [`requestMappedRandomness`](#coordinator-fn-requestmappedrandomness).
|
|
994
|
+
|
|
995
|
+
The request block is before the registry's first epoch: `epochForBlock(block.number)` is 0.
|
|
996
|
+
|
|
997
|
+
**What to do:** Not expected on the Arc deployments, whose epochs have started. Check that you call the coordinator proxy for your chain; on a new deployment, wait for `firstEpochStart`.
|
|
998
|
+
|
|
999
|
+
**Reading and recovery**
|
|
1000
|
+
|
|
1001
|
+
#### <a id="coordinator-error-unknownrequest"></a>`UnknownRequest`
|
|
1002
|
+
|
|
1003
|
+
`error UnknownRequest()` · Selector `0x6d080297` · Source: `D20VRFCoordinator.sol` lines 114, 549–552
|
|
1004
|
+
|
|
1005
|
+
**Raised by:** [`getRequest`](#coordinator-fn-getrequest), [`getMapping`](#coordinator-fn-getmapping), [`getMappedResult`](#coordinator-fn-getmappedresult), [`requestFeePaid`](#coordinator-fn-requestfeepaid), [`requestRefundBps`](#coordinator-fn-requestrefundbps), [`refundRequest`](#coordinator-fn-refundrequest), [`retryCallback`](#coordinator-fn-retrycallback), [`retryRefundCallback`](#coordinator-fn-retryrefundcallback), [`fulfillRandomness`](#coordinator-fn-fulfillrandomness), [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch), [`storeBlockHash`](#coordinator-fn-storeblockhash), [`verifyRequestProof`](#coordinator-fn-verifyrequestproof), [`requestSeed`](#coordinator-fn-requestseed), [`getProofContext`](#coordinator-fn-getproofcontext).
|
|
1006
|
+
|
|
1007
|
+
No request has this ID: 0, or not below `nextRequestId()`. An unknown ID also reverts a whole `fulfillRandomnessBatch`.
|
|
1008
|
+
|
|
1009
|
+
**What to do:** Take `requestId` from the `RandomnessRequested` log of the request receipt, and read from the same chain and coordinator proxy.
|
|
1010
|
+
|
|
1011
|
+
#### <a id="coordinator-error-notfulfilled"></a>`NotFulfilled`
|
|
1012
|
+
|
|
1013
|
+
`error NotFulfilled()` · Selector `0x07bc6c3e` · Source: `D20VRFCoordinator.sol` lines 118, 347, 459
|
|
1014
|
+
|
|
1015
|
+
**Raised by:** [`getMappedResult`](#coordinator-fn-getmappedresult), [`retryCallback`](#coordinator-fn-retrycallback).
|
|
1016
|
+
|
|
1017
|
+
`getMappedResult` or `retryCallback` on a request without an accepted proof, including an expired or refunded one.
|
|
1018
|
+
|
|
1019
|
+
**What to do:** Poll `getRequest(requestId)` until `fulfilled`. Once a block timestamp is after `deadline` without fulfillment, the request has expired and only `refundRequest` applies.
|
|
1020
|
+
|
|
1021
|
+
#### <a id="coordinator-error-alreadydelivered"></a>`AlreadyDelivered`
|
|
1022
|
+
|
|
1023
|
+
`error AlreadyDelivered()` · Selector `0xb9f79653` · Source: `D20VRFCoordinator.sol` lines 119, 460
|
|
1024
|
+
|
|
1025
|
+
**Raised by:** [`retryCallback`](#coordinator-fn-retrycallback).
|
|
1026
|
+
|
|
1027
|
+
`retryCallback` on a request whose callback already succeeded.
|
|
1028
|
+
|
|
1029
|
+
**What to do:** Nothing to retry.
|
|
1030
|
+
|
|
1031
|
+
#### <a id="coordinator-error-refundnotavailable"></a>`RefundNotAvailable`
|
|
1032
|
+
|
|
1033
|
+
`error RefundNotAvailable()` · Selector `0x0b4d6981` · Source: `D20VRFCoordinator.sol` lines 128, 471
|
|
1034
|
+
|
|
1035
|
+
**Raised by:** [`refundRequest`](#coordinator-fn-refundrequest).
|
|
1036
|
+
|
|
1037
|
+
`refundRequest` on a request that is fulfilled, already refunded, or not yet past its deadline (the block timestamp must be greater than `deadline`).
|
|
1038
|
+
|
|
1039
|
+
**What to do:** Read `getRequest`: use the result if `fulfilled`, stop if `refunded`, otherwise retry after a block with a later timestamp than `deadline`.
|
|
1040
|
+
|
|
1041
|
+
#### <a id="coordinator-error-notrefunded"></a>`NotRefunded`
|
|
1042
|
+
|
|
1043
|
+
`error NotRefunded()` · Selector `0xfae7079c` · Source: `D20VRFCoordinator.sol` lines 131, 495
|
|
1044
|
+
|
|
1045
|
+
**Raised by:** [`retryRefundCallback`](#coordinator-fn-retryrefundcallback).
|
|
1046
|
+
|
|
1047
|
+
`retryRefundCallback` on a request that has not been refunded.
|
|
1048
|
+
|
|
1049
|
+
**What to do:** Call `refundRequest` after the deadline first.
|
|
1050
|
+
|
|
1051
|
+
#### <a id="coordinator-error-refundcallbackalreadydelivered"></a>`RefundCallbackAlreadyDelivered`
|
|
1052
|
+
|
|
1053
|
+
`error RefundCallbackAlreadyDelivered()` · Selector `0x6502f8ae` · Source: `D20VRFCoordinator.sol` lines 132, 496
|
|
1054
|
+
|
|
1055
|
+
**Raised by:** [`retryRefundCallback`](#coordinator-fn-retryrefundcallback).
|
|
1056
|
+
|
|
1057
|
+
`retryRefundCallback` after an `onRefund` notification already succeeded (`refundCallbackDelivered`).
|
|
1058
|
+
|
|
1059
|
+
**What to do:** Nothing to retry.
|
|
1060
|
+
|
|
1061
|
+
#### <a id="coordinator-error-insufficientcallbackgas"></a>`InsufficientCallbackGas`
|
|
1062
|
+
|
|
1063
|
+
`error InsufficientCallbackGas()` · Selector `0xa2c23f0d` · Source: `D20VRFCoordinator.sol` lines 122, 480, 505, 621–622
|
|
1064
|
+
|
|
1065
|
+
**Raised by:** [`refundRequest`](#coordinator-fn-refundrequest), [`retryCallback`](#coordinator-fn-retrycallback), [`retryRefundCallback`](#coordinator-fn-retryrefundcallback), [`fulfillRandomness`](#coordinator-fn-fulfillrandomness), [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch).
|
|
1066
|
+
|
|
1067
|
+
Too little gas remained to forward the full callback budget and keep the coordinator's reserve: `gasLimit + gasLimit/63 + 140,000` before a fulfillment callback, `100,000 + 100,000/63 + 140,000` after refund settlement, `gasLimit + gasLimit/63 + 50,000` before a refund notification. The coordinator reverts instead of forwarding less.
|
|
1068
|
+
|
|
1069
|
+
**What to do:** Raise the transaction gas limit: 400,000 for `refundRequest`, `gasLimit + 250,000` for `retryCallback`, `gasLimit + 150,000` for `retryRefundCallback` (README [Gas for refund and retry calls](README.md#gas-for-refund-and-retry-calls)). `eth_estimateGas` finds the minimum.
|
|
1070
|
+
|
|
1071
|
+
**Credits and withdrawals**
|
|
1072
|
+
|
|
1073
|
+
#### <a id="coordinator-error-norefundcredit"></a>`NoRefundCredit`
|
|
1074
|
+
|
|
1075
|
+
`error NoRefundCredit()` · Selector `0x1d59da8e` · Source: `D20VRFCoordinator.sol` lines 129, 519
|
|
1076
|
+
|
|
1077
|
+
**Raised by:** [`withdrawRefundCredit`](#coordinator-fn-withdrawrefundcredit).
|
|
1078
|
+
|
|
1079
|
+
`withdrawRefundCredit` from an address without refund credit. Credit is keyed by the refund address, which must be `msg.sender`.
|
|
1080
|
+
|
|
1081
|
+
**What to do:** Call from the refund address; `refundCredits(address)` shows the balance.
|
|
1082
|
+
|
|
1083
|
+
#### <a id="coordinator-error-transferfailed"></a>`TransferFailed`
|
|
1084
|
+
|
|
1085
|
+
`error TransferFailed()` · Selector `0x90b8ec18` · Source: `D20VRFCoordinator.sol` lines 124, 523, 534, 545
|
|
1086
|
+
|
|
1087
|
+
**Raised by:** [`withdrawRefundCredit`](#coordinator-fn-withdrawrefundcredit), [`withdrawFees`](#coordinator-fn-withdrawfees), [`withdrawKeeperCredit`](#coordinator-fn-withdrawkeepercredit).
|
|
1088
|
+
|
|
1089
|
+
The `recipient` of `withdrawRefundCredit`, `withdrawFees` or `withdrawKeeperCredit` rejected the native transfer. Balances are unchanged.
|
|
1090
|
+
|
|
1091
|
+
**What to do:** Choose a recipient that accepts plain native transfers.
|
|
1092
|
+
|
|
1093
|
+
#### <a id="coordinator-error-onlyfeerecipient"></a>`OnlyFeeRecipient`
|
|
1094
|
+
|
|
1095
|
+
`error OnlyFeeRecipient()` · Selector `0x07d8ed3d` · Source: `D20VRFCoordinator.sol` lines 123, 529
|
|
1096
|
+
|
|
1097
|
+
**Raised by:** [`withdrawFees`](#coordinator-fn-withdrawfees).
|
|
1098
|
+
|
|
1099
|
+
`withdrawFees` from an address other than `feeRecipient()`.
|
|
1100
|
+
|
|
1101
|
+
**What to do:** Only the fee recipient withdraws protocol fees.
|
|
1102
|
+
|
|
1103
|
+
#### <a id="coordinator-error-nokeepercredit"></a>`NoKeeperCredit`
|
|
1104
|
+
|
|
1105
|
+
`error NoKeeperCredit()` · Selector `0x0d106640` · Source: `D20VRFCoordinator.sol` lines 130, 541
|
|
1106
|
+
|
|
1107
|
+
**Raised by:** [`withdrawKeeperCredit`](#coordinator-fn-withdrawkeepercredit).
|
|
1108
|
+
|
|
1109
|
+
`withdrawKeeperCredit` from an address without keeper credit.
|
|
1110
|
+
|
|
1111
|
+
**What to do:** `keeperCredits(address)` shows the balance.
|
|
1112
|
+
|
|
1113
|
+
**Proofs and keepers**
|
|
1114
|
+
|
|
1115
|
+
#### <a id="coordinator-error-notready"></a>`NotReady`
|
|
1116
|
+
|
|
1117
|
+
`error NotReady()` · Selector `0x9488aaa6` · Source: `D20VRFCoordinator.sol` lines 115, 566
|
|
1118
|
+
|
|
1119
|
+
**Raised by:** [`fulfillRandomness`](#coordinator-fn-fulfillrandomness), [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch), [`storeBlockHash`](#coordinator-fn-storeblockhash), [`verifyRequestProof`](#coordinator-fn-verifyrequestproof), [`requestSeed`](#coordinator-fn-requestseed), [`getProofContext`](#coordinator-fn-getproofcontext).
|
|
1120
|
+
|
|
1121
|
+
The request cannot be proven yet: its epoch packet is not published, or `block.number` is below `targetBlock + confirmationBlocks`.
|
|
1122
|
+
|
|
1123
|
+
**What to do:** For a consumer this only means the request is still waiting. Keepers retry after publication and confirmations.
|
|
1124
|
+
|
|
1125
|
+
#### <a id="coordinator-error-blockhashunavailable"></a>`BlockHashUnavailable`
|
|
1126
|
+
|
|
1127
|
+
`error BlockHashUnavailable()` · Selector `0xbfc9f0d3` · Source: `D20VRFCoordinator.sol` lines 116, 569
|
|
1128
|
+
|
|
1129
|
+
**Raised by:** [`fulfillRandomness`](#coordinator-fn-fulfillrandomness), [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch), [`storeBlockHash`](#coordinator-fn-storeblockhash), [`verifyRequestProof`](#coordinator-fn-verifyrequestproof), [`requestSeed`](#coordinator-fn-requestseed), [`getProofContext`](#coordinator-fn-getproofcontext).
|
|
1130
|
+
|
|
1131
|
+
The target block hash was never stored and is outside the 256-block `BLOCKHASH` window. The request can no longer be fulfilled.
|
|
1132
|
+
|
|
1133
|
+
**What to do:** Call `refundRequest` after the deadline. Keepers call `storeBlockHash` before the window closes.
|
|
1134
|
+
|
|
1135
|
+
#### <a id="coordinator-error-alreadyfulfilled"></a>`AlreadyFulfilled`
|
|
1136
|
+
|
|
1137
|
+
`error AlreadyFulfilled()` · Selector `0x4a4117f9` · Source: `D20VRFCoordinator.sol` lines 117, 393
|
|
1138
|
+
|
|
1139
|
+
**Raised by:** [`fulfillRandomness`](#coordinator-fn-fulfillrandomness).
|
|
1140
|
+
|
|
1141
|
+
`fulfillRandomness` on a fulfilled request.
|
|
1142
|
+
|
|
1143
|
+
**What to do:** Nothing to do; read the result.
|
|
1144
|
+
|
|
1145
|
+
#### <a id="coordinator-error-requestrefunded"></a>`RequestRefunded`
|
|
1146
|
+
|
|
1147
|
+
`error RequestRefunded()` · Selector `0xe0dec416` · Source: `D20VRFCoordinator.sol` lines 127, 394
|
|
1148
|
+
|
|
1149
|
+
**Raised by:** [`fulfillRandomness`](#coordinator-fn-fulfillrandomness).
|
|
1150
|
+
|
|
1151
|
+
`fulfillRandomness` on a refunded request.
|
|
1152
|
+
|
|
1153
|
+
**What to do:** The request is settled and will never have a result.
|
|
1154
|
+
|
|
1155
|
+
#### <a id="coordinator-error-requestexpired"></a>`RequestExpired`
|
|
1156
|
+
|
|
1157
|
+
`error RequestExpired()` · Selector `0xfef01cd2` · Source: `D20VRFCoordinator.sol` lines 126, 395
|
|
1158
|
+
|
|
1159
|
+
**Raised by:** [`fulfillRandomness`](#coordinator-fn-fulfillrandomness).
|
|
1160
|
+
|
|
1161
|
+
`fulfillRandomness` in a block whose timestamp is after the request's deadline.
|
|
1162
|
+
|
|
1163
|
+
**What to do:** The request can only be refunded with `refundRequest`.
|
|
1164
|
+
|
|
1165
|
+
#### <a id="coordinator-error-wrongpublickey"></a>`WrongPublicKey`
|
|
1166
|
+
|
|
1167
|
+
`error WrongPublicKey()` · Selector `0x2b0bb68e` · Source: `D20VRFCoordinator.sol` lines 120, 594
|
|
1168
|
+
|
|
1169
|
+
**Raised by:** [`fulfillRandomness`](#coordinator-fn-fulfillrandomness), [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch), [`verifyRequestProof`](#coordinator-fn-verifyrequestproof).
|
|
1170
|
+
|
|
1171
|
+
The proof's `pk` is not the coordinator's VRF key.
|
|
1172
|
+
|
|
1173
|
+
**What to do:** Only proofs from the configured key are accepted.
|
|
1174
|
+
|
|
1175
|
+
#### <a id="coordinator-error-wrongseed"></a>`WrongSeed`
|
|
1176
|
+
|
|
1177
|
+
`error WrongSeed()` · Selector `0xf36cbea4` · Source: `D20VRFCoordinator.sol` lines 121, 596
|
|
1178
|
+
|
|
1179
|
+
**Raised by:** [`fulfillRandomness`](#coordinator-fn-fulfillrandomness), [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch), [`verifyRequestProof`](#coordinator-fn-verifyrequestproof).
|
|
1180
|
+
|
|
1181
|
+
The proof's `seed` differs from `requestSeed(requestId)`.
|
|
1182
|
+
|
|
1183
|
+
**What to do:** Prove the stored seed; it cannot change.
|
|
1184
|
+
|
|
1185
|
+
#### <a id="coordinator-error-evidencepackettoolarge"></a>`EvidencePacketTooLarge`
|
|
1186
|
+
|
|
1187
|
+
`error EvidencePacketTooLarge()` · Selector `0xcfbc3ebf` · Source: `D20VRFCoordinator.sol` lines 134, 452
|
|
1188
|
+
|
|
1189
|
+
**Raised by:** [`fulfillRandomness`](#coordinator-fn-fulfillrandomness), [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch).
|
|
1190
|
+
|
|
1191
|
+
The encoded proof exceeds `MAX_EVIDENCE_PACKET_BYTES`. A proof always encodes to 416 bytes, so valid calls never reach this bound.
|
|
1192
|
+
|
|
1193
|
+
**What to do:** None expected.
|
|
1194
|
+
|
|
1195
|
+
#### <a id="coordinator-error-invalidbatch"></a>`InvalidBatch`
|
|
1196
|
+
|
|
1197
|
+
`error InvalidBatch()` · Selector `0x33b094a1` · Source: `D20VRFCoordinator.sol` lines 137, 404
|
|
1198
|
+
|
|
1199
|
+
**Raised by:** [`fulfillRandomnessBatch`](#coordinator-fn-fulfillrandomnessbatch).
|
|
1200
|
+
|
|
1201
|
+
`fulfillRandomnessBatch` with no IDs, more than 16, or a different number of proofs.
|
|
1202
|
+
|
|
1203
|
+
**What to do:** Send 1 to 16 IDs with one proof each.
|
|
1204
|
+
|
|
1205
|
+
#### <a id="coordinator-error-invalidscan"></a>`InvalidScan`
|
|
1206
|
+
|
|
1207
|
+
`error InvalidScan()` · Selector `0x3e6249a2` · Source: `D20VRFCoordinator.sol` lines 133, 316
|
|
1208
|
+
|
|
1209
|
+
**Raised by:** [`getPendingRequestIds`](#coordinator-fn-getpendingrequestids).
|
|
1210
|
+
|
|
1211
|
+
`getPendingRequestIds` with `fromId` 0, `limit` 0 or `limit` above 256.
|
|
1212
|
+
|
|
1213
|
+
**What to do:** Start at 1 and page with at most 256.
|
|
1214
|
+
|
|
1215
|
+
**Administration, initialization and upgrades**
|
|
1216
|
+
|
|
1217
|
+
#### <a id="coordinator-error-invalidconfig"></a>`InvalidConfig`
|
|
1218
|
+
|
|
1219
|
+
`error InvalidConfig()` · Selector `0x35be3ac8` · Source: `D20VRFCoordinator.sol` lines 108, 174–175, 198, 202, 207, 216, 530, 539
|
|
1220
|
+
|
|
1221
|
+
**Raised by:** [`withdrawFees`](#coordinator-fn-withdrawfees), [`withdrawKeeperCredit`](#coordinator-fn-withdrawkeepercredit), [`setPricing`](#coordinator-fn-setpricing), [`setRefundBps`](#coordinator-fn-setrefundbps), [`setKeeperFeeBps`](#coordinator-fn-setkeeperfeebps), [`setFeeRecipient`](#coordinator-fn-setfeerecipient), [`initialize`](#coordinator-fn-initialize).
|
|
1222
|
+
|
|
1223
|
+
A value is out of bounds: in `initialize` (zero fee recipient, confirmations 0 or above 64, keeper share above 10000, minimum fee above 10 USDC, registry without code), `setFeeRecipient` with zero, `setKeeperFeeBps` above 10000, `setPricing` outside its bounds, `setRefundBps` outside 5000 to 10000, or a zero `recipient` for `withdrawFees` or `withdrawKeeperCredit`.
|
|
1224
|
+
|
|
1225
|
+
**What to do:** Use values within the bounds given for each function.
|
|
1226
|
+
|
|
1227
|
+
#### <a id="coordinator-error-invalidpublickey"></a>`InvalidPublicKey`
|
|
1228
|
+
|
|
1229
|
+
`error InvalidPublicKey()` · Selector `0xa2d0fee8` · Source: `D20VRFCoordinator.sol` lines 110, 177
|
|
1230
|
+
|
|
1231
|
+
**Raised by:** [`initialize`](#coordinator-fn-initialize).
|
|
1232
|
+
|
|
1233
|
+
`initialize` with a VRF public key that is not on secp256k1.
|
|
1234
|
+
|
|
1235
|
+
**What to do:** Deployment-time only.
|
|
1236
|
+
|
|
1237
|
+
#### <a id="coordinator-error-reentrancyguardreentrantcall"></a>`ReentrancyGuardReentrantCall`
|
|
1238
|
+
|
|
1239
|
+
`error ReentrancyGuardReentrantCall()` · Selector `0x3ee5aeb5`
|
|
1240
|
+
|
|
1241
|
+
**Raised by:** any `nonReentrant` function entered from a callback or transfer.
|
|
1242
|
+
|
|
1243
|
+
A `nonReentrant` coordinator function (a request, `storeBlockHash`, a fulfillment, a retry, `refundRequest` or a withdrawal) was entered while another was running, for example a request made inside `rawFulfillRandomness` or `onRefund`. Inside a callback the coordinator catches it and records the callback as failed.
|
|
1244
|
+
|
|
1245
|
+
**What to do:** Do not call coordinator state-changing functions from callbacks; request again in a separate transaction.
|
|
1246
|
+
|
|
1247
|
+
#### <a id="coordinator-error-ownableunauthorizedaccount"></a>`OwnableUnauthorizedAccount`
|
|
1248
|
+
|
|
1249
|
+
`error OwnableUnauthorizedAccount(address account)` · Selector `0x118cdaa7`
|
|
1250
|
+
|
|
1251
|
+
**Raised by:** [`setPricing`](#coordinator-fn-setpricing), [`setRefundBps`](#coordinator-fn-setrefundbps), [`setKeeperFeeBps`](#coordinator-fn-setkeeperfeebps), [`setFeeRecipient`](#coordinator-fn-setfeerecipient), [`transferOwnership`](#coordinator-fn-transferownership), [`acceptOwnership`](#coordinator-fn-acceptownership), [`renounceOwnership`](#coordinator-fn-renounceownership), [`upgradeToAndCall`](#coordinator-fn-upgradetoandcall).
|
|
1252
|
+
|
|
1253
|
+
`account` is not the owner (owner-only functions) or not the pending owner (`acceptOwnership`).
|
|
1254
|
+
|
|
1255
|
+
**What to do:** Only the owner can administer or upgrade the contract; on Arc Mainnet that is the DAO treasury Safe recorded in the deployment manifest.
|
|
1256
|
+
|
|
1257
|
+
#### <a id="coordinator-error-ownableinvalidowner"></a>`OwnableInvalidOwner`
|
|
1258
|
+
|
|
1259
|
+
`error OwnableInvalidOwner(address owner)` · Selector `0x1e4fbdf7`
|
|
1260
|
+
|
|
1261
|
+
**Raised by:** [`initialize`](#coordinator-fn-initialize).
|
|
1262
|
+
|
|
1263
|
+
`initialize` was given the zero address as owner.
|
|
1264
|
+
|
|
1265
|
+
**What to do:** Deployment-time only.
|
|
1266
|
+
|
|
1267
|
+
#### <a id="coordinator-error-renouncedisabled"></a>`RenounceDisabled`
|
|
1268
|
+
|
|
1269
|
+
`error RenounceDisabled()` · Selector `0x89051165` · Source: `D20VRFCoordinator.sol` lines 135, 195
|
|
1270
|
+
|
|
1271
|
+
**Raised by:** [`renounceOwnership`](#coordinator-fn-renounceownership).
|
|
1272
|
+
|
|
1273
|
+
The owner called `renounceOwnership`, which is disabled.
|
|
1274
|
+
|
|
1275
|
+
**What to do:** Move ownership with `transferOwnership` and `acceptOwnership`.
|
|
1276
|
+
|
|
1277
|
+
#### <a id="coordinator-error-invalidinitialization"></a>`InvalidInitialization`
|
|
1278
|
+
|
|
1279
|
+
`error InvalidInitialization()` · Selector `0xf92ee8a9`
|
|
1280
|
+
|
|
1281
|
+
**Raised by:** [`initialize`](#coordinator-fn-initialize).
|
|
1282
|
+
|
|
1283
|
+
`initialize` on a proxy that is already initialized, or on an implementation contract, whose initializers are disabled at construction.
|
|
1284
|
+
|
|
1285
|
+
**What to do:** None: initialization happens once, atomically, when `D20Proxy` is deployed.
|
|
1286
|
+
|
|
1287
|
+
#### <a id="coordinator-error-notinitializing"></a>`NotInitializing`
|
|
1288
|
+
|
|
1289
|
+
`error NotInitializing()` · Selector `0xd7e6bcf8`
|
|
1290
|
+
|
|
1291
|
+
**Raised by:** no public function (declared by OpenZeppelin `Initializable`).
|
|
1292
|
+
|
|
1293
|
+
Declared by the OpenZeppelin initializer helpers. No public function of this contract can reach it.
|
|
1294
|
+
|
|
1295
|
+
**What to do:** None.
|
|
1296
|
+
|
|
1297
|
+
#### <a id="coordinator-error-uupsunauthorizedcallcontext"></a>`UUPSUnauthorizedCallContext`
|
|
1298
|
+
|
|
1299
|
+
`error UUPSUnauthorizedCallContext()` · Selector `0xe07c8dba`
|
|
1300
|
+
|
|
1301
|
+
**Raised by:** [`upgradeToAndCall`](#coordinator-fn-upgradetoandcall), [`proxiableUUID`](#coordinator-fn-proxiableuuid).
|
|
1302
|
+
|
|
1303
|
+
`upgradeToAndCall` called on the implementation instead of through the proxy, or `proxiableUUID` called through the proxy.
|
|
1304
|
+
|
|
1305
|
+
**What to do:** Owner upgrade procedure only.
|
|
1306
|
+
|
|
1307
|
+
#### <a id="coordinator-error-uupsunsupportedproxiableuuid"></a>`UUPSUnsupportedProxiableUUID`
|
|
1308
|
+
|
|
1309
|
+
`error UUPSUnsupportedProxiableUUID(bytes32 slot)` · Selector `0xaa1d49a4`
|
|
1310
|
+
|
|
1311
|
+
**Raised by:** [`upgradeToAndCall`](#coordinator-fn-upgradetoandcall).
|
|
1312
|
+
|
|
1313
|
+
The new implementation reports a `proxiableUUID` other than the ERC-1967 implementation slot.
|
|
1314
|
+
|
|
1315
|
+
**What to do:** Owner upgrade procedure only.
|
|
1316
|
+
|
|
1317
|
+
#### <a id="coordinator-error-erc1967invalidimplementation"></a>`ERC1967InvalidImplementation`
|
|
1318
|
+
|
|
1319
|
+
`error ERC1967InvalidImplementation(address implementation)` · Selector `0x4c9c8ce3`
|
|
1320
|
+
|
|
1321
|
+
**Raised by:** [`upgradeToAndCall`](#coordinator-fn-upgradetoandcall).
|
|
1322
|
+
|
|
1323
|
+
The new implementation has no code or no `proxiableUUID`.
|
|
1324
|
+
|
|
1325
|
+
**What to do:** Owner upgrade procedure only.
|
|
1326
|
+
|
|
1327
|
+
#### <a id="coordinator-error-erc1967nonpayable"></a>`ERC1967NonPayable`
|
|
1328
|
+
|
|
1329
|
+
`error ERC1967NonPayable()` · Selector `0xb398979f`
|
|
1330
|
+
|
|
1331
|
+
**Raised by:** [`upgradeToAndCall`](#coordinator-fn-upgradetoandcall).
|
|
1332
|
+
|
|
1333
|
+
`upgradeToAndCall` was sent value with empty `data`.
|
|
1334
|
+
|
|
1335
|
+
**What to do:** Owner upgrade procedure only.
|
|
1336
|
+
|
|
1337
|
+
#### <a id="coordinator-error-addressemptycode"></a>`AddressEmptyCode`
|
|
1338
|
+
|
|
1339
|
+
`error AddressEmptyCode(address target)` · Selector `0x9996b315`
|
|
1340
|
+
|
|
1341
|
+
**Raised by:** [`upgradeToAndCall`](#coordinator-fn-upgradetoandcall).
|
|
1342
|
+
|
|
1343
|
+
Declared by OpenZeppelin `Address` for the delegatecall in `upgradeToAndCall`. Not reachable in practice, because the new implementation must already have code.
|
|
1344
|
+
|
|
1345
|
+
**What to do:** None.
|
|
1346
|
+
|
|
1347
|
+
#### <a id="coordinator-error-failedcall"></a>`FailedCall`
|
|
1348
|
+
|
|
1349
|
+
`error FailedCall()` · Selector `0xd6bda275`
|
|
1350
|
+
|
|
1351
|
+
**Raised by:** [`upgradeToAndCall`](#coordinator-fn-upgradetoandcall).
|
|
1352
|
+
|
|
1353
|
+
The initialization call made by `upgradeToAndCall` reverted without revert data.
|
|
1354
|
+
|
|
1355
|
+
**What to do:** Owner upgrade procedure only.
|
|
1356
|
+
|
|
1357
|
+
## <a id="registry"></a>EpochEntropy
|
|
1358
|
+
|
|
1359
|
+
The epoch registry. A consumer never needs to call it: a request fixes its epoch automatically, and the coordinator reads the registry for targets and for the keeper-share recipient. The first group and the events matter to consumers and verifiers (README [Replay and verification](README.md#replay-and-verification)); publication and administration are listed for completeness.
|
|
1360
|
+
|
|
1361
|
+
Epoch sources are recipes in an owner-managed, append-only registry: each has an id, a canonical request whose `keccak256` is the query hash its signer signs, a data template that fixes the exact signed bytes the registry accepts (README [Data templates](README.md#data-templates)) and the JSON body keepers post to the provider gateway. A catalog lists 1 to `MAX_SOURCES` registered recipes with one signer each; each epoch selects from the catalog in force for it (`catalogAt`).
|
|
1362
|
+
|
|
1363
|
+
### <a id="registry-types"></a>Types
|
|
1364
|
+
|
|
1365
|
+
#### <a id="registry-type-epochentropy-epoch"></a>`EpochEntropy.Epoch`
|
|
1366
|
+
|
|
1367
|
+
Returned by `getEpoch`; all zero until the epoch is published.
|
|
1368
|
+
|
|
1369
|
+
Source: `EpochEntropy.sol` lines 45–48
|
|
1370
|
+
|
|
1371
|
+
| Field | Type | Meaning |
|
|
1372
|
+
| --- | --- | --- |
|
|
1373
|
+
| `epochHash` | `bytes32` | Epoch commitment: `keccak256(abi.encode(EPOCH_DOMAIN, chainId, registry, catalogHash, epochId, epochStart, anchorHash, source, queryHash, dataHash, attestationHash))`. |
|
|
1374
|
+
| `catalogHash` | `bytes32` | Hash of the catalog in force for the epoch (`catalogAt`) at publication. |
|
|
1375
|
+
| `anchorHash` | `bytes32` | Hash of block `epochStart - 1`, which selects the source. |
|
|
1376
|
+
| `source` | `uint8` | Committed slot in the epoch's catalog, 0 to `sourceCountAt(epochId) - 1`: the selected slot or a fallback. The recipe is the catalog's recipe at that slot. |
|
|
1377
|
+
| `queryHash` | `bytes32` | `keccak256` of the canonical request of the slot's recipe. |
|
|
1378
|
+
| `dataHash` | `bytes32` | `keccak256` of the signed response data. |
|
|
1379
|
+
| `attestationHash` | `bytes32` | `keccak256(abi.encode(queryHash, timestamp, dataHash, keccak256(signature)))`. |
|
|
1380
|
+
| `signedAt` | `uint256` | Attestation timestamp in Unix seconds. |
|
|
1381
|
+
| `committedBlock` | `uint64` | Publication block. Requests of the epoch target `max(requestBlock, committedBlock + 1)`. |
|
|
1382
|
+
|
|
1383
|
+
#### <a id="registry-type-epochentropy-selection"></a>`EpochEntropy.Selection`
|
|
1384
|
+
|
|
1385
|
+
Returned by `getEpochSelection` and `getEpochFallbackSelection`.
|
|
1386
|
+
|
|
1387
|
+
Source: `EpochEntropy.sol` lines 43–44, 262–273
|
|
1388
|
+
|
|
1389
|
+
| Field | Type | Meaning |
|
|
1390
|
+
| --- | --- | --- |
|
|
1391
|
+
| `source` | `uint8` | Slot in the epoch's catalog. |
|
|
1392
|
+
| `recipe` | `uint8` | Registered recipe id at that slot. |
|
|
1393
|
+
| `airnode` | `address` | Signer of that slot in the catalog in force for the epoch. |
|
|
1394
|
+
| `selector` | `bytes32` | `keccak256(abi.encode(SELECT_DOMAIN, catalogHash, epochId, anchor))`; the slot is `(selector mod count + attempt) mod count` with `count = sourceCountAt(epochId)`. |
|
|
1395
|
+
| `queryHash` | `bytes32` | `keccak256` of `canonicalRequest`. |
|
|
1396
|
+
| `canonicalRequest` | `string` | Canonical request of the recipe, as `getRecipe` returns it. |
|
|
1397
|
+
|
|
1398
|
+
#### <a id="registry-type-epochentropy-attestation"></a>`EpochEntropy.Attestation`
|
|
1399
|
+
|
|
1400
|
+
Signed source response passed to `commitEpoch` and `commitEpochFallback`.
|
|
1401
|
+
|
|
1402
|
+
Source: `EpochEntropy.sol` lines 42, 280–300
|
|
1403
|
+
|
|
1404
|
+
| Field | Type | Meaning |
|
|
1405
|
+
| --- | --- | --- |
|
|
1406
|
+
| `timestamp` | `uint256` | Signing time in Unix seconds; not in the future and at most `MAX_ATTESTATION_AGE` old at publication. |
|
|
1407
|
+
| `data` | `bytes` | Signed response bytes, at most `MAX_DATA_BYTES` (128), matching the data template of the slot's recipe exactly. |
|
|
1408
|
+
| `signature` | `bytes` | Signature over `toEthSignedMessageHash(keccak256(abi.encodePacked(queryHash, timestamp, data)))`. |
|
|
1409
|
+
|
|
1410
|
+
### <a id="registry-epoch-state-for-consumers-and-verifiers"></a>Epoch state for consumers and verifiers
|
|
1411
|
+
|
|
1412
|
+
Views, callable by anyone. Epoch IDs start at 1; each epoch lasts `EPOCH_LENGTH` (200) blocks.
|
|
1413
|
+
|
|
1414
|
+
#### <a id="registry-fn-epochforblock"></a>`epochForBlock`
|
|
1415
|
+
|
|
1416
|
+
```solidity
|
|
1417
|
+
function epochForBlock(uint256 number) external view returns (uint64)
|
|
1418
|
+
```
|
|
1419
|
+
|
|
1420
|
+
Selector `0x7018ebb1` · Caller: Anyone (view) · Source: `EpochEntropy.sol` lines 235–237
|
|
1421
|
+
|
|
1422
|
+
Epoch containing a block: 0 before `firstEpochStart`, otherwise `1 + (number - firstEpochStart) / 200`. A request belongs to `epochForBlock(requestBlock)`.
|
|
1423
|
+
|
|
1424
|
+
#### <a id="registry-fn-epochstart"></a>`epochStart`
|
|
1425
|
+
|
|
1426
|
+
```solidity
|
|
1427
|
+
function epochStart(uint64 epochId) external view returns (uint64)
|
|
1428
|
+
```
|
|
1429
|
+
|
|
1430
|
+
Selector `0xa1587509` · Caller: Anyone (view) · Source: `EpochEntropy.sol` lines 231–234
|
|
1431
|
+
|
|
1432
|
+
First block of an epoch: `firstEpochStart + (epochId - 1) × 200`.
|
|
1433
|
+
|
|
1434
|
+
**Errors:** [`InvalidEpoch`](#registry-error-invalidepoch).
|
|
1435
|
+
|
|
1436
|
+
#### <a id="registry-fn-getepoch"></a>`getEpoch`
|
|
1437
|
+
|
|
1438
|
+
```solidity
|
|
1439
|
+
function getEpoch(uint64 epochId) external view returns (EpochEntropy.Epoch)
|
|
1440
|
+
```
|
|
1441
|
+
|
|
1442
|
+
Selector `0x12a02c82` · Caller: Anyone (view) · Source: `EpochEntropy.sol` line 252
|
|
1443
|
+
|
|
1444
|
+
The published [`EpochEntropy.Epoch`](#registry-type-epochentropy-epoch) record, or all zero while unpublished; it never reverts. A non-zero `epochHash` means published.
|
|
1445
|
+
|
|
1446
|
+
#### <a id="registry-fn-catalogat"></a>`catalogAt`
|
|
1447
|
+
|
|
1448
|
+
```solidity
|
|
1449
|
+
function catalogAt(uint64 epochId) external view returns (bytes32 hash, uint8[] recipes, address[] signers)
|
|
1450
|
+
```
|
|
1451
|
+
|
|
1452
|
+
Selector `0xec993599` · Caller: Anyone (view) · Source: `EpochEntropy.sol` lines 212–220, 226–230
|
|
1453
|
+
|
|
1454
|
+
The catalog in force for an epoch: its hash and the recipe id and signer of each slot, in slot order. That is the latest scheduled version whose `fromEpoch` is at or below `epochId`, otherwise the initial catalog: recipes 0 to 3 with the initial signers and hash `catalogHash()`. Replay needs this catalog, not the initial signer getters.
|
|
1455
|
+
|
|
1456
|
+
#### <a id="registry-fn-sourcecountat"></a>`sourceCountAt`
|
|
1457
|
+
|
|
1458
|
+
```solidity
|
|
1459
|
+
function sourceCountAt(uint64 epochId) external view returns (uint256)
|
|
1460
|
+
```
|
|
1461
|
+
|
|
1462
|
+
Selector `0x3edc6b12` · Caller: Anyone (view) · Source: `EpochEntropy.sol` lines 221–225, 226–230
|
|
1463
|
+
|
|
1464
|
+
Number of slots in the catalog in force for an epoch, and so the number of selection attempts, 0 to count - 1.
|
|
1465
|
+
|
|
1466
|
+
#### <a id="registry-fn-getrecipe"></a>`getRecipe`
|
|
1467
|
+
|
|
1468
|
+
```solidity
|
|
1469
|
+
function getRecipe(uint8 recipe) external view returns (bytes32 queryHash, string canonicalRequest, bytes template, string body)
|
|
1470
|
+
```
|
|
1471
|
+
|
|
1472
|
+
Selector `0xba01b103` · Caller: Anyone (view) · Source: `EpochEntropy.sol` lines 132–136, 139–142
|
|
1473
|
+
|
|
1474
|
+
A registered recipe: `queryHash` (`keccak256` of `canonicalRequest`), the canonical request its signer signs, the data template its signed data must match and the JSON body keepers post to the provider gateway. Registered recipes never change. `readEpochRecipes` in `@d20dao/vrf-sdk/epoch` reads recipes with this view and checks each query hash.
|
|
1475
|
+
|
|
1476
|
+
**Errors:** [`InvalidConfig`](#registry-error-invalidconfig).
|
|
1477
|
+
|
|
1478
|
+
#### <a id="registry-fn-reciperequest"></a>`recipeRequest`
|
|
1479
|
+
|
|
1480
|
+
```solidity
|
|
1481
|
+
function recipeRequest(uint8 recipe) external view returns (string)
|
|
1482
|
+
```
|
|
1483
|
+
|
|
1484
|
+
Selector `0x7ce4b6e0` · Caller: Anyone (view) · Source: `EpochEntropy.sol` lines 137–142
|
|
1485
|
+
|
|
1486
|
+
Canonical request of a registered recipe, the same string `getRecipe` returns.
|
|
1487
|
+
|
|
1488
|
+
**Errors:** [`InvalidConfig`](#registry-error-invalidconfig).
|
|
1489
|
+
|
|
1490
|
+
#### <a id="registry-fn-recipecount"></a>`recipeCount`
|
|
1491
|
+
|
|
1492
|
+
```solidity
|
|
1493
|
+
function recipeCount() external view returns (uint256)
|
|
1494
|
+
```
|
|
1495
|
+
|
|
1496
|
+
Selector `0x69cfdf74` · Caller: Anyone (view) · Source: `EpochEntropy.sol` line 131
|
|
1497
|
+
|
|
1498
|
+
Number of registered recipes; ids run from 0 to `recipeCount() - 1`.
|
|
1499
|
+
|
|
1500
|
+
### <a id="registry-registry-reads"></a>Registry reads
|
|
1501
|
+
|
|
1502
|
+
Views, callable by anyone.
|
|
1503
|
+
|
|
1504
|
+
| Function | Selector | Meaning | Source |
|
|
1505
|
+
| --- | --- | --- | --- |
|
|
1506
|
+
| <a id="registry-fn-firstepochstart"></a>`firstEpochStart() returns (uint64)` | `0x219f2428` | First block of epoch 1: the initialization block plus 200. | lines 40, 83 |
|
|
1507
|
+
| <a id="registry-fn-committer"></a>`committer() returns (address)` | `0x5bc8e8f9` | Primary publishing address. The coordinator pays it the keeper share of the requests it serves itself and of every request whose proof came from a wallet this registry does not authorize. | lines 39, 281 |
|
|
1508
|
+
| <a id="registry-fn-isbackupcommitter"></a>`isBackupCommitter(address account) returns (bool)` | `0x1d97e417` | Whether an address may publish epochs besides `committer()`. | line 118 |
|
|
1509
|
+
| <a id="registry-fn-isauthorizedcommitter"></a>`isAuthorizedCommitter(address account) returns (bool)` | `0x1579ab83` | Whether an address may publish epochs at all: `committer()` or an allowed backup committer. The coordinator reads it to decide whether a proof submitter earns the keeper share. | lines 119–121 |
|
|
1510
|
+
| <a id="registry-fn-backupcommittercount"></a>`backupCommitterCount() returns (uint256)` | `0xa815c5bf` | Number of allowed backup committers, at most `MAX_BACKUP_COMMITTERS`. | lines 63, 107–117 |
|
|
1511
|
+
| <a id="registry-fn-cataloghash"></a>`catalogHash() returns (bytes32)` | `0x830c083a` | Initial catalog hash, bound into `protocolConfigurationHash`. Never changes; `catalogAt` gives the catalog of an epoch. | lines 41, 84 |
|
|
1512
|
+
| <a id="registry-fn-epochanchors"></a>`epochAnchors(uint64) returns (bytes32)` | `0x48a030fb` | Checkpointed anchor of an epoch (hash of block `epochStart - 1`); zero until a request, `checkpointEpoch` or publication stores it. | lines 53, 241–244 |
|
|
1513
|
+
| <a id="registry-fn-hyperliquidsigner"></a>`hyperliquidSigner() returns (address)` | `0xf2a12563` | Initial-catalog signer of slot 0 (recipe 0, Hyperliquid BTC volume). Never changes; see `catalogAt`. | line 34 |
|
|
1514
|
+
| <a id="registry-fn-ethereumblocksigner"></a>`ethereumBlockSigner() returns (address)` | `0xd25eacfc` | Initial-catalog signer of slot 1 (recipe 1, Ethereum block hash). Never changes; see `catalogAt`. | lines 35–36 |
|
|
1515
|
+
| <a id="registry-fn-btctradesigner"></a>`btcTradeSigner() returns (address)` | `0xb3b9cbb0` | Initial-catalog signer of slot 2 (recipe 2, TickerLayer BTCUSD). Never changes; see `catalogAt`. | line 37 |
|
|
1516
|
+
| <a id="registry-fn-ethtradesigner"></a>`ethTradeSigner() returns (address)` | `0x3a700168` | Initial-catalog signer of slot 3 (recipe 3, TickerLayer ETHUSD). Never changes; see `catalogAt`. | line 38 |
|
|
1517
|
+
|
|
1518
|
+
### <a id="registry-source-selection-and-publication"></a>Source selection and publication
|
|
1519
|
+
|
|
1520
|
+
Used by keepers. Publication is restricted to the committer and backup committers; the selection views and `checkpointEpoch` are open to anyone.
|
|
1521
|
+
|
|
1522
|
+
#### <a id="registry-fn-getepochselection"></a>`getEpochSelection`
|
|
1523
|
+
|
|
1524
|
+
```solidity
|
|
1525
|
+
function getEpochSelection(uint64 epochId) external view returns (EpochEntropy.Selection s)
|
|
1526
|
+
```
|
|
1527
|
+
|
|
1528
|
+
Selector `0xec4960ad` · Caller: Anyone (view) · Source: `EpochEntropy.sol` lines 253, 262–273
|
|
1529
|
+
|
|
1530
|
+
The selected source of an epoch, attempt 0, as an [`EpochEntropy.Selection`](#registry-type-epochentropy-selection).
|
|
1531
|
+
|
|
1532
|
+
**Errors:** [`InvalidEpoch`](#registry-error-invalidepoch), [`PreparationClosed`](#registry-error-preparationclosed), [`AnchorUnavailable`](#registry-error-anchorunavailable), [`InvalidConfig`](#registry-error-invalidconfig).
|
|
1533
|
+
|
|
1534
|
+
#### <a id="registry-fn-getepochfallbackselection"></a>`getEpochFallbackSelection`
|
|
1535
|
+
|
|
1536
|
+
```solidity
|
|
1537
|
+
function getEpochFallbackSelection(uint64 epochId, uint8 attempt) external view returns (EpochEntropy.Selection s)
|
|
1538
|
+
```
|
|
1539
|
+
|
|
1540
|
+
Selector `0x0e5a0e02` · Caller: Anyone (view) · Source: `EpochEntropy.sol` lines 254–255, 262–273
|
|
1541
|
+
|
|
1542
|
+
The source for attempt 0 to `sourceCountAt(epochId) - 1`; attempt n uses the slot n positions after the selected one.
|
|
1543
|
+
|
|
1544
|
+
**Errors:** [`InvalidFallback`](#registry-error-invalidfallback), [`InvalidEpoch`](#registry-error-invalidepoch), [`PreparationClosed`](#registry-error-preparationclosed), [`AnchorUnavailable`](#registry-error-anchorunavailable), [`InvalidConfig`](#registry-error-invalidconfig).
|
|
1545
|
+
|
|
1546
|
+
#### <a id="registry-fn-fallbackopensat"></a>`fallbackOpensAt`
|
|
1547
|
+
|
|
1548
|
+
```solidity
|
|
1549
|
+
function fallbackOpensAt(uint64 epochId, uint8 attempt) external view returns (uint64)
|
|
1550
|
+
```
|
|
1551
|
+
|
|
1552
|
+
Selector `0x98208050` · Caller: Anyone (view) · Source: `EpochEntropy.sol` lines 256–260
|
|
1553
|
+
|
|
1554
|
+
First block at which an attempt may be published: `epochStart + attempt × FALLBACK_DELAY_BLOCKS` (20). With at most `MAX_SOURCES` (10) slots the last window opens 180 blocks into the epoch.
|
|
1555
|
+
|
|
1556
|
+
**Errors:** [`InvalidFallback`](#registry-error-invalidfallback), [`InvalidEpoch`](#registry-error-invalidepoch).
|
|
1557
|
+
|
|
1558
|
+
#### <a id="registry-fn-nextepochtoprepare"></a>`nextEpochToPrepare`
|
|
1559
|
+
|
|
1560
|
+
```solidity
|
|
1561
|
+
function nextEpochToPrepare(uint256 number) external view returns (uint64)
|
|
1562
|
+
```
|
|
1563
|
+
|
|
1564
|
+
Selector `0xc78fafe2` · Caller: Anyone (view) · Source: `EpochEntropy.sol` line 238
|
|
1565
|
+
|
|
1566
|
+
Same value as `epochForBlock(number)`.
|
|
1567
|
+
|
|
1568
|
+
#### <a id="registry-fn-checkpointepoch"></a>`checkpointEpoch`
|
|
1569
|
+
|
|
1570
|
+
```solidity
|
|
1571
|
+
function checkpointEpoch(uint64 epochId) external returns (bytes32 anchor)
|
|
1572
|
+
```
|
|
1573
|
+
|
|
1574
|
+
Selector `0x16de78cb` · Caller: Anyone · Source: `EpochEntropy.sol` lines 239–244, 245–251
|
|
1575
|
+
|
|
1576
|
+
Stores the anchor of a started epoch (hash of block `epochStart - 1`) if not stored yet, and returns it. The coordinator calls it on every request, so the anchor of an epoch with requests survives the 256-block `BLOCKHASH` window.
|
|
1577
|
+
|
|
1578
|
+
**Errors:** [`InvalidEpoch`](#registry-error-invalidepoch), [`PreparationClosed`](#registry-error-preparationclosed), [`AnchorUnavailable`](#registry-error-anchorunavailable).
|
|
1579
|
+
|
|
1580
|
+
#### <a id="registry-fn-commitepoch"></a>`commitEpoch`
|
|
1581
|
+
|
|
1582
|
+
```solidity
|
|
1583
|
+
function commitEpoch(uint64 epochId, EpochEntropy.Attestation a) external
|
|
1584
|
+
```
|
|
1585
|
+
|
|
1586
|
+
Selector `0xb1580277` · Caller: Committer or backup committer · Source: `EpochEntropy.sol` lines 274, 280–300
|
|
1587
|
+
|
|
1588
|
+
Publishes the packet of the selected source once per epoch, from the epoch start: checks that the attestation is not future-dated and at most 240 seconds old, that its data matches the data template of the slot's recipe exactly, and that the slot's signer in the epoch's catalog signed it. Stores the record and emits the packet. Publishing earns nothing by itself: the keeper share of each request goes to the authorized wallet that submits its accepted proof, or to `committer()` when the submitter is not authorized.
|
|
1589
|
+
|
|
1590
|
+
**Emits:** [`EpochCommitted`](#registry-event-epochcommitted).
|
|
1591
|
+
|
|
1592
|
+
**Errors:** [`OnlyCommitter`](#registry-error-onlycommitter), [`AlreadyCommitted`](#registry-error-alreadycommitted), [`InvalidEpoch`](#registry-error-invalidepoch), [`FallbackNotOpen`](#registry-error-fallbacknotopen), [`AnchorUnavailable`](#registry-error-anchorunavailable), [`InvalidConfig`](#registry-error-invalidconfig), [`InvalidTime`](#registry-error-invalidtime), [`InvalidData`](#registry-error-invaliddata), [`ECDSAInvalidSignatureLength`](#registry-error-ecdsainvalidsignaturelength), [`ECDSAInvalidSignatureS`](#registry-error-ecdsainvalidsignatures), [`ECDSAInvalidSignature`](#registry-error-ecdsainvalidsignature), [`InvalidSigner`](#registry-error-invalidsigner), [`PacketTooLarge`](#registry-error-packettoolarge).
|
|
1593
|
+
|
|
1594
|
+
#### <a id="registry-fn-commitepochfallback"></a>`commitEpochFallback`
|
|
1595
|
+
|
|
1596
|
+
```solidity
|
|
1597
|
+
function commitEpochFallback(uint64 epochId, uint8 attempt, EpochEntropy.Attestation a) external
|
|
1598
|
+
```
|
|
1599
|
+
|
|
1600
|
+
Selector `0x5768d9a1` · Caller: Committer or backup committer · Source: `EpochEntropy.sol` lines 275–279, 280–300
|
|
1601
|
+
|
|
1602
|
+
Publishes fallback attempt 1 to `sourceCountAt(epochId) - 1`, using the slot `attempt` positions after the selected source, once `fallbackOpensAt(epochId, attempt)` is reached. Same checks as `commitEpoch`.
|
|
1603
|
+
|
|
1604
|
+
**Emits:** [`EpochCommitted`](#registry-event-epochcommitted).
|
|
1605
|
+
|
|
1606
|
+
**Errors:** [`InvalidFallback`](#registry-error-invalidfallback), [`OnlyCommitter`](#registry-error-onlycommitter), [`AlreadyCommitted`](#registry-error-alreadycommitted), [`InvalidEpoch`](#registry-error-invalidepoch), [`FallbackNotOpen`](#registry-error-fallbacknotopen), [`AnchorUnavailable`](#registry-error-anchorunavailable), [`InvalidConfig`](#registry-error-invalidconfig), [`InvalidTime`](#registry-error-invalidtime), [`InvalidData`](#registry-error-invaliddata), [`ECDSAInvalidSignatureLength`](#registry-error-ecdsainvalidsignaturelength), [`ECDSAInvalidSignatureS`](#registry-error-ecdsainvalidsignatures), [`ECDSAInvalidSignature`](#registry-error-ecdsainvalidsignature), [`InvalidSigner`](#registry-error-invalidsigner), [`PacketTooLarge`](#registry-error-packettoolarge).
|
|
1607
|
+
|
|
1608
|
+
### <a id="registry-recipes-and-catalogs"></a>Recipes and catalogs
|
|
1609
|
+
|
|
1610
|
+
Owner-only; on Arc Mainnet the owner is the DAO treasury Safe. A recipe or catalog never changes a published epoch.
|
|
1611
|
+
|
|
1612
|
+
#### <a id="registry-fn-registerrecipe"></a>`registerRecipe`
|
|
1613
|
+
|
|
1614
|
+
```solidity
|
|
1615
|
+
function registerRecipe(string canonicalRequest, bytes template, string body) external returns (uint8 recipe)
|
|
1616
|
+
```
|
|
1617
|
+
|
|
1618
|
+
Selector `0x5add5c50` · Caller: Owner · Source: `EpochEntropy.sol` lines 123–130, 143–152
|
|
1619
|
+
|
|
1620
|
+
Appends an immutable recipe and returns its id, the next index. The canonical request is 1 to `MAX_REQUEST_BYTES` (1024) bytes, the body 1 to `MAX_BODY_BYTES` (2048) bytes, and the template must be a well-formed data template of at most `MAX_TEMPLATE_BYTES` (256) bytes; at most `MAX_RECIPES` (256) recipes exist. The contract does not check that the body canonicalizes to the request; keepers refuse a recipe whose body does not. A changed listing is registered as a new id.
|
|
1621
|
+
|
|
1622
|
+
**Emits:** [`RecipeRegistered`](#registry-event-reciperegistered).
|
|
1623
|
+
|
|
1624
|
+
**Errors:** [`OwnableUnauthorizedAccount`](#registry-error-ownableunauthorizedaccount), [`InvalidRecipe`](#registry-error-invalidrecipe), [`InvalidTemplate`](#registry-error-invalidtemplate).
|
|
1625
|
+
|
|
1626
|
+
#### <a id="registry-fn-schedulecatalog"></a>`scheduleCatalog`
|
|
1627
|
+
|
|
1628
|
+
```solidity
|
|
1629
|
+
function scheduleCatalog(uint8[] recipes, address[] signers, uint64 fromEpoch) external
|
|
1630
|
+
```
|
|
1631
|
+
|
|
1632
|
+
Selector `0x42984450` · Caller: Owner · Source: `EpochEntropy.sol` lines 190–211
|
|
1633
|
+
|
|
1634
|
+
Schedules a catalog for epochs from `fromEpoch`, which must be at least two epochs after the current one: 1 to `MAX_SOURCES` (10) distinct registered recipe ids with one non-zero signer each, in slot order. Its hash is `keccak256(abi.encode(RECIPE_DOMAIN, recipes, signers))`. If the latest scheduled version has not taken effect yet (its `fromEpoch` is after the current epoch) it is replaced, so that version never applies; this can return the next epoch to the previous catalog. The current epoch keeps its catalog.
|
|
1635
|
+
|
|
1636
|
+
**Emits:** [`CatalogScheduled`](#registry-event-catalogscheduled).
|
|
1637
|
+
|
|
1638
|
+
**Errors:** [`OwnableUnauthorizedAccount`](#registry-error-ownableunauthorizedaccount), [`InvalidConfig`](#registry-error-invalidconfig), [`InvalidEpoch`](#registry-error-invalidepoch).
|
|
1639
|
+
|
|
1640
|
+
#### <a id="registry-fn-initializereciperegistry"></a>`initializeRecipeRegistry`
|
|
1641
|
+
|
|
1642
|
+
```solidity
|
|
1643
|
+
function initializeRecipeRegistry() external
|
|
1644
|
+
```
|
|
1645
|
+
|
|
1646
|
+
Selector `0x8700b456` · Caller: Owner, once per proxy, as the `upgradeToAndCall` data of the recipe-registry upgrade · Source: `EpochEntropy.sol` lines 87–95
|
|
1647
|
+
|
|
1648
|
+
Registers built-in recipes 0 to 5 on a registry initialized before the recipe registry, whose initial catalog selects recipes 0 to 3. It runs once per proxy (reinitializer version 2) and refuses a registry that already has recipes, which includes every registry initialized by this implementation, or a catalog scheduled under the earlier hardcoded recipe ids.
|
|
1649
|
+
|
|
1650
|
+
**Emits:** [`RecipeRegistered`](#registry-event-reciperegistered), [`Initialized`](#registry-event-initialized).
|
|
1651
|
+
|
|
1652
|
+
**Errors:** [`InvalidInitialization`](#registry-error-invalidinitialization), [`OwnableUnauthorizedAccount`](#registry-error-ownableunauthorizedaccount), [`InvalidConfig`](#registry-error-invalidconfig).
|
|
1653
|
+
|
|
1654
|
+
### <a id="registry-owner-administration"></a>Owner administration
|
|
1655
|
+
|
|
1656
|
+
Owner-only functions revert `OwnableUnauthorizedAccount` for anyone else. No setter can change a published epoch.
|
|
1657
|
+
|
|
1658
|
+
#### <a id="registry-fn-setcommitter"></a>`setCommitter`
|
|
1659
|
+
|
|
1660
|
+
```solidity
|
|
1661
|
+
function setCommitter(address next) external
|
|
1662
|
+
```
|
|
1663
|
+
|
|
1664
|
+
Selector `0xdd51ce22` · Caller: Owner · Source: `EpochEntropy.sol` lines 100–103
|
|
1665
|
+
|
|
1666
|
+
Changes the primary publishing address, which is also the keeper-share recipient the coordinator reads at each acceptance.
|
|
1667
|
+
|
|
1668
|
+
**Emits:** [`CommitterChanged`](#registry-event-committerchanged).
|
|
1669
|
+
|
|
1670
|
+
**Errors:** [`OwnableUnauthorizedAccount`](#registry-error-ownableunauthorizedaccount), [`InvalidConfig`](#registry-error-invalidconfig).
|
|
1671
|
+
|
|
1672
|
+
#### <a id="registry-fn-setbackupcommitter"></a>`setBackupCommitter`
|
|
1673
|
+
|
|
1674
|
+
```solidity
|
|
1675
|
+
function setBackupCommitter(address account, bool allowed) external
|
|
1676
|
+
```
|
|
1677
|
+
|
|
1678
|
+
Selector `0xd870d0c6` · Caller: Owner · Source: `EpochEntropy.sol` lines 104–117
|
|
1679
|
+
|
|
1680
|
+
Allows or removes a backup committer: a separate wallet that may call `commitEpoch` and `commitEpochFallback` under exactly the committer's rules, for example a follower keeper that takes over while the primary keeper is down. It has no other role, and the coordinator pays it the keeper share of the requests whose accepted proofs it submits itself. Reverts for the zero address, for allowing the current committer, for a call that does not change the address's status, and for more than `MAX_BACKUP_COMMITTERS` (4).
|
|
1681
|
+
|
|
1682
|
+
**Emits:** [`BackupCommitterSet`](#registry-event-backupcommitterset).
|
|
1683
|
+
|
|
1684
|
+
**Errors:** [`OwnableUnauthorizedAccount`](#registry-error-ownableunauthorizedaccount), [`InvalidConfig`](#registry-error-invalidconfig).
|
|
1685
|
+
|
|
1686
|
+
#### <a id="registry-fn-owner"></a>`owner`
|
|
1687
|
+
|
|
1688
|
+
```solidity
|
|
1689
|
+
function owner() external view returns (address)
|
|
1690
|
+
```
|
|
1691
|
+
|
|
1692
|
+
Selector `0x8da5cb5b` · Caller: Anyone (view)
|
|
1693
|
+
|
|
1694
|
+
Current owner: upgrade authority and the only account that can call the setters.
|
|
1695
|
+
|
|
1696
|
+
#### <a id="registry-fn-pendingowner"></a>`pendingOwner`
|
|
1697
|
+
|
|
1698
|
+
```solidity
|
|
1699
|
+
function pendingOwner() external view returns (address)
|
|
1700
|
+
```
|
|
1701
|
+
|
|
1702
|
+
Selector `0xe30c3978` · Caller: Anyone (view)
|
|
1703
|
+
|
|
1704
|
+
Account nominated by `transferOwnership` that has not accepted yet; zero when none.
|
|
1705
|
+
|
|
1706
|
+
#### <a id="registry-fn-transferownership"></a>`transferOwnership`
|
|
1707
|
+
|
|
1708
|
+
```solidity
|
|
1709
|
+
function transferOwnership(address newOwner) external
|
|
1710
|
+
```
|
|
1711
|
+
|
|
1712
|
+
Selector `0xf2fde38b` · Caller: Owner
|
|
1713
|
+
|
|
1714
|
+
Starts a two-step transfer by nominating `newOwner`; ownership moves only when that account calls `acceptOwnership`. A new call replaces the nomination, and the zero address cancels it.
|
|
1715
|
+
|
|
1716
|
+
**Emits:** [`OwnershipTransferStarted`](#registry-event-ownershiptransferstarted).
|
|
1717
|
+
|
|
1718
|
+
**Errors:** [`OwnableUnauthorizedAccount`](#registry-error-ownableunauthorizedaccount).
|
|
1719
|
+
|
|
1720
|
+
#### <a id="registry-fn-acceptownership"></a>`acceptOwnership`
|
|
1721
|
+
|
|
1722
|
+
```solidity
|
|
1723
|
+
function acceptOwnership() external
|
|
1724
|
+
```
|
|
1725
|
+
|
|
1726
|
+
Selector `0x79ba5097` · Caller: Pending owner
|
|
1727
|
+
|
|
1728
|
+
Completes the transfer to the caller and clears the nomination.
|
|
1729
|
+
|
|
1730
|
+
**Emits:** [`OwnershipTransferred`](#registry-event-ownershiptransferred).
|
|
1731
|
+
|
|
1732
|
+
**Errors:** [`OwnableUnauthorizedAccount`](#registry-error-ownableunauthorizedaccount).
|
|
1733
|
+
|
|
1734
|
+
#### <a id="registry-fn-renounceownership"></a>`renounceOwnership`
|
|
1735
|
+
|
|
1736
|
+
```solidity
|
|
1737
|
+
function renounceOwnership() external view
|
|
1738
|
+
```
|
|
1739
|
+
|
|
1740
|
+
Selector `0x715018a6` · Caller: Owner · Source: `EpochEntropy.sol` lines 97–98
|
|
1741
|
+
|
|
1742
|
+
Disabled and declared `view`: the owner gets `RenounceDisabled` and anyone else `OwnableUnauthorizedAccount`, so the contract always has an owner and upgrade authority can only move through an accepted transfer.
|
|
1743
|
+
|
|
1744
|
+
**Errors:** [`OwnableUnauthorizedAccount`](#registry-error-ownableunauthorizedaccount), [`RenounceDisabled`](#registry-error-renouncedisabled).
|
|
1745
|
+
|
|
1746
|
+
#### <a id="registry-fn-upgradetoandcall"></a>`upgradeToAndCall`
|
|
1747
|
+
|
|
1748
|
+
```solidity
|
|
1749
|
+
function upgradeToAndCall(address newImplementation, bytes data) external payable
|
|
1750
|
+
```
|
|
1751
|
+
|
|
1752
|
+
Selector `0x4f1ef286` · Caller: Owner, through the proxy
|
|
1753
|
+
|
|
1754
|
+
UUPS upgrade: points the proxy at `newImplementation`, which must report the ERC-1967 slot from `proxiableUUID`, and delegatecalls `data` when it is non-empty. An upgrade can change any behavior described here. Integrators check the implementation when they integrate and again whenever a proxy emits `Upgraded` or the deployment manifest records an upgrade (README [Security and trust](README.md#security-and-trust)).
|
|
1755
|
+
|
|
1756
|
+
**Emits:** [`Upgraded`](#registry-event-upgraded).
|
|
1757
|
+
|
|
1758
|
+
**Errors:** [`UUPSUnauthorizedCallContext`](#registry-error-uupsunauthorizedcallcontext), [`OwnableUnauthorizedAccount`](#registry-error-ownableunauthorizedaccount), [`ERC1967InvalidImplementation`](#registry-error-erc1967invalidimplementation), [`UUPSUnsupportedProxiableUUID`](#registry-error-uupsunsupportedproxiableuuid), [`ERC1967NonPayable`](#registry-error-erc1967nonpayable), [`AddressEmptyCode`](#registry-error-addressemptycode), [`FailedCall`](#registry-error-failedcall).
|
|
1759
|
+
|
|
1760
|
+
#### <a id="registry-fn-proxiableuuid"></a>`proxiableUUID`
|
|
1761
|
+
|
|
1762
|
+
```solidity
|
|
1763
|
+
function proxiableUUID() external view returns (bytes32)
|
|
1764
|
+
```
|
|
1765
|
+
|
|
1766
|
+
Selector `0x52d1902d` · Caller: Anyone (view)
|
|
1767
|
+
|
|
1768
|
+
ERC-1822 check used by `upgradeToAndCall`. Returns the ERC-1967 implementation slot when called on an implementation contract directly and reverts through the proxy.
|
|
1769
|
+
|
|
1770
|
+
**Errors:** [`UUPSUnauthorizedCallContext`](#registry-error-uupsunauthorizedcallcontext).
|
|
1771
|
+
|
|
1772
|
+
#### <a id="registry-fn-initialize"></a>`initialize`
|
|
1773
|
+
|
|
1774
|
+
```solidity
|
|
1775
|
+
function initialize(address[4] signers, address initialOwner, address initialCommitter) external
|
|
1776
|
+
```
|
|
1777
|
+
|
|
1778
|
+
Selector `0xfda9f5ca` · Caller: Once, by `D20Proxy` at deployment · Source: `EpochEntropy.sol` lines 78–86
|
|
1779
|
+
|
|
1780
|
+
Sets the four initial-catalog signers of recipes 0 to 3, the owner and the committer, and registers built-in recipes 0 to 5. Epoch 1 starts 200 blocks after the initialization block.
|
|
1781
|
+
|
|
1782
|
+
**Emits:** [`OwnershipTransferred`](#registry-event-ownershiptransferred), [`RecipeRegistered`](#registry-event-reciperegistered), [`Initialized`](#registry-event-initialized).
|
|
1783
|
+
|
|
1784
|
+
**Errors:** [`InvalidInitialization`](#registry-error-invalidinitialization), [`OwnableInvalidOwner`](#registry-error-ownableinvalidowner), [`InvalidConfig`](#registry-error-invalidconfig).
|
|
1785
|
+
|
|
1786
|
+
### <a id="registry-constants"></a>Constants
|
|
1787
|
+
|
|
1788
|
+
Views returning values fixed in the implementation code.
|
|
1789
|
+
|
|
1790
|
+
| Constant | Returns | Value | Selector | Meaning |
|
|
1791
|
+
| --- | --- | --- | --- | --- |
|
|
1792
|
+
| <a id="registry-fn-epoch_length"></a>`EPOCH_LENGTH` | `uint64` | `200` | `0xac4746ab` | Blocks per epoch. |
|
|
1793
|
+
| <a id="registry-fn-max_attestation_age"></a>`MAX_ATTESTATION_AGE` | `uint256` | `240 seconds` | `0xb9f7bb8d` | Oldest attestation accepted at publication, in seconds; also exported by `@d20dao/vrf-sdk/epoch`. |
|
|
1794
|
+
| <a id="registry-fn-max_packet_bytes"></a>`MAX_PACKET_BYTES` | `uint256` | `2048` | `0x48cad11b` | Upper bound on the `EpochCommitted` packet. |
|
|
1795
|
+
| <a id="registry-fn-fallback_delay_blocks"></a>`FALLBACK_DELAY_BLOCKS` | `uint64` | `20` | `0x0a48a95d` | Blocks between fallback windows. |
|
|
1796
|
+
| <a id="registry-fn-max_sources"></a>`MAX_SOURCES` | `uint256` | `10` | `0x64aefc06` | Most slots in a catalog. |
|
|
1797
|
+
| <a id="registry-fn-max_recipes"></a>`MAX_RECIPES` | `uint256` | `256` | `0x0c148333` | Most registered recipes; ids are `uint8`. |
|
|
1798
|
+
| <a id="registry-fn-max_request_bytes"></a>`MAX_REQUEST_BYTES` | `uint256` | `1024` | `0x4b62e5b4` | Longest canonical request of a recipe. |
|
|
1799
|
+
| <a id="registry-fn-max_body_bytes"></a>`MAX_BODY_BYTES` | `uint256` | `2048` | `0x2ade18c2` | Longest gateway request body of a recipe. |
|
|
1800
|
+
| <a id="registry-fn-max_data_bytes"></a>`MAX_DATA_BYTES` | `uint256` | `128` | `0xf1d11a6c` | Longest signed data a template accepts. |
|
|
1801
|
+
| <a id="registry-fn-max_template_bytes"></a>`MAX_TEMPLATE_BYTES` | `uint256` | `256` | `0x30a3bee5` | Longest data template. |
|
|
1802
|
+
| <a id="registry-fn-max_backup_committers"></a>`MAX_BACKUP_COMMITTERS` | `uint256` | `4` | `0xc195af66` | Most backup committers allowed at once. |
|
|
1803
|
+
| <a id="registry-fn-recipe_domain"></a>`RECIPE_DOMAIN` | `bytes32` | `keccak256("D20_EPOCH_RECIPES")` | `0xacea73c8` | Domain tag of catalog hashes. |
|
|
1804
|
+
| <a id="registry-fn-select_domain"></a>`SELECT_DOMAIN` | `bytes32` | `keccak256("D20_EPOCH_SELECT")` | `0x10181587` | Domain tag of the source selector. |
|
|
1805
|
+
| <a id="registry-fn-epoch_domain"></a>`EPOCH_DOMAIN` | `bytes32` | `keccak256("D20_EPOCH")` | `0xbece738c` | Domain tag of the epoch commitment. |
|
|
1806
|
+
| <a id="registry-fn-upgrade_interface_version"></a>`UPGRADE_INTERFACE_VERSION` | `string` | `"5.0.0"` | `0xad3cb1cc` | OpenZeppelin UUPS interface version: upgrades go through `upgradeToAndCall` only. |
|
|
1807
|
+
|
|
1808
|
+
### <a id="registry-events"></a>Events
|
|
1809
|
+
|
|
1810
|
+
**Epochs, recipes and catalogs**
|
|
1811
|
+
|
|
1812
|
+
#### <a id="registry-event-epochcommitted"></a>`EpochCommitted`
|
|
1813
|
+
|
|
1814
|
+
```solidity
|
|
1815
|
+
event EpochCommitted(uint64 indexed epochId, bytes32 indexed epochHash, bytes packet)
|
|
1816
|
+
```
|
|
1817
|
+
|
|
1818
|
+
Topic 0 `0xc9db8d1389570196eda0f2c6c4e2f78429c2f812db30b6b1022b5e0b5162ef72` · Emitted by: [`commitEpoch`](#registry-fn-commitepoch), [`commitEpochFallback`](#registry-fn-commitepochfallback) · Source: `EpochEntropy.sol` lines 71, 297–299
|
|
1819
|
+
|
|
1820
|
+
An epoch was published. `packet` is `abi.encode(canonicalRequest, attestation)`: decode it with `decodeEpochEvidencePacket` and verify with `replayEpochCommitment`. Requests of the epoch now have a target block.
|
|
1821
|
+
|
|
1822
|
+
#### <a id="registry-event-reciperegistered"></a>`RecipeRegistered`
|
|
1823
|
+
|
|
1824
|
+
```solidity
|
|
1825
|
+
event RecipeRegistered(uint8 indexed recipe, bytes32 indexed queryHash, string canonicalRequest, bytes template, string body)
|
|
1826
|
+
```
|
|
1827
|
+
|
|
1828
|
+
Topic 0 `0xbc5c1e3f4647d7f37dc8b4fe5e26e7c58ae35b8c9fb1db0233ddedba0d7f5fd8` · Emitted by: [`registerRecipe`](#registry-fn-registerrecipe), [`initializeRecipeRegistry`](#registry-fn-initializereciperegistry), [`initialize`](#registry-fn-initialize) · Source: `EpochEntropy.sol` lines 74, 151
|
|
1829
|
+
|
|
1830
|
+
Recipe `recipe` was registered. The event carries the complete definition, so every recipe can be rebuilt from logs; `getRecipe` returns the same values.
|
|
1831
|
+
|
|
1832
|
+
#### <a id="registry-event-catalogscheduled"></a>`CatalogScheduled`
|
|
1833
|
+
|
|
1834
|
+
```solidity
|
|
1835
|
+
event CatalogScheduled(uint64 indexed fromEpoch, bytes32 indexed catalogHash, uint8[] recipes, address[] signers)
|
|
1836
|
+
```
|
|
1837
|
+
|
|
1838
|
+
Topic 0 `0xc91bcd562b1edaabdb2772ada76957511610c715ef892b9c9af1f35be93c3c4f` · Emitted by: [`scheduleCatalog`](#registry-fn-schedulecatalog) · Source: `EpochEntropy.sol` lines 73, 210
|
|
1839
|
+
|
|
1840
|
+
A catalog was scheduled for epochs from `fromEpoch`: recipe ids and signers in slot order. A later `CatalogScheduled` emitted while this version has not taken effect replaces it, so when rebuilding catalogs from history drop replaced versions, or read `catalogAt(epochId)`.
|
|
1841
|
+
|
|
1842
|
+
**Administration and upgrades**
|
|
1843
|
+
|
|
1844
|
+
#### <a id="registry-event-committerchanged"></a>`CommitterChanged`
|
|
1845
|
+
|
|
1846
|
+
```solidity
|
|
1847
|
+
event CommitterChanged(address indexed previousCommitter, address indexed newCommitter)
|
|
1848
|
+
```
|
|
1849
|
+
|
|
1850
|
+
Topic 0 `0x3f67cc70f736070aaac75db90cef1ab4047521b73e8a38d02852e8bf1a91e7e0` · Emitted by: [`setCommitter`](#registry-fn-setcommitter) · Source: `EpochEntropy.sol` lines 72, 102
|
|
1851
|
+
|
|
1852
|
+
New primary publishing address; it also receives the keeper share of proofs submitted by wallets the registry does not authorize.
|
|
1853
|
+
|
|
1854
|
+
#### <a id="registry-event-backupcommitterset"></a>`BackupCommitterSet`
|
|
1855
|
+
|
|
1856
|
+
```solidity
|
|
1857
|
+
event BackupCommitterSet(address indexed account, bool allowed)
|
|
1858
|
+
```
|
|
1859
|
+
|
|
1860
|
+
Topic 0 `0x20380b8c17d904db7d905a51f1538057d280a6cecca38882832ba0261b39fa66` · Emitted by: [`setBackupCommitter`](#registry-fn-setbackupcommitter) · Source: `EpochEntropy.sol` lines 75, 116
|
|
1861
|
+
|
|
1862
|
+
`account` may now publish epochs (`allowed` true) or no longer may (`allowed` false).
|
|
1863
|
+
|
|
1864
|
+
#### <a id="registry-event-ownershiptransferstarted"></a>`OwnershipTransferStarted`
|
|
1865
|
+
|
|
1866
|
+
```solidity
|
|
1867
|
+
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner)
|
|
1868
|
+
```
|
|
1869
|
+
|
|
1870
|
+
Topic 0 `0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700` · Emitted by: [`transferOwnership`](#registry-fn-transferownership)
|
|
1871
|
+
|
|
1872
|
+
`transferOwnership` nominated `newOwner`; the zero address means a nomination was cancelled.
|
|
1873
|
+
|
|
1874
|
+
#### <a id="registry-event-ownershiptransferred"></a>`OwnershipTransferred`
|
|
1875
|
+
|
|
1876
|
+
```solidity
|
|
1877
|
+
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
|
|
1878
|
+
```
|
|
1879
|
+
|
|
1880
|
+
Topic 0 `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0` · Emitted by: [`acceptOwnership`](#registry-fn-acceptownership), [`initialize`](#registry-fn-initialize)
|
|
1881
|
+
|
|
1882
|
+
Ownership moved: from the zero address at initialization, and at each `acceptOwnership`.
|
|
1883
|
+
|
|
1884
|
+
#### <a id="registry-event-upgraded"></a>`Upgraded`
|
|
1885
|
+
|
|
1886
|
+
```solidity
|
|
1887
|
+
event Upgraded(address indexed implementation)
|
|
1888
|
+
```
|
|
1889
|
+
|
|
1890
|
+
Topic 0 `0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b` · Emitted by: [`upgradeToAndCall`](#registry-fn-upgradetoandcall), proxy deployment
|
|
1891
|
+
|
|
1892
|
+
The proxy now runs `implementation`. Emitted by the proxy at deployment and at every `upgradeToAndCall`. Compare the address with the deployment manifest; an implementation you have not reviewed means stop and review before sending more requests.
|
|
1893
|
+
|
|
1894
|
+
#### <a id="registry-event-initialized"></a>`Initialized`
|
|
1895
|
+
|
|
1896
|
+
```solidity
|
|
1897
|
+
event Initialized(uint64 version)
|
|
1898
|
+
```
|
|
1899
|
+
|
|
1900
|
+
Topic 0 `0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2` · Emitted by: [`initializeRecipeRegistry`](#registry-fn-initializereciperegistry), [`initialize`](#registry-fn-initialize)
|
|
1901
|
+
|
|
1902
|
+
`initialize` ran on the proxy (`version` 1) or `initializeRecipeRegistry` did (`version` 2). Each implementation contract also emitted it once at construction with `version` 2^64 − 1, which locks the implementation against initialization.
|
|
1903
|
+
|
|
1904
|
+
### <a id="registry-errors"></a>Errors
|
|
1905
|
+
|
|
1906
|
+
**Epoch reads**
|
|
1907
|
+
|
|
1908
|
+
#### <a id="registry-error-invalidepoch"></a>`InvalidEpoch`
|
|
1909
|
+
|
|
1910
|
+
`error InvalidEpoch()` · Selector `0xd5b25b63` · Source: `EpochEntropy.sol` lines 66, 204, 232
|
|
1911
|
+
|
|
1912
|
+
**Raised by:** [`epochStart`](#registry-fn-epochstart), [`getEpochSelection`](#registry-fn-getepochselection), [`getEpochFallbackSelection`](#registry-fn-getepochfallbackselection), [`fallbackOpensAt`](#registry-fn-fallbackopensat), [`checkpointEpoch`](#registry-fn-checkpointepoch), [`commitEpoch`](#registry-fn-commitepoch), [`commitEpochFallback`](#registry-fn-commitepochfallback), [`scheduleCatalog`](#registry-fn-schedulecatalog).
|
|
1913
|
+
|
|
1914
|
+
Epoch 0 was passed to `epochStart`, `fallbackOpensAt`, a selection view, `checkpointEpoch` or a commit, or `scheduleCatalog` got a `fromEpoch` less than two epochs after the current one.
|
|
1915
|
+
|
|
1916
|
+
**What to do:** Epoch IDs start at 1; schedule at least two epochs ahead.
|
|
1917
|
+
|
|
1918
|
+
#### <a id="registry-error-preparationclosed"></a>`PreparationClosed`
|
|
1919
|
+
|
|
1920
|
+
`error PreparationClosed()` · Selector `0x8e2a3c7d` · Source: `EpochEntropy.sol` lines 66, 247
|
|
1921
|
+
|
|
1922
|
+
**Raised by:** [`getEpochSelection`](#registry-fn-getepochselection), [`getEpochFallbackSelection`](#registry-fn-getepochfallbackselection), [`checkpointEpoch`](#registry-fn-checkpointepoch).
|
|
1923
|
+
|
|
1924
|
+
The epoch has not started (`block.number` is below `epochStart(epochId)`), so its anchor block hash does not exist yet.
|
|
1925
|
+
|
|
1926
|
+
**What to do:** Wait for the epoch to start.
|
|
1927
|
+
|
|
1928
|
+
#### <a id="registry-error-anchorunavailable"></a>`AnchorUnavailable`
|
|
1929
|
+
|
|
1930
|
+
`error AnchorUnavailable()` · Selector `0x60776ed3` · Source: `EpochEntropy.sol` lines 66, 250
|
|
1931
|
+
|
|
1932
|
+
**Raised by:** [`getEpochSelection`](#registry-fn-getepochselection), [`getEpochFallbackSelection`](#registry-fn-getepochfallbackselection), [`checkpointEpoch`](#registry-fn-checkpointepoch), [`commitEpoch`](#registry-fn-commitepoch), [`commitEpochFallback`](#registry-fn-commitepochfallback).
|
|
1933
|
+
|
|
1934
|
+
The anchor (hash of block `epochStart - 1`) was never checkpointed and is outside the 256-block `BLOCKHASH` window.
|
|
1935
|
+
|
|
1936
|
+
**What to do:** The epoch can no longer be selected or published. Every request checkpoints its epoch's anchor, so an epoch with requests is not affected.
|
|
1937
|
+
|
|
1938
|
+
**Publication**
|
|
1939
|
+
|
|
1940
|
+
#### <a id="registry-error-onlycommitter"></a>`OnlyCommitter`
|
|
1941
|
+
|
|
1942
|
+
`error OnlyCommitter()` · Selector `0xfffe5af3` · Source: `EpochEntropy.sol` lines 67, 281
|
|
1943
|
+
|
|
1944
|
+
**Raised by:** [`commitEpoch`](#registry-fn-commitepoch), [`commitEpochFallback`](#registry-fn-commitepochfallback).
|
|
1945
|
+
|
|
1946
|
+
A commit from an address that is neither `committer()` nor an allowed backup committer.
|
|
1947
|
+
|
|
1948
|
+
**What to do:** Only the committer and backup committers publish; check `isBackupCommitter`.
|
|
1949
|
+
|
|
1950
|
+
#### <a id="registry-error-alreadycommitted"></a>`AlreadyCommitted`
|
|
1951
|
+
|
|
1952
|
+
`error AlreadyCommitted()` · Selector `0xbfec5558` · Source: `EpochEntropy.sol` lines 67, 282
|
|
1953
|
+
|
|
1954
|
+
**Raised by:** [`commitEpoch`](#registry-fn-commitepoch), [`commitEpochFallback`](#registry-fn-commitepochfallback).
|
|
1955
|
+
|
|
1956
|
+
The epoch already has a published packet.
|
|
1957
|
+
|
|
1958
|
+
**What to do:** Nothing to publish; read `getEpoch`.
|
|
1959
|
+
|
|
1960
|
+
#### <a id="registry-error-fallbacknotopen"></a>`FallbackNotOpen`
|
|
1961
|
+
|
|
1962
|
+
`error FallbackNotOpen()` · Selector `0xf8635228` · Source: `EpochEntropy.sol` lines 69, 283
|
|
1963
|
+
|
|
1964
|
+
**Raised by:** [`commitEpoch`](#registry-fn-commitepoch), [`commitEpochFallback`](#registry-fn-commitepochfallback).
|
|
1965
|
+
|
|
1966
|
+
`block.number` is below `fallbackOpensAt(epochId, attempt)`; for attempt 0, before the epoch start.
|
|
1967
|
+
|
|
1968
|
+
**What to do:** Wait for the window.
|
|
1969
|
+
|
|
1970
|
+
#### <a id="registry-error-invalidfallback"></a>`InvalidFallback`
|
|
1971
|
+
|
|
1972
|
+
`error InvalidFallback()` · Selector `0x5a93724d` · Source: `EpochEntropy.sol` lines 69, 258, 266, 277
|
|
1973
|
+
|
|
1974
|
+
**Raised by:** [`getEpochFallbackSelection`](#registry-fn-getepochfallbackselection), [`fallbackOpensAt`](#registry-fn-fallbackopensat), [`commitEpochFallback`](#registry-fn-commitepochfallback).
|
|
1975
|
+
|
|
1976
|
+
An attempt at or above `sourceCountAt(epochId)`, or attempt 0 passed to `commitEpochFallback`.
|
|
1977
|
+
|
|
1978
|
+
**What to do:** Use attempts 1 to `sourceCountAt(epochId) - 1` for fallbacks.
|
|
1979
|
+
|
|
1980
|
+
#### <a id="registry-error-invalidtime"></a>`InvalidTime`
|
|
1981
|
+
|
|
1982
|
+
`error InvalidTime()` · Selector `0x6f7eac26` · Source: `EpochEntropy.sol` lines 67, 285
|
|
1983
|
+
|
|
1984
|
+
**Raised by:** [`commitEpoch`](#registry-fn-commitepoch), [`commitEpochFallback`](#registry-fn-commitepochfallback).
|
|
1985
|
+
|
|
1986
|
+
The attestation timestamp is in the future or more than `MAX_ATTESTATION_AGE` (240 seconds) before the publication block.
|
|
1987
|
+
|
|
1988
|
+
**What to do:** A saved packet is never refreshed; its requests expire and are refunded.
|
|
1989
|
+
|
|
1990
|
+
#### <a id="registry-error-invaliddata"></a>`InvalidData`
|
|
1991
|
+
|
|
1992
|
+
`error InvalidData()` · Selector `0x5cb045db` · Source: `EpochEntropy.sol` lines 67, 286–287
|
|
1993
|
+
|
|
1994
|
+
**Raised by:** [`commitEpoch`](#registry-fn-commitepoch), [`commitEpochFallback`](#registry-fn-commitepochfallback).
|
|
1995
|
+
|
|
1996
|
+
The signed data does not match the data template of the slot's recipe exactly, which includes data longer than `MAX_DATA_BYTES` (128).
|
|
1997
|
+
|
|
1998
|
+
**What to do:** Publish only a response that matches the selected recipe's template, unmodified.
|
|
1999
|
+
|
|
2000
|
+
#### <a id="registry-error-invalidsigner"></a>`InvalidSigner`
|
|
2001
|
+
|
|
2002
|
+
`error InvalidSigner()` · Selector `0x815e1d64` · Source: `EpochEntropy.sol` lines 67, 289
|
|
2003
|
+
|
|
2004
|
+
**Raised by:** [`commitEpoch`](#registry-fn-commitepoch), [`commitEpochFallback`](#registry-fn-commitepochfallback).
|
|
2005
|
+
|
|
2006
|
+
The signature does not recover to the slot's signer in the epoch's catalog.
|
|
2007
|
+
|
|
2008
|
+
**What to do:** Use `catalogAt(epochId)` for the expected signer.
|
|
2009
|
+
|
|
2010
|
+
#### <a id="registry-error-ecdsainvalidsignature"></a>`ECDSAInvalidSignature`
|
|
2011
|
+
|
|
2012
|
+
`error ECDSAInvalidSignature()` · Selector `0xf645eedf`
|
|
2013
|
+
|
|
2014
|
+
**Raised by:** [`commitEpoch`](#registry-fn-commitepoch), [`commitEpochFallback`](#registry-fn-commitepochfallback).
|
|
2015
|
+
|
|
2016
|
+
The signature does not recover to any address (OpenZeppelin `ECDSA`).
|
|
2017
|
+
|
|
2018
|
+
**What to do:** Publish the exact signature from the response.
|
|
2019
|
+
|
|
2020
|
+
#### <a id="registry-error-ecdsainvalidsignaturelength"></a>`ECDSAInvalidSignatureLength`
|
|
2021
|
+
|
|
2022
|
+
`error ECDSAInvalidSignatureLength(uint256 length)` · Selector `0xfce698f7`
|
|
2023
|
+
|
|
2024
|
+
**Raised by:** [`commitEpoch`](#registry-fn-commitepoch), [`commitEpochFallback`](#registry-fn-commitepochfallback).
|
|
2025
|
+
|
|
2026
|
+
The signature is not 65 bytes (OpenZeppelin `ECDSA`).
|
|
2027
|
+
|
|
2028
|
+
**What to do:** Publish the exact signature from the response.
|
|
2029
|
+
|
|
2030
|
+
#### <a id="registry-error-ecdsainvalidsignatures"></a>`ECDSAInvalidSignatureS`
|
|
2031
|
+
|
|
2032
|
+
`error ECDSAInvalidSignatureS(bytes32 s)` · Selector `0xd78bce0c`
|
|
2033
|
+
|
|
2034
|
+
**Raised by:** [`commitEpoch`](#registry-fn-commitepoch), [`commitEpochFallback`](#registry-fn-commitepochfallback).
|
|
2035
|
+
|
|
2036
|
+
The signature has a high `s` value (OpenZeppelin `ECDSA`).
|
|
2037
|
+
|
|
2038
|
+
**What to do:** Publish the exact signature from the response.
|
|
2039
|
+
|
|
2040
|
+
#### <a id="registry-error-packettoolarge"></a>`PacketTooLarge`
|
|
2041
|
+
|
|
2042
|
+
`error PacketTooLarge()` · Selector `0xda85e8a5` · Source: `EpochEntropy.sol` lines 68, 298
|
|
2043
|
+
|
|
2044
|
+
**Raised by:** [`commitEpoch`](#registry-fn-commitepoch), [`commitEpochFallback`](#registry-fn-commitepochfallback).
|
|
2045
|
+
|
|
2046
|
+
The encoded packet exceeds `MAX_PACKET_BYTES` (2048).
|
|
2047
|
+
|
|
2048
|
+
**What to do:** Not reachable: the recipe and data bounds keep every packet within `MAX_PACKET_BYTES`.
|
|
2049
|
+
|
|
2050
|
+
**Recipes, administration, initialization and upgrades**
|
|
2051
|
+
|
|
2052
|
+
#### <a id="registry-error-invalidrecipe"></a>`InvalidRecipe`
|
|
2053
|
+
|
|
2054
|
+
`error InvalidRecipe()` · Selector `0x7b776f4c` · Source: `EpochEntropy.sol` lines 70, 147
|
|
2055
|
+
|
|
2056
|
+
**Raised by:** [`registerRecipe`](#registry-fn-registerrecipe).
|
|
2057
|
+
|
|
2058
|
+
`registerRecipe` got an empty canonical request or body, a canonical request over `MAX_REQUEST_BYTES` or a body over `MAX_BODY_BYTES`, or `MAX_RECIPES` recipes are already registered.
|
|
2059
|
+
|
|
2060
|
+
**What to do:** Shorten the request or body. Recipe ids are never freed.
|
|
2061
|
+
|
|
2062
|
+
#### <a id="registry-error-invalidtemplate"></a>`InvalidTemplate`
|
|
2063
|
+
|
|
2064
|
+
`error InvalidTemplate()` · Selector `0xec55b8cd` · Source: `EpochEntropy.sol` lines 70, 148
|
|
2065
|
+
|
|
2066
|
+
**Raised by:** [`registerRecipe`](#registry-fn-registerrecipe).
|
|
2067
|
+
|
|
2068
|
+
`registerRecipe` got a data template that is not well formed (README [Data templates](README.md#data-templates)).
|
|
2069
|
+
|
|
2070
|
+
**What to do:** Build the template with `encodeDataTemplate`, which names the broken rule, before registering.
|
|
2071
|
+
|
|
2072
|
+
#### <a id="registry-error-invalidconfig"></a>`InvalidConfig`
|
|
2073
|
+
|
|
2074
|
+
`error InvalidConfig()` · Selector `0x35be3ac8` · Source: `EpochEntropy.sol` lines 66, 81, 93, 101, 108, 110, 140, 196, 200
|
|
2075
|
+
|
|
2076
|
+
**Raised by:** [`getRecipe`](#registry-fn-getrecipe), [`recipeRequest`](#registry-fn-reciperequest), [`getEpochSelection`](#registry-fn-getepochselection), [`getEpochFallbackSelection`](#registry-fn-getepochfallbackselection), [`commitEpoch`](#registry-fn-commitepoch), [`commitEpochFallback`](#registry-fn-commitepochfallback), [`scheduleCatalog`](#registry-fn-schedulecatalog), [`initializeRecipeRegistry`](#registry-fn-initializereciperegistry), [`setCommitter`](#registry-fn-setcommitter), [`setBackupCommitter`](#registry-fn-setbackupcommitter), [`initialize`](#registry-fn-initialize).
|
|
2077
|
+
|
|
2078
|
+
A zero signer or committer in `initialize`; a zero address in `setCommitter`; in `setBackupCommitter` the zero address, allowing the committer, an unchanged status or a fifth backup committer; in `scheduleCatalog` an empty or oversized catalog, mismatched lengths, a repeated or unregistered recipe or a zero signer; `initializeRecipeRegistry` on a registry that already has recipes or a scheduled catalog; or a recipe id that is not registered, in `getRecipe` and `recipeRequest` or, on a registry upgraded without `initializeRecipeRegistry`, in selection and publication.
|
|
2079
|
+
|
|
2080
|
+
**What to do:** Correct the arguments; recipe ids run from 0 to `recipeCount() - 1`. A registry upgraded without the recipe step needs `initializeRecipeRegistry` from its owner.
|
|
2081
|
+
|
|
2082
|
+
#### <a id="registry-error-ownableunauthorizedaccount"></a>`OwnableUnauthorizedAccount`
|
|
2083
|
+
|
|
2084
|
+
`error OwnableUnauthorizedAccount(address account)` · Selector `0x118cdaa7`
|
|
2085
|
+
|
|
2086
|
+
**Raised by:** [`registerRecipe`](#registry-fn-registerrecipe), [`scheduleCatalog`](#registry-fn-schedulecatalog), [`initializeRecipeRegistry`](#registry-fn-initializereciperegistry), [`setCommitter`](#registry-fn-setcommitter), [`setBackupCommitter`](#registry-fn-setbackupcommitter), [`transferOwnership`](#registry-fn-transferownership), [`acceptOwnership`](#registry-fn-acceptownership), [`renounceOwnership`](#registry-fn-renounceownership), [`upgradeToAndCall`](#registry-fn-upgradetoandcall).
|
|
2087
|
+
|
|
2088
|
+
`account` is not the owner (owner-only functions) or not the pending owner (`acceptOwnership`).
|
|
2089
|
+
|
|
2090
|
+
**What to do:** Only the owner can administer or upgrade the contract; on Arc Mainnet that is the DAO treasury Safe recorded in the deployment manifest.
|
|
2091
|
+
|
|
2092
|
+
#### <a id="registry-error-ownableinvalidowner"></a>`OwnableInvalidOwner`
|
|
2093
|
+
|
|
2094
|
+
`error OwnableInvalidOwner(address owner)` · Selector `0x1e4fbdf7`
|
|
2095
|
+
|
|
2096
|
+
**Raised by:** [`initialize`](#registry-fn-initialize).
|
|
2097
|
+
|
|
2098
|
+
`initialize` was given the zero address as owner.
|
|
2099
|
+
|
|
2100
|
+
**What to do:** Deployment-time only.
|
|
2101
|
+
|
|
2102
|
+
#### <a id="registry-error-renouncedisabled"></a>`RenounceDisabled`
|
|
2103
|
+
|
|
2104
|
+
`error RenounceDisabled()` · Selector `0x89051165` · Source: `EpochEntropy.sol` lines 68, 98
|
|
2105
|
+
|
|
2106
|
+
**Raised by:** [`renounceOwnership`](#registry-fn-renounceownership).
|
|
2107
|
+
|
|
2108
|
+
The owner called `renounceOwnership`, which is disabled.
|
|
2109
|
+
|
|
2110
|
+
**What to do:** Move ownership with `transferOwnership` and `acceptOwnership`.
|
|
2111
|
+
|
|
2112
|
+
#### <a id="registry-error-invalidinitialization"></a>`InvalidInitialization`
|
|
2113
|
+
|
|
2114
|
+
`error InvalidInitialization()` · Selector `0xf92ee8a9`
|
|
2115
|
+
|
|
2116
|
+
**Raised by:** [`initializeRecipeRegistry`](#registry-fn-initializereciperegistry), [`initialize`](#registry-fn-initialize).
|
|
2117
|
+
|
|
2118
|
+
`initialize` on a proxy that is already initialized or on an implementation contract, whose initializers are disabled at construction, or `initializeRecipeRegistry` on a proxy that has already reached initializer version 2.
|
|
2119
|
+
|
|
2120
|
+
**What to do:** None: `initialize` happens once when `D20Proxy` is deployed, and `initializeRecipeRegistry` once in the recipe-registry upgrade.
|
|
2121
|
+
|
|
2122
|
+
#### <a id="registry-error-notinitializing"></a>`NotInitializing`
|
|
2123
|
+
|
|
2124
|
+
`error NotInitializing()` · Selector `0xd7e6bcf8`
|
|
2125
|
+
|
|
2126
|
+
**Raised by:** no public function (declared by OpenZeppelin `Initializable`).
|
|
2127
|
+
|
|
2128
|
+
Declared by the OpenZeppelin initializer helpers. No public function of this contract can reach it.
|
|
2129
|
+
|
|
2130
|
+
**What to do:** None.
|
|
2131
|
+
|
|
2132
|
+
#### <a id="registry-error-uupsunauthorizedcallcontext"></a>`UUPSUnauthorizedCallContext`
|
|
2133
|
+
|
|
2134
|
+
`error UUPSUnauthorizedCallContext()` · Selector `0xe07c8dba`
|
|
2135
|
+
|
|
2136
|
+
**Raised by:** [`upgradeToAndCall`](#registry-fn-upgradetoandcall), [`proxiableUUID`](#registry-fn-proxiableuuid).
|
|
2137
|
+
|
|
2138
|
+
`upgradeToAndCall` called on the implementation instead of through the proxy, or `proxiableUUID` called through the proxy.
|
|
2139
|
+
|
|
2140
|
+
**What to do:** Owner upgrade procedure only.
|
|
2141
|
+
|
|
2142
|
+
#### <a id="registry-error-uupsunsupportedproxiableuuid"></a>`UUPSUnsupportedProxiableUUID`
|
|
2143
|
+
|
|
2144
|
+
`error UUPSUnsupportedProxiableUUID(bytes32 slot)` · Selector `0xaa1d49a4`
|
|
2145
|
+
|
|
2146
|
+
**Raised by:** [`upgradeToAndCall`](#registry-fn-upgradetoandcall).
|
|
2147
|
+
|
|
2148
|
+
The new implementation reports a `proxiableUUID` other than the ERC-1967 implementation slot.
|
|
2149
|
+
|
|
2150
|
+
**What to do:** Owner upgrade procedure only.
|
|
2151
|
+
|
|
2152
|
+
#### <a id="registry-error-erc1967invalidimplementation"></a>`ERC1967InvalidImplementation`
|
|
2153
|
+
|
|
2154
|
+
`error ERC1967InvalidImplementation(address implementation)` · Selector `0x4c9c8ce3`
|
|
2155
|
+
|
|
2156
|
+
**Raised by:** [`upgradeToAndCall`](#registry-fn-upgradetoandcall).
|
|
2157
|
+
|
|
2158
|
+
The new implementation has no code or no `proxiableUUID`.
|
|
2159
|
+
|
|
2160
|
+
**What to do:** Owner upgrade procedure only.
|
|
2161
|
+
|
|
2162
|
+
#### <a id="registry-error-erc1967nonpayable"></a>`ERC1967NonPayable`
|
|
2163
|
+
|
|
2164
|
+
`error ERC1967NonPayable()` · Selector `0xb398979f`
|
|
2165
|
+
|
|
2166
|
+
**Raised by:** [`upgradeToAndCall`](#registry-fn-upgradetoandcall).
|
|
2167
|
+
|
|
2168
|
+
`upgradeToAndCall` was sent value with empty `data`.
|
|
2169
|
+
|
|
2170
|
+
**What to do:** Owner upgrade procedure only.
|
|
2171
|
+
|
|
2172
|
+
#### <a id="registry-error-addressemptycode"></a>`AddressEmptyCode`
|
|
2173
|
+
|
|
2174
|
+
`error AddressEmptyCode(address target)` · Selector `0x9996b315`
|
|
2175
|
+
|
|
2176
|
+
**Raised by:** [`upgradeToAndCall`](#registry-fn-upgradetoandcall).
|
|
2177
|
+
|
|
2178
|
+
Declared by OpenZeppelin `Address` for the delegatecall in `upgradeToAndCall`. Not reachable in practice, because the new implementation must already have code.
|
|
2179
|
+
|
|
2180
|
+
**What to do:** None.
|
|
2181
|
+
|
|
2182
|
+
#### <a id="registry-error-failedcall"></a>`FailedCall`
|
|
2183
|
+
|
|
2184
|
+
`error FailedCall()` · Selector `0xd6bda275`
|
|
2185
|
+
|
|
2186
|
+
**Raised by:** [`upgradeToAndCall`](#registry-fn-upgradetoandcall).
|
|
2187
|
+
|
|
2188
|
+
The initialization call made by `upgradeToAndCall` reverted without revert data.
|
|
2189
|
+
|
|
2190
|
+
**What to do:** Owner upgrade procedure only.
|