Docs / Mechanics / Positions and weighting
Positions and weighting
A position is one NFT with BNB locked behind it. How often that position gets drawn depends on how little BNB is behind it. This page gives the formula, the reason for it, and a worked table.
What a position is
To open a position you supply two things in the same transaction.
- An NFT you own on BNB Smart Chain, which transfers into the pool.
- An amount of BNB, the backing, which locks alongside it.
From that moment the position is active. It counts toward the pool price, it can be drawn, and it starts earning both a share of acquisition fees and $BWA emissions.
The backing is the number that does all the work. It sets how often the position is drawn, it moves the price the whole pool quotes, and it is the amount an acquirer can sell the NFT back for.
The weight formula
backingWei the position backing, in wei totalWeight the sum of every active position weight
Weights are held as integers. totalWeight is a single running sum: adding a position adds its weight, removing one subtracts it. There is never a loop over positions to price or to draw.
Why the numerator is 1e36
Solidity divides integers and throws the remainder away. If the numerator were small, a large backing would divide down to zero and that position could never be drawn at all.
1e36 is large enough that this cannot happen at any backing a person would plausibly lock. A backing of 1 BNB is 1e18 wei, which gives a weight of 1e18. Even a backing far larger than the supply of BNB still lands on a weight comfortably above zero.
Why the weighting is inverse
Every acquirer pays the same price, and that price is a single number for the whole pool. For that to be fair, the pool needs to know what an acquirer should expect to receive.
Inverse weighting is what makes that number computable and stable. Under weight = 1e36 / backing, the expected backing an acquirer draws is the harmonic mean of every active backing, exactly. Not close to it, exactly it. The pricing page shows why.
It also has a plain effect anyone can feel. Cheap listings come up constantly. Expensive listings are rare. Someone paying a small fee is mostly going to draw small positions, and drawing a large one is the unlikely outcome it should be.
Read the direction carefully. Less BNB behind a position means it is drawn more often. A position with half the backing of another is drawn twice as often as it.
Worked example Illustrative
Five positions, chosen to make the arithmetic checkable by hand. These are not live numbers and nothing here is read from chain.
| # | Backing (BNB) | Backing (wei) | Weight | Drawn | vs #5 | Draws until picked |
|---|---|---|---|---|---|---|
| 1 | 0.05 | 5e16 | 2.0e19 | 52.63% | 20x | 1.9 |
| 2 | 0.10 | 1e17 | 1.0e19 | 26.32% | 10x | 3.8 |
| 3 | 0.20 | 2e17 | 5.0e18 | 13.16% | 5x | 7.6 |
| 4 | 0.50 | 5e17 | 2.0e18 | 5.26% | 2x | 19.0 |
| 5 | 1.00 | 1e18 | 1.0e18 | 2.63% | 1x | 38.0 |
| Total | 1.85 | — | 3.8e19 | 100.00% | — | — |
Reading the rows:
- Weight is
1e36 / backingWei. For position 1 that is1e36 / 5e16 = 2e19. - Drawn is that weight over the total,
2e19 / 3.8e19 = 52.63%. The five probabilities sum to 100.00%. - vs #5 is the ratio of the two weights, which is also the ratio of the two backings the other way up. Position 1 has one twentieth the backing of position 5 and is drawn twenty times as often.
- Draws until picked is
1 / probability, the average number of acquisitions before this position comes up, holding the pool unchanged. Position 5 waits about 38 acquisitions. Position 1 waits about 2.
The pool price that follows from these five backings is worked out on the pricing page. It comes to 0.13157895 BNB of expected backing, and an acquisition fee of 0.13486842 BNB.
Choosing a backing amount
There is a real trade in this decision, and it runs in both directions.
Low backing
Drawn quickly and often. Your position turns over fast, which means it spends few acquisitions earning fees before it closes.
You are also quoting a low floor. An acquirer who draws it can sell the NFT back to you for 90% of a small number, which is cheap for them and leaves you holding the NFT.
High backing
Rarely drawn. The position sits in the pool across many acquisitions, and acquisition earnings are split equally across active positions, so it collects on every one of them.
The cost is capital. That BNB is locked until the position is drawn or you withdraw it.
Two effects push back against simply locking as much as possible.
- Acquisition earnings are equal per acquisition across all active positions. Ten times the backing does not mean ten times the fees. Every active position earns the same per acquisition, and gains only by staying in the pool longer.
- $BWA emissions to depositors accrue on a square root of backing accumulator. Quadrupling your backing doubles your emission share rather than quadrupling it. The token page has the table.
A backing near the middle of the pool is the ordinary choice. Sitting far below the harmonic mean turns your position over quickly. Sitting far above it locks capital in exchange for a longer earning life and a smaller marginal claim on emissions.
The deposit floor
A deposit has to put up at least minBackingBps of what the pool is currently worth, which is 2500 bps, or a quarter of the expected value of a draw. On an empty pool the floor is the flat minBacking of 0.001 BNB instead.
The floor exists because the acquisition price is a harmonic mean, and a harmonic mean is dominated by its smallest members. Without it a handful of near worthless listings would drag the price for the whole pool down toward their own backing, and every honest depositor would be left sitting in a pool nobody wants to draw from. Making the floor track the pool keeps that from being cheap to do.
The owner can lower it to zero or raise it, but the contract will not accept anything above 5000 bps, so it cannot be turned into a gate that blocks deposits outright.
totalWeight does two jobs
The same running sum answers both questions the protocol asks.
Selection reads totalWeight to scale the random number. Pricing divides into it to get the harmonic mean. One accumulator, kept current by one addition or subtraction per deposit and per close, so both stay O(1) no matter how many positions are open.
Position lifecycle
| State | Counts toward price | Can be drawn | Earning |
|---|---|---|---|
| Staged | No | No | No |
| Active | Yes | Yes | Yes |
| Drawn | No | No | No |
| Settled | No | No | No |
| Withdrawn | No | No | No |
A position leaves the pool the moment it is drawn. Its weight comes out of totalWeight at that point, so the price the next acquirer sees already reflects its absence.
Deposits made while a request is open
A deposit that arrives while a randomness request is in flight is staged rather than added straight away, first in first out, and it becomes active once the open request settles.
This keeps the snapshot an acquirer paid against honest. The set of positions they could draw, and the price they were quoted, cannot be changed by anyone depositing after they committed. Randomness covers the queue in full.