A simple, modular staking smart contract built on Solana using Rust and Anchor. Users can deposit SPL tokens, track their staked balance, and withdraw at any time. The contract is designed for clarity, security, and extensibility, with comprehensive integration tests.
- Stake SPL tokens: Users can deposit and withdraw tokens at will.
- Per-user staking accounts: Each user has a unique staking account.
- Vault: Program-controlled vault holds staked tokens securely.
- Security: Uses Anchor's
init_if_neededwith unique seeds to prevent re-initialization attacks. - Comprehensive tests: Integration tests for all major flows and error cases.
- Rust (1.75.0+): Install Rust
- Solana CLI (1.18.0+): Install Solana
- Anchor CLI: Install Anchor
- Node.js (16+), Yarn:
npm install -g yarn - Git
staking/
├── programs/
│ └── staking/
│ ├── src/
│ │ ├── lib.rs
│ │ └── staking/
│ │ ├── mod.rs
│ │ ├── initialize.rs
│ │ ├── deposit.rs
│ │ ├── withdraw.rs
│ │ └── state.rs
│ └── Cargo.toml
├── tests/
│ └── staking.ts
├── Anchor.toml
├── package.json
├── tsconfig.json
└── README.md
- Clone the repository
git clone https://github.com/NVN404/stake.git
cd stake/staking- Install dependencies
yarn install- Configure Solana localnet
solana config set --url http://localhost:8899
solana-test-validator- Airdrop SOL to your wallet
solana airdrop 5
solana balance- Build the program
anchor build
# or
cargo build-bpf- Deploy locally
anchor deploy
solana program show Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnSRun integration tests:
anchor testTest coverage includes:
- Creating a mock SPL token
- Initializing the vault
- Depositing tokens
- Withdrawing tokens
- Failing to withdraw more than balance
- Program ID:
Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS
- Vault: Stores the token mint address
- StakingAccount: Tracks each user’s staked balance and owner
initialize: Creates the vault and initializes a token account for the vaultdeposit: Transfers tokens from the user to the vault and updates the staking account balancewithdraw: Transfers tokens from the vault to the user, checking for sufficient balance and ownership
- Overflow: Prevents arithmetic overflow in deposits
- Underflow: Prevents withdrawing more than the staked balance
- Unauthorized: Ensures only the staking account owner can withdraw
- The use of
init_if_neededis safe due to unique seeds (user and vault keys), preventing re-initialization attacks. Review Anchor docs for more details.
MIT