Skip to main content

Bonding Curve Plugin

Status: Stable – available on Solana devnet.

Import identifier in policy expressions: @BondingCurvePlugin.*

The Bonding Curve Plugin exposes pure, read‑only helpers that let Tarobase policies perform constant‑product AMM math entirely on‑chain, without requiring custom Rust code. Use it to verify that a trade meets slippage constraints or honours locked liquidity before you allow a create on a buy/sell operation.

No transactional (state‑changing) functions are provided. All helpers may be used anywhere an expression expects a numeric value: rules.*, hooks.*, or LLM prompts.


Function reference

FunctionSignatureReturnsDescription
getTokensOutProduct@BondingCurvePlugin.getTokensOutProduct(tokenAmount, currentSolReserves, currentTokenReserves, initialSolReserves, initialTokenReserves)UIntCalculates tokens a buyer receives when they provide tokenAmount of SOL to the curve (i.e., a buy). All parameters are lamports / smallest‑unit tokens.
getSolOutProduct@BondingCurvePlugin.getSolOutProduct(solAmount, currentSolReserves, currentTokenReserves, initialSolReserves, initialTokenReserves)UIntCalculates lamports a seller receives when they provide solAmount of tokens to the curve (i.e., a sell). All parameters are lamports / smallest‑unit tokens.

Formula – Both helpers implement the classic x · y = k constant‑product invariant, accounting for the supplied amount and the initial virtual reserves. The results are rounded down to the nearest integer to guarantee conservativeness.


Quick‑start examples

1. Enforcing minimum tokens received on a buy

"operations/$agentId/buy/$buyId": {
"fields": {
"solIn": "UInt", // lamports user intends to spend
"minTokens": "UInt" // desired minimum token amount (smallest units)
},
"rules": {
"create": "@BondingCurvePlugin.getTokensOutProduct(@newData.solIn, @TokenPlugin.getBalance($agentId, @TokenPlugin.SOL), @TokenPlugin.getBalance($agentId, @TokenPlugin.getTokenMintAddress($agentId, get(/agents/$agentId).tokenName, get(/agents/$agentId).tokenSymbol)), INITIAL_SOL, INITIAL_TOKENS) >= @newData.minTokens"
}
}

Replace INITIAL_SOL / INITIAL_TOKENS with constants or stored fields.

2. Respecting locked liquidity on a sell

"operations/$agentId/sell/$sellId": {
"fields": { "tokenIn": "UInt", "minLamports": "UInt" },
"rules": {
"create": "@BondingCurvePlugin.getSolOutProduct(@newData.tokenIn, @TokenPlugin.getBalance($agentId, @TokenPlugin.SOL), @TokenPlugin.getBalance($agentId, TOKEN_MINT), INITIAL_SOL, INITIAL_TOKENS) >= @newData.minLamports && (@TokenPlugin.getBalance($agentId, @TokenPlugin.SOL) - get(/agents/$agentId).lockedLiquidity) >= @BondingCurvePlugin.getSolOutProduct(@newData.tokenIn, …)"
}
}

This pattern prevents draining SOL below lockedLiquidity while still honouring the curve price.


Best practices

  • All inputs are integers – use lamports and smallest‑unit tokens, never floats.
  • Cache currentSolReserves / currentTokenReserves with @TokenPlugin.getBalance to avoid double calculation inside complex expressions.
  • Store initial virtual reserves in the parent agents/$agentId document or as constants; they must match the values used when the curve was bootstrapped.
  • Use cross‑multiplication (or the helper itself) rather than division for slippage checks to avoid precision loss.
  • Because the helpers are pure, calling them has zero compute‑unit cost on the transaction beyond basic arithmetic.