LiteSVM Docs

Time & Sysvars

Methods for manipulating time and system variables

Time Manipulation

warp_to_slot

pub fn warp_to_slot(&mut self, slot: u64)

Jump to a specific slot. Only forward time travel is supported.

// Get current slot
let clock: Clock = svm.get_sysvar();
let current_slot = clock.slot;

// Jump forward 100 slots
svm.warp_to_slot(current_slot + 100);

// Verify
let new_clock: Clock = svm.get_sysvar();
assert_eq!(new_clock.slot, current_slot + 100);

Manual Clock Manipulation

use solana_sdk::clock::Clock;

// Read clock
let mut clock: Clock = svm.get_sysvar();

// Modify fields
clock.slot = 1000;
clock.epoch = 10;
clock.unix_timestamp = 1735689600;

// Write back
svm.set_sysvar(&clock);

Use warp_to_slot() for most time manipulation. Use manual clock modification only when you need precise control over multiple fields.

Sysvars

get_sysvar

pub fn get_sysvar<T: Sysvar>(&self) -> T

Read sysvar value.

use solana_sdk::clock::Clock;
use solana_sdk::rent::Rent;
use solana_sdk::epoch_schedule::EpochSchedule;

let clock: Clock = svm.get_sysvar();
let rent: Rent = svm.get_sysvar();
let epoch_schedule: EpochSchedule = svm.get_sysvar();

set_sysvar

pub fn set_sysvar<T: Sysvar>(&mut self, sysvar: &T)

Write sysvar value.

use solana_sdk::rent::Rent;

let rent = Rent {
    lamports_per_byte_year: 3480,
    exemption_threshold: 2.0,
    burn_percent: 50,
};

svm.set_sysvar(&rent);

Common Sysvars

Clock

use solana_sdk::clock::Clock;

let clock: Clock = svm.get_sysvar();
println!("Slot: {}", clock.slot);
println!("Timestamp: {}", clock.unix_timestamp);
println!("Epoch: {}", clock.epoch);

Rent

use solana_sdk::rent::Rent;

let rent: Rent = svm.get_sysvar();
let min_balance = rent.minimum_balance(data_len);

Epoch Schedule

use solana_sdk::epoch_schedule::EpochSchedule;

let schedule: EpochSchedule = svm.get_sysvar();
println!("Slots per epoch: {}", schedule.slots_per_epoch);

Stake History

use solana_sdk::stake_history::{StakeHistory, StakeHistoryEntry};

let mut stake_history = StakeHistory::default();
stake_history.add(
    0, // epoch
    StakeHistoryEntry {
        effective: 1_000_000,
        activating: 0,
        deactivating: 0,
    },
);

svm.set_sysvar(&stake_history);

Time-Based Testing Patterns

Test Slot-Based Features

let mut svm = LiteSVM::new();

// Get starting slot
let start_slot = svm.get_sysvar::<Clock>().slot;

// Try action before unlock slot (should fail)
let result = call_locked_program(&mut svm);
assert!(result.is_err());

// Warp to unlock slot
svm.warp_to_slot(start_slot + 1000);

// Now it should succeed
let result = call_locked_program(&mut svm);
assert!(result.is_ok());

Test Timestamp-Based Features

let mut svm = LiteSVM::new();

// Get current timestamp
let clock: Clock = svm.get_sysvar();
let current_time = clock.unix_timestamp;

// Warp forward 1 hour (3600 seconds)
// Slots roughly correspond to ~0.4 seconds on Solana
let target_slot = clock.slot + (3600.0 / 0.4) as u64;
svm.warp_to_slot(target_slot);

// Verify timestamp increased
let new_clock: Clock = svm.get_sysvar();
assert!(new_clock.unix_timestamp >= current_time + 3600);

Test Vesting Schedules

// Setup vesting with 100 slot period
let vesting_period = 100;
let start_slot = svm.get_sysvar::<Clock>().slot;

// Test before vesting completes
let result = claim_vested_tokens(&mut svm);
assert!(result.is_err()); // Too early

// Warp past vesting period
svm.warp_to_slot(start_slot + vesting_period + 1);

// Now claim should succeed
let result = claim_vested_tokens(&mut svm);
assert!(result.is_ok());

Common Use Cases

  • Vesting schedules
  • Time-locked withdrawals
  • Stake/unstake cooldown periods
  • Auction end times
  • Rental periods
  • Epoch-based rewards

Important Notes

  1. Forward only - You can only warp forward in time, not backward
  2. Slot to time - Slots roughly correspond to ~0.4 seconds on Solana mainnet
  3. Clock sysvar - Always updated when using warp_to_slot()
  4. No automatic updates - Unlike real validators, time doesn't advance automatically between transactions