乐趣区

关于区块链:Gear-合约大揭秘

# Gear 合约揭秘

Gearfans 举办了 3 次 Gear workshop,从第一次的 [ping-pong](https://wiki.gear-tech.io/zh-cn/developing-contracts/examples/ping/) 合约,到 [去中心化 twitter](https://wiki.gear-tech.io/zh-cn/developing-contracts/examples/feeds),再到 [Erc20](https://wiki.gear-tech.io/zh-cn/developing-contracts/examples/erc20)。那咱们来介绍下 Gear 合约的根本构造。## Gear 合约最小必要构造

[no_mangle]

pub unsafe extern “C” fn init() {}

[no_mangle]

pub unsafe extern “C” fn handle() {}


这 2 个办法是 Gear 合约的最小必要构造。`init()` 函数在合约初始化时执行一次。`handle()` 函数负责解决所有由咱们程序处理的传入音讯。** 小知识点 **:`#[no_mangle]` 示意禁止 Rust 编译器批改办法的名字,简略来讲 Rust 函数能在其它语言中被调用,必须禁用编译器的名称批改性能。回到 ping-pong 合约,代码如下:

![no_std]

use gstd::{msg, prelude::*};

[no_mangle]

pub unsafe extern “C” fn handle() {

let new_msg = String::from_utf8(msg::load_bytes()).expect("Invalid message");

if new_msg == "PING" {msg::reply_bytes("PONG", 12_000_000, 0);
}

}

[no_mangle]

pub unsafe extern “C” fn init() {}


咱们只解决了 `handle()` 了,`init()` 能够不做任何解决。`handle()` 的逻辑是:失去新音讯 `new_msg`,如果 new_msg 是 PING,通过 `msg::reply_bytes` 发送 PONG 信息。### gstd::msg

在 solidity 合约中,咱们也常常应用 `msg`:`msg.sender msg.value`。`msg::source()` 与 solidity 的 `msg.sender` 含意雷同,指信息的发送者或者源头,即调用合约的地址。`gstd::msg` 罕用的办法:

msg::load() // 获取以后正在解决的音讯

msg::source() // 获取音讯的发送者

msg::reply() // 发送一条新音讯作为对以后正在的音讯的回应
msg::reply_bytes() // 发送一条新音讯作为对以后正在的音讯的回应
msg::reply_to() // 获取以后音讯的 id

msg::send() // 发送一个新的音讯给合约或用户


## 残缺的合约

残缺的合约,根本会有 4 局部:`metadata! handle() init() meta_state()`

![no_std]

use gstd::msg;

gstd::metadata! {
title: “ERC20”,
init:

input: InitConfig,

handle:

input: Action,
output: Event,

state:

input: State,
output: StateReply,

}

[no_mangle]

pub unsafe extern “C” fn handle() {}

[no_mangle]

pub unsafe extern “C” fn init() {}

[no_mangle]

pub unsafe extern “C” fn meta_state() -> *mut [i32; 2] {}


### metadata! 宏

`metadata!` 是 Gear 定义的宏,它会定义合约构造,相似 abi。

gstd::metadata! {
title: “ERC20”,
init:

input: InitConfig, // 定义初始化参数 

handle:

input: Action, // 定义合约办法,供 handle 应用
output: Event, // 定义事件,在调用合约办法后,会调用合约事件,供 handle 应用 

state:

input: State, // 定义 meta_state 的输出格局,供 meta_state 应用
output: StateReply, // 定义 meta_state 的输入格局,供 meta_state 应用 

}


### meta_state

`meta_state()` 函数,它将立刻返回状态,而且不须要任何 Gas。看下 erc20 的 meta_state,代码如下:

[no_mangle]

pub unsafe extern “C” fn meta_state() -> *mut [i32; 2] {

let query: State = msg::load().expect("failed to decode input argument");

let encoded = match query {State::Name => StateReply::Name(FUNGIBLE_TOKEN.name.clone()).encode(),
    State::Symbol => StateReply::Name(FUNGIBLE_TOKEN.symbol.clone()).encode(),
    State::Decimals => StateReply::Decimals(18).encode(),
    State::TotalSupply => StateReply::TotalSupply(FUNGIBLE_TOKEN.total_supply).encode(),
    State::BalanceOf(account) => {StateReply::Balance(FUNGIBLE_TOKEN.balance_of(&account)).encode()}
};

let result = gstd::macros::util::to_wasm_ptr(&(encoded[..]));
core::mem::forget(encoded);
result

}


通过 meta_state 咱们会读取到合约的 `Name Symbol Decimals BalanceOf TotalSupply` 这些根本属性。![read_state.png](https://img.learnblockchain.cn/attachments/2022/02/O2gEc2cV620d155a4d6ca.png)

### 具体讲讲 handle

handle 是 Gear 合约的重要函数,handle 通过 `msg::load()` 的信息,而后依据信息品种,用不同的函数解决数据,并发送信息。以下代码是 去中心化 twitter 的 handle,要害都在 `match action {}`,如果信息是 `ChannelAction::Meta` 会做什么解决,如果信息是 `ChannelAction::Post`,又会做什么解决。

[no_mangle]

pub unsafe extern “C” fn handle() {

let action: ChannelAction = msg::load().expect(&format!("CHANNEL {:?}: Unable to decode Channel Action",
    STATE.name()));

match action {
    ChannelAction::Meta => {msg::reply(meta, 100_000_000, 0);
    }

    ChannelAction::Subscribe => {}

    ChannelAction::Unsubscribe => {msg::reply((), 0, 0);
    }

    ChannelAction::Post(text) => {msg::reply((), 0, 0);
    }
}

}


## 总结

Gear 合约有一个最根本的构造,实现这个构造,就实现了 1 个简略的合约。gstd 是 Gear 智能合约的规范库,为智能合约提供足够的性能和办法。1 个残缺的 Gear 合约,会有 4 局部:`metadata! handle() init() meta_state()`。更多对于 Gear 合约的例子,请看 https://github.com/gear-tech/apps 与 https://github.com/gear-tech/gear/tree/master/examples。
退出移动版