Gear 合约大揭秘

简介: Gear 合约大揭秘

来介绍下 Gear 合约的基本结构

#[no_mangle]
pub unsafe extern "C" fn init() {}
#[no_mangle]
pub unsafe extern "C" fn handle() {}
# 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 合约最小必要结构
```rust
#[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 合约中,我们也经常使用 msgmsg.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 这些基本属性。

具体讲讲 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/appshttps://github.com/gear-tech/gear/tree/master/examples


目录
相关文章
|
运维 监控 Linux
Linux 部署1Panel现代化运维管理面板&远程访问
Linux 部署1Panel现代化运维管理面板&远程访问
|
XML 移动开发 小程序
抖音小程序开发 唤起收银台支付(可以选择支付宝APP支付或微信H5支付)
字节跳动也开放了小程序给商家接入,可以在旗下APP如抖音、今日头条、今日头条极速版等应用中即点即用,基于庞大的数亿用户量为其引流,帮助商家获取用户流量,销售商品,其模式和微信小程序差不多。
2385 0
抖音小程序开发 唤起收银台支付(可以选择支付宝APP支付或微信H5支付)
|
Python
python使用pip镜像源加速安装包(清华、阿里、中科大)
python使用pip镜像源加速安装包(清华、阿里、中科大)
9076 0
python使用pip镜像源加速安装包(清华、阿里、中科大)
|
11月前
|
存储 传感器 人工智能
《软硬协同优化,解锁鸿蒙系统AI应用性能新高度》
在数字化时代,鸿蒙系统与AI的融合备受关注。鸿蒙凭借微内核架构和分布式特性,支持语音助手、图像识别等AI应用,提升用户体验。为应对复杂AI需求,软硬件协同优化成为关键:软件方面通过算法、资源管理和框架优化挖掘潜力;硬件方面则通过芯片适配、传感器和存储优化提供动力。两者协同实现资源共享、任务调度和数据处理的突破,大幅提升性能,推动智能化体验迈向新高度。
606 9
|
网络协议 安全 物联网
IPv4 与 IPv6: 理解它们的基本区别
IPv4 与 IPv6: 理解它们的基本区别
4179 0
|
运维 安全 网络安全
|
存储 前端开发 Java
若依修改----数据字典,可以用于维护系统中常见的静态数据,为什么不写死,用字典维护?数据字典的好处是一个地方编写数据,在多个地方,复用他,静态选项这里填完,换其他,用户性别这里的男女,就转成而来字典
若依修改----数据字典,可以用于维护系统中常见的静态数据,为什么不写死,用字典维护?数据字典的好处是一个地方编写数据,在多个地方,复用他,静态选项这里填完,换其他,用户性别这里的男女,就转成而来字典
|
架构师 NoSQL 中间件
挑战架构师极限:分布式锁的四种实现方式,优劣对比让你一目了然!
【8月更文挑战第29天】在2024年软考架构师考试中,掌握分布式锁的实现方法极其重要。本文详细介绍了基于数据库、Redis及ZooKeeper三种常见分布式锁方案。数据库锁简单易懂但性能低;Redis锁性能优越且支持自动续期,但需引入中间件;ZooKeeper锁可靠性高,适用于分布式环境,但实现复杂。通过对比各方案优缺点,帮助考生更好地应对考试,选择最适合业务场景的分布式锁策略。
1377 0
|
Linux Shell 测试技术
linux基本功系列之uptime命令实战
linux基本功系列之uptime命令实战
578 0
linux基本功系列之uptime命令实战
|
大数据
《阿里云产品手册2022-2023 版》——大数据计算
《阿里云产品手册2022-2023 版》——大数据计算
198 0