MOAC实战 - 9. 合约多文件编译与构造函数传值

前言

去以太坊或者是波场等了解其他的优秀合约,会发现,有很多的合约时多文件的。使用引用的形式去引入一些第三方的库。如何编译多个合约文件,这在本地编译的时候会出现各种路径问题,相关文档的找寻也比较费时费力。

开发一个特有的合约参数,源码和编译后的代码一般都要开源和交付于专门的审计机构进行审计。那么里面配置的地址等初始值不可直接写入到合约内部,我们一般采用构造函数的形式,在合约部署的时候外部提供参数给合约。

针对以上两种不同的情况,本文提供了解决方案。

多文件编译

如上图所示,多文件的引入大多使用 import 关键字。

我们采用线上编译的方式,跳过线下编译的一些坑。

如上图,我们编译合约文件后,发现出现很多的 CONTRACT 。

在这里我们可以把我们需要的 CONTRACT 的 abi 和 bytecode 给复制出来。

如之前文章 合约部署 一文附件中的 ERC20 的合约代码,我们编译成功的应该是一下的文件结构

1
2
3
4
5
6
7
8
9
10
11
TESTDIR
├── ERC20.sol
├── ERC20Detailed.sol
├── ERC20Mintable.sol
├── IERC20.sol
├── MinterRole.sol
├── Roles.sol
├── SafeMath.sol
├── Token.sol
├── Test.abi
├── Test.bytecode

关键点是 Token.sol 引用了别的合约文件,别的合约文件又引用了其他的库文件等。我们只需要编译 Token.sol即可。

如上图,我们先选中,Token 这个 CONTRACT, 然后把 abi 和 bytecode 给复制出来,另存为新的文件即可。

我们可以大致看一下 abi 里面的内容。

我么可以看出来,abi文件中已经达到了 270 行左右,大致读了下,里面声明了很多的 ERC20 的方法。我们编译的代码是全的。

我们只需要拿这个 abi 和 bytecode 去使用即可,多文件合约编译完成了。

合约构造参数部署时传值

像上面的这样的合约,大家如果见过肯定会有疑问,在MOAC链上部署的时候如何向构造参数里面传值?

下面直接用代码来说明

读这些代码前,建议先看前几章,有一些牵连。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 读取合约BYTECODE
const solPath = path.join(__dirname, 'xxx/Token.bytecode');
const solFile = fs.readFileSync(solPath, 'utf8');
const bytecodeJson = JSON.parse(solFile).object;

// 读取ABI
const abiPath = path.join(__dirname, 'xxx/Token.abi');
const abiFile = JSON.parse(fs.readFileSync(abiPath, 'utf8'));


// 构造函数传入参数
const paramsNames = abiFile.find((item) => item.type == "constructor").inputs.map((input) => input.name);
const paramsKeys = abiFile.find((item) => item.type == "constructor").inputs.map((input) => input.type);
const paramsKeyValues = [
'0x3E7F188981bb007CFF261d6E0Fb1A6cedBc4cfAd',
'test',
't',
18,
10000000,
false,
];
const byteParams = chain3.encodeParams(paramsKeys, paramsKeyValues);


const bytecode = "0x"+bytecodeJson+byteParams; // byte类型的

有NodeJs的基础的同学大致可以看出代码很简单。

这里大致解释下。

这里读取了 bytecode 和 abi 两个文件。

分析了 abi 文件中构造函数的地方,把构造函数的 type 取出来当 key(abi 里面用的是数组,数组是有顺序得到),配置上值使用 chain3 的内部方法进行编码。

把参数编码加到了之前得到的 bytecode 后面 构成新的 bytecode。

这块代码很简单, paramsNames 这个参数没有用到,大家可以 console.log() 看一下入参的名字。

后续的步骤和之前的发布合约步骤相同。

参考资料

  • 版权声明: 本博客所有文章,未经许可,任何单位及个人不得做营利性使用!转载请标明出处!如有侵权请联系作者。
  • Copyrights © 2015-2020 翟天野

请我喝杯咖啡吧~