Something.cool
  • Getting started
    • Why Something.cool?
    • 1st stage - Bonding curve
    • 2nd stage - CoolDEX trading
  • Zero-fee coins
    • What is Zero-fee coin?
    • How to launch Zero-fee coin
  • Community coins
    • What is Community coin?
    • Community contribution / How it works?
      • Holders
      • Liquidity providers
      • Burning
    • How to launch Сommunity coin
  • Features
    • Coin Explore
      • New Pairs
      • Coin Vision
    • Spaces
    • Rewards
  • Community
    • Referral program
    • X
    • Media kit
  • Developer Resources
  • Platform Architecture
    • Technical Introduction
    • Overview
    • Components
  • SC Bonding Curve
    • Overview
    • Functions
      • Create Token
      • Buy Token
      • Sell Token
      • Migrate
      • Admin Set Properties
    • Price Calculation
    • Fees
  • CoolDEX
    • Overview
    • Functions
      • Initialize Pool
      • Swap Base In
      • Swap Base Out
      • Deposit
      • Withdraw
      • Withdraw PnL
    • Price Calculation
    • Fees
  • Token Types
    • Token Types
  • Migration Process
    • Migration Process
  • Rewards Claiming
    • Overview
    • Authentication
    • Endpoints
    • Errors
    • Example
  • Reference
    • SC Bonding Curve IDL
    • CoolDEX IDL
    • Log Structure
    • DEVNET EXAMPLES
  • INTERNAL API
    • Overview
    • Register
  • Example: Registering a User via Internal API (JavaScript)
Powered by GitBook
On this page
  • Instruction
  • Parameters
  • Account Setup
  • Function Logic
  • Price Calculation
  • Notes
  • Example Usage
  1. SC Bonding Curve
  2. Functions

Sell Token

Sells tokens back to the bonding curve in exchange for SOL.

Instruction

SCBondingCurveInstruction::SellToken {
    pda_token_nonce: u8,
    token_to_spend: u64,
    min_sol_to_receive: u64,
    logging_account_bump: u8,
}

Parameters

Parameter
Type
Description

pda_token_nonce

u8

Nonce for the token owner PDA

token_to_spend

u64

Amount of tokens to sell

min_sol_to_receive

u64

Minimum acceptable SOL amount to receive (slippage protection)

logging_account_bump

u8

Bump for the logging authority PDA

Account Setup

#
Account
Description
Derivation

1

Payer account

Transaction signer (User wallet)

-

2

Token program

SPL Token program

TOKEN_PROGRAM_ID

3

Token owner PDA

Bonding curve account

[Buffer.from("token_owner"), mint.toBuffer(), [nonce]]

4

Token mint

Token mint address

Provided by user

5

Owner token account

Token account for PDA

getAssociatedTokenAddress(mint, ownerPDA, true)

6

User token account

User's token account

getAssociatedTokenAddress(mint, userWallet, false)

7

Fee account

Platform fee account

Fixed address (see Reference section)

8

Program account

SC bonding curve program

SC bonding curve program ID

9

Properties account

Platform configuration

[Buffer.from("settings")]

10

Log authority account

For structured logs

[Buffer.from("logging_authority")]

Function Logic

  1. Verifies the PDA token owner matches the expected PDA for the token mint

  2. Retrieves platform fee from properties account (currently 1%)

  3. Verifies the token is not finalized or mark as finalized if migration threshold is crossed

  4. Checks if trading is closed for the token

  5. Calculates expected SOL return amount using the bonding curve formula

  6. Verifies expected SOL amount meets minimum specified (slippage check)

  7. Updates pool balances in the bonding curve account

  8. Transfers tokens from user to the bonding curve

  9. Calculates fee amount and deducts from the SOL return

  10. Transfers remaining SOL to the user

  11. Transfers fee amount to the fee account

  12. Records sell data in logs

Price Calculation

sol_amount = pool_sol_balance * token_amount / (pool_token_balance + token_amount)

Where:

  • pool_token_balance = virtual_token + real_token

  • pool_sol_balance = virtual_sol + real_sol

  • token_amount = amount of tokens being sold

Notes

  • The platform fee is deducted from the SOL return amount

  • If the sale would leave less than POOL_MIGRATION_RESERVES tokens in the pool, the token is marked as finalized

  • Once finalized, a token can no longer be traded on the bonding curve

Example Usage

// Derive PDAs and other accounts
const [tokenOwnerPDA, pdaTokenNonce] = PublicKey.findProgramAddressSync(
  [Buffer.from("token_owner"), tokenMint.toBuffer()],
  SC_BONDING_CURVE_PROGRAM_ID
)

const [propertiesAccount] = PublicKey.findProgramAddressSync(
  [Buffer.from("settings")],
  SC_BONDING_CURVE_PROGRAM_ID
)

const [logAuthority, logAuthorityBump] = PublicKey.findProgramAddressSync(
  [Buffer.from("logging_authority")],
  SC_BONDING_CURVE_PROGRAM_ID
)

// Get token accounts
const ownerTokenAccount = getAssociatedTokenAddressSync(tokenMint, tokenOwnerPDA, true)

const userTokenAccount = getAssociatedTokenAddressSync(tokenMint, wallet.publicKey, false)

// Create instruction data buffer
const data = Buffer.alloc(18)
data.writeUint8(3, 0) // Instruction index for SellToken
data.writeUint8(pdaTokenNonce, 1) // PDA nonce
data.writeBigUInt64LE(tokenToSpend, 2) // Token amount
data.writeBigUInt64LE(minSolToReceive, 10) // Minimum SOL
data.writeUint8(logAuthorityBump, 18) // Log authority bump

const sellTokenIx = new TransactionInstruction({
  programId: SC_BONDING_CURVE_PROGRAM_ID,
  keys: [
    { pubkey: wallet.publicKey, isSigner: true, isWritable: true },
    { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
    { pubkey: tokenOwnerPDA, isSigner: false, isWritable: true },
    { pubkey: tokenMint, isSigner: false, isWritable: false },
    { pubkey: ownerTokenAccount, isSigner: false, isWritable: true },
    { pubkey: userTokenAccount, isSigner: false, isWritable: true },
    { pubkey: FEE_ACCOUNT, isSigner: false, isWritable: true },
    { pubkey: SC_BONDING_CURVE_PROGRAM_ID, isSigner: false, isWritable: false },
    { pubkey: propertiesAccount, isSigner: false, isWritable: false },
    { pubkey: logAuthority, isSigner: false, isWritable: false },
  ],
  data: data,
})
PreviousBuy TokenNextMigrate

Last updated 2 months ago