A minimal educational implementation of a perpetual futures trading program on Solana. This demonstrates the core concepts of opening positions, funding payments, and liquidations.
β οΈ Not Production Ready: This implementation is missing critical components like secure price oracles, order book matching, proper risk management, and extensive security checks. Use as a learning resource and starting point only.
The program implements a simplified perpetual futures system with these key components:
- Positions: Long/short exposure with collateral backing
- Funding Mechanism: Periodic payments between longs and shorts
- Liquidation System: Automatic closure of undercollateralized positions
- Market State: Global parameters and funding rates
pub struct Position {
pub owner: Pubkey, // Position owner
pub base_amount: i64, // Signed position size (+ = long, - = short)
pub collateral: u64, // Locked collateral in quote token
pub last_funding_index: i64, // Last applied funding index
pub entry_price: u64, // Entry price (1e9 precision)
}pub struct MarketState {
pub funding_index: i64, // Cumulative funding index
pub funding_rate_per_slot: i64, // Current funding rate
pub open_interest: u64, // Total position size
pub bump: u8, // PDA bump
pub last_funding_slot: u64, // Last funding update
pub mark_price: u64, // Current mark price
}Creates or modifies a trading position.
Parameters:
base_delta: i64- Position size change (positive = long, negative = short)collateral_delta: u64- Additional collateral to depositentry_price: u64- Price for the position (1e9 precision)
Accounts:
- User (signer)
- Token program
- User's collateral token account
- Vault token account (PDA)
- Position account (PDA)
- Market state account (PDA)
- Rent sysvar
- Clock sysvar
- System program
Updates the global funding rate and index.
Accounts:
- Market state account (writable)
- Clock sysvar
Liquidates an undercollateralized position.
Accounts:
- Liquidator (signer)
- Token program
- Liquidator's token account
- Vault token account (PDA)
- Position account (writable)
- Market state account (writable)
- Clock sysvar
Voluntarily closes a position and returns collateral.
Accounts:
- User/owner (signer)
- Token program
- User's token account
- Vault token account (PDA)
- Position account (writable)
- Market state account (writable)
-
Install WSL:
# Run as Administrator in Command Prompt or PowerShell wsl --install # Reboot if prompted
-
Setup development environment in WSL:
# Open WSL terminal and run all subsequent commands in WSL sudo apt update && sudo apt install curl git build-essential
-
Use WSL for all development:
- Always use WSL terminal for building and deploying
- WSL Tunnel Extension if using VS Code
- Run
./scripts/1_build.sh
-
Install Solana CLI:
# Unix/Mac/WSL sh -c "$(curl -sSfL https://release.solana.com/v1.18.0/install)" # Windows (Direct - NOT recommended, use WSL instead) # Download and run: https://release.solana.com/v1.18.0/solana-install-init-x86_64-pc-windows-msvc.exe
-
Install Rust and Solana BPF toolchain:
rustup component add rust-src solana install init
-
Create/Import Wallet:
# Create new keypair solana-keygen new --outfile ~/.config/solana/id.json # OR import existing (e.g., from Phantom) solana-keygen recover "prompt://?key=0"
Before deploying to devnet, you need test SOL. The official faucet has rate limits (2 requests per 8 hours).
-
Automated Faucet Script (Recommended):
# Try multiple faucets automatically ./scripts/2_getsol.sh [amount] # Default: 1 SOL # Examples: ./scripts/2_getsol.sh # Get 1 SOL ./scripts/2_getsol.sh 2 # Get 2 SOL
-
Manual Options:
- Official Faucet: https://faucet.solana.com (rate limited)
- SolFaucet: https://solfaucet.com (manual interaction required)
- Community Discord: Ask in Solana communities
-
Check Your Balance:
solana balance
-
Clone and Build:
cd simple_perps # Unix/Mac/WSL (recommended for all platforms) ./scripts/1_build.sh
Note for Windows users: Always prefer WSL environment for development.
-
Deploy to Devnet:
# Unix/Mac/WSL (recommended for all platforms) ./scripts/3_deploy.sh devnet -
Deploy to Mainnet:
# Unix/Mac/WSL (ensure you have sufficient SOL!) ./scripts/3_deploy.sh mainnet
- Base Rate: 0.01% per slot
- Rate Adjustment: Higher rates for increased open interest
- Payment Direction: Longs pay shorts when funding is positive (and vice versa)
- Frequency: Updated every slot (programmable)
- Minimum Ratio: 150% (1.5x leverage)
- Liquidation Threshold: Below 150% collateral ratio
- Liquidation Penalty: 10% of collateral to liquidator
- All prices use 1e9 (1 billion) precision
- Example: $100.50 = 100,500,000,000
This is an educational implementation with several important limitations:
- Oracle Integration: Uses manual price updates instead of secure oracles
- Order Book: No matching engine or limit orders
- Risk Management: Minimal position sizing and exposure limits
- Multi-Asset: Single market only
- Governance: No parameter updates or emergency controls
- Insurance Fund: No backstop for bad debt
- Circuit Breakers: No halt mechanisms for extreme volatility
- Price Manipulation: Mark price can be set arbitrarily
- Front-Running: No MEV protection
- Flash Loan Attacks: Insufficient oracle and validation
- Precision Errors: Basic integer arithmetic without comprehensive overflow checks
cargo test-
Position Lifecycle:
- Open long position with collateral
- Apply funding updates
- Close position and verify PnL
-
Liquidation Testing:
- Create undercollateralized position
- Trigger liquidation
- Verify penalty distribution
-
Funding Mechanics:
- Multiple positions with different funding indices
- Verify cumulative funding calculations
# Fund test wallet
solana airdrop 2
# Deploy program
./scripts/3_deploy.sh devnet
# Test with client integrationsimple_perps/
βββ src/
β βββ lib.rs # Main program logic
βββ scripts/
β βββ 1_build.sh # Unix build script (includes env setup)
β βββ 2_getsol.sh # Get SOL from faucet
β βββ 3_deploy.sh # Unix deployment script
β βββ 4_runexample.sh # Run example test
βββ Cargo.toml # Rust dependencies
βββ README.md # This file
// Pseudo-code for client integration
const position = await openPosition({
baseDelta: 1_000_000_000, // 1 unit long
collateralDelta: 150_000_000_000, // 150 USDC
entryPrice: 100_500_000_000, // $100.50
});// Should be called periodically (every slot or less frequent)
await updateFunding();// Monitor positions for liquidation opportunities
const positions = await getUndercollateralizedPositions();
for (const position of positions) {
await liquidatePosition(position);
}To make this production-ready, you would need:
- Oracle Integration: Pyth, Switchboard, or custom oracle network
- Order Book: Matching engine with limit/market orders
- Risk Engine: Position limits, leverage caps, circuit breakers
- Multi-Asset Support: Cross-margin, portfolio risk
- Governance: DAO controls for parameters
- Insurance Fund: Bad debt coverage
- MEV Protection: Commit-reveal schemes or other mechanisms
- Audit: Comprehensive security audit
- Emergency Controls: Pause/upgrade mechanisms
- Advanced Features: Stop losses, take profits, advanced order types
- Solana Program Library
- Anchor Framework (for easier development)
- Perpetual Protocol Whitepaper
- dYdX Perpetuals
- Mango Markets
MIT License - See LICENSE file for details.
This is an educational project. Contributions welcome for:
- Bug fixes in the learning implementation
- Additional documentation
- Test coverage improvements
- Client integration examples
Not suitable for production use without significant additional development and security auditing.