开发合约前,我们先选择下将要用的编辑工具
我常用的有 clion 和vscode,电脑os为mac,不过其他系统差别不大,如果你习惯用于Windows,那建议选择 Windows Subsystem for Linux,不建议用其他三方封装的工具,以免更新不及时,或者不兼容,导致生产上出问题.

下面我们讲用以vscode 做演示.

配置智能合约项目

先用vscode打开eosio.cdt项目代码目录,按提示安装相应的扩展插件.一般只需要安装个 c/c++
等vscode加载索引完,会根据eosio.cdt项目下的cmakelists.txt 配置好开发环境及其include路径.
所以我一般习惯是直接将自己的智能合约项目直接clone 在 eosio.cdt/examples目录下,省的自己做相关依赖配置.

我们先假定一个智能合约项目,项目名为bcskill.game (项目名与合约名一致,省的后面弄混)
新建bcskill.game目录(目录名也要与合约名一致,方便后面部署),路径为eosio.cdt/examples/bcskill.game
目录结构如下

eosio.cdt/examples/bcskill.game
eosio.cdt/examples/bcskill.game/common //存放一些公用的源码文件
eosio.cdt/examples/bcskill.game/bcskill.game.hpp //智能合约头文件
eosio.cdt/examples/bcskill.game/bcskill.game.cpp // 智能合约源文件
eosio.cdt/examples/bcskill.game/README.md // 帮助文档

习惯的代码结构

bcskill.game.hpp

#pragma once
//一些常用的头文件依赖 根据实际所需添加
#include <eosiolib/eosio.hpp>
#include <eosiolib/time.hpp>
#include <eosiolib/transaction.hpp>
#include <eosiolib/asset.hpp>
#include <eosiolib/crypto.h>namespace bcskillgame // 为自己的项目创建单独的命名空间
{
// 一些用到的命名空间 根据实际需要添加using eosio::time_point;using eosio::microseconds;using eosio::name;using namespace std;// 定义下一些用到的宏,比如系统EOS代币符号#define EOS_SYMBOL symbol(symbol_code("EOS"),4)一些内部会用到的结构体struct play_hero_info{uint8_t hero_id;uint8_t hero_grade;uint8_t count;};...// 定义所需的table表 struct [[eosio::table("system"), eosio::contract("bcskill.game")]] system{uint64_t id;bool upgrading; //升级或维护中,暂时停止合约内所有的业务time_point zero_time;auto primary_key() const { return id; }};// `eosio::table("system")`中的system为合约内table的名字,后面可以用 get table 这个名字查看链上此table数据//  eosio::contract("bcskill.game")]] 中的 "bcskill.game" 为合约的名字,也就是我们之前定好的,也就是说这个表属于"bcskill.game" 合约...// 为上面定义好的table 创建实例化对象typedef eosio::multi_index<"system"_n, system> system_tables;// multi_index<"system" 中的 system 为table的表名, 第二个system 为表的定义名.system_tables为实例化后的对象名.//下面开始创建合约类class [[eosio::contract("bcskill.game")]] bcskill_contract : public eosio::contract // 从系统合约对象继承下{public:using eosio::contract::contract; // 引入父命名空间// 创建合约action接口 后面可以用push action调用ACTION upgrading(bool upgrading);...private:// 添加一些私有的数据类型// 一些整数类型可以用 enum 枚举enum GAME_STATUS_TYPE{GAME_STATUS_PADDING = 1,GAME_STATUS_RUNNING,GAME_STATUS_FINISHED};// 如果是小数,可以用classclass RACE_PWOER_TYPE{public:static constexpr auto RACE_PWOER_ORC_HUM_TA = 0.3;static constexpr auto RACE_PWOER_UD_VS_HUM_ORC_TA = 0.3;static constexpr auto RACE_PWOER_HUM_ORC_TA_VS_NE = 0.3;static constexpr auto RACE_PWOER_NE_VS_UD = 1.3;};// 合约内不建议使用小数操作,一些场景可以先统一增大倍数,转为整数class UPDATE_RATE_TYPE{public:static constexpr auto PROBABILITY_ACCURACY = 100;static constexpr auto UPDATE_RATE_1_SUCCESS = 0.7 * PROBABILITY_ACCURACY;...};// 定义写私有的方法,合约内部使用,这里的方法不会被 push action调用到bool is_upgrading();};
}

bcskill.game.cpp

#include "bcskill.game.hpp" //引入头文件
// 引入一些其他的头文件,比如
#include "common/utils.hpp"
// 引入所需的命名空间
using namespace bcskillgame;
using namespace eosio;
// 为头文件中各个action添加实现方法
void bcskill_contract::upgrading(bool upgrading){require_auth( _self.value );system_tables system_table(_self, _self.value);auto itr = system_table.begin();if(itr == system_table.end()){system_table.emplace( _self, [&]( auto& s ) {s.id = system_table.available_primary_key();s.upgrading = upgrading;});}else{system_table.modify( itr, _self, [&]( auto& s ) {s.upgrading = upgrading;});}
}
...
// 一些私有方法实现
bool bcskill_contract::is_upgrading(){bool result = false;system_tables system_table(_self, _self.value);auto itr = system_table.begin();if(itr != system_table.end()){result = itr->upgrading;}return result;
}
....// 为action 申明调用
extern "C" {[[noreturn]] void apply(uint64_t receiver, uint64_t code, uint64_t action) {if(code=="eosio.token"_n.value && action=="transfer"_n.value) {execute_action( name(receiver), name(code), &bcskill_contract::transfer);}else if(code==receiver){switch(action){EOSIO_DISPATCH_HELPER( bcskill_contract, (upgrading) //只有添加后,action才能被外部 push actiondefault:eosio_assert(false, "it is not my action"); // 为安全,防止被恶意调用,影响合约响应break;}}eosio_exit(0);}
};

此时合约的基本代码结构已完成

编译合约

进入代码目录执行

eosio-cpp -o bcskill.game.wasm bcskill.game.cpp --abigen

执行完毕后,会生成
bcskill.game.abi 和 bcskill.game.wasm
我们可以简单的理解为 abi 为(.h)头文件,wasm 为dll或so 库.
我们想执行某个账号下的合约时,先会获取这个合约的abi信息,也就是先获取合约内所有的action接口,然后根据所指定的接口在发起交易,执行合约内对应的逻辑.

合约部署

cleos -u https://api.eoslaomao.com  set contract bcskillsurou ../bcskill.game/ -p bcskillsurou

合约执行

cleos -u https://api.eoslaomao.com push action bcskillsurou upgrading '{"upgrading": 1}' -p bcskillsurou

查看链上table

cleos -u https://api.eoslaomao.com get table bcskillsurou bcskillsurou system

类似返回数据如下

{"rows": [{"id": 0,"upgrading": 1,"zero_time": "2019-03-30T16:00:00.000"}],"more": false
}

建议

对于数据类型的选取,编写前,最好专门花时间确定下,避免不必要的RAM浪费或者后面数据溢出.
比如uint8_t 到 uint64_t的选取,如果小于255 就用 uint8_t节约内存
对于一些数据table的划分,最好能实现评估下,如果前端没有全局(_self)查找或排序要求,创建对应合适的scope下,降低find时的消耗.
尽量避免后面做数据迁移.迁移会存在一些人为的操作失误风险,以及期间可能需要暂停dapp,影响用户体验.

EOS智能合约开发-智能合约编写相关推荐

  1. 原 EOS智能合约开发入门

    链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载. EOS智能合约的开发需要使用llvm和abigen来生成abi文件. 为此eos提供了一个 名为eosiocpp的工具. ...

  2. c++ eos智能合约开发_十分钟教你开发EOS智能合约

    EOS环境搭建和启动节点 下面从EOS入门的环境搭建.编译运行一个智能合约.发送一些Aigsen,给大家做一些展示,希望能让非技术人员也有一些收获. 首先下载EOS环境搭建和启动节点.这一步其实还是比 ...

  3. c++ eos智能合约开发_干货|EOS智能合约开发(一)EOS环境搭建和启动节点

    引言 EOS的智能合约采用C++ 编写,因为C++ 的高效性,没有C++ 编程基础的同学可以先学习<Efficient&Elegant:Java程序员入门Cpp>.EOS中用户开发 ...

  4. c++ eos智能合约开发_TrustBase平台智能合约的开发与实现

    2020年11月,TrustBase团队研究并实现了基于Web的波卡智能合约应用平台.鉴于波卡智能合约开发缺少完善易用的开发工具的支持,TrustBase团队自主开发了基于Substrate框架的全新 ...

  5. c++ eos智能合约开发_EOS智能合约开发为何编译成WebAssembly?

    许多人正试图学习如何在EOS上开发智能合约.但是,这些智能合约是由C++编写的,并编译成WebAssembly,这对大多数非c++程序员来说似乎很奇怪.因此,在深入了解EOS之前,最好先学习一些关于W ...

  6. c++ eos智能合约开发_EOS开发完全解析(六):手摸手实现第一个EOS智能合约——Hello EOS...

    一.概述 EOS智能合约由C++编写,所以真正商业开发的时候,肯定是需要全面学习C++语法的,通过最近爆出的越来越多的合约漏洞我们就知道问题的严重性了.可以毫不客气的说,写智能合约要比写以往任何代码都 ...

  7. EOS智能合约开发-开发环境搭建

    我们先尽量简单直白的说下什么是EOS链,资源,智能合约,以及之间的关系. EOS链 我们可以把EOS链想成一个由多台服务器组成的一个计算机云集群{无意突出此链的中心化}.每台服务器(节点)上都部署着一 ...

  8. c++ eos智能合约开发_[EOS智能合约]第二节:用EOS开发一个To-do List小应用

    EOS Asia 本教程原文作者为EOS Asia,亚洲最具技术实力和最国际化的EOS超级节点竞选者.EOS Asia 同时也是EOS Gems和Traffic Exchange Token这两个项目 ...

  9. EOS智能合约开发(四)EOS智能合约部署及调试(附编程示例)

    EOS的智能合约里面有一个action(动作)和transaction(交易)的概念. 对于我们开发以太坊开发者来说,基本上只有transaction的概念.如果我只要执行一种操作,而且是只读操作,就 ...

最新文章

  1. 【Android 逆向】ARM CPU 架构体系 ( ARM 内存模型 | ARM 架构堆的实现 | ARM 架构栈的实现 )
  2. java 应用程序的打包发行
  3. Deep learning chapter16
  4. python stdout stderr 一起输出_python – 使用subprocess.Popen()时,stderr和stdout没有输出
  5. android 编译时解析xml布局,android – 在xml布局中引用build.gradle versionName属性
  6. jQuery里如何使用ajax发送请求
  7. JVM与计算机之间的关系
  8. python精彩编程200例-编程语言入门经典100例【Python版】
  9. BCB中利用剪贴板复制粘贴
  10. 项目范围频繁变更怎么办?
  11. 软件测试交行项目的流程,交通银行流程引擎POC测试报告——IntelliFlow.pdf
  12. AD实用操作(三)- 原理图器件配置参数批量修改
  13. Mac 安装Mactex教程
  14. 开源组件系列(5):数据的序列化(Thrift、Protobuf、Avro)
  15. 编程之美——1.2 中国象棋将帅问题(转)
  16. 德鲁周记13--最小二乘、RANSAC与霍夫变换的区别
  17. Linux九阴真经之摧心掌残卷11(rpm和yum包管理)
  18. Mysql操作联系题
  19. 【2012NOIP普及组】T1. 质因数分解 试题解析
  20. 2022-2028年中国视觉人工智能行业市场现状分析及发展前景展望报告

热门文章

  1. 洛谷P1424小鱼的航程(改进版)【C
  2. 期货有现货支撑(股票,期货,现货)
  3. DCGAN生成二次元头像实战,Anime Faces数据集下载
  4. mysql 索引类型详解
  5. python 如何封装dll_python封装dll的方法
  6. android busybox 路径,Android Install busybox
  7. Python视觉深度学习系列教程 第二卷 第4章 微调网络
  8. js:一百以内质素的求法
  9. linux单个IP地址绑定多个域名详解
  10. eolinker搭建(Linux版)