This post is an in-depth exploration of bonding curves and is loosely based on a talk and workshop I gave at the 2nd Token Engineering Meetup in NYC. In the first half of the article, I’ll try to provide some intuition into how one might use bonding curves. The second half is more technical and includes some math that will hopefully aid the reader in parameterizing and implementing bonding curves. Feel free to skip to the section most relevant to you.
Bonding Curve Use Cases — some background and thoughts 🤔
- Intrinsic Value & Pyramid Schemes
- Secondary Markets and Liquidity
Parameterizing Bonding Curves — for the MATH HEADS 🤓
- Power Function Curves
- Computing Buy and Sell Prices
- Why Bancor Formula?
- Beyond Power Functions: Sigmoid Curve
If you are new to bonding curves, please consider reading my earlier post on the subject — it will serve as a much better introduction:
And for some cool bonding curve history and more links, check out this post by one of the pioneers of the concept, Simon de la Rouviere:
In any case, here is a refresher:
A bonding curve contract is an automatic market maker (a smart contract that enables users to buy and sell tokens) with the following properties:
- A token can be minted (bought) at any time according to a price set by a smart contract.
- This price increases as token supply grows.
- The money (like ETH or DAI) paid for tokens is kept in the smart contract (reserve pool).
- At any point in time, a token can be burned (sold) back to the contract.
Intrinsic Value vs Pyramid Schemes
Bonding curves are a great tool for designing incentive mechanisms. At its essence, a bonding curve is a way to incentivize early adopters — those buying in at the bottom of the curve. Of course if there is no intrinsic value to the bonded token, the bonding curve may be a pyramid scheme and is more susceptible to manipulation.
For a bonded token to have intrinsic value it should entitle the holder to some future cash flows. If that’s the case, we can easily compute the present value of the tokens as the sum of all future cash flows. Once we know how much a token is worth, it becomes harder to manipulate its price.
For example, if you are purchasing tokens of a continuous organization (sort of like buying equity in a traditional corporation), and the token entitles you to a portion of future cash flows of that organization, you’ll be able to estimate the token’s present value. If you are able to observe when the bonded token is overpriced, it will be harder for attackers to execute a pump and dump. If, on the other hand, we create a bonding curve and attach it to a meme without any promise of future cash flows, we’ll have a much harder time reasoning about the fair price of the bonded token. In this case the bonding curve is easier to manipulate and is much more like a gambling game.
This distinction becomes a more convoluted with apps like POWH where token holders do earn cash from subsequent transactions 😮. But in this case any cash flow projections are based on the assumption that it is a pyramid scheme, since all potential earnings depend on more users joining.
Bonded tokens that don’t have tangible intrinsic value are not necessarily useless pyramid schemes. We know that cultural trends, ideas, and narratives may possess intangible value and yet have a tangible impact on the real world. The art world is a good example of this — intangible qualities of art are assigned tangible value via the art market. A bonding curve can be similarly used to create tokens that represent intangible qualities that a large number of humans find valuable. However, extra care must be exercised in order to avoid rampant manipulation when implementing these kinds of bonding curves.
In general, all bonding curves are susceptible to manipulation, like pump and dump schemes. There are several ways to mitigate these attacks. Most of them have to do with forcing some sort of time-lock on selling tokens, or charging a premium for selling. A great way to mitigate pump and dump attacks is to disallow sell functionality all together. If users want to sell their tokens, they will have to find buyers on the secondary markets which will make dumping the token harder for the attacker, especially early on when the market size is small and there is little liquidity.
Secondary Markets and Liquidity
It’s obvious that any bonded token can be traded outside of the bonding curve smart contract — on decentralized or centralized exchanges. So, if a token starts actively trading on an external exchange, which market dictates the price?
Some bonding curve contracts will dictate the price no matter what, like in the case of a flat curve, where the price is hard-pegged to the backing currency:
Such a contract can mint an infinite amount of tokens at a constant price. If one can buy a DPT (dumb peg token) for 10 DAI via the bonding curve, I doubt anyone will want to pay more than that on an exchange.
But in the case of a token with an extremely steep bonding curve, there will eventually be a point when even a small order will move the price by a big amount. At that time, most of the trading and price discovery will take place on an external exchange and the bonding curve contract will simply follow along.
The token price will be most influenced by the exchange with the biggest market depth (the market’s ability to sustain relatively large market orders without impacting the price of the security). This is because if the price on any two exchanges diverges, arbitrageurs will take advantage of the price difference and the exchange with a lower market depth will be the first to adjust its price to eliminate the price disparity.
Of course, if the two markets have similar market depth, both markets will move by the same amount. This illustrates the fact that if a bonding curve has significant market depth in comparison to the open market, it can dampen the volatility of the latter.
Finally we can use bonding curves on a micro level as an automated market maker within curation markets in the same way market makers are used in prediction markets. Curation markets are characterized by enabling staking (or betting) on distinct elements of a continuous data feed. For example, staking on the most educational post in a feed about AI technology.
To enable staking on a given post we can use a post-specific bonding curve. The bonding curve contract can mint shares as needed, but never burns them (shares cannot be sold). After some time, the best posts will earn a payout which can be distributed to all the users that hold shares of that post. Depending on the design, all or some of the tokens held by the curve can at that point also be returned to the original buyers.
Of course deciding which posts deserve to get a payout is not a trivial task. Vanilla curation market proposals and Steemit, the original and biggest existing market, use the amount of tokens staked on a post to determine ‘winners’. This is akin to a self-fulfilling prediction market — one where the prediction also determines the outcome (this is why assassination markets are a problem). If we want to avoid manipulation and enforce meaningful curation criteria, the outcome should never be based on the amount of tokens staked on a given post. More about how we accomplish this with the Relevant protocol in a future blog post.
And now for some math!
Defining a Vanilla Curve
The most common bonding curves used today are those that can be expressed by a power function:
Where y = token price x = token supply n = exponent parameter m = slope parameter
For example, the curve below has parameters
n = 2 and
m = 1/400
By playing around with parameters
m we can finetune the bonding curve for our desired use case.
Computing Buy and Sell Prices
Because the price of the token changes with each infinitesimally small change in token supply, if we want to buy k tokens, we must integrate the price function.
For example, to figure out the amount of money one must pay for buying
k tokens given current supply
s we compute following integral:
If we solve for
k, we’ll also have a function for computing how many tokens we should mint if a user sends
p reserve tokens to the contract:
We could use the above equations to implement our bonding curve in Solidity except for one problem — to solve the above equations, we would need to compute
s^(n+1) which can end up being bigger than
2^256 with a large-enough
s. This will cause an integer overflow and break our computation. For example, if
n = 10, the maximum amount of tokens we will be able to mint is
(2^256)^(1/11) = 10,134,188. (*note this is without accounting for precision error! If we want to include precision, of say 10000, the maximum amount of tokens is 1,013). However for small exponents this method is feasible, as long as we have reasonable safeguards against a potential integer overflow.
But we can also avoid the overflow issue in a general case! At any given point, we know how much money the contract currently holds — thats our
poolBalance which is the area under the curve between 0 and
totalSupply visualized below:
b and we have:
If our exponent,
n, is small, we can have a simplified formula for computing price based on the power function formula:
Of course this doesn’t solve our overflow problem because we still have to compute a large exponent. So we simplify further and get:
p is the price of buying
Solving the equation for tokens to mint, given deposit
p, we have:
Why Bancor Formula?
The above equations are the essence and beauty of the bancor formula. We can easily avoid an integer overflow in our smart contracts by using the current
poolBalance of the contract instead of using the slope parameter
m. There is another parameter bancor formula introduces — the
It turns out, the reserve ratio is just another way to express the exponent parameter:
Thus the final bancor price formula becomes:
We are now able to express bancor parameters in terms of slope and exponent and vise versa! (Coincidentally Billy Rennekamp just published an article on this topic as well)
Note that most of the bonding curve smart contracts out there today are using the original bancor parameter names that are a little confusing:
reserveRatio = connectorWeight poolBalance =connectorBalance tokenSupply = supply
There are other problems the bancor formula poses:
- It’s not intuitive what the initial parameters should be for a given curve — the power function params are more intuitive and easier to model.
- Contracts are difficult to initialise — one must deploy the contract with some initial
- If at any point the
tokenSupplybecomes 0, the contract becomes stuck and unusable.
We already have a fix for (1). To recap, if we want to parameterize a curve using bancor parameters, we can use the formulas below.
Let: r = reserveRatio b = poolBalance s = totalSupply
Then our exponent parameter
n can be expressed as:
and the power formula can be re-written like so:
Finally, to make parameterization more intuitve, we can define a new parameter
p_s to denote the price of the token when
tokenSupply = s then our price equation becomes:
We can now draw some curves and tweak the parameters to get the desired outcome: https://www.desmos.com/calculator/8gxacjujal
To solve issues (2) and (3) I propose the following:
When initiating a contract, define the reserve ratio
r, and slope
m. Whenever token supply is 0, use the power function with slope parameter
m to compute the price:
So if current supply is 0 and a user wants to buy
s tokens, they will need to deposit
p reserve tokens into the contract:
Alternately if a user sends a contract the amount
p of the reserve currency, we compute the amount
s of tokens to mint:
Beyond Power Functions—Sigmoid
We don’t have to limit ourselves to power functions when designing bonding curves. In theory any function with an easily-computed definite integral can be used. In practice, if we are building smart contracts on Ethereum, we need to work within the constraints imposed by Solidity and be mindful of things like integer overflow.
One class of functions that may have exciting applications is sigmoid functions (introduced in this post by
). They looks like this:
A token with this kind of curve exhibits exponential growth in its early stages and then gradually transitions to a stable token pegged to the reserve currency. The most common sigmoid function is this:
and it has the following integral:
You might notice that this will very quickly cause a problem for our smart contracts. Not only do we have to compute a logarithm, but as our token supply increases
e^x will very quickly overflow and prevent us from computing buy and sell prices.
Luckily there is another sigmoid function with a very friendly integral:
It’s integral is (click here if you’re curious how one would compute it):
We can add some parameters to this function in order to be able to customize it to our needs:
Where: a = the height of the curve (or maximumPrice/2) b = the token supply at the inflection point happens (aka midway point) c = the steepness of the curve
You can play around with the curve parameters here: https://www.desmos.com/calculator/j1yxue0euk
Computing buy and sell prices is fairly straightforward and can be easily implemented in a smart contract. Below is the formula for the price
k tokens given token supply
Btw, Wolfram Alpha is a pretty cool tool for working with equations.
Implementing this curve in a smart contract should very easy, so I’m looking forward to seeing projects use sigmoids!
- Bonding curves are incentive mechanisms, but are easily susceptible to pump and dump attacks. The easier it is to find out the intrinsic value of a bonded token, the harder it will be to manipulate. Disallowing selling is also an effective way to mitigate attacks.
- A market (including a bonding curve market maker) with the biggest market depth will always will have the biggest impact on token price.
- Bonding curves are a great market maker for curation markets and are similar to market makers in prediction markets.
- Bancor formula helps avoid integer overflow when computing bonding curve prices, but can be improved to make parameterization more intuitive and to make the contract usable when token supply is 0.
- Sigmoid bonding curves are cool and easy to implement.
If you are interested in implementing some of the proposals mentioned in this article, go for it! These are:
- Bancor formula with intuitive parameter names
- Bancor formula with slope parameter to account for cases when token supply is 0
- A sigmoid bonding curve contract
Feel free to submit a pull request here and please reach out if you’re working on any of this stuff or have questions!