技术指南 | 手把手教你Wasm合约开发:(C++篇)
一、Hello World
#include<ontiolib/ontio.hpp>#include<stdio.h> using namespace ontio;class hello:public contract { public: using contract::contract: void sayHello(){ printf("hello world!"); } }; ONTIO_DISPATCH(hello, (sayHello));
1.1 合约入口
ONTIO_DISPATCH(hello, (sayHello));
printf("hello world!");这个“Hello world!”会在节点的日志中以调试信息打印出来。在实际的应用中, printf 只能用作调试的目的, 一个实际的智能合约,需要实现更多更复杂的功能。
1.2 智能合约 API
二、红包合约
很多情况下我们都会通过各种 App,如微信等聊天工具发红包。我们可以给朋友发送红包,也可以抢其他人发送的红包,收到的钱会记入到个人微信账户中。
类似于微信的流程,我们将尝试创建一个智能合约。用户使用该合约,可以发送 ONT,ONG 或者是标准的 OEP-4的 Token 资产红包给他的朋友们,而朋友们抢到的红包可以直接转入到他们的钱包账户中。
2.1 创建合约
- createRedEnvelope: 创建红包
- queryEnvelope: 查询红包信息
- claimEnvelope: 抢红包
#include<ontiolib/ontio.hpp> using namespace ontio; class redEnvelope: public contract{ } ONTIO_DISPATCH(redEnvelope, (createRedEnvelope)(queryEnvelope)(claimEnvelope))
std::string rePrefix = "RE_PREFIX_"; std::string sentPrefix = "SENT_COUNT_"; std::string claimPrefix = "CLAIM_PREFIX_";
address ONTAddress = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; address ONGAddress = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2};
struct receiveRecord{ address account; //用户地址 asset amount; //抢到的金额 ONTLIB_SERIALIZE(receiveRecord,(account)(amount)) }; struct EnvelopeStruct{ address tokenAddress; //资产token的地址 asset totalAmount; //红包总金额 asset totalPackageCount; //红包总数 asset remainAmount; //当前剩余的金额 asset remainPackageCount; //当前剩余的红包数 std::vector<struct receiveRecord> records; //已经抢完的记录 ONTLIB_SERIALIZE( EnvelopeStruct, (tokenAddress)(totalAmount)(totalPackageCount)(remainAmount)(remainPackageCount)(records) ) };
ONTLIB_SERIALIZE(receiveRecord,(account)(amount))
2.2 创建红包
bool createRedEnvelope(address owner,asset packcount, asset amount,address tokenAddr ){ return true; }
ontio_assert(check_witness(owner),"checkwitness failed");
if (isONTToken(tokenAddr)){ ontio_assert(amount >= packcount,"ont amount should greater than packcount"); }
key sentkey = make_key(sentPrefix,owner.tohexstring()); asset sentcount = 0; storage_get(sentkey,sentcount); sentcount += 1; storage_put(sentkey,sentcount);
H256 hash ; hash256(make_key(owner,sentcount),hash) ; key rekey = make_key(rePrefix,hash256ToHexstring(hash));
address selfaddr = self_address(); if (isONTToken(tokenAddr)){ bool result = ont::transfer(owner,selfaddr ,amount); ontio_assert(result,"transfer native token failed!"); }else if (isONGToken(tokenAddr)){ bool result = ong::transfer(owner,selfaddr ,amount); ontio_assert(result,"transfer native token failed!"); }else{ std::vector<char> params = pack(std::string("transfer"),owner,selfaddr,amount); bool res; call_contract(tokenAddr,params, res ); ontio_assert(res,"transfer oep4 token failed!"); }
NOTE 2:和普通的钱包地址一样, 合约地址也可以接受任意类型的资产。但是合约地址是由合约编译后的二进制代码 hash 产生的,所以没有对应的私钥,也就无法随意操作合约中的资产,如果你没有在合约中设置对资产的操作,就意味着你将无法控制这部分资产。
7. 将合约的信息保存在存储中:
struct EnvelopeStruct es ; es.tokenAddress = tokenAddr; es.totalAmount = amount; es.totalPackageCount = packcount; es.remainAmount = amount; es.remainPackageCount = packcount; es.records = {}; storage_put(rekey, es);
char buffer [100]; sprintf(buffer, "{\"states\":[\"%s\", \"%s\", \"%s\"]}","createEnvelope",owner.tohexstring().c_str(),hash256ToHexstring(hash).c_str()); notify(buffer); return true;
2.3 查询红包
std::string queryEnvelope(std::string hash){ key rekey = make_key(rePrefix, hash); struct EnvelopeStruct es; storage_get(rekey, es); return formatEnvelope(es); }
2.4 领取红包
1. 领取红包需要输入领取人的账户和红包的hash:
bool claimEnvelope(address account, std::string hash){ return true; }
ontio_assert(check_witness(account),"checkwitness failed"); key claimkey = make_key(claimPrefix,hash,account); asset claimed = 0 ; storage_get(claimkey,claimed); ontio_assert(claimed == 0,"you have claimed this Envelope!");
key rekey = make_key(rePrefix,hash); struct EnvelopeStruct es; storage_get(rekey,es); ontio_assert(es.remainAmount > 0, "the Envelope has been claimed over!"); ontio_assert(es.remainPackageCount > 0, "the Envelope has been claimed over!");
struct receiveRecord record ; record.account = account; asset claimAmount = 0;
if (es.remainPackageCount == 1){ claimAmount = es.remainAmount; record.amount = claimAmount; }else{ H256 random = current_blockhash() ; char part[8]; memcpy(part,&random,8); uint64_t random_num = *(uint64_t*)part; uint32_t percent = random_num % 100 + 1; claimAmount = es.remainAmount * percent / 100; //ont case if (claimAmount == 0){ claimAmount = 1; }else if(isONTToken(es.tokenAddress)){ if ( (es.remainAmount - claimAmount) < (es.remainPackageCount - 1)){ claimAmount = es.remainAmount - es.remainPackageCount + 1; } } record.amount = claimAmount; } es.remainAmount -= claimAmount; es.remainPackageCount -= 1; es.records.push_back(record);
address selfaddr = self_address(); if (isONTToken(es.tokenAddress)){ bool result = ont::transfer(selfaddr,account ,claimAmount); ontio_assert(result,"transfer ont token failed!"); } else if (isONGToken(es.tokenAddress)){ bool result = ong::transfer(selfaddr,account ,claimAmount); ontio_assert(result,"transfer ong token failed!"); } else{ std::vector<char> params = pack(std::string("transfer"),selfaddr,account,claimAmount); bool res = false; call_contract(es.tokenAddress,params, res ); ontio_assert(res,"transfer oep4 token failed!"); }
storage_put(claimkey,claimAmount); storage_put(rekey,es); char buffer [100]; std::sprintf(buffer, "{\"states\":[\"%s\",\"%s\",\"%s\",\"%lld\"]}","claimEnvelope",hash.c_str(),account.tohexstring().c_str(),claimAmount); notify(buffer); return true;
2.5 合约测试
- 使用 CLI
请参考:https://github.com/ontio/ontology-wasm-cdt-cpp/blob/master/How_To_Run_ontologywasm_node.md
- 使用 Golang SDK
请参考:https://github.com/ontio/ontology-wasm-cdt-cpp/blob/master/example/other/main.go
三、总结
我们欢迎更多的 Wasm 技术爱好者加入本体开发社区,共同打造技术生态。
免责声明:
1.本文内容综合整理自互联网,观点仅代表作者本人,不代表本站立场。
2.资讯内容不构成投资建议,投资者应独立决策并自行承担风险。
- 贝佐斯最后一封股东信:宇宙希望你成为普通人,千万别让它成为现实2021-04-19 17:02
- Props,让互联网与区块链无缝对接的「中间件」2021-04-19 17:02
- Coinbase高管到底卖了多少股票?2021-04-19 16:03
- 通往未来之路:下一代互联网与Metaverse2021-04-19 16:03
- 央行前行长周小川谈比特币:要提醒,要小心2021-04-19 15:03
- 链上新知 |电子图片卖出7000万美金,让马斯克都来站台的NFT究竟是什么?2021-04-19 15:02
- Crypto VC,LP怎么投?2021-04-19 13:03
- 周末比特币融资利率跌至-0.03%低点,为7个月以来最低水平2021-04-19 11:02