Docs / Mechanics / Randomness
Randomness
The draw uses Chainlink VRF v2.5 in subscription mode, on a subscription used by nothing else. Requests settle strictly in the order they were made, and deposits that arrive mid request are held back so they cannot reshape a draw somebody already paid for.
Why the randomness has to come from outside
The pool hands out positions worth real money, and the cheap positions come up far more often than the expensive ones. If the number that picks a position could be predicted or nudged, the whole design falls over.
Chain data cannot supply it. Block hashes, timestamps, prevrandao and balances are all either visible in advance or influenced by whoever produces the block. Anyone able to see the outcome before committing could request only when the draw favours them, and anyone able to influence it could aim at the largest backing in the pool.
VRF answers with a number plus a proof that the number was generated from a key committed to in advance. The proof is checked on chain. Nobody, including the party generating it, can pick which number comes out.
Subscription mode, on a dedicated subscription
VRF can be paid for per request or from a prefunded subscription. BWA uses a subscription, and that subscription serves no other contract.
| Property | How it is set up |
|---|---|
| Funding | LINK is held in the subscription balance and drawn down per request |
| Consumers | The BWA pool contract, and nothing else |
| Owner | The subscription owner, who can add LINK and manage consumers |
| Cost to the acquirer | Quoted at request time as a separate VRF service fee |
The subscription is dedicated because a shared one is a shared failure. Another consumer on the same subscription could drain the LINK balance and every BWA request would start failing for reasons that have nothing to do with BWA.
The service fee is charged to the acquirer alongside the acquisition fee, and it is never refundable. Randomness is bought the moment the request is made. Pricing covers how the two figures are quoted.
Requests settle in order
More than one acquisition can be in flight at a time. The protocol keeps them in a strict queue.
Requests settle strictly in the order they were made. A later request can never jump ahead of an earlier one, and can never change the pool an earlier one is going to sample.
VRF makes no promise about the order its callbacks arrive in. Two requests made seconds apart can come back in either order, depending on gas and confirmations. The protocol does not let that ordering matter: randomness for a later request is held until every request ahead of it has settled.
Why this is worth the extra bookkeeping:
- The first acquirer paid against a snapshot of the pool. If a later request settled first, it would remove a position from that pool and the first acquirer would be sampling a set they never agreed to.
- Ordering that depends on callback timing is ordering that can be bought. Strict queue order removes the incentive to race entirely.
- Every acquirer can see exactly where they sit in the queue and what has to happen before their turn.
Deposits are staged first in, first out
A deposit that lands while a randomness request is open does not join the pool straight away.
- The deposit is accepted
The NFT and its backing move into the protocol. Nothing about the deposit is rejected or delayed for the depositor.
- It is held in a staging queue
The position does not count toward
totalWeight, does not move the price, and cannot be drawn. - The open request settles
The acquirer ahead of it gets the pool they paid for, unchanged.
- Staged positions go active, in arrival order
Weights are added to
totalWeight, the price updates, and the new positions start earning.
First in, first out matters here for the same reason ordering does elsewhere. If staged deposits activated in any other order, the sequence would be worth manipulating.
The practical effect for a depositor is a short wait before a position goes live during busy periods. The practical effect for an acquirer is that the price and the position set they committed to are the price and position set they get. Positions covers the depositor side.
Confirmations, words and callback gas
Three request parameters bound what the protocol can ask VRF for. All three are enforced by the coordinator.
| Parameter | Range | What it controls |
|---|---|---|
| Request confirmations | 3 to 200 | How many blocks the coordinator waits before answering. More blocks means the requesting block is buried deeper and a reorg is less able to disturb the request. |
| Words per request | 1 to 500 | How many random words come back. A draw needs one. |
| Callback gas limit | 2,500,000 max | The gas the coordinator makes available to the fulfilment function. Set it above what settlement actually costs, because a callback that runs out of gas does not get retried for free. |
BNB Smart Chain produces a block roughly every 0.45 seconds, so the confirmation range works out to about 1.35 seconds at the low end and about 90 seconds at the high end of waiting before the coordinator will respond.
Gas lanes
The key hash picks the gas lane, which is the ceiling on the gas price the coordinator is prepared to pay to deliver the callback. The higher lane costs more per request and keeps confirming when the chain is busy.
- Lane, 200 gwei
- 0x130dba50ad435d4ecc214aad0d5820474137bd68e7e77724144f27c3c377d3d4
- Lane, 500 gwei
- 0xeb0f72532fed5c94b4caf7b49caf454b35a729608a441101b9269efb7efe2c6c
If a request never returns
Randomness can fail to arrive. The coordinator could run out of LINK on the subscription, the callback could exceed its gas limit, or the fulfilment could simply never be delivered. The protocol does not assume it always comes back.
- The request has an expiry
Past it, the request can be closed without randomness. The window is — until the deployed contract can be read.
- The acquisition fee becomes a pull based credit
The pool fee is credited to the acquirer's address. They withdraw it themselves, in their own transaction, whenever they choose. Nothing is pushed, so a reverting recipient cannot jam anything.
- The VRF service fee is not returned
It was spent on requesting randomness at the moment the request was made. This is why it is quoted separately from the pool fee rather than folded into one number.
- The queue advances
The expired request stops blocking the requests behind it, and staged deposits become active in arrival order.
The property being protected is that no single stuck request can freeze the protocol. Expiry is permissionless in the same way the 7 day finalisation is: closing out a dead request must never depend on one particular address deciding to act.
Infrastructure on BNB Smart Chain
These are live mainnet addresses. Copy them from here rather than typing them out.
- Chain
- 56 (0x38), native BNB, 18 decimals
- VRF v2.5 coordinator
- 0xd691f04bc0C9a24Edb78af9E005Cf85768F694C9
- LINK
- 0x404460C6A5EdE2D891e8297795264fDe62ADBB75
- Subscription id
- —
- Consumer (pool)
- —
The subscription is funded with LINK and the vault is registered on it as a consumer, so every request is paid for from that balance.