A complete off-chain implementation of a quadratic bonding curve in Python,
with integer-only arithmetic throughout (no floats, no math.pow, no np.power).
Price function: p(s) = k·s²
Reserve function: R(s) = (k/3)·s³
| File | Description |
|---|---|
bonding_curve.py |
Core implementation: buy, sell, reserve, icbrt |
tests.py |
Test suite covering zero supply, tiny payments, large supply, round-trips |
WRITE_UP.md |
Derivation of R(s), fair-launch analysis, Newton's method explanation |
No dependencies beyond Python 3.8+.
# Run tests
python tests.py
# Or with pytest
pip install pytest
pytest tests.py -vExpected output: 6/6 suites passed, all individual tests PASS.
from bonding_curve import buy, sell, reserve
k = 1 # scaling constant
# How much SOL backs 100 tokens?
print(reserve(100, k)) # 333333
# Pay 10^9 lamports from supply=0, how many tokens?
tokens = buy(0, 10**9, k)
print(tokens) # 1442
# Sell those tokens back, how much SOL returned?
proceeds = sell(tokens, tokens, k)
print(proceeds) # ≤ 10^9, difference is unused dustChosen for simplicity. Any positive integer k is supported via the optional parameter. With k=3, reserve has no floor-division loss (k/3 = 1 exactly).
All computations use Python's arbitrary-precision integers. The // operator
is used for integer floor division consistently throughout.
Implemented from scratch in icbrt(). Converges in 2–5 iterations for n ≤ 10^18
. See WRITE_UP.md §3 for the derivation and convergence analysis.
When a buyer purchases Δs tokens and immediately sells them back:
sell(s + Δs, Δs)returns exactlyreserve(s + Δs) - reserve(s)- This is always ≤ the original payment (the difference is "dust", lamports left over because icbrt rounds token count down)
- The contract never overpays:
proceeds ≤ paymentis a hard invariant
sell() raises ValueError if tokens_burned > supply. It does not silently clamp — callers must validate inputs.
| Test suite | What it covers |
|---|---|
icbrt |
Perfect cubes, non-perfect cubes (floor), 10^18, exhaustive [0,1000) |
reserve |
Zero supply, k=1 spot checks, monotonicity |
buy |
Zero payment, small/large supply, cost invariant for 16 (supply, payment) pairs |
sell |
Zero tokens, spot checks, large supply |
round-trip |
5 cases across supply and payment scales; proceeds ≤ payment + reserve-equality |
edge/stress |
10^18 supply, k variations, 999999³ cube root |