本文将介绍 Solana 中与 Solidity 区块变量对应的概念。
本文将介绍 Solana 中与 Solidity 区块变量对应的概念。
Solidity 中常见的区块变量包括:
我们假设你已了解其作用,如需复习,可参考 Solidity 全局变量文档。
Solana 通过 Clock 系统变量 的 unix_timestamp 字段提供区块时间戳。
初始化 Anchor 项目:
anchor init sysvar
更新 lib.rs 中的 initialize 函数:

pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
let clock: Clock = Clock::get()?;
msg!(
"Block timestamp: {}",
// Get block.timestamp
clock.unix_timestamp,
);
Ok(())
}
说明:
使用 chrono 库计算星期几。更新 Cargo.toml:

[dependencies]
chrono = "0.4.31"
在 lib.rs 中导入并添加函数:

use anchor_lang::prelude::*;
use chrono::*;
declare_id!("5pgNWTorN1n9YBgGGmt7nWm8aebWWk4oFCJLR1CBe4vz");
#[program]
pub mod sysvar {
use super::*;
pub fn get_day_of_the_week(_ctx: Context<Initialize>) -> Result<()> {
let clock = Clock::get()?;
let time_stamp = clock.unix_timestamp;
let date_time = NaiveDateTime::from_timestamp_opt(time_stamp, 0).unwrap();
let day_of_the_week = date_time.weekday();
msg!("Week day is: {}", day_of_the_week);
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize {}
更新测试文件 tests/sysvar.ts:

it("Get day of the week", async () => {
const tx = await program.methods.getDayOfTheWeek().rpc();
console.log("Your transaction signature", tx);
});
运行 anchor test,日志示例:

Transaction executed in slot 8:
Signature: 4sUThuBBDnb5fU4UvwkeBsvXePgHPVDunK9kMmgL8PXmM8RLJUJP5z49PzAngmQWzC7j3FcCTWjkQ5dMdhRjzREq
Status: Ok
Log Messages:
Program 5pgNWTorN1n9YBgGGmt7nWm8aebWWk4oFCJLR1CBe4vz invoke [1]
Program log: Instruction: GetDayOfTheWeek
Program log: Week day is: Wed
Program 5pgNWTorN1n9YBgGGmt7nWm8aebWWk4oFCJLR1CBe4vz consumed 1463 of 200000 compute units
Program 5pgNWTorN1n9YBgGGmt7nWm8aebWWk4oFCJLR1CBe4vz success
Solana 使用“槽号(slot number)”而非直接的“区块号”。槽号与区块号相关但不完全相同,具体区别将在后续教程中讨论,暂不深入。
以太坊的 block.coinbase 表示矿工地址,而 Solana 使用 领导者计划(PoH + PoS 共识),无挖矿概念。目前无法直接获取领导者地址。
Solana 提供 RecentBlockhashes 系统变量,但已被弃用,未来将移除。然而,缺乏此方法的 sysvar 可以使用sysvar_name::from_account_info
来访问。

use anchor_lang::{prelude::*, solana_program::sysvar::recent_blockhashes::RecentBlockhashes};
declare_id!("5pgNWTorN1n9YBgGGmt7nWm8aebWWk4oFCJLR1CBe4vz");
#[program]
pub mod sysvar {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
// RECENT BLOCK HASHES
let arr = [ctx.accounts.recent_blockhashes.clone()];
let accounts_iter = &mut arr.iter();
let sh_sysvar_info = next_account_info(accounts_iter)?;
let recent_blockhashes = RecentBlockhashes::from_account_info(sh_sysvar_info)?;
let data = recent_blockhashes.last().unwrap();
msg!("The recent block hash is: {:?}", data.blockhash);
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize<'info> {
/// CHECK: readonly
pub recent_blockhashes: AccountInfo<'info>,
}
测试文件 tests/sysvar.ts:

import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { Sysvar } from "../target/types/sysvar";
describe("sysvar", () => {
anchor.setProvider(anchor.AnchorProvider.env());
const program = anchor.workspace.Sysvar as Program<Sysvar>;
it("Is initialized!", async () => {
const tx = await program.methods
.initialize()
.accounts({
recentBlockhashes: anchor.web3.SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
})
.rpc();
console.log("Transaction hash:", tx);
});
});
日志示例:

Transaction executed in slot 5:
Signature: 5CU76Tj9zv84CDnLT1XDzDGTyCdE9DKdD8a8vaKxBuso8QJmU4RAWY5dL5Jz6yHV2sUBJJoMDtDkZn6jEgrH2NA5
Status: Ok
Log Messages:
Program 5pgNWTorN1n9YBgGGmt7nWm8aebWWk4oFCJLR1CBe4vz invoke [1]
Program log: Instruction: Initialize
Program log: The recent block hash is: JAy9nAV7nEMDoc4iDSxxRRJNxNx76WsjaZsAUAiELgsF
Program 5pgNWTorN1n9YBgGGmt7nWm8aebWWk4oFCJLR1CBe4vz consumed 13763 of 200000 compute units
Program 5pgNWTorN1n9YBgGGmt7nWm8aebWWk4oFCJLR1CBe4vz success
注意:本地测试网的哈希与主网不同。
Solana 每个区块的计算单位上限为 4800 万,单笔交易默认限制为 20 万单位(可调整至 140 万,见 示例)。程序内无法直接访问此限制。
以太坊的 block.basefee 基于 EIP-1559 动态调整,而 Solana 的交易费用静态,无此变量。
block.difficulty 是 PoW 区块链的概念,Solana 使用 PoH + PoS,无难度参数。
Solana 不兼容 EVM,无 block.chainid。程序无法直接感知运行于 Devnet、Testnet 或 Mainnet,但可通过 cfg 根据集群调整逻辑,见 示例。
【笔记配套代码】
https://github.com/0xE1337/rareskills_evm_to_solana
【参考资料】
https://learnblockchain.cn/column/119
https://www.rareskills.io/solana-tutorial
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!