---
title: Deploying Programs
description: Learn how to deploy programs to a LiteSVM test instance
---

## Getting Started

```rust
let mut svm = LiteSVM::new();
```

This creates the basic litesvm test instance, which includes all runtime
features enabled, default sysvars, precompiles, spl programs, sigverify, and all
built in programs like the system program.

To interact with any other program in your tests, you must deploy that program
to your test environment.

1. Build and deploy the program you want to test

2. Find all programs that the above program makes CPI calls to and deploy those
   programs

<Callout type="info">
  **Example:** If your program is using data feeds from Pyth, you will need to
  have the Pyth program deployed to your test instance.
</Callout>

## Basic Program Deployment

### Method 1: Deploy from Bytes

Deploy programs directly from byte arrays for fastest test execution:

```rust
use litesvm::LiteSVM;
use solana_sdk::signature::{read_keypair_file, Signer};

let mut svm = LiteSVM::new();

// Read the program's keypair to get correct ID
let program_keypair = read_keypair_file("target/deploy/my_program-keypair.json")
    .expect("Program keypair file not found");
let program_id = program_keypair.pubkey();

// Include bytes at compile time
let program_bytes = include_bytes!("../target/deploy/my_program.so");

// Deploy from bytes
svm.add_program(program_id, program_bytes)
    .expect("Failed to deploy program");

// Verify deployment
assert!(svm.get_account(&program_id).is_some(), "Program account not created");
assert!(svm.get_account(&program_id).unwrap().executable, "Program not executable");
```

`include_bytes!` embeds the binary directly into the test executable at compile
time, eliminating I/O during test execution.

<div className="grid grid-cols-1 md:grid-cols-2 gap-2 my-3">
  <div className="bg-gray-50 dark:bg-gray-950/20 border border-gray-200 dark:border-gray-800 rounded-lg px-2 pt-0.5 pb-2">
    <h4 className="text-xs font-semibold text-gray-800 dark:text-gray-300 mb-1.5 flex items-center gap-1.5">
      <span className="text-sm">✓</span> Pros
    </h4>
    <ul className="space-y-1 text-xs text-gray-900 dark:text-gray-200">
      <li className="flex items-start gap-1.5">
        <span className="text-gray-600 dark:text-gray-400 mt-0.5">•</span>
        <span>Faster at runtime (no disk reads)</span>
      </li>
      <li className="flex items-start gap-1.5">
        <span className="text-gray-600 dark:text-gray-400 mt-0.5">•</span>
        <span>Self-contained test binary</span>
      </li>
      <li className="flex items-start gap-1.5">
        <span className="text-gray-600 dark:text-gray-400 mt-0.5">•</span>
        <span>Works even if .so file is deleted after compilation</span>
      </li>
    </ul>
  </div>

  <div className="bg-gray-50 dark:bg-gray-950/20 border border-gray-200 dark:border-gray-800 rounded-lg px-2 pt-0.5 pb-2">
    <h4 className="text-xs font-semibold text-gray-800 dark:text-gray-300 mb-1.5 flex items-center gap-1.5">
      <span className="text-sm">✗</span> Cons
    </h4>
    <ul className="space-y-1 text-xs text-gray-900 dark:text-gray-200">
      <li className="flex items-start gap-1.5">
        <span className="text-gray-600 dark:text-gray-400 mt-0.5">•</span>
        <span>Larger test binary size</span>
      </li>
      <li className="flex items-start gap-1.5">
        <span className="text-gray-600 dark:text-gray-400 mt-0.5">•</span>
        <span>Must recompile tests when .so changes</span>
      </li>
    </ul>
  </div>
</div>

### Method 2: Deploy from File (.so)

Load programs from the file system when they change frequently:

```rust
use litesvm::LiteSVM;
use solana_sdk::signature::{read_keypair_file, Signer};

let mut svm = LiteSVM::new();

// Read keypair for correct program ID
let program_keypair = read_keypair_file("target/deploy/program-keypair.json").unwrap();
let program_id = program_keypair.pubkey();

// Deploy from file
svm.add_program_from_file(program_id, "target/deploy/program.so")
    .expect("Failed to deploy program from file");

// Always verify
assert!(svm.get_account(&program_id).unwrap().executable);
```

<div className="grid grid-cols-1 md:grid-cols-2 gap-2 my-3">
  <div className="bg-gray-50 dark:bg-gray-950/20 border border-gray-200 dark:border-gray-800 rounded-lg px-2 pt-0.5 pb-2">
    <h4 className="text-xs font-semibold text-gray-800 dark:text-gray-300 mb-1.5 flex items-center gap-1.5">
      <span className="text-sm">✓</span> Pros
    </h4>
    <ul className="space-y-1 text-xs text-gray-900 dark:text-gray-200">
      <li className="flex items-start gap-1.5">
        <span className="text-gray-600 dark:text-gray-400 mt-0.5">•</span>
        <span>Smaller test binary</span>
      </li>
      <li className="flex items-start gap-1.5">
        <span className="text-gray-600 dark:text-gray-400 mt-0.5">•</span>
        <span>Can pick up .so changes without recompiling tests</span>
      </li>
      <li className="flex items-start gap-1.5">
        <span className="text-gray-600 dark:text-gray-400 mt-0.5">•</span>
        <span>More flexible for CI/CD pipelines</span>
      </li>
    </ul>
  </div>

  <div className="bg-gray-50 dark:bg-gray-950/20 border border-gray-200 dark:border-gray-800 rounded-lg px-2 pt-0.5 pb-2">
    <h4 className="text-xs font-semibold text-gray-800 dark:text-gray-300 mb-1.5 flex items-center gap-1.5">
      <span className="text-sm">✗</span> Cons
    </h4>
    <ul className="space-y-1 text-xs text-gray-900 dark:text-gray-200">
      <li className="flex items-start gap-1.5">
        <span className="text-gray-600 dark:text-gray-400 mt-0.5">•</span>
        <span>Slower (disk I/O at runtime)</span>
      </li>
      <li className="flex items-start gap-1.5">
        <span className="text-gray-600 dark:text-gray-400 mt-0.5">•</span>
        <span>Requires .so file to exist at test execution time</span>
      </li>
      <li className="flex items-start gap-1.5">
        <span className="text-gray-600 dark:text-gray-400 mt-0.5">•</span>
        <span>File path must be correct relative to test execution directory</span>
      </li>
    </ul>
  </div>
</div>

## Pulling Programs from Mainnet/Devnet

When you need a program that you don't have the code for, use the Solana CLI to
dump programs from live clusters and use them in tests:

```bash
# Dump a program from mainnet
solana program dump gSbePebfvPy7tRqimPoVecS2UsBvYv46ynrzWocc92s pyth.so --url mainnet-beta

# Dump from devnet
solana program dump YourProgramID program.so --url devnet
```

Then load it in your tests:

```rust
svm.add_program_from_file(
    pubkey!("gSbePebfvPy7tRqimPoVecS2UsBvYv46ynrzWocc92s"),
    "pyth.so"
).unwrap();
```

## Best Practices

### 1. Choose the Right Deployment Method

- **Use `add_program()`** when:
  - Programs are embedded in your test binary at compile time
  - You want faster test execution (no runtime I/O)
  - Self-contained tests

- **Use `add_program_from_file()`** when:
  - Programs are built separately (i.e. pulling from devnet)
  - Program change frequently during development (can rerun tests without
    recompiling)
  - You have CI/CD environments where .so files are artifacts

### Understanding Program Keypairs

When you build a Solana program:

1. **Anchor** creates `target/deploy/program-keypair.json`
2. **Native** builds create a keypair file alongside the `.so` file
3. The program's **on-chain address** is this keypair's public key, which is
   also known as the program ID.
4. For **PDAs**,`find_program_address()` requires the program ID as a seed
5. For **CPIs**, the program ID is used to call other programs

## Common Issues and Solutions

### Silent Deployment Failures

**Problem**: Program appears to deploy but transactions fail with
"InvalidProgramForExecution".

**Cause**: Program ID doesn't match the keypair.

**Solution**:

```rust
// Always use the keypair-derived ID
let keypair = read_keypair_file("target/deploy/program-keypair.json").unwrap();
let program_id = keypair.pubkey();

svm.add_program(program_id, &program_bytes).unwrap();

// Verify with detailed checks
let account = svm.get_account(&program_id)
    .expect("Program account doesn't exist");

assert!(account.executable, "Program not executable");
assert_eq!(account.owner, solana_sdk::bpf_loader::id(), "Wrong owner");
assert!(!account.data.is_empty(), "Program data is empty");

println!("✅ Program verified at {}", program_id);
```

### Program Not Found Error

**Error**: `TransactionError::InvalidProgramForExecution`

**Common Causes**:

1. Program not deployed
2. Wrong program ID used in instruction
3. Program ID mismatch with keypair

**Debugging Steps**:

```rust
// Step 1: Check if program exists
if let Some(account) = svm.get_account(&program_id) {
    println!("Program exists");
    println!("  Executable: {}", account.executable);
    println!("  Owner: {}", account.owner);
    println!("  Data length: {}", account.data.len());
} else {
    println!("Program does not exist at {}", program_id);
}

// Step 2: Verify the ID matches keypair
let expected_keypair = read_keypair_file("target/deploy/program-keypair.json").unwrap();
let expected_id = expected_keypair.pubkey();

if program_id != expected_id {
    println!("  ID mismatch!");
    println!("  Used: {}", program_id);
    println!("  Expected: {}", expected_id);
}

// Step 3: Check instruction program ID
println!("Instruction program_id: {}", instruction.program_id);
assert_eq!(instruction.program_id, program_id, "Instruction uses wrong program ID");
```

### CPI to Undeployed Programs

**Problem**: Your program makes a CPI call to a program that is not deployed.

**Solution**: Deploy all dependency programs:

```rust
// Find all dependency programs and make sure they are deployed
svm.add_program_from_file(
    pubkey!("gSbePebfvPy7tRqimPoVecS2UsBvYv46ynrzWocc92s"),
    "pyth.so"
).unwrap();

```

If you need to pull the program from a cluster, review
[this section](#pulling-programs-from-mainnetdevnet).

### Insufficient Lamports for Deployment

**Note**: LiteSVM automatically handles rent-exempt balance for programs.

```rust
// No need to manually fund - LiteSVM handles this
svm.add_program(program_id, &program_bytes).unwrap();

// But you can check the rent if needed
let program_len = program_bytes.len();
let required_lamports = svm.minimum_balance_for_rent_exemption(program_len);
println!("Program requires {} lamports for rent exemption", required_lamports);
```

## Deployment Verification Checklist

<Steps>
<Step>
**Read the program keypair**

```rust
let keypair = read_keypair_file("target/deploy/program-keypair.json").unwrap();
let program_id = keypair.pubkey();
```

</Step>

<Step>
**Deploy with matching ID**

```rust
svm.add_program(program_id, &program_bytes).unwrap();
```

</Step>

<Step>
**Verify deployment**

```rust
assert!(svm.get_account(&program_id).unwrap().executable);
```

</Step>

<Step>
Deploy any programs your program calls via CPI to the litesvm test instance

</Step>
</Steps>

## Next Steps

In the next section, we'll learn how to execute program instructions and handle
complex transaction patterns.
