Skip to content

YazhuEth/SPL-Staking-Program

Repository files navigation

Solana SPL Token Staking Program (spl_staking_program)

A Solana program that enables staking of any SPL token. Built with Anchor framework.

Features

  • Stake any SPL token
  • Unstake at any time (no lock period)
  • Track staking history and statistics
  • Multiple users can stake in the same pool
  • Daily reward epochs with anti-gaming measures

Installation & Setup

Note: This program is named spl_staking_program in the codebase.

1. Install Dependencies

# Install Solana CLI (You can check the official solana website)
curl --proto '=https' --tlsv1.2 -sSfL https://solana-install.solana.workers.dev | bash

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source $HOME/.cargo/env

# Install Anchor
cargo install --git https://github.com/coral-xyz/anchor avm --locked --force
avm install latest
avm use latest

# Install project dependencies
npm install

2. Configure Solana CLI

# Generate deployment wallet in project directory
# Make sure you're in the project root directory where Anchor.toml is located
solana-keygen new -o payer.json  # Creates payer.json in current directory

# Configure CLI
solana config set --url localhost # For local testing
solana config get # Verify your settings

Development Workflow

1. Local Development

# Start local validator in a separate terminal
solana-test-validator

# Build and deploy
anchor build
anchor deploy

2. Testing & Analysis

Reward Calculation Example

I provide an example script (scripts/analysis/calculate_rewards.ts) that shows how to handle reward calculations.

⚠️ Important considerations for rewards:

  • Users can stake/unstake at any time
  • Hard to track exact amounts between movements
  • Solution: Use daily epochs
    Day 1: User stakes 100 → Eligible for rewards
    Day 2: User unstakes 50 → No rewards for this day
    Day 3: No movements → Rewards on remaining 50
    
  • Skip rewards for epochs with movements
  • Only reward "stable" staking periods

To run the example:

The script uses anchor.AnchorProvider.env() which requires two environment variables:

  • ANCHOR_PROVIDER_URL: Network RPC URL
  • ANCHOR_WALLET: Path to your wallet keypair

You can configure these in two ways:

  1. For the entire terminal session:
# Configure for local validator
export ANCHOR_PROVIDER_URL="http://127.0.0.1:8899"
export ANCHOR_WALLET="./payer.json"

# Or for devnet
export ANCHOR_PROVIDER_URL="https://api.devnet.solana.com"
export ANCHOR_WALLET="./payer.json"

# Or for mainnet
export ANCHOR_PROVIDER_URL="https://api.mainnet-beta.solana.com"
export ANCHOR_WALLET="./payer.json"

# Then run analysis
ts-node scripts/analysis/calculate_rewards.ts
  1. Just for one command:
# All in one line
ANCHOR_PROVIDER_URL="http://127.0.0.1:8899" ANCHOR_WALLET="./payer.json" ts-node scripts/analysis/calculate_rewards.ts

Note: This is the same mechanism that anchor test uses internally to configure the test environment.

This is just one possible approach - you might want to:

  • Use a database to track historical stakes
  • Implement on-chain epoch tracking
  • Create your own reward distribution logic

Run Program Tests

# Run all tests with logs
anchor test -- --show-output

# Run specific test file
anchor test tests/staking.ts -- --show-output

Analyze Staking Rewards

# Make sure you're connected to the right network
solana config set --url devnet  # or mainnet-beta

# Run reward analysis script
ts-node scripts/analysis/calculate_rewards.ts

The reward analysis script:

  • Calculates rewards based on daily epochs
  • Shows staking statistics per user
  • Displays pool-wide metrics
  • Identifies stable stakers (no movements in current epoch)

Note: Users who stake/unstake during an epoch won't receive rewards for that epoch to ensure accurate reward calculation.

3. Devnet Testing

# Configure for devnet
solana config set --url devnet

# Get SOL from faucet
solana airdrop 2 payer.json

# Update Anchor.toml
[provider]
cluster = "devnet"
wallet = "./payer.json"

# Deploy
anchor deploy --provider.cluster devnet

# Initialize program
ts-node scripts/initialize.ts

4. Mainnet Deployment

# 1. Configure for mainnet
solana config set --url mainnet-beta

# 2. Update Anchor.toml
[provider]
cluster = "mainnet"
wallet = "./payer.json"

# 3. Generate program keypair
solana-keygen new -o target/deploy/spl_staking_program-keypair.json --force

# 4. Update program ID
anchor keys sync

# 5. Build
anchor build

# 6. Deploy
anchor deploy --provider.cluster mainnet
# Or use npm script
npm run deploy:mainnet

# 7. Initialize
ts-node scripts/initialize.ts
# Or use npm script
npm run init

Network Configuration

Local Development

solana config set --url localhost

Devnet Testing

solana config set --url devnet

Mainnet Deployment

solana config set --url mainnet-beta

Verify your configuration:

solana config get

Useful Commands

Program Management

# Check program ID for spl_staking_program
solana address -k target/deploy/spl_staking_program-keypair.json

# Check program status
solana program show <PROGRAM_ID>

# Check wallet balance
solana balance -k payer.json

# Close program and recover rent (specify network)
# For devnet:
solana program close <PROGRAM_ID> --url devnet --keypair payer.json --bypass-warning

# For mainnet:
solana program close <PROGRAM_ID> --url mainnet-beta --keypair payer.json --bypass-warning

Important Notes

Security

  • Always backup payer.json and program keypair
  • Test thoroughly on devnet before mainnet
  • Verify network configuration before transactions
  • Double-check program ID in all files

Costs

  • Devnet: Free (use airdrop)
  • Mainnet deployment: ~2.8 SOL (recoverable)
  • Transaction fees: ~0.00001 SOL per tx

Troubleshooting

Common Issues

  1. Wrong Network: Use solana config get to verify
  2. Insufficient Balance: Use solana balance to check
  3. Build Errors: Try anchor clean && anchor build
  4. Test Validator: Use solana-test-validator --reset to clear state

Error Recovery

# Clean build artifacts
anchor clean

# Reset local validator
solana-test-validator --reset

# Close program if needed (specify network)
solana program close <PROGRAM_ID> --url devnet --keypair payer.json --bypass-warning  # For devnet
solana program close <PROGRAM_ID> --url mainnet-beta --keypair payer.json --bypass-warning  # For mainnet

# Verify program deployment
solana program show $(solana address -k target/deploy/spl_staking_program-keypair.json)

About

Example Solana program for staking SPL tokens built with Anchor. Includes basic stake/unstake functionality and reward calculation. This is a demonstration project that can and should be improved before production use.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors