1 个不稳定版本

0.0.1 2022年6月22日

#40#parity-wasm

Apache-2.0

17KB

ink!

Parity 的 ink! 用于编写智能合约

linux codecov coveralls loc stack-exchange

squink,ink! 的吉祥物ink! 是一个 嵌入式领域特定语言,用于在基于 Substrate 框架的区块链上用 Rust 编写智能合约。ink! 合约被编译成 WebAssembly。


初学者指导教程  •   ink! 文档门户  •   开发者文档


更多相关链接

目录

尝试一下

如果您想进行本地设置,可以使用我们的快速入门工具 substrate-contracts-node。它是一个简单的 Substrate 区块链,其中包括用于智能合约功能的 Substrate 模块 —— contracts 摊位(更多信息请参阅 如何工作)。

我们还在 Rococo 上有一个名为 Canvas 的实时测试网。Canvas 是一个基于 Substrate 的并行链,支持 ink! 智能合约。有关使用此测试网的进一步说明,请参阅我们的文档

对于这两种类型的链,可以使用 合约 UI 将您的合约实例化到链上并与之交互。

用法

编译智能合约的先决条件是安装 Rust 和 Cargo。以下是安装指南

我们还建议安装 cargo-contract。它是一个 CLI 工具,可帮助设置和管理使用 ink! 编写的 WebAssembly 智能合约。

cargo install cargo-contract --force

使用 --force 确保您已更新到最新的 cargo-contract 版本。

要初始化一个新的 ink! 项目,您可以使用以下命令:

cargo contract new flipper

这将在您的工作目录中创建一个名为 flipper 的文件夹。该文件夹包含一个脚手架 Cargo.toml 和一个 lib.rs,这两个文件都包含使用 ink! 所需的构建块。

lib.rs 包含我们的 hello world 合约 —— Flipper,我们将在下一节中进行解释。

为了构建合约,只需在 flipper 文件夹中执行以下命令:

cargo +nightly contract build

结果,您将在合约的 target 文件夹中获得一个文件 target/flipper.wasm,一个 metadata.json 文件和一个 <contract-name>.contract 文件。该 .contract 文件将 Wasm 和元数据合并到一个文件中,并在实例化合约时使用。

你好,世界! — 翻转器

Flipper 合约是一个简单的合约,只包含一个 bool 值。它提供方法来

  • 将值从 true 翻转到 false(反之亦然)
  • 并返回当前状态。

下面是使用 ink! 的 ink_lang 版本的代码。

use ink_lang as ink;

#[ink::contract]
mod flipper {
    /// The storage of the flipper contract.
    #[ink(storage)]
    pub struct Flipper {
        /// The single `bool` value.
        value: bool,
    }

    impl Flipper {
        /// Instantiates a new Flipper contract and initializes
        /// `value` to `init_value`.
        #[ink(constructor)]
        pub fn new(init_value: bool) -> Self {
            Self {
                value: init_value,
            }
        }

        /// Flips `value` from `true` to `false` or vice versa.
        #[ink(message)]
        pub fn flip(&mut self) {
            self.value = !self.value;
        }

        /// Returns the current state of `value`.
        #[ink(message)]
        pub fn get(&self) -> bool {
            self.value
        }
    }

    /// Simply execute `cargo test` in order to test your contract
    /// using the below unit tests.
    #[cfg(test)]
    mod tests {
        use super::*;
        use ink_lang as ink;

        #[ink::test]
        fn it_works() {
            let mut flipper = Flipper::new(false);
            assert_eq!(flipper.get(), false);
            flipper.flip();
            assert_eq!(flipper.get(), true);
        }
    }
}

我们示例文件夹中的 flipper/src/lib.rs 文件包含 exactly this code。运行 cargo contract build 以构建您的第一个 ink! 智能合约。

示例

examples 文件夹中,您可以找到许多用 ink! 编写的示例。

其中一些最有趣的示例包括:

  • delegator —— 实现跨合约调用。
  • trait-erc20 —— 定义一个用于 Erc20 合约的 trait 并实现它。
  • erc721 —— Erc721 NFT 代币的示例实现。
  • dns —— 一个简单的 DomainNameService 智能合约。
  • ……更多内容,只需浏览文件夹即可 🙃。

要构建一个单例示例,请导航到示例的根目录并运行

cargo contract build

现在你应该在合同的 target 文件夹中有一个 <name>.contract 文件。

有关如何将此文件上传到链的信息,请参阅玩一玩部分或我们的智能合约研讨会

它如何工作

  • Substrate的模块化实体运行时聚合框架(FRAME)包含一个模块,该模块实现了智能合约需要的典型函数的API(存储、查询账户信息等)。这个模块被称为 contracts
  • contracts 模块要求智能合约作为Wasm blob上传到区块链。
  • ink! 是一种智能合约语言,它针对 contracts 暴露的API。因此,ink! 合约被编译为Wasm。
  • 在执行 cargo contract build 时,会创建一个额外的文件 metadata.json。它包含有关合约提供哪些方法供其他方调用的信息。

ink! 宏和属性概述

入口点

在带有 #[ink::contract] 注解的模块中,这些属性是可用的

属性 适用范围 描述
#[ink(storage)] struct 定义上。 定义 ink! 存储结构。每个合约只能有一个 ink! 存储定义。
#[ink(message)] 适用于方法。 将 ink! 存储结构中的方法标记为消息,使其可供API调用合约。
#[ink(constructor)] 适用于方法。 将 ink! 存储结构中的方法标记为构造函数,使其可供API实例化合约。
#[ink(event)] struct 定义上。 定义 ink! 事件。合约可以定义多个此类 ink! 事件。
#[ink(anonymous)] 适用于 ink! 事件。 指示 ink! 代码生成器将 ink! 事件视为匿名,在发出时省略事件签名作为主题。与 Solidity 中的匿名事件非常相似。
#[ink(topic)] 适用于 ink! 事件字段。 指示 ink! 代码生成器为给定字段提供主题哈希。ink! 事件只能有有限数量的此类主题字段。与 Solidity 中的索引事件参数类似。
#[ink(payable)] 适用于 ink! 消息。 允许在 ink! 消息的调用中接收价值。ink! 构造函数隐式为可支付的。
#[ink(selector=S:u32)] 适用于 ink! 消息和 ink! 构造函数。 指定特定实体的具体调度选择器。这允许合约作者精确控制其API的选择器,从而在更改API名称时不会中断。
#[ink(selector= _)] 适用于 ink! 消息。 指定如果没有其他 ink! 消息匹配选择器,则调用的回退消息。
#[ink(namespace=N:string)] 适用于 ink! 特性实现块。 更改特性实现中所有 ink! 消息和 ink! 构造函数的输出选择器。允许区分具有重叠消息或构造函数名称的特性实现。仅谨慎使用并考虑周全!
#[ink(impl)] 适用于 ink! 实现块。 告诉 ink! 代码生成器某些实现块应获得访问 ink! 内部的权限,即使它不包含任何 ink! 消息或 ink! 构造函数。

请参阅此处,了解有关这些属性和#[ink::contract]宏的详细信息。

特质定义

使用#[ink::trait_definition]定义您自己的特定义,然后ink!智能合约可以实施。例如,查看此代码以了解如何使用它,或查看文档以获取详细信息。

链下测试

#[ink::test]过程宏使链外测试成为可能。例如,查看此代码以了解如何使用这些功能,或查看文档以获取详细信息。

开发者文档

我们有一个非常全面的文档门户,但如果您正在寻找crate级别的文档本身,那么这些是相关的链接

软件包 文档 描述
ink_lang ink!公开的语言功能。请参阅此处以了解您可以在#[ink::contract]中使用哪些属性。
ink_storage ink!中可用的数据结构。
ink_env 与智能合约Wasm执行器交互的低级接口。还包括链外测试API
ink_prelude 用于访问alloc crate类型的通用API。

社区徽章

正常设计

Built with ink!

[![Built with ink!](https://raw.githubusercontent.com/paritytech/ink/master/.images/badge.svg)](https://github.com/paritytech/ink)

平面设计

Built with ink!

[![Built with ink!](https://raw.githubusercontent.com/paritytech/ink/master/.images/badge_flat.svg)](https://github.com/paritytech/ink)

贡献

有关更多信息,请访问我们的贡献指南

请使用在scripts/check-*目录下提供的脚本,以在工作空间或所有示例上运行检查。请在推送PR中的工作之前执行此操作。

许可证

本存储库中的所有代码均受Apache License 2.0许可。

如果您对我们的产品许可有任何疑问,请联系我们

无运行时依赖

功能