BondingCurveTemplate
Manages bonding curve trading, quadratic pricing, graduation trigger, and the refund safety net. Deployed as a minimal proxy per token.
Minimal Proxy (EIP-1167) — one instance per deployed token. Initialized by the Factory.
State Variables
| Name | Type | Description |
|---|---|---|
state | PackedState | Packed struct: flags, current_supply_lots, deployment_timestamp, fees_collected |
refund_per_lot | uint256 | Fixed refund amount per lot (set when refund mode activates) |
token | address | The token this curve manages |
deployer | address | The address that deployed this token pair |
Write Functions
initialize(_token: address)
payable
external
Initialize the bonding curve with a token address. Called by the Factory during deployment. msg.value must equal DEPLOYER_INITIAL_PAYMENT (0.0006 ETH / 0.0012 BNB). Sets deployer = tx.origin.
"Already initialized"— flags ≠ 0"Must send 0.0006 ETH"/"Must send 0.0012 BNB"— wrong value"Invalid token"— zero address
buy(token_lots: uint256)
payable
nonreentrant
Buy token lots on the bonding curve. Mints token_lots * LOT_SIZE tokens to msg.sender. If this purchase fills the supply to MAX_SUPPLY_LOTS, triggers graduation automatically.
| Name | Type | Description |
|---|---|---|
token_lots | uint256 | Number of lots to buy (≥ 1) |
msg.value must equal exactly the total returned by quote_buy_price(token_lots).
"Below minimum"— token_lots < 1"Not initialized"/"Invalid state"— wrong lifecycle state"Supply exceeded"— new supply > 800,000"User limit exceeded"— user would hold > 36,000 lots"Incorrect payment"— msg.value ≠ quoted total
Buy(buyer, lots, eth_sent, base_price, tax)
If graduating: Graduated(token, deployer)
sell(token_lots: uint256)
external
nonreentrant
Sell token lots back to the curve. Burns the tokens and sends ETH proceeds to msg.sender. Deployer cannot call this function.
| Name | Type | Description |
|---|---|---|
token_lots | uint256 | Number of lots to sell (≥ 1) |
"Deployer locked"— msg.sender is deployer"Below minimum"— token_lots < 1"Insufficient tokens"— balance < token_lots * LOT_SIZE"Cannot sell at floor"— supply at INITIAL_SUPPLY_LOTS"Insufficient contract balance"— shouldn't happen normally
Sell(seller, lots, eth_returned, base_price, tax)
initiate_refund()
external
Activate refund mode after the 3-day bonding period expires without graduation. Calculates and locks refund_per_lot. Anyone can call.
"Period not over"— bonding period hasn't expired"Invalid state"— already graduated or in refund mode"No refunds"— zero balance or no eligible lots
refund_claim(token_lots: uint256)
external
nonreentrant
Claim ETH refund by burning tokens. Only available in refund mode. Deployer cannot claim.
| Name | Type | Description |
|---|---|---|
token_lots | uint256 | Number of lots to refund |
"Not refund mode"— refund not activated"Deployer cannot refund"— msg.sender is deployer"Insufficient tokens"— balance too low
RefundClaimed(user, lots, eth_received)
View Functions
quote_buy_price(token_lots) → (uint256, uint256, uint256)
view
Get the price quote for buying lots. Returns (base, tax, total) where total = base + tax. Use the total as msg.value for buy().
quote_sell_price(token_lots) → (uint256, uint256, uint256)
view
Get the price quote for selling lots. Returns (base, tax, proceeds) where proceeds = base - tax.
get_supply_lots() → uint32
view
Current supply in lots (includes deployer's initial 60,000).
get_sales_balance() → uint256
view
ETH balance minus collected fees.
get_fees_collected() → uint80
view
Total accumulated fees in the bonding curve (before graduation split).
is_graduated() → bool
view
Whether the curve has graduated (FLAG_GRADUATED is set).
is_refund_mode() → bool
view
Whether refund mode is active (FLAG_REFUND_MODE is set).
get_user_token_balance(user) → uint256
view
Returns user's token balance in lots (balanceOf / LOT_SIZE).