MultiversX区块链数据读取Skill multiversx-blockchain-data

用于在MultiversX智能合约中读取链上状态数据,包括调用者信息、账户余额、区块时间戳、ESDT代币元数据、本地角色、代码元数据等,是区块链开发和智能合约编程的关键技能,适用于DApp开发、DeFi应用和NFT项目。

智能合约 0 次安装 0 次浏览 更新于 3/21/2026

名称:multiversx-blockchain-data 描述:在MultiversX智能合约中读取链上状态。适用于访问调用者信息、账户余额、区块时间戳、ESDT代币元数据、本地角色、代码元数据或任何来自self.blockchain()的数据。

MultiversX 区块链数据 — self.blockchain() API 参考

MultiversX智能合约中读取链上状态的完整参考(SDK v0.64+)。

调用者与账户信息

方法 返回 描述
.get_caller() ManagedAddress 发起当前调用的地址
.get_sc_address() ManagedAddress 本合约自己的地址
.get_owner_address() ManagedAddress 合约所有者地址
.check_caller_is_owner() () 如果调用者不等于所有者,则恐慌。等同于 #[only_owner]
.check_caller_is_user_account() () 如果调用者是智能合约(非外部拥有账户),则恐慌。
.is_smart_contract(address) bool 检查一个地址是否为智能合约
.get_shard_of_address(address) u32 获取地址的分片ID
// 所有者守卫(手动替代 #[only_owner])
self.blockchain().check_caller_is_owner();

// 防止合约到合约调用(反闪电贷)
self.blockchain().check_caller_is_user_account();

// 在发送前检查目标是否为智能合约
let is_sc = self.blockchain().is_smart_contract(&target);

余额

方法 返回 描述
.get_balance(address) BigUint 任何地址的EGLD余额
.get_sc_balance(token_id, nonce) BigUint 本合约的任何代币余额(EGLD或ESDT)。token_idimpl AsRef<TokenId>
.get_esdt_balance(address, token_id, nonce) BigUint 任何地址的ESDT余额。token_id&EsdtTokenIdentifier
// 检查自己的EGLD余额
let egld = self.blockchain().get_balance(&self.blockchain().get_sc_address());

// 检查自己的ESDT余额(通过get_sc_balance更简单)
let balance = self.blockchain().get_sc_balance(&my_token_id, 0u64);

区块信息

当前区块

方法 返回 描述
.get_block_timestamp_seconds() TimestampSeconds 区块时间戳(秒)(v0.63+)
.get_block_timestamp_millis() TimestampMillis 区块时间戳(毫秒)(v0.63+)
.get_block_nonce() u64 区块Nonce(高度)
.get_block_round() u64 区块轮次
.get_block_epoch() u64 当前纪元
.get_block_round_time_millis() DurationMillis 轮次持续时间(毫秒)(v0.63+)
.get_block_random_seed() ManagedByteArray<48> 48字节随机种子

前一个区块

方法 返回 描述
.get_prev_block_timestamp_seconds() TimestampSeconds 前一个区块时间戳(秒)
.get_prev_block_timestamp_millis() TimestampMillis 前一个区块时间戳(毫秒)
.get_prev_block_nonce() u64 前一个区块Nonce
.get_prev_block_round() u64 前一个区块轮次
.get_prev_block_epoch() u64 前一个纪元
.get_prev_block_random_seed() ManagedByteArray<48> 前一个区块随机种子

纪元起始信息

方法 返回 描述
.get_epoch_start_block_timestamp_millis() TimestampMillis 当前纪元开始的时间
.get_epoch_start_block_nonce() u64 纪元起始时的区块Nonce
.get_epoch_start_block_round() u64 纪元起始时的区块轮次

已弃用的时间戳方法(请勿使用)

已弃用 替代方法
.get_block_timestamp() .get_block_timestamp_seconds() v0.63
.get_block_timestamp_ms() .get_block_timestamp_millis() v0.63
.get_prev_block_timestamp() .get_prev_block_timestamp_seconds() v0.63
.get_prev_block_timestamp_ms() .get_prev_block_timestamp_millis() v0.63
.get_block_round_time_ms() .get_block_round_time_millis() v0.63
.epoch_start_block_timestamp_ms() .get_epoch_start_block_timestamp_millis() v0.63
.epoch_start_block_timestamp_millis() .get_epoch_start_block_timestamp_millis() v0.63.1
.epoch_start_block_nonce() .get_epoch_start_block_nonce() v0.63.1
.epoch_start_block_round() .get_epoch_start_block_round() v0.63.1

交易信息

方法 返回 描述
.get_tx_hash() ManagedByteArray<32> 当前交易哈希
.get_gas_left() u64 剩余gas
.get_state_root_hash() ManagedByteArray<32> 状态根哈希

ESDT 代币元数据

方法 返回 描述
.get_esdt_token_data(address, token_id, nonce) EsdtTokenData 完整代币数据(数量、属性、创建者、版税、URI等)
.get_esdt_token_type(address, token_id, nonce) EsdtTokenType 代币类型枚举(可替代、不可替代、半可替代、元数据)
.get_token_attributes::<T>(token_id, nonce) T: TopDecode 从本合约账户反序列化的NFT/SFT属性
.get_current_esdt_nft_nonce(address, token_id) u64 地址上代币的最后铸造Nonce
// EsdtTokenData 字段:
pub struct EsdtTokenData<M: ManagedTypeApi> {
    pub token_type: EsdtTokenType,
    pub amount: BigUint<M>,
    pub frozen: bool,
    pub hash: ManagedBuffer<M>,
    pub name: ManagedBuffer<M>,
    pub attributes: ManagedBuffer<M>,  // 原始字节 — 使用 get_token_attributes 进行类型化
    pub creator: ManagedAddress<M>,
    pub royalties: BigUint<M>,         // 0-10000(基点)
    pub uris: ManagedVec<M, ManagedBuffer<M>>,
}
// 将NFT属性读取为类型化结构体
#[derive(TopDecode)]
struct MyNftAttributes {
    level: u8,
    power: u64,
}

let attrs: MyNftAttributes = self.blockchain()
    .get_token_attributes::<MyNftAttributes>(&nft_token_id, nft_nonce);

ESDT 状态与角色

方法 返回 描述
.is_esdt_frozen(address, token_id, nonce) bool 代币是否对该地址冻结
.is_esdt_paused(token_id) bool 代币转账是否全局暂停
.is_esdt_limited_transfer(token_id) bool 代币是否启用有限转账
.get_esdt_local_roles(token_id) EsdtLocalRoleFlags 本合约对代币的角色的位掩码
// 在铸造前检查角色
let roles = self.blockchain().get_esdt_local_roles(&token_id);
require!(
    roles.has_role(&EsdtLocalRole::NftCreate),
    "合约缺少NftCreate角色"
);

代码检查

方法 返回 描述
.get_code_metadata(address) CodeMetadata 合约代码元数据(可升级、可读、可支付标志)
.get_code_hash(address) ManagedBuffer 合约WASM代码的哈希
.is_builtin_function(name) bool 函数名是否为协议内置函数

原生代币

方法 返回 描述
.get_native_token() ManagedRef<TokenId> 返回 EGLD-000000 作为 TokenId
.is_native_token(token_id) bool 检查 TokenId 是否为 EGLD-000000

验证器

方法 返回 描述
.get_cumulated_validator_rewards() BigUint 本合约累积的验证器奖励

回传(跨合约调用后)

方法 返回 描述
.get_back_transfers() BackTransfers 从同步/异步调用返回的所有代币
.reset_back_transfers() () 清除当前回传(防止重复读取)

有关完整回传模式,请参阅 multiversx-cross-contract-calls 技能。

常见模式

基于时间的逻辑

let now = self.blockchain().get_block_timestamp_seconds();
let deadline = self.deadline().get();
require!(now < deadline, "截止时间已过");

分片感知操作

let caller_shard = self.blockchain().get_shard_of_address(
    &self.blockchain().get_caller()
);
let sc_shard = self.blockchain().get_shard_of_address(
    &self.blockchain().get_sc_address()
);
let same_shard = caller_shard == sc_shard;
// 如果同一分片,可以使用同步调用;否则需要异步调用

代币属性验证

fn validate_nft(&self, token_id: &EsdtTokenIdentifier, nonce: u64) {
    let sc_addr = self.blockchain().get_sc_address();
    let data = self.blockchain().get_esdt_token_data(&sc_addr, token_id, nonce);
    require!(data.amount > 0u64, "NFT未拥有");
    require!(!data.frozen, "代币已冻结");
}

转账前余额检查

let sc_balance = self.blockchain().get_sc_balance(&token_id, 0u64);
require!(sc_balance >= amount, "合约余额不足");
self.tx().to(&recipient).esdt((token_id, 0u64, amount)).transfer();

反模式

// 错误:使用已弃用的get_block_timestamp() — 返回原始u64
let ts = self.blockchain().get_block_timestamp();

// 正确:使用类型化时间戳(v0.63+)
let ts = self.blockchain().get_block_timestamp_seconds();

// 错误:存储原始u64时间戳,混合秒和毫秒
self.last_action().set(self.blockchain().get_block_timestamp_millis().as_u64_millis());

// 正确:存储类型化时间戳
self.last_action().set(self.blockchain().get_block_timestamp_seconds());

// 错误:使用get_balance检查自己的EGLD — 需要传递自己的地址
let bal = self.blockchain().get_balance(&self.blockchain().get_sc_address());

// 正确:使用get_sc_balance,它通过原生代币检测处理EGLD
let bal = self.blockchain().get_sc_balance(&self.blockchain().get_native_token(), 0u64);