You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Solana Rust合约获取Unix时间戳BpfClock单元测试报错问询

报错原因

UnsupportedSysvar错误来源于Solana本地单元测试运行时的限制:BpfClock::get()依赖链上BPF运行时的sysvar全局接口,默认单元测试环境没有实现该能力,只有实际链上执行环境或者带模拟链的集成测试环境支持该调用。

解决方案

方案1:官方推荐低消耗实现(兼容单元测试)

Solana官方更推荐将Clock sysvar作为指令的传入账户使用,相比内部调用BpfClock::get()计算单元消耗还要低10%左右,同时方便单元测试时手动注入模拟时间。

  1. 合约逻辑调整
// 指令处理函数参数新增clock账户
pub fn process_withdraw(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
    let clock_account = next_account_info(accounts)?;
    // 校验账户为Clock sysvar合法地址
    assert_eq!(clock_account.key, &sysvar::clock::id());
    let clock = Clock::from_account_info(clock_account)?;
    let current_timestamp: i64 = clock.unix_timestamp;
    // 后续业务逻辑
}
  1. 单元测试模拟时间
use solana_program::clock::Clock;
use solana_program::sysvar::Sysvar;
use solana_program_test::AccountSharedData;

#[test]
fn test_withdraw() {
    // 构造自定义时间的Clock实例
    let mut mock_clock = Clock::default();
    mock_clock.unix_timestamp = 1620000000; // 按需设置测试用时间戳
    // 生成模拟Clock账户传入指令账户列表即可
    let clock_account = AccountSharedData::new_data(
        1,
        &mock_clock,
        &solana_program::sysvar::id(),
    ).unwrap();
    // 剩余测试逻辑
}

方案2:最小改动兼容实现

如果不想调整现有指令的账户结构,可通过特性开关区分运行环境,链上走低消耗的BpfClock调用,测试环境走模拟时间:

let current_timestamp: i64 = {
    #[cfg(not(test))]
    {
        let clock = BpfClock::get()?;
        clock.unix_timestamp
    }
    #[cfg(test)]
    {
        // 测试环境返回固定模拟时间,也可通过全局变量动态调整测试时间
        1620000000
    }
};

链上环境下BpfClock方案的计算单元消耗仅为SystemTime方案的1/3左右,完全满足低消耗要求。

内容的提问来源于stack exchange,提问作者Gnoose

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 15:45:02