EOS 学习笔记 3- 智能合约

本贴最后更新于 2217 天前,其中的信息可能已经渤澥桑田

参考文档
https://developers.eos.io/eosio-home/docs/the-abi
https://blog.csdn.net/yuanfangyuan_block/article/details/80403276

ABI 学习

What is an ABI?

The Application Binary Interface (ABI) is a JSON-based description on how to convert user actions between their JSON and Binary representations. The ABI also describes how to convert the database state to/from JSON. Once you have described your contract via an ABI then developers and users will be able to interact with your contract seamlessly via JSON.

{

"version": "eosio::abi/1.0",

"types": [],

"structs": [],

"actions": [],

"tables": [],

"ricardian_clauses": [],

"abi_extensions": [],

"___comment" : ""

}

Types

类型

预置的类型列表https://github.com/EOSIO/eos/blob/master/libraries/chain/abi_serializer.cpp#L65-L103

An ABI enables any client or interface to interpret and even generate an GUI for you contract. For this to work in a consistent manner, describe the custom types that are used as a parameter in any public action or struct that needs to be described in the ABI.

Structs

描述 hpp 定义的结构体

Structs that are exposed to the ABI also need to be described. By looking at eosio.token.hpp, it can be quickly determined which structs are utilized by public actions. This is particularly important for the next step.

A struct's object definition in JSON looks like the following:

"structs": [

//Explicit Structs

{

"name": "account",

"base": "",

"fields": [

{

"name": "balance",

"type": "asset"

}

]

},

{

"name": "currency_stats",

"base": "",

"fields": [

{

"name": "supply",

"type": "asset"

},

{

"name": "max_supply",

"type": "asset"

},

{

"name": "issuer",

"type": "name"

}

]

},

//Implicit Structs

{

"name": "create",

"base": "",

"fields": [

{

"name": "issuer",

"type": "name"

},

{

"name": "maximum_supply",

"type": "asset"

}

]

},

{

"name": "issue",

"base": "",

"fields": [

{

"name": "to",

"type": "name"

},

{

"name": "quantity",

"type": "asset"

},

{

"name": "memo",

"type": "string"

}

]

},

{

"name": "transfer",

"base": "",

"fields": [

{

"name": "from",

"type": "name"

},

{

"name": "to",

"type": "name"

},

{

"name": "quantity",

"type": "asset"

},

{

"name": "memo",

"type": "string"

}

]

}

]

Actions

An action's JSON object definition looks like the following:

{

"name": "transfer", //The name of the action as defined in the contract

"type": "transfer", //The name of the implicit struct as described in the ABI

"ricardian_contract": "" //An optional ricardian clause to associate to this action describing its intended functionality.

}

Tables

Describe the tables. Here's a table's JSON object definition:

Here's how the accounts table would be described in the ABI

{

"name": "accounts",

"type": "account", // Corresponds to previously defined struct

"index_type": "i64",

"key_names" : ["primary_key"],

"key_types" : ["uint64"]

}

Ricardian Clauses

Ricardian clauses describe the intended outcome of a particular actions. It may also be utilized to establish terms between the sender and the contract.

hpp 头文件

eosio.token.hpp
https://blog.csdn.net/yuanfangyuan_block/article/details/80403276
为了帮助大家熟悉 EOS 智能合约,EOS 官方提供了一个代币(资产)智能合约 Demo —— eosio.token。eosio.token 智能合约目前还不是特别完善,个别功能还没有完成。但这个示例合约给出了 EOS 官方智能合约开发的标准结构和开发方法,并且真正的 EOS 代币也会借鉴这个示例合约的逻辑,是 EOS 智能合约入门的经典案例。

照例,eosio.token 合约由三个文件(cpp,hpp,abi)文件组成,本篇文章将为大家讲解 eosio.token.hpp 文件。原文件地址:https://github.com/EOSIO/eos/tree/master/contracts/eosio.token

预处理指令 & 头文件
代码的开头声明了头文件,主要是 eos 智能合约的 API 库。

//预处理指令,防止文件被重复包含
#pragma once

//eos 资产(asset)头文件
#include <eosiolib/asset.hpp>
//eos 智能合约 API 库
#include <eosiolib/eosio.hpp>

cpp 实现

eosio.token.cpp
https://blog.csdn.net/yuanfangyuan_block/article/details/80403312
之前的文章介绍了 eosio.token 智能合约的 hpp 文件,这次向大家介绍 eosio.token.cpp 文件,cpp 文件即 C++ 代码文件,智能合约所有的业务逻辑内容都是在 cpp 文件中实现的。

eosio.token.cpp 文件地址: https://github.com/EOSIO/eos/blob/master/contracts/eosio.token/eosio.token.cpp

了解 C/C++ 开发的同学肯定熟悉,cpp 文件的主要使命是实现 hpp 文件中声明的函数(方法),包括公有函数(EOS 里也叫 action)和私有函数。hpp 里挖的坑,cpp 要一个不留地实现。

私有函数
照惯例,私有函数都是工具函数,供类内部的其他函数调用。

sub_balance(减资产)函数
作用:从指定账户中减去资产
参数:被操作账户,资产数,资产状态

//参数:被操作账户          资产种类与数量      资产状态结构体
void token::sub_balance( account_name owner, asset value, const currency_stats& st ) {
   //建立一个 multi_index,用来操作数据库
   //这里的参数 _self 表示数据的拥有者为智能合约本身,参数 owner 表示储存在名为被操作账户的表中
   //这样并不是直接建立了一个新表,而是让 C++ 程序与数据库对应的表之间建立了数据传输的通道
   accounts from_acnts( _self, owner );
   
   //在数据表中查询要减少的代币结构体,就是 hpp 文件中定义的 account 结构体
   const auto& from = from_acnts.get( value.symbol.name() );
   //校验,要减少的代币数量应该小于目前拥有的代币数量,否则会报错。
   eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" );
   
   //判断是否有被操作账户的授权
   if( has_auth( owner ) ) {
      //校验,账户是否被冻结
      eosio_assert( !st.can_freeze || !from.frozen, "account is frozen by issuer" );
      //校验,这种代币是否被冻结
      eosio_assert( !st.can_freeze || !st.is_frozen, "all transfers are frozen by issuer" );
      //校验,账户是否在白名单中
      eosio_assert( !st.enforce_whitelist || from.whitelist, "account is not white listed" );
   //如果没有被操作账户的授权,检查是否有发币者的授权
   } else if( has_auth( st.issuer ) ) {
      //如果有发币者的授权,那么肯定是在召回代币,查看代币是否可以召回
      eosio_assert( st.can_recall, "issuer may not recall token" );
   } else {
      //如果两种授权都没有,则失败,没有足够的权限
      eosio_assert( false, "insufficient authority" );
   }
   //通过 Lambda 表达式(匿名函数)修改将代币结构体
   from_acnts.modify( from, owner, [&]( auto& a ) {
      //匿名函数 函数体   
       a.balance -= value;
   });
}
  • EOS
    7 引用 • 33 回帖 • 1 关注
  • 智能合约

    智能合约(Smart contract)是一种旨在以信息化方式传播、验证或执行合同的计算机协议。智能合约允许在没有第三方的情况下进行可信交易,这些交易可追踪且不可逆转。智能合约概念于 1994 年由 Nick Szabo 首次提出。

    1 引用 • 11 回帖 • 2 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...