IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 区块链 -> 本体技术视点 | 关于本体EVM合约开发,你必须知道的事(三) -> 正文阅读

[区块链]本体技术视点 | 关于本体EVM合约开发,你必须知道的事(三)

图片

上周,本体宣布支持 EVM 的测试网正式部署并向全球开发者开放 EVM 兼容公测。同时,与知名代码审计机构慢雾科技合作发布《本体安全漏洞与威胁情报赏金计划》(https://slowmist.io/en/ontology/)正式启动,上报单个有效漏洞奖励最高可达12,000美金。

图片

上一期,我们介绍了在本体上开发和部署 EVM 合约的工具,以及如何使用 MetaMask 插件数据客户端来管理以太坊数据客户端。这一期,我们将为您带来本体 EVM 合约开发流程演示。

第四部分 EVM 合约开发流程演示

下面我们将使用 Hardhat 工具来演示在本体网络中开发部署和测试 EVM 合约的完整流程。

4.1 环境准备

  • 安装 nodejs(https://nodejs.org/en/

  • 安装 Hardhat(https://hardhat.org/getting-started/

4.2 合约设计

4.2.1 合约逻辑

我们将以一个红包合约为例,该合约主要提供以下功能:

  • 发红包

  • 领红包

每次发红包需要指定红包金额和该红包数量。

例如,红包总金额是100个通证,红包的数量是10,即有10个不同的地址领取红包。为了简单起见,我们设置每个红包金额相等, 也就是每个地址可以领10个通证。

根据以上的逻辑我们可以设置如下的存储结构:

EIP20Interface public Token; // support Token address
uint public nextPacketId; // the next redpacket ID

// packetId -> Packet, store all the redpacket
mapping(uint => Packet) public packets;

//packetId -> address -> bool,? store receive redpacket record
mapping(uint => mapping(address => bool)) public receiveRecords;

struct Packet {
? ? uint[] assetAmounts;// Number of Tokens per copy
? ? uint receivedIndex; // Number of red packets received
}

4.2.2 定义合约事件

在合约执行的过程中,我们可以通过添加事件来追溯合约执行流程。

在本例中我们设计以下两个事件:

  • 发红包时,合约会生成红包的 ID,该 ID 要通过事件推送给调用者

  • 领取红包时,需要推送一个事件用来记录领取的红包 ID 和 Token 数量

event SendRedPacket(uint packetId, uint amount);
event ReceiveRedPacket(uint packetId, uint amount);

4.2.3 定义函数

sendRedPacket

1. 发红包。任何人都可以调用该接口,将一定量的通证打给该合约地址,从而其他的地址可以从该合约地址领取红包。

注意:?在调用该方法之前,需要先授权该合约地址能够从用户的地址把通证转移走,所以需要先调用该通证的 approve 方法。

function sendRedPacket(uint amount, uint packetNum) public payable returns (uint) {
? ? require(amount >= packetNum, "amount >= packetNum");
? ? require(packetNum > 0 && packetNum < 100, "packetNum>0 && packetNum < 100");
? ? uint before = Token.universalBalanceOf(address(this));
? ? Token.universalTransferFrom(address(msg.sender), address(this), amount);
? ? uint afterValue = Token.universalBalanceOf(address(this));
? ? uint delta = afterValue - before;
? ? uint id = nextPacketId;
? ? uint[] memory assetAmounts = new uint[](packetNum);
? ? for (uint i = 0; i < packetNum; i++) {
? ? ? ? assetAmounts[i] = delta / packetNum;
? ? }
? ? packets[id] = Packet({assetAmounts : assetAmounts, receivedIndex : 0});
? ? nextPacketId = id + 1;
? ? emit SendRedPacket(id, amount);
? ? return id;
}

? receivePacket

2. 领取红包。任何地址都可以通过调用该接口领取红包,调用该接口的时候需要指定红包的 ID,即指定要领取的红包。

function receivePacket(uint packetId) public payable returns (bool) {
? ? require(packetId < nextPacketId, "not the redpacket");
? ? Packet memory p = packets[packetId];
? ? if (p.assetAmounts.length < 1) {
? ? ? ? return false;
? ? }
? ? require(p.receivedIndex < p.assetAmounts.length - 1, "It's over");
? ? require(receiveRecords[packetId][address(msg.sender)] == false, "has received");
? ? p.receivedIndex = p.receivedIndex + 1;
? ? bool res = Token.universalTransfer(msg.sender, p.assetAmounts[p.receivedIndex]);
? ? require(res, "Token transfer failed");
? ? packets[packetId] = p;
? ? receiveRecords[packetId][address(msg.sender)] == true;
? ? emit ReceiveRedPacket(packetId, p.assetAmounts[p.receivedIndex]);
? ? return true;
}

合约完整的代码请参考此链接:(https://github.com/ontio/ontology/tree/master/docs/specifications/evm_refernce/contract-demo/hardhatdemo/contracts)。

4.3 使用 Hardhat 编译和测试合约

4.3.1 创建 Hardhat 项目

mkdir hardhatdemo
cd hardhatdemo
npm init
npm install --save-dev hardhat
npx hardhat

4.3.2 修改 hardhat.config.js 文件

? 添加测试网节点配置信息

module.exports = {

? ? defaultNetwork: "ontology_testnet",

? ? networks: {

? ? ? ? hardhat: {},

? ? ? ? ontology_testnet: {

? ? ? ? ? ? url: "http://polaris2.ont.io:20339",

? ? ? ? ? ? chainId: 5851,

? ? ? ? ? ? gasPrice:500,

? ? ? ? ? ? gas:2000000,

? ? ? ? ? ? timeout:10000000,

? ? ? ? ? ? accounts: ["用户私钥1",

? ? ? ? ? ? "用户私钥2"]

? ? ? ? }

? ? },

? ? solidity: {

? ? ? ? version: "0.8.0",

? ? ? ? settings: {

? ? ? ? ? ? optimizer: {

? ? ? ? ? ? ? ? enabled: true,

? ? ? ? ? ? ? ? runs: 200

? ? ? ? ? ? }

? ? ? ? }

? ? },

};

accounts 字段指定的私钥数组,对应的地址需要有测试网的 ONG 来支付交易的手续费,可以在这里(https://developer.ont.io/)领取测试网 ONG。

4.3.3 文件准备

把红包合约代码文件放到 contracts 文件夹下,为了支持 ERC-20?数字资产的转账,我们还需要 EIP20Interface.sol,UniversalERC20.sol 和 TokenDemo.sol 文件,可以从此处(https://github.com/ontio/ontology/tree/master/docs/specifications/evm_refernce/contract-demo/hardhatdemo)下载相关文件。

4.3.4 在 test 文件夹下添加测试代码

describe("RedPacket", function () {

? ? let TokenDemo, redPacket, owner, acct1, assetAmount, packetAmount;
? ? beforeEach(async function () {
? ? ? ? const TokenDemo = await ethers.getContractFactory("TokenDemo");
? ? ? ? TokenDemo = await TokenDemo.deploy(10000000, "L Token", 18, "LT");
? ? ? ? await TokenDemo.deployed();
? ? ? ? const RedPacket = await ethers.getContractFactory("RedPacket");
? ? ? ? redPacket = await RedPacket.deploy(TokenDemo.address);
? ? ? ? await redPacket.deployed();
? ? ? ? [owner, acct1] = await ethers.getSigners();
? ? ? ? assetAmount = 1000;
? ? ? ? packetAmount = 10;
? ? });
? ? it("Token", async function () {
? ? ? ? expect(await redPacket.Token()).to.equal(TokenDemo.address);
? ? });
? ? it("sendRedPacket", async function () {
? ? ? ? const approveTx = await TokenDemo.approve(redPacket.address, assetAmount);
? ? ? ? await approveTx.wait();

? ? ? ? const sendRedPacketTx = await redPacket.sendRedPacket(assetAmount, packetAmount);
? ? ? ? await sendRedPacketTx.wait();
? ? ? ? let balance = await TokenDemo.balanceOf(redPacket.address);
? ? ? ? expect(balance.toString()).to.equal(assetAmount.toString());

? ? ? ? res = await redPacket.nextPacketId();
? ? ? ? expect(res.toString()).to.equal("1");

? ? ? ? await redPacket.connect(acct1).receivePacket(0);
? ? ? ? balance = await TokenDemo.balanceOf(acct1.address);
? ? ? ? expect(balance.toString()).to.equal((assetAmount / packetAmount).toString());
? ? });
});

4.3.5 编译合约

在项目根目录执行如下命令编译合约

$ npx hardhat compile
Compiling 5 files with 0.8.0
Compilation finished successfully

该命令执行完成后会生成如下的文件夹

├── artifacts
├── cache
├── contracts
├── hardhat.config.js
├── node_modules
├── package-lock.json
├── package.json
├── scripts
└── test

4.3.6 测试合约

$ npx hardhat test

执行结果如下

?

$ npx hardhat test
? RedPacket
? ? ? Token
? ? ? sendRedPacket (16159ms)


? 2 passing (41s)

以上便是本体 EVM 合约开发的完整演示流程,希望我们提供的教程能够帮助到您。下期,我们将为您提供 Web3 API 参考,并教您如何使用 Ontology Bridge 本体跨链桥实现本体数字资产与以太坊数字资产的一键互跨,敬请期待。

如有任何问题,可通过 research@ont.io 联络我们。

添加本体小姐姐微信(ontology_2020)并备注【技术】可进行技术探讨或加入社群。

图片

  区块链 最新文章
盘点具备盈利潜力的几大加密板块,以及潜在
阅读笔记|让区块空间成为商品,打造Web3云
区块链1.0-比特币的数据结构
Team Finance被黑分析|黑客自建Token“瞒天
区块链≠绿色?波卡或成 Web3“生态环保”标
期货从入门到高深之手动交易系列D1课
以太坊基础---区块验证
进入以太坊合并的五个数字
经典同态加密算法Paillier解读 - 原理、实现
IPFS/Filecoin学习知识科普(四)
上一篇文章      下一篇文章      查看所有文章
加:2021-09-18 10:11:36  更:2021-09-18 10:11:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 4:31:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计