quasar-svm 0.1.0

Lightweight Solana virtual machine for local transaction execution
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
# QuasarSVM - Rust API

QuasarSVM is a lightweight Solana virtual machine that executes transactions locally without an RPC connection or validator. Provide program ELFs, account state, and instructions — get back logs, compute units, return data, and resulting accounts.

## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
quasar-svm = "0.1"
```

## Quick Start

```rust
use quasar_svm::{QuasarSvm, Pubkey, SPL_TOKEN_PROGRAM_ID};
use quasar_svm::token::*;
use spl_token::state::Account as SplTokenAccount;
use solana_program_pack::Pack;

let authority = Pubkey::new_unique();

let mint = create_keyed_mint_account(&Pubkey::new_unique(), &Mint { decimals: 6, supply: 10_000, ..Default::default() });
let alice = create_keyed_associated_token_account(&authority, &mint.address, 5_000);
let bob   = create_keyed_associated_token_account(&Pubkey::new_unique(), &mint.address, 0);

let ix = spl_token::instruction::transfer(
    &SPL_TOKEN_PROGRAM_ID,
    &alice.address,
    &bob.address,
    &authority,
    &[],
    1_000,
).unwrap();

let mut svm = QuasarSvm::new(); // SPL programs loaded by default

let result = svm.process_instruction(&ix, &[mint, alice, bob]);

result.assert_success();

// Verify by unpacking account data
let bob_account = result.account(&bob.address).unwrap();
let bob_token = SplTokenAccount::unpack(&bob_account.data).unwrap();
assert_eq!(bob_token.amount, 1_000);
```

## Architecture

QuasarSVM is built as a C FFI wrapper around the low-level Solana SVM execution pipeline. It directly uses:
- `solana-program-runtime`
- `solana-bpf-loader-program`
- `agave-syscalls`

The system produces `libquasar_svm.dylib/.so/.dll` and `include/quasar_svm.h` for FFI integration. SPL Token, Token-2022, and Associated Token Account program binaries are embedded via `include_bytes!`.

## Core API

### QuasarSvm

#### Creating a VM

```rust
let svm = QuasarSvm::new();
```

All SPL programs load by default.

**To disable specific programs:**

```rust
use quasar_svm::QuasarSvmConfig;

let svm = QuasarSvm::new_with_config(QuasarSvmConfig {
    token: true,             // default: true
    token_2022: false,       // disable Token-2022
    associated_token: true,  // default: true
});
```

**Or load programs manually:**

```rust
let svm = QuasarSvm::new_with_config(QuasarSvmConfig {
    token: false,
    token_2022: false,
    associated_token: false,
})
.with_token_program()
.with_token_2022_program()
.with_associated_token_program();
```

#### Loading Programs

Load a custom program from an ELF binary:

```rust
let elf = std::fs::read("target/deploy/my_program.so").unwrap();
svm.add_program(&program_id, &loader_keys::LOADER_V3, &elf);

// Builder-style
let svm = QuasarSvm::new()
    .with_program(&program_id, &elf)
    .with_program_loader(&program_id, &loader_keys::LOADER_V2, &elf);
```

Load bundled SPL programs:

```rust
let svm = QuasarSvm::new()
    .with_token_program()
    .with_token_2022_program()
    .with_associated_token_program();
```

#### Executing Instructions

Two execution methods — single or chain:

| Method | Behavior |
|--------|----------|
| `process_instruction` | Execute one instruction atomically. |
| `process_instruction_chain` | Execute multiple instructions as one atomic chain. |

```rust
// Single instruction
let result = svm.process_instruction(&ix, &accounts);

// Multiple instructions — atomic
let result = svm.process_instruction_chain(&[ix1, ix2], &accounts);
```

Accounts are `&[Account]` — a slice of `Account` structs.

#### Sysvars

```rust
svm.sysvars.warp_to_slot(200);          // updates clock.slot + slot_hashes
svm.set_clock(clock);
svm.set_rent(rent);
svm.set_epoch_schedule(epoch_schedule);
svm.set_compute_budget(200_000);
```

### ExecutionResult

Every execution returns an `ExecutionResult` struct with methods for inspecting the execution outcome.

#### Fields

| Field | Type | Description |
|-------|------|-------------|
| `raw_result` | `Result<(), InstructionError>` | Status of the execution |
| `compute_units_consumed` | `u64` | Compute units used |
| `execution_time_us` | `u64` | Execution time in microseconds |
| `return_data` | `Vec<u8>` | Program return data |
| `resulting_accounts` | `Vec<Account>` | Resulting account states |
| `logs` | `Vec<String>` | Execution logs |

#### Assertion Methods

```rust
result.assert_success();
result.assert_error(ProgramError::InsufficientFunds);
assert!(result.is_success());
assert!(result.is_error());
result.print_logs();
```

#### Account Lookup

```rust
let acct: Option<&Account> = result.account(&pubkey);
```

## Account Types

### Account

The universal account type:

```rust
pub struct Account {
    pub address: Pubkey,
    pub lamports: u64,
    pub data: Vec<u8>,
    pub owner: Pubkey,
    pub executable: bool,
}
```

### Account Factories

All factories return `Account` with the address as the first parameter.

#### System Account

Create a system-owned account with a SOL balance:

```rust
use quasar_svm::token::create_keyed_system_account;

let account = create_keyed_system_account(&pubkey, 1_000_000_000);
```

#### Mint Account

Create a pre-initialized SPL Token mint:

```rust
use quasar_svm::token::{create_keyed_mint_account, create_keyed_mint_account_with_program, Mint};

// Uses SPL_TOKEN_PROGRAM_ID by default
let account = create_keyed_mint_account(
    &pubkey,
    &Mint { decimals: 6, ..Default::default() },
);

// Token-2022
let account = create_keyed_mint_account_with_program(
    &pubkey,
    &Mint { decimals: 6, ..Default::default() },
    &SPL_TOKEN_2022_PROGRAM_ID,
);
```

#### Token Account

Create a pre-initialized token account:

```rust
use quasar_svm::token::{create_keyed_token_account, create_keyed_token_account_with_program, TokenAccount};

// Uses SPL_TOKEN_PROGRAM_ID by default
let account = create_keyed_token_account(
    &pubkey,
    &TokenAccount { mint, owner, amount: 5_000, ..Default::default() },
);

// Token-2022
let account = create_keyed_token_account_with_program(
    &pubkey,
    &TokenAccount { mint, owner, amount: 5_000, ..Default::default() },
    &SPL_TOKEN_2022_PROGRAM_ID,
);
```

#### Associated Token Account

Derive the ATA address automatically and create a pre-initialized token account:

```rust
use quasar_svm::token::{create_keyed_associated_token_account, create_keyed_associated_token_account_with_program};

// Uses SPL_TOKEN_PROGRAM_ID by default
let account = create_keyed_associated_token_account(&wallet, &mint, 5_000);
// account.address is the derived ATA address

// Token-2022
let account = create_keyed_associated_token_account_with_program(&wallet, &mint, 5_000, &SPL_TOKEN_2022_PROGRAM_ID);
```

## Token Types

### Mint

```rust
pub struct Mint {
    pub mint_authority: Option<Pubkey>,
    pub supply: u64,
    pub decimals: u8,
    pub freeze_authority: Option<Pubkey>,
}

let mint = Mint::default(); // decimals = 9, supply = 0, no authorities
let mint = Mint { decimals: 6, supply: 10_000, ..Default::default() };
```

### TokenAccount

```rust
// Re-exported from spl_token::state
pub struct TokenAccount {
    pub mint: Pubkey,
    pub owner: Pubkey,
    pub amount: u64,
    pub delegate: Option<Pubkey>,
    pub state: AccountState,
    pub is_native: Option<u64>,
    pub delegated_amount: u64,
    pub close_authority: Option<Pubkey>,
}

let token = TokenAccount { mint, owner, amount: 5_000, state: AccountState::Initialized, ..Default::default() };
```

### AccountState

```rust
// From spl_token::state::AccountState
pub enum AccountState {
    Uninitialized = 0,
    Initialized  = 1, // default
    Frozen       = 2,
}
```

## Token Instructions

Use the `spl_token` crate directly to create instructions:

```rust
use spl_token::instruction;

// Transfer
let ix = instruction::transfer(
    &SPL_TOKEN_PROGRAM_ID,
    &source,
    &destination,
    &authority,
    &[],
    1_000,
).unwrap();

// MintTo
let ix = instruction::mint_to(
    &SPL_TOKEN_PROGRAM_ID,
    &mint,
    &destination,
    &mint_authority,
    &[],
    5_000,
).unwrap();

// Burn
let ix = instruction::burn(
    &SPL_TOKEN_PROGRAM_ID,
    &source,
    &mint,
    &authority,
    &[],
    500,
).unwrap();
```

## Reading Token Account Data

Use `spl_token::state` to unpack account data from execution results:

```rust
use spl_token::state::{Account as SplTokenAccount, Mint as SplMint};
use solana_program_pack::Pack;

let bob_account = result.account(&bob_address).unwrap();
let bob_token = SplTokenAccount::unpack(&bob_account.data).unwrap();
assert_eq!(bob_token.amount, 1_000);

let mint_account = result.account(&mint_address).unwrap();
let mint = SplMint::unpack(&mint_account.data).unwrap();
assert_eq!(mint.supply, 15_000);
```

## Token-2022 Support

All factories that create token-related accounts have `_with_program` variants. Use `SPL_TOKEN_2022_PROGRAM_ID` to create Token-2022 accounts:

```rust
use quasar_svm::SPL_TOKEN_2022_PROGRAM_ID;

let mint = create_keyed_mint_account_with_program(&mint_addr, &mint_opts, &SPL_TOKEN_2022_PROGRAM_ID);
let token = create_keyed_token_account_with_program(&token_addr, &token_opts, &SPL_TOKEN_2022_PROGRAM_ID);
let ata = create_keyed_associated_token_account_with_program(&wallet, &mint_addr, amount, &SPL_TOKEN_2022_PROGRAM_ID);
```

## Built-in Programs

The system program, BPF Loader v2, and Upgradeable Loader v3 are always available. SPL programs are bundled and loaded on demand.

## Full Example

```rust
use quasar_svm::{QuasarSvm, Pubkey, SPL_TOKEN_PROGRAM_ID};
use quasar_svm::token::*;
use spl_token::state::Account as SplTokenAccount;
use solana_program_pack::Pack;

let authority = Pubkey::new_unique();
let recipient = Pubkey::new_unique();

let mint  = create_keyed_mint_account(
    &Pubkey::new_unique(),
    &Mint { decimals: 6, supply: 10_000, ..Default::default() },
);
let alice = create_keyed_associated_token_account(&authority, &mint.address, 5_000);
let bob   = create_keyed_associated_token_account(&recipient, &mint.address, 0);

let ix = spl_token::instruction::transfer(
    &SPL_TOKEN_PROGRAM_ID,
    &alice.address,
    &bob.address,
    &authority,
    &[],
    1_000,
).unwrap();

let mut svm = QuasarSvm::new(); // Token program loaded by default

let result = svm.process_instruction(&ix, &[mint, alice, bob]);

result.assert_success();

// Verify by unpacking account data
let bob_account = result.account(&bob.address).unwrap();
let bob_token = SplTokenAccount::unpack(&bob_account.data).unwrap();
assert_eq!(bob_token.amount, 1_000);

let alice_account = result.account(&alice.address).unwrap();
let alice_token = SplTokenAccount::unpack(&alice_account.data).unwrap();
assert_eq!(alice_token.amount, 4_000);
```

## Workspace

| Crate | Path | Purpose |
|-------|------|---------|
| `quasar-svm` | `svm/` | Core execution engine — `QuasarSvm`, `ExecutionResult`, `Account`, token helpers |
| `quasar-svm-ffi` | `ffi/` | C-ABI wrapper for Node.js FFI via koffi |
| TypeScript bindings | `bindings/node/` | `web3.js` and `kit` API layers over the native engine |