Jan 25, 2022 | Dave White, Frankie, Justin Roiland
This paper introduces the Constant Rate Issuance Sales Protocol, or CRISP, a pricing mechanism that aims to sell NFTs at a targeted rate over time.
If we want to sell 100 NFTs per day but are on pace to sell only 10, CRISP will slowly decay the "buy it now" price. If we want to sell 100 NFTs per day but are on pace to sell 200, CRISP will rapidly increase the “buy it now” price with every new sell.
We provide a Python notebook modeling the mechanism's behavior, as well as a reference Solidity implementation.
Imagine you have an unlimited set of NFTs that you want to sell at a constant rate — say, 100 per day.
You might design an auction system to achieve this goal. You could sell all 100 in a single auction, or perhaps hold 100 different auctions of one NFT each.
However, the user experience of an auction can be quite unwieldy — auctions cost gas, and we want users to be able to buy one of these NFTs at any time, without having to wait for an auction to terminate.
CRISP tracks the rate at which NFTs are being sold, and compares it to a target rate.
When NFTs are being sold too quickly relative to the target rate, we want to be able to adjust prices quickly. The higher the sales rate compared to the target rate, the faster we want to raise prices.
On the other hand, when NFTs are being sold too slowly relative to the target rate, we do not want to be too hasty to lower prices. After all, there had been sufficient demand to support the current price at some point in the past. As a result, we decay prices slowly over time.
We measure the sales rate using an Exponential Moving Sum, or EMS.
The EMS is an adaptation of the Exponential Moving Average that is commonly used in quantitative trading to measure the accumulation of some quantity over a recency-weighted window of time. It is cheap to calculate and requires little storage.
The CRISP EMS in particular tracks the number of NFTs sold over a recent time period defined by
sale averaging halflife. A
sale averaging halflife of 100 would mean that a sale 100 blocks ago would add only
The EMS at block
Given two blocks,
We can translate a target sales rate to a target EMS using the above formula. Assuming we are targeting a rate of 1 sale every
(see Appendix for proof).
If the current EMS is above the target, the sales rate is by definition too high. As a result, we want to charge more for the next NFT, because that will (presumably) reduce demand, or, at the very least, increase revenue.
The faster we are selling NFTs relative to the desired rate, the more quickly we should update prices. So, we define a variable
and then set
price increase speed controls how quickly price reacts to differences between the target and observed rates.
In this example, we model CRISP over a period of 200 blocks. We are targeting one sale per 100 blocks, and using a sale halflife of 700 blocks. In the given period, we see purchases happening every 50 blocks, which is above our target. This pushes the EMS upward on every purchase, and price reacts accordingly.
When the current EMS is below target, the sales rate is too low. As a result, we want to charge less for the next NFT, making it a more attractive purchase.
However, we want to decay prices slowly over time, because we managed to hit the target rate at previous prices and we don’t want to drop prices more than we have to.
Assuming the last sale happened on block
price decay halflife controls the rate of decay.
Because we only want to decay price when the sales rate is below the target, if the current sale is the first since the sales rate dropped below the target price, we calculate decay starting from the block when the rate dropped below the target, not from time since the last sale.
In this example, we model CRISP over a period of 300 blocks. Again, we target one sale every 100 blocks. In the given period, only one purchase happens, on the 200th block. We see that the current EMS slowly falls over the first 200 blocks, but price does not start falling until around the 100th block, when the current EMS falls below the target. Since after the purchase, the EMS is still below target, price does not increase.
An example of CRISP over a longer time period. At first, purchase rate is too high, so price increases with every purchase. After a period with no purchases, price and purchase rate roughly stabilize.
A Python notebook and Solidity implementation are available at https://github.com/FrankieIsLost/CRISP.
We hope CRISP will unlock a host of cool and interesting NFT dynamics.
If you spot any problems or think of any improvements, we'd love to hear from you! You can reach us at @Dave__White, @FrankieIsLost, and @justinroiland on Twitter.
Assume we are targeting a sales rate of 1 sale every nth block. Then, using formula (1), the EMS on the block of the
This is a geometric series which converges to
Hence, we can translate between target sales rates and target EMS.
Acknowledgments: Dan Robinson, Will Robinson, Sam Sends, Jim Prosser, 0xmons, t11s, nnnnicholas, Grug, mewny
Disclaimer: This post is for general information purposes only. It does not constitute investment advice or a recommendation or solicitation to buy or sell any investment and should not be used in the evaluation of the merits of making any investment decision. It should not be relied upon for accounting, legal or tax advice or investment recommendations. This post reflects the current opinions of the authors and is not made on behalf of Paradigm or its affiliates and does not necessarily reflect the opinions of Paradigm, its affiliates or individuals associated with Paradigm. The opinions reflected herein are subject to change without being updated.