Staking Pool

Token staking with configurable reward rates and compound interest

Deployed Anchor 0.32
Program ID E3xDfoQKgqdCNgnK1B77xgRjKYjEsBCXvPxZDGoxercH
Binary Size 344K
Cluster Devnet

Instructions

IX initialize_pool

Creates a new staking pool for a specific token mint with a configurable reward rate.

ParameterTypeDescription
reward_rateu64Reward tokens distributed per second per staked token
IX stake

Stakes tokens into the pool, creating or updating the user's stake entry.

ParameterTypeDescription
amountu64Number of tokens to stake
IX unstake

Withdraws staked tokens from the pool back to the owner's wallet.

ParameterTypeDescription
amountu64Number of tokens to unstake
IX claim_rewards

Claims accumulated staking rewards without unstaking the principal.

ParameterTypeDescription
No parameters

Accounts

StakePool

FieldTypeDescription
authorityPubkeyPool creator and configuration authority
mintPubkeyToken mint for this staking pool
reward_rateu64Reward rate per second per staked token
total_stakedu64Total tokens currently staked in the pool
accumulated_rewardu64Accumulated reward per token (scaled)
last_updatei64Timestamp of the last reward calculation
bumpu8PDA bump seed

StakeEntry

FieldTypeDescription
poolPubkeyThe staking pool this entry belongs to
ownerPubkeyWallet that owns this stake
amountu64Number of tokens staked
reward_debtu64Reward debt for accurate reward calculation
bumpu8PDA bump seed

PDA Derivation

pool
seeds = [b"pool", authority, mint]
stake
seeds = [b"stake", pool, owner]
vault
seeds = [b"vault", pool]

Error Codes

InsufficientStake Cannot unstake more tokens than currently staked
NothingToClaim No rewards have accrued since the last claim
Overflow Arithmetic overflow in reward calculation

Usage Example

import { Program, BN } from "@coral-xyz/anchor";
import { PublicKey } from "@solana/web3.js";

// Derive PDAs
const [poolPda] = PublicKey.findProgramAddressSync(
  [Buffer.from("pool"), authority.publicKey.toBuffer(), mint.toBuffer()],
  program.programId
);
const [stakePda] = PublicKey.findProgramAddressSync(
  [Buffer.from("stake"), poolPda.toBuffer(), staker.publicKey.toBuffer()],
  program.programId
);

// Stake 1000 tokens
await program.methods
  .stake(new BN(1_000_000_000))
  .accounts({
    pool: poolPda,
    stakeEntry: stakePda,
    owner: staker.publicKey,
    mint,
  })
  .signers([staker])
  .rpc();