Docs / Mechanics / Pricing and allocation
Pricing and allocation
One price, the same for everyone, built from the pool itself. It is the harmonic mean of every active backing plus 2.5%. Under inverse weighting the harmonic mean is the exact expected value of a draw, not an approximation of it.
One price for a random position
Rather than picking a listing, an acquirer pays a single acquisition fee and receives one position drawn at random from every active position in the pool.
So the price has one job: it has to equal the value of an average draw, or the whole thing is either a gift or a trap. The protocol computes that value directly.
The formula
EV harmonic mean of every active position backing n number of active positions surchargeBps 250, which is 2.5%
The harmonic mean is what you get by averaging the reciprocals and flipping the result back. It sits well below the ordinary average whenever the numbers are spread out, and it is dragged down hard by the smallest values in the set. That is the correct behaviour here, because the smallest backings are the ones you are most likely to draw.
Why it is exact
Write the weight of position i as w_i = 1e36 / b_i, where b_i is its backing. The constant cancels out of every ratio, so treat it as w_i = 1 / b_i and let W = sum(1 / b_j).
Look at the third line. Every position contributes 1 / W to the expected value, and that term has no b_i left in it. A position backed with 0.05 BNB and a position backed with 1 BNB push the expected value by exactly the same amount, because the small one is drawn proportionally more often in precisely the ratio that cancels its smaller payout.
This is an identity, not an approximation and not a fit. It holds for any set of backings, any number of positions, at any moment. The acquisition fee is the mathematically fair expected value with a fixed surcharge on top, and nothing else.
It also means the expected value has a very cheap form: EV = n / W. The protocol already keeps W as a running sum for the draw, so the price is one division away at all times.
Worked example Illustrative
The same five positions used on the positions page. Nothing here is read from chain.
| # | Backing (BNB) | 1 / backing | Probability | Contribution to EV |
|---|---|---|---|---|
| 1 | 0.05 | 20 | 52.63% | 0.02631579 |
| 2 | 0.10 | 10 | 26.32% | 0.02631579 |
| 3 | 0.20 | 5 | 13.16% | 0.02631579 |
| 4 | 0.50 | 2 | 5.26% | 0.02631579 |
| 5 | 1.00 | 1 | 2.63% | 0.02631579 |
| Sum | 1.85 | 38 | 100.00% | 0.13157895 |
The contribution column is identical on every row, which is the identity above showing up in numbers. Five positions, each contributing 1 / 38 of a BNB, gives 5 / 38 = 0.13157895 BNB.
| Line | BNB | How it is arrived at |
|---|---|---|
| Expected backing (EV) | 0.13157895 | 5 / 38 |
| Surcharge at 250 bps | 0.00328947 | EV * 250 / 10000 |
| Acquisition fee | 0.13486842 | what the acquirer pays into the pool |
For contrast, the ordinary average of those five backings is 0.37 BNB. Pricing on the ordinary average would charge 2.81x what an acquirer should expect to receive, because it treats the 1 BNB position as if it came up as often as the 0.05 BNB one.
The 2.5% surcharge
The surcharge is the only margin in the acquisition. It is a flat 250 bps on top of the expected value, and it does not change with pool size, position count or how the backings are spread.
The surcharge is then divided three ways.
| Destination | BNB | Rule |
|---|---|---|
| Protocol | 0.00134868 | ownerAcquisitionFeeBps 100, which is 1% of the whole acquisition fee |
| Depositors and the $BWA buy | 0.00194079 | Split between the two on the dynamic schedule |
| Surcharge | 0.00328947 | 2.5% of EV |
The protocol cut is taken out of the surcharge, not added to it. An acquirer pays EV * 1.025 whatever the owner fee is set to. Raising or lowering it moves money between the protocol and depositors, and never touches the price.
What is left of the surcharge splits between depositor earnings and buying $BWA, and that split moves with how busy the protocol is. The dynamic surcharge split has the schedule.
Computing EV in constant time
A naive implementation would walk every position to sum the reciprocals, which gets more expensive as the pool grows and eventually fails to fit in a block. The protocol never does that.
totalWeight is a running sum of inverse backings, maintained by one addition when a position becomes active and one subtraction when it leaves.
Substituting totalWeight = 1e36 * sum(1 / b_i) gives EV = n / sum(1 / b_i), the harmonic mean, from one multiply and one divide. Pricing costs the same gas with five positions in the pool as with fifty thousand.
The same accumulator drives selection. Scaling the VRF random word by totalWeight and walking to the matching position is the draw. Price and probability are two readings of one number.
Slippage
An acquisition is not instant. The fee is quoted and paid when the request is made, and the position is picked when Chainlink VRF returns. Between those two moments other people deposit and other requests settle, so the pool that gets sampled is not exactly the pool that was quoted.
The protocol snapshots the price at request time and enforces a band around it. The two sides of that band are set by different people, because they protect different people.
| Direction | What it means | Who is exposed | Bound |
|---|---|---|---|
| Price drifts up | EV rose after the request. The acquirer would receive more than they paid for. | Depositors, who would be handing over an above-price position | selectionSlippageBps, fixed at 1000, which is 10% |
| Price drifts down | EV fell after the request. The acquirer would receive less than they paid for. | The acquirer, who would be overpaying | Chosen per request by the acquirer, anywhere from 0% to 100% |
The upward cap is a protocol parameter because it is the pool's exposure and every depositor shares it. The downward tolerance is per request because only the acquirer knows how much drift they are willing to eat rather than wait and try again. Setting it to 0% means any drop at all voids the acquisition. Setting it to 100% means settle regardless.
Optional bounds
Two further limits can be attached to a request. Both are optional and both are snapshotted with everything else.
| Bound | Effect |
|---|---|
| maxAcquisitionFee | A hard ceiling on what the request may cost. If the fee at settlement is above it, the acquisition does not proceed. |
| minWeightedValue | A floor on the weighted value of the pool being sampled. If the pool has thinned out below it, the acquisition does not proceed. |
Refunds
Three situations end a request without a position changing hands.
- The pool empties before settlement
Every active position was drawn or withdrawn while the request was in flight. There is nothing left to sample.
- The price moves outside the snapshotted bounds
EV drifted up past
selectionSlippageBps, or down past the tolerance the acquirer set, or one of the optional bounds was breached. - The request expires
Randomness never arrived. Randomness covers what the protocol does then.
Refunds are pull based
A refund is recorded as a credit against your address. The protocol does not send BNB back to you as part of the failing transaction. You call the withdrawal yourself, whenever you like.
This is deliberate. A push refund can fail if the recipient is a contract that reverts on receipt, and a failed push inside settlement would jam the queue for everyone behind it. Crediting and letting the owner pull means one address's behaviour can never stall another's.
The VRF service fee is separate
Requesting randomness costs money, and that money is spent the moment the request is made whether or not the acquisition ever completes.
The VRF service fee is quoted separately from the pool fee and is never refundable. If a request is refunded, the acquisition fee comes back as a credit. The VRF service fee does not.
Both numbers are shown before you commit, so the total is never a surprise. They are listed apart because they behave differently, not to bury one of them.