Skip to content

jvr0x/solana-sol-vault

Repository files navigation

Sol Vault

A simple, secure Solana program for depositing and withdrawing SOL using Program Derived Addresses (PDAs).

Overview

Sol Vault is an Anchor-based Solana program that allows users to create personal vaults for storing SOL. Each user's vault is a PDA derived from their wallet address, ensuring secure and isolated storage.

Features

  • Deposit SOL: Transfer SOL from your wallet to your personal vault
  • Withdraw SOL: Retrieve all SOL from your vault back to your wallet
  • PDA-based Vaults: Each user has a unique vault address derived from their public key
  • Rent-Exempt Validation: Ensures deposits meet minimum rent requirements
  • Security Checks: Prevents double deposits and invalid operations

Prerequisites

Before you begin, ensure you have the following installed:

  • Rust (v1.70.0 or later)

    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  • Solana CLI (v1.18.0 or later)

    sh -c "$(curl -sSfL https://release.solana.com/stable/install)"
  • Anchor (v0.32.1)

    cargo install --git https://github.com/coral-xyz/anchor --tag v0.32.1 anchor-cli
  • Node.js (v18 or later) and Yarn

    # Install Node.js from https://nodejs.org
    npm install -g yarn

Installation

  1. Clone the repository:

    git clone <repository-url>
    cd sol_vault
  2. Install dependencies:

    yarn install
  3. Build the program:

    anchor build
  4. Sync program keys:

    anchor keys sync

Project Structure

sol_vault/
├── programs/
│   └── sol_vault/
│       └── src/
│           ├── lib.rs              # Program entry point
│           ├── error.rs            # Custom error definitions
│           ├── constants.rs        # Program constants
│           ├── state.rs            # State definitions (if any)
│           └── instructions/
│               ├── mod.rs          # VaultAction account struct
│               ├── deposit.rs      # Deposit instruction handler
│               └── withdraw.rs     # Withdraw instruction handler
├── tests/
│   └── sol_vault.ts                # TypeScript integration tests
├── Anchor.toml                     # Anchor configuration
└── README.md                       # This file

Program Architecture

Program ID

Afud3vbjgWYm8ySXuH1P1Ln5aDnbxDD2aZgYZpkeTMRG

Instructions

1. Deposit

Transfers SOL from the user's wallet to their vault.

Accounts:

  • signer (mut, signer): User's wallet account
  • vault_account (mut, PDA): User's vault account derived from ["vault", signer.key]
  • system_program: System program for transfers

Parameters:

  • amount (u64): Amount of lamports to deposit

Validations:

  • Amount must be greater than the rent-exempt minimum (~890,880 lamports)
  • Vault must not already contain funds

PDA Seeds:

[b"vault", signer.key.as_ref()]

2. Withdraw

Transfers all SOL from the user's vault back to their wallet.

Accounts:

  • signer (mut, signer): User's wallet account
  • vault_account (mut, PDA): User's vault account
  • system_program: System program for transfers

Validations:

  • Vault must contain lamports

Usage

Running Tests

# Run all tests on localnet
anchor test

# Run tests with logs
anchor test -- --features=debug

# Run specific test
anchor test -- --grep "Deposit"

Local Development

  1. Start a local validator:

    solana-test-validator
  2. In another terminal, build and deploy:

    anchor build
    anchor deploy
  3. Run the tests:

    anchor test --skip-local-validator

Deploying to Devnet

  1. Set Solana CLI to devnet:

    solana config set --url https://api.devnet.solana.com
  2. Airdrop SOL for deployment fees:

    solana airdrop 2
  3. Update Anchor.toml to include devnet configuration:

    [programs.devnet]
    sol_vault = "Afud3vbjgWYm8ySXuH1P1Ln5aDnbxDD2aZgYZpkeTMRG"
  4. Deploy:

    anchor build
    anchor deploy --provider.cluster devnet
  5. Initialize the IDL:

    anchor idl init -f target/idl/sol_vault.json <PROGRAM_ID> --provider.cluster devnet

Deploying to Mainnet

⚠️ WARNING: Mainnet deployment costs real SOL and should only be done after thorough testing and auditing.

  1. Set Solana CLI to mainnet:

    solana config set --url https://api.mainnet-beta.solana.com
  2. Update Anchor.toml:

    [programs.mainnet]
    sol_vault = "Afud3vbjgWYm8ySXuH1P1Ln5aDnbxDD2aZgYZpkeTMRG"
  3. Deploy:

    anchor build --verifiable
    anchor deploy --provider.cluster mainnet

Client Integration Example

TypeScript

import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { SolVault } from "../target/types/sol_vault";

// Setup
const provider = anchor.AnchorProvider.env();
anchor.setProvider(provider);
const program = anchor.workspace.solVault as Program<SolVault>;
const user = provider.wallet.publicKey;

// Derive vault PDA
const [vaultPDA] = anchor.web3.PublicKey.findProgramAddressSync(
  [Buffer.from("vault"), user.toBuffer()],
  program.programId
);

// Deposit 1 SOL
const depositAmount = new anchor.BN(1_000_000_000);
await program.methods
  .deposit(depositAmount)
  .accounts({
    signer: user,
  })
  .rpc();

// Withdraw all SOL
await program.methods
  .withdraw()
  .accounts({
    signer: user,
  })
  .rpc();

Error Codes

Code Error Description
6000 VaultAlreadyExists Attempted to deposit to a vault that already contains funds
6001 InvalidAmount Deposit amount is less than the rent-exempt minimum or vault is empty

Security Considerations

✅ Implemented Safeguards

  • PDA-based vaults: Ensures each user has a unique, isolated vault
  • Rent-exempt validation: Prevents accounts from being closed by the runtime
  • Overflow checks: Enabled in release profile to prevent arithmetic errors
  • Signer validation: All operations require proper signatures
  • Account ownership: Anchor validates account ownership automatically

⚠️ Known Limitations

  • Single deposit only: Once a vault has funds, no additional deposits are allowed until withdrawn
  • All-or-nothing withdrawal: Withdraw transfers all lamports; partial withdrawals not supported
  • No access control: Any user can interact with their own vault (by design)

🔒 Recommendations Before Production

  1. Professional Audit: Have the code audited by a reputable security firm
  2. Extensive Testing: Test on devnet with real scenarios
  3. Admin Controls: Consider adding pause/emergency withdrawal features
  4. Upgradability: Ensure proper upgrade authority management
  5. Monitoring: Implement logging and monitoring for deployed programs

Development

Building

# Standard build
anchor build

# Verifiable build (for mainnet)
anchor build --verifiable

# Clean build
anchor clean && anchor build

Testing

# Run all tests
anchor test

# Run with verbose output
RUST_LOG=debug anchor test

# Run without rebuilding
anchor test --skip-build

Formatting

# Format Rust code
cargo fmt

# Format TOML files
taplo fmt

# Format TypeScript tests
yarn prettier --write "tests/**/*.ts"

Linting

# Run Clippy
cargo clippy -- -D warnings

# Check Anchor IDL
anchor idl parse -f programs/sol_vault/src/lib.rs

Contributing

Contributions are welcome! Please follow these guidelines:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'feat: add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Resources

Support

For questions or issues, please open an issue on GitHub or reach out to the development team.


Built with ❤️ using Anchor Framework

About

Simple SOL vault using anchor.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published