MarketMathCore

MarketMathCore encodes the time-decaying pricing curve and trade execution math used by FiraMarket. OracleLib provides the TWAP ring buffer.

circle-info

Source: src/fira_bonding/core/Market/MarketMathCore.sol, src/fira_bonding/core/Market/OracleLib.sol

MarketMathCore

This library operates entirely on in-memory MarketState structs for gas efficiency. It never reads from or writes to storage directly.

Pricing model

The AMM prices BT relative to FW using a logit curve:

exchangeRate = ln(proportion / (1 - proportion)) / rateScalar + rateAnchor

Where proportion = totalBt / (totalBt + totalAsset) and totalAsset is FW reserves converted to underlying asset units via the BC index.

  • rateScalar scales inversely with time-to-expiry (scalarRoot × 365 days / timeToExpiry), making the curve steeper near maturity.

  • rateAnchor is recalculated after each trade so that the current pool proportion yields the last recorded implied rate.

Liquidity math

  • First deposit: Mints sqrt(fw × bt) - MINIMUM_LIQUIDITY LP tokens, locking 1000 wei permanently.

  • Subsequent deposits: Mints proportional to the limiting token.

  • Removal: Returns proportional shares of both reserves.

Trade execution

executeTradeCore loads pre-computed values, calculates the FW amount from the exchange rate, applies fees, and updates state. Fees are split between the swapper (as worse pricing) and the reserve (as a percentage of the fee). The post-trade implied rate is recalculated and stored.

Key invariants

  • Exchange rate is always >= 1e18 (reverts otherwise)

  • BT proportion cannot exceed MAX_MARKET_PROPORTION (96%)

  • Implied rate is always > 0 after a trade

  • MINIMUM_LIQUIDITY prevents the first-depositor attack

OracleLib

Adapted from Uniswap V3's oracle. Stores Observation structs (timestamp + cumulative ln(impliedRate) + initialized flag) in a fixed-size array of 65,535 slots.

  • write() — Appends a new observation if the block timestamp differs from the last

  • grow() — Pre-initializes storage slots to reduce gas during swaps

  • observe() — Returns cumulative values at requested time offsets using binary search

  • TWAP is computed by the caller as (cumulative[now] - cumulative[ago]) / duration

Last updated