【许晓笛】 EOS 智能合约案例解析(2)

详解 EOS 智能合约的 cpp 文件

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

eosio.token.cpp 文件地址: github.com/EOSIO/eos/b…

了解 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;});
}复制代码

add_balance(增加资产)函数

作用:从指定账户中增加资产 参数:被操作账户,资产数,资产状态,存储资源支付账户

//                   参数:被操作账户         代币数量      代币状态结构体             储存支付账户
void token::add_balance( account_name owner, asset value, const currency_stats& st, account_name ram_payer )
{//建立一个 multi_index,用来操作数据库accounts to_acnts( _self, owner );//在数据表中查询要增加的代币结构体auto to = to_acnts.find( value.symbol.name() );//如果 to == to_acnts.end(),说明查找到数据表的末尾都没有对应的结构体,说明该账户没有该代币if( to == to_acnts.end() ) {//校验,该代币是否开启了白名单功能eosio_assert( !st.enforce_whitelist, "can only transfer to white listed accounts" );//使用 emplace 方法,在数据表中增加一项to_acnts.emplace( ram_payer, [&]( auto& a ){//匿名函数体,代币数量等于每次转入的数量,因为之前没有a.balance = value;});//如果数据表中已经存在此项,只需增加代币数量} else {//检查账户是否在白名单中eosio_assert( !st.enforce_whitelist || to->whitelist, "receiver requires whitelist by issuer" );//使用 modify 方法,修改项目to_acnts.modify( to, 0, [&]( auto& a ) {//直接修改代币数量a.balance += value;});}
}
复制代码

公有函数

EOS 合约中的公有函数大多是供别的账户调用的 Action,根据 hpp 文件,我们需要实现 create、issue、transfer 三个公有函数(action)。

create(新建代币)函数

create 函数用来创建一种新的代币,并设置这种新代币的各种参数。

                    //参数:发币账户
void token::create( account_name issuer,//最大发行量asset        maximum_supply,//发币者是否可以冻结代币uint8_t      issuer_can_freeze,//发币者是否可以召回代币uint8_t      issuer_can_recall,//是否可以设置白名单uint8_t      issuer_can_whitelist )
{//需要 eosio.token 账户本身的授权require_auth( _self );auto sym = maximum_supply.symbol;//校验,新代币名称是否有效eosio_assert( sym.is_valid(), "invalid symbol name" );//校验,最大发行量是否有效eosio_assert( maximum_supply.is_valid(), "invalid supply");//校验,最大发行量是否大于零eosio_assert( maximum_supply.amount > 0, "max-supply must be positive");//建立一个 milti_index 数据表,用来与数据库交互stats statstable( _self, sym.name() );//在表中搜索相同名称的代币auto existing = statstable.find( sym.name() );//校验,是否已经存在相同名称的代币eosio_assert( existing == statstable.end(), "token with symbol already exists" );//使用 emplace 方法,在数据表中增加一项statstable.emplace( _self, [&]( auto& s ) {// 使用匿名函数,将传入的参数赋值给 currency_stats 结构体s.supply.symbol = maximum_supply.symbol;s.max_supply    = maximum_supply;s.issuer        = issuer;s.can_freeze    = issuer_can_freeze;s.can_recall    = issuer_can_recall;s.can_whitelist = issuer_can_whitelist;});
}复制代码

transfer(转账)函数

transfer 应该是这个智能合约最常用的函数,就是将代币从一个账户转到另一个。

                    //转出方账户名
void token::transfer( account_name from,//转入方账户名account_name to,//代币种类与数量asset        quantity,//转账备忘(目前还没实现)string       /*memo*/ )
{//打印转账提示print( "transfer" );//检查转出方权限require_auth( from );//得到代币名称auto sym = quantity.symbol.name();//建立一个 milti_index 数据表,用来与数据库交互stats statstable( _self, sym );//在数据表中寻找代币的 currency_stats 结构体const auto& st = statstable.get( sym );//向转出方获取回执require_recipient( from );//向转入方获取回执require_recipient( to );//校验,转出的代币是否有效eosio_assert( quantity.is_valid(), "invalid quantity" );//校验,转账数量要大于0eosio_assert( quantity.amount > 0, "must transfer positive quantity" );//调用 sub_balance 私有方法sub_balance( from, quantity, st );//调用 add_balance 私有方法add_balance( to, quantity, st, from );
}
复制代码

issue(发币)函数

上面的 create 函数创建代币后只是给定了参数,并没有真正的代币被创建出来,需要 issue 函数进行发币。

                //参数:代币接收方     代币数量和种类      备忘
void token::issue( account_name to, asset quantity, string memo )
{//打印提示print( "issue" );//获取代币名称auto sym = quantity.symbol.name();//建立一个 milti_index 数据表,用来与数据库交互stats statstable( _self, sym );//在数据表中搜索代币 currency_stats 结构体const auto& st = statstable.get( sym );//检查发币者授权require_auth( st.issuer );//检查资产是否有效eosio_assert( quantity.is_valid(), "invalid quantity" );//检查资产是否大于零eosio_assert( quantity.amount > 0, "must issue positive quantity" );//检查创造的总资产是否大于最大代币数eosio_assert( quantity <= st.max_supply - st.supply, "quantity exceeds available supply");//更新资产创造数量记录statstable.modify( st, 0, [&]( auto& s ) {s.supply += quantity;});//给发布者增加资产add_balance( st.issuer, quantity, st, st.issuer );//判断代币接受方是否是发币者if( to != st.issuer ){//这里使用了一个特殊处理,先给发币者增加相应的代币,再调用 transfer 函数转账给代币接受方。//这样做的目的是让代币接受方收到通知SEND_INLINE_ACTION( *this, transfer, {st.issuer,N(active)}, {st.issuer, to, quantity, memo} );}
}
复制代码

设置 action

大家知道 EOS 系统的智能合约是以 action 为基本动作单位的,我们要将需要声明为 action 的函数告知 EOS 系统,通过以下宏即可实现。

//将 create issue transfer 三个共有函数声明为 action,供其他账户调用。
EOSIO_ABI( eosio::token, (create)(issue)(transfer) )
复制代码

相关文章和视频推荐

【许晓笛】 EOS 智能合约案例解析(1)

圆方圆学院汇集大批区块链名师,打造精品的区块链技术课程。 在各大平台都长期有优质免费公开课,欢迎报名收看。

公开课地址:ke.qq.com/course/3451…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/450245.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 中 transient关键字

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 java语言的关键字&#xff0c;变量修饰符&#xff0c;如果用transient声明一个实例变量&#xff0c;当对象存储时&#xff0c;它的值不需…

java中int转成String位数不足前面补零

java中int转成String位数不足前面补零 转载自&#xff1a;http://ych0108.iteye.com/blog/2174134java中int转String位数不够前面补零 String.format("%010d", 25); //25为int型 10代表前面要补的字符 10代表字符串长度 d表示参数为整数类型 今天想将int 转String 位…

Oops! the requested resource is not found!

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 情况一&#xff1a;调用 dubbo 服务失败&#xff0c;报错如题&#xff1a;Oops! the requested resource is not found! 原因很简单&am…

django URL路由基础

URL是Web服务的入口&#xff0c;用户通过浏览器发送过来的任何请求&#xff0c;都是发送到一个指定的URL地址&#xff0c;然后被响应。 在Django项目中编写路由&#xff0c;就是向外暴露我们接收哪些URL的请求&#xff0c;除此之外的任何URL都不被处理&#xff0c;也没有返回。…

Linux在超级计算机领域一统天下

摘要&#xff1a;在世界超级计算机排行榜500强榜单中&#xff0c;基于Linux的超级计算机占据了462个席位&#xff0c;比率高达92%。基于Windows的超级计算机仅有2个席位&#xff0c;份额为0.4%。中国基于Windows的超级计算机Magic Cube排名94位&#xff0c;澳大利亚基于Windows…

Qtum量子链漏洞赏金计划正式开启

本次Qtum量子链赏金计划为了更好的借助社区的力量参与到QTUM主网及周边应用的开发建设中&#xff0c;让QTUM持续地保持安全、高效的运行&#xff0c;同时能满足更多用户的需求。Bug分级与奖励体系1、如果已经有类似的Issue或者Qtum团队已经知道并在解决该问题的情况将不适用于该…

.SpelEvaluationException: EL1008E: Property or field ‘cache_department_list_Tree‘ cannot be found

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 报错如题&#xff1a; .SpelEvaluationException: EL1008E: Property or field cache_department_list_Tree cannot be found on object…

修过的一个android framework原生系统代码bug

“坑”描述&#xff1a; 在对我们自己研发的一款android终端进行camera拍照压力测试时&#xff0c;发现当拍照张数达到几万张时&#xff0c;查看内存占用情况&#xff0c;发现内存泄露。 填“坑”&#xff1a; frameworks/base/core/jni/android/graphics/YuvToJpegEncoder.…

Koa项目搭建过程详细记录

2019独角兽企业重金招聘Python工程师标准>>> Java中的Spring MVC加MyBatis基本上已成为Java Web的标配。Node JS上对应的有Koa、Express、Mongoose、Sequelize等。Koa一定程度上可以说是Express的升级版。许多Node JS项目已开始使用非关系型数据库(MongoDB)。Sequel…

商业项目中代码质量是否重要?

这是一篇比较老的 文章&#xff0c;但是文中的这些问题在现在仍然普遍存在。代码质量的高低与商业产品的优劣是否有直接的影响&#xff1f;开发者Frank Sommers在文中给出了他的看法。文章内容如下。在大多数商业项目中&#xff0c;代码质量并不被看重&#xff0c;因为大部分情…

Class is not a root resource. It, or one of its interfaces must be annotated with @Path:

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 报错如题&#xff1a; Class is not a root resource. It, or one of its interfaces must be annotated with Path:XXXX 这是一个dub…

Equation漏洞混淆利用分析总结(下)

样本三 如下所示在该样本中&#xff0c;使用了Ole10Native的流&#xff0c;因此没有equative head&#xff0c;默认读取红框中的4位长度。之后的metf head为01. 可以看到metf head的长度为01时&#xff0c;直接进入到if判断中(该if中的函数实际是一个异常处理函数&#xff0c;但…

闲扯工程师的版本管理概念

如果你所在的公司还在通过qq给客户发sdk升级包等&#xff0c;你可以考虑换一家公司了。

resource fork, Finder information, or similar detr

1.关闭当前项目和Xcode 2.打开终端或者iterm cd ~/Library/Developer/Xcode/DerivedData/ 3. xattr -rc . 4.重新打开项目 5.如果不行那你就再试试其他的办法吧&#xff0c;我就是这样弄好的 如果有需要装系统的话可以看一下我自己封装的系统&#xff0c;原装系统无精简&#x…

5 个常用的软件质量指标

在软件开发中&#xff0c;软件质量是衡量软件是否符合需求、标准的重要体现。除了 代码质量外&#xff0c;影响软件整体质量的因素还有很多。因此&#xff0c;要确保软件的整体质量&#xff0c;就需要在各个环节严格控制。本文列出了衡量软件质量的5个最常用的指标。1. SLOC&a…

介绍一个对陌生程序快速进行性能瓶颈分析的技巧

前言 工作多年&#xff0c;一直做的是curd系统。前几年做的系统应用场景&#xff0c;大多对数据库依赖比较重。例如报表统计&#xff0c;数据迁移&#xff0c;批量对账等。所以这些系统出现性能瓶颈一般出在数据库操作上面。 如果程序因为数据库操作出现性能瓶颈是比较好办的&a…

[WARNING] The POM for XXX-system:jar:1.9.0-SNAPSHOT is missing, no dependency information available

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 在 git-bash 中 想要启动一个工程服务就是不成功&#xff0c;始终提示jar包找不到&#xff0c;本地代码已提交。 这时可直接登陆git&am…

关于tcp网络通讯的几个场景的小测试

以下场景基于阻塞式IO 发送端向接收端快速的发送数据&#xff0c;接收端如果不接受或者很慢速的接受会发生什么情况。 发送端快速向接收端发送大量数据&#xff0c;然后立即退出&#xff0c;接收端会发生什么情况。

测试一体机ASM failgroup的相关问题处理

环境&#xff1a;3台虚拟机 RHEL 7.3 Oracle RAC 11.2.0.4问题现象&#xff1a;RAC运行正常&#xff0c;ASM磁盘组Normal冗余&#xff0c;有failgroup整体故障&#xff0c;有failgroup配置错误。温馨提示&#xff1a;本文并不是市场上任何一款商业的一体机产品&#xff0c;只是…

掌握穷变富的12条原则 迅速从普通人变成有钱人

“穷忙”和“富闲”是对立面&#xff0c;“穷”对“忙”&#xff0c;“富”对“闲”&#xff0c;很多“穷忙女”是在拿青春当赌注&#xff0c;希望自己今天的“美丽”明天就能在市场上有个不错的“回报”&#xff1b;而多数“富闲女”则是在拿智慧当筹码&#xff0c;既不可替代…