环境与内置方法

环境

环境能够用于在合约代码中访问某些区块链执行上下文中的信息。以获取合约调用者的账户地址为例,可以通过如下形式在合约方法中借助环境取得该信息:

1
self.env().get_caller();

其中self是执行合约方法时当前合约对象的引用。在构建合约时,Liquid 会自动在合约实现一个名为env的私有方法。env方法不接受任何参数,但会返回一个环境访问器。获得环境访问器后,便可以通过环境访问器调用所需方法,能且仅能通过环境访问器获取区块链执行上下文信息。目前环境访问器提供了以下方法:

  • pub fn get_caller(self) -> address
    
  • 获取合约调用者的账户地址。

  • pub fn get_tx_origin(self) -> address
    
  • 获取整个合约调用链中,最开始发起调用的调用方的账户地址,此时获得的账户地址一定是一个外部账户地址。

  • pub fn now(self) -> timestamp
    
  • 获取当前区块的时间戳,以 13 位时间戳的形式表示。其中timestampu64类型的别名。

  • pub fn get_address(self) -> address
    
  • 获取合约自身的账户地址。

  • pub fn is_contract(self, account: &address) -> bool
    
  • 传入某个账户地址,判断该账户是否为合约账户。

  •  pub fn emit<E>(self, event: E)
    
  • 触发事件,要求模板参数E必须为被#[liquid(event)]属性标注的结构体类型。

每次调用环境相关的的接口时,都需要消耗一个环境访问器,因此不能通过如下方式复用环境访问器:

1
2
3
4
let env_access = &self.env();
let caller = env_access.get_caller();
// Compile error, due to that `env_access` had been consumed already.
env_access.emit(some_event);

正确的方式是每次调用环境相关的接口时都调用self.env()创建一个环境访问器对象。环境访问器极为轻量,因此无需担心创建时的性能开销:

1
2
let caller = self.env().get_caller();
self.env().emit(some_event);

内置函数

Liquid 提供了一些基本的内置函数。在构建合约时,Liquid 会自动导入这些函数,因此在合约代码中可以直接使用这些函数。内置函数包括:

  • pub fn require<Q>(expr: bool, msg: Q)
    where
        Q: AsRef<str>,
    
  • 断言函数,用于判断布尔类型的断言表达式expr是否成立。若断言成立,则合约代码继续向下执行;若不成立,则直接终止合约代码的运行并引发交易回滚,然后将异常信息msg放入交易回执中一并返回至合约的调用方。