Skip to content

Commit

Permalink
refactor doc of intrinsic
Browse files Browse the repository at this point in the history
  • Loading branch information
vita-dounai committed Mar 19, 2021
1 parent 4f7a5b9 commit a9e77b2
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 27 deletions.
130 changes: 108 additions & 22 deletions docs/contract/intrinsic.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,135 @@
# 环境与内置函数
# 环境与内置方法

## 环境

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

```eval_rst
.. code-block:: rust
:linenos:
self.env().get_caller();
```

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

<ul class="method-introduction">
<li>

```rust
pub fn get_caller(self) -> address
```

</li>
<p>

获取合约调用者的账户地址。

</p>
<li>

```rust
self.env().get_caller();
pub fn get_tx_origin(self) -> address
```

其中`self`是执行合约方法时当前合约对象的引用。在编译合约时,Liquid会自动为您的合约实现一个名为`env`的私有方法。`env`方法不接受任何参数,但会返回一个环境访问器对象, 您无需关心环境访问器的具体实现细节,只需要知道能且仅能通过环境访问器访问区块链执行环境信息。获得环境访问器后,您便可以在其上调用您所需要接口了。目前Liquid中提供了以下访问区块链执行环境信息的接口:
</li>
<p>

- `get_caller`
获取整个合约调用链中,最开始发起调用的调用方的账户地址,此时获得的账户地址一定是一个外部账户地址。

签名:`get_caller() -> Address`
</p>
<li>

功能:获取直接调用当前合约的调用者的地址。
```rust
pub fn now(self) -> timestamp
```

- `emit`
</li>
<p>

签名:`emit<E>(event: E)`其中`E`为事件类型,即您标注了`#[liquid(event)]`的结构体类型(可参考[事件](./event.html)
获取当前区块的时间戳,以 13 位时间戳的形式表示。其中`timestamp`为`u64`类型的别名。

功能:触发一个事件,事件会以日志的形式记录在交易的回执中。
</p>
<li>

每次调用环境相关的的接口时,都需要消耗一个环境访问器对象,因此您不能通过如下方式复用环境访问器对象:
```rust
pub fn get_address(self) -> address
```

</li>
<p>
获取合约自身的账户地址。
</p>
<li>

```rust
// 环境访问器对象无法复用,编译报错
let env_access = &self.env();
let caller = env_access.get_caller();
env_access.emit(some_event);
pub fn is_contract(self, account: &address) -> bool
```

正确的方式每次调用环境相关的接口时都创建一个环境访问器对象,环境访问器极为轻量,因为您无需担心创建时的性能开销:
</li>

<p>
传入某个账户地址,判断该账户是否为合约账户。
</p>
<li>

```rust
let caller = self.env().get_caller();
self.env().emit(some_event);
pub fn emit<E>(self, event: E)
```

</li>
<p>

触发事件,要求模板参数`E`必须为被`#[liquid(event)]`属性标注的结构体类型。

</p>
</ul>

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

<div class="wrong-example">

```eval_rst
.. code-block:: rust
:linenos:
:emphasize-lines: 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);
```

</div>

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

```eval_rst
.. code-block:: rust
:linenos:
let caller = self.env().get_caller();
self.env().emit(some_event);
```

## 内置函数

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

<ul class="method-introduction">
<li>

```rust
pub fn require<Q>(expr: bool, msg: Q)
where
Q: AsRef<str>,
```

</li>

- `require`
<p>

签名:`require<Q>(expr: bool, msg: Q)`,其中泛型参数Q需要实现`AsRef<str>`,常见的`str``String`等类型均可以作为`msg`参数的类型
断言函数,用于判断布尔类型的断言表达式`expr`是否成立。若断言成立,则合约代码继续向下执行;若不成立,则直接终止合约代码的运行并引发交易回滚,然后将异常信息`msg`放入交易回执中一并返回至合约的调用方。

功能:断言函数,用于判断某个值为布尔类型的表达式`expr`是否成立。若成立,合约继续向下执行;若不成立,则引发交易回滚,并向外抛出所指定的异常信息`msg`,异常信息会随着交易回执一并返回至用户。
</p>
</ul>
6 changes: 1 addition & 5 deletions docs/contract/state.md
Original file line number Diff line number Diff line change
Expand Up @@ -740,11 +740,7 @@ impl<'a, K, Q, V> core::ops::IndexMut<&'a Q> for Mapping<K, V>
where
K: Borrow<Q>,
{
fn index_mut(&mut self, index: &'a Q) -> &mut Self::Output {
self.get_mut(index).expect(
"[liquid_lang::Mapping::index_mut] Error: expected `index` to be existed",
)
}
fn index_mut(&mut self, index: &'a Q) -> &mut Self::Output;
}
```

Expand Down

0 comments on commit a9e77b2

Please sign in to comment.