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.

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

weight = 1e36 / backingWei probability = weight / totalWeight

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.

Five active positions, weights and draw probabilities
# Backing (BNB) Backing (wei) Weight Drawn vs #5 Draws until picked
10.055e162.0e1952.63%20x1.9
20.101e171.0e1926.32%10x3.8
30.202e175.0e1813.16%5x7.6
40.505e172.0e185.26%2x19.0
51.001e181.0e182.63%1x38.0
Total1.85—3.8e19100.00%——

Reading the rows:

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.

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.

totalWeight = sum(1e36 / backing_i) = 1e36 * sum(1 / backing_i) EV = n * 1e36 / totalWeight = n / sum(1 / backing_i)

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

StateCounts toward priceCan be drawnEarning
StagedNoNoNo
ActiveYesYesYes
DrawnNoNoNo
SettledNoNoNo
WithdrawnNoNoNo

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.

Read next