前段时间Jarvis+在以太坊部署了JAR的智能合约,并为参加活动用户陆续发放JAR。下面由我们的技术人员Michael借本次机会为大家讲解一下,如何快速构建以太坊智能合约。
随着智能经济的逐渐升温,智能合约在智能经济中的中枢作用逐渐显现。智能合约作为智能经济的灵魂,有着不可替代的作用。在以太坊智能经济生态中,智能合约已被构建成以Solidity语言为开发语言,多种集成开发环境支持的,影响深远且功能强大的智能经济中枢。在以太坊智能经济生态中,负责绝大多数的信用转移和传递。
本文将介绍如何利用Truffle Framework和OpenZeppelin-Solidity两个强大的工具快速地开发一个以太坊智能合约。
1. 构建开发环境
Truffle Framework是一个世界级的开发环境。同时拥有智能合约的测试框架和虚拟以太坊资产。使用Truffle 开发环境,会让智能合约的开发变得非常简单。通过Truffle可以实现:
- 内置智能合约编译,链接,部署和二进制管理
- 智能合约测试
- 可编写脚本的可扩展部署和迁移框架
- 用于部署到任意数量的公共和专用网络的网络管理
- 支持ERC 190标准,使用ethPM和NPM进行包管理
- 交互式控制台,用于直接合同通
- 可配置的构建管道,支持紧密集成
- 在Truffle环境中执行脚本的外部脚本运行器
OpenZeppelin-Solidity 是OpenZeppelin 组织使用Solidity 语言开发的一套智能合约基础库。包括了对智能合约的运算、安全智能合约信用体系的构建等基础性的功能。使用这样一套开发库,开发者就不必再从头做起,直接可以实现智能合约的主要功能了。OpenZeppelin-Solidity 保持着持续地更新,不断地完善合约库的功能和安全特性。OpenZeppelin-Solidity 的源代码都是公开的,可以通过https://github.com/OpenZeppelin/openzeppelin-solidity 进行查看。
创建一个以太坊智能合约项目的方法很简单,只需要在Node.js 的支持下运行几个简单的命令。如果还没有安装Node.js,请访问:https://nodejs.org/en/ 安装Node.js。然后在命令行下,通过npm 安装Truffle framework
$ npm install -g truffle
以全局的方式安装好Truffle Framework 之后,再创建项目文件夹:
$ mkdir myFirstContract
$ cd myFirstContract
然后在项目文件夹内,运行truffle 初始化命令,下载项目文件模板。然后,安装OpenZeppelin-Solidity 库
$ truffle init
$ npm init -y
$ npm install -E openzeppelin-solidity
在一系列配置结束之后,就可以使用Visual Studio Code打开项目文件夹了。如果没有安装Visual Studio Code,可以通过http://code.visualstudio.com 来进行下载。打开项目文件夹后,目录内容如下:
1
其中,contract 文件夹用来保存开发的智能合约源代码。文件夹中的Migrations.sol 是Truffle 用来帮助部署Solidity智能合约的辅助代码,请不要随意改动。mirgations 文件夹是用来保存部署、编译和测试合约的JavaScript 脚本代码的文件夹。test文件夹内保存单元测试源代码。Truffle-config.js 和truffle.js 文件是保存Truffle Framework 配置文件信息的,其实两个文件中的内容一样,truffle.js 文件用于macOS 和Linux操作系统。在Windows下,为了避免重名,改用truffle-config.js作为配置文件。
2. 开发一个智能合约
智能合约的开发,可以用Visual Studio Code 来完成。可以先通过Visual Studio Code 在contracts 目录下创建一个Solidity源代码文件MyCalculator.sol。而后,在源代码文件的第一行标注出来期望使用的Solidity 编译器版本。Solidity 规定在每个源代码文件的第一行都要指定一下可以编译源代码的Solidity 编译器的版本。由于Solidity 语言还在持续地改进,这样做是非常有必要的。
pragma solidity ^0.4.24;
然后就是要引用第三方的函数库文件了。其实主要就是OpenZeppelin-Solidity 库的文件。由于去年持续爆出了利用智能合约运算值溢出的漏洞导致的一系列安全风险,OpenZeppelin-Solidity 实现了SafeMath.sol 这个安全运算库。在简单数学运算之后进行数值检查,化解风险。因此,在智能合约运算时应尽量使用这个函数库。开发人员可以通过import 关键字引入这个函数库。
import"../node_modules/openzeppelin-solidity/contracts/math/SafeMath.sol";
在引入了第三方库之后,就可以开始正式地编写智能合约了。Solidity规定,智能合约的关键字是contract,类似于日常编程使用的类声明关键字class。这里仅通过创建一个简单的合约进行展示。
pragma solidity ^0.4.24;
import"../node_modules/openzeppelin-solidity/contracts/math/SafeMath.sol";
contract MyCalculator {
using SafeMath for uint256;
function myAdd(uint256 x, uint256 y) public pure returns(uint256 result)
result = x.add(y);
return result;
}
}
代码中的add 方法通过SafeMath中的安全运算函数add,实现两个无符号大整形数字的加法运算。深挖一下SafeMath中的add方法,可以看到在计算结束后,add函数还对计算结果进行了判断,加法运算溢出之后的结果返回给调用端,避免了黑客利用数据运算上下界溢出来对数字资产进行破坏。
function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
c = _a + _b;
assert(c >= _a);
return c;
}
3. 智能合约的编译和部署
在智能合约编写完成之后,就要开始对智能合约的编译了。能够部署到以太坊上面的智能合约都是编译好的二进制字节流,而不是源代码文件。
Truffle Framework 的Node.js包内已经包含了Solidity编译器。因此,编译智能合约变得非常简单,在Visual Studio Code 中打开终端视图,在终端视图中输入truffle compile 命令,即可完成编译。在Windows 操作系统下,不能直接使用truffle compile命令,因为当前目录下有一个truffle.js 文件,操作系统会默认运行这个JavaScript文件而不是truffle本身。可使用truffle.cmd compile 规避名字冲突。
智能合约的测试的部分功能是可以通过本地完成的。对于相对复杂的操作,比如生成一笔交易,就要进行上链测试了。在这里先介绍如何在本地进行测试的方法。
首先,需要安装以太坊本地模拟器ganache。这个工具可以在本地模拟一个以太坊节点,并且生成十组有效的钱包地址和私钥。安装的方法是通过npm 安装ganache 命令行工具。
$ npm I ganache-cli -g --save
安装结束后,可以通过直接键入ganache-cli 命令运行这个本地模拟器。模拟器会持续侦听本地8545端口来处理请求。
在安装和运行模拟器之后,还要修改一下truffle.js 或者truffle-config.js文件,创建一个本地测试网络配置,以便truffle可以连接到本地8545端口。
module.exports = {
networks: {
development: {
host: 'localhost',
port: 8545,
network_id: '*', // eslint-disable-line camelcase
},
},
solc: {
optimizer: {
enabled: true,
runs: 200
}
}
};
在这一切都就绪之后,还需要编写一些JavaScript代码来实现智能合约的部署。要在migration文件夹中创建一个JavaScript 文件“2_deploy_MyCalc.js”。
在这个JavaScript中添加部署智能合约的脚本内容。
varMyCalc=artifacts.require("./MyCalculator.sol");
module.exports=async function(deployer, network, accounts) {
await deployer.deploy(MyCalc);
const deployedMyCalc = await MyCalc.deployed();
console.log("===============================================");
console.log("address = " + deployedMyCalc.address);
console.log("===============================================");
}
代码中通过artifacts.require 导入智能合约源代码文件。然后使用deployer 对象部署智能合约到以太坊网络上面。
正式部署,需要使用truffle migrate 命令,通过—network 指定truffle.js 文件中预先配置好的网络参数。
当看到生成的智能合约地址时,就代表本次合约部署成功了。
4. 智能合约的测试
配置好本地网络之后,就可以编写测试代码了。智能合约测试代码采用JavaScript 编写,代码需要放置在test 文件夹内。首先创建一个名为MyCalc.test.js 的文件。然后在文件中添加测试代码。
const myCalculator = artifacts.require('MyCalculator');
contract('MyCalculator', function ([_, creator]) {
let myCalc;
beforeEach(async function() {
const myCalc = await myCalculator.new();
});
it('test 56 + 72', async function () {
const sum = await myCalc.myAdd(56, 72);
assert(sum.eq(128));
});
});
在测试代码中,首先导入MyCalculator 智能合约,然后创建一个智能合约对象,最后调用合约对象中的方法对方法返回值进行校验。在Truffle的最新版本中还加入了单步调试的功能。如果有必要,还可以在本地测试链上详细调试每一行智能合约代码。
以上仅仅展示了一个智能合约最简单的步骤。如果需要实现更多的功能,就需要在测试链上进行测试了。链上测试的重点在于对于交易的格式以及交易的数据正确性等等。
目前著名的以太坊测试链主要是:
Ø ropsten(https://ropsten.etherscan.io/)
Ø kovan(https://kovan.etherscan.io/)
Ø rinkeby(https://rinkeby.etherscan.io/)
他们的区别在于共识机制的不同,所幸这些测试网都有区块链浏览器支持,同时又有水管可以自动申请测试ether。下面以kovan为例,看一下如何将智能合约部署到测试网上面。
向测试网部署智能合约,需要安装另外一个组件:truffle-hdwallet-provider
$ npm i truffle-hdwallet-provider –save
在安装完成之后,需要在truffle.js 配置文件中做些修改。要通过infura创建测试网对应的provider对象。
const HDWalletProvider = require('truffle-hdwallet-provider');
const providerWithMnemonic = (mnemonic, rpcEndpoint) =>new HDWalletProvider(mnemonic, rpcEndpoint);
const infuraProvider = network => providerWithMnemonic(process.env.MNEMONIC || '',`https://${network}.infura.io/${process.env.INFURA_API_KEY}`);
const kovanProvider = infuraProvider('kovan');
然后在truffle.js配置文件中加入kovan 测试网的配置项目。
kovan: {
provider: kovanProvider,
//gasPrice: 1000000000,
network_id: 42, // eslint-disable-line camelcase
},
请注意,每个测试网络为了互相区分,他们的network_id 都是不同的。
总结
通过使用Truffle Framework、OpenZeppelin-Solidity 和Visual Studio Code,开发人员可以在几十分钟之内就让自己开发的智能合约部署到以太坊区块链上。快捷、安全和高效率是这套开发组件的显著特点。
感谢大家的阅读,有任何问题可以通过官方渠道联系我们,