web3.js编译Solidity,发布,调用全部流程

根据 web3.js编译Solidity,发布,调用全部流程(手把手教程)进行。因为这篇文章中的一些方法和最新版本的不一样了,中间遇到了一些坑,现把解决方法记录如下:

准备工作

安装 Node.js 、安装以太节点以及合约代码等与web3.js编译Solidity,发布,调用全部流程(手把手教程)中的一致。

  • 安装好的NodeJs版本为:v10.15.3
  • 安装好的以太节点版本为:ethereumjs-testrpc@6.0.3

遇到的坑

第一个坑:Solidity安装

按照官方文档使用 npm install -g solc 安装。

安装后验证版本应该使用 solcjs --version ,而不是 solc --version 。而且这边安装的是最新版本,也为后面的步骤埋下了坑。

第二个坑:TypeError: Cannot read property ‘solidity’ of undefined

使用以下代码:

1
2
let source = "pragma solidity ^0.4.0;contract Calc{ /*区块链存储*/ uint count; /*执行会写入数据,所以需要`transaction`的方式执行。*/ function add(uint a, uint b) returns(uint){ count++; return a + b; } /*执行不会写入数据,所以允许`call`的方式执行。*/ function getCount() returns (uint){ return count; }}";
let calc = web3.eth.compile.solidity(source);

运行的时候报:

1
2
3
4
5
6
7
8
9
10
11
12
13
let calc = web3.eth.compile.solidity(source);
^
TypeError: Cannot read property 'solidity' of undefined
at Object.<anonymous> (/data/eth-contract/src/index.js:15:29)
at Module._compile (internal/modules/cjs/loader.js:701:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
at Module.load (internal/modules/cjs/loader.js:600:32)
at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
at Function.Module._load (internal/modules/cjs/loader.js:531:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:754:12)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)

这个是因为 Geth 在 1.5.9 版本以后就不支持此功能。见:Ethereum Dapp初心者之路(7): web3.eth.compile.solidity()替代方案

所以参考 https://ethereum.stackexchange.com/questions/6346/solc-version-command-not-found 文章,将代码改为:

1
2
3
4
const fs = require("fs");
const solc = require('solc');
let source = fs.readFileSync('Calc.sol', 'UTF-8');
let compilationData = solc.compile(source);

第三个坑:编译报错

编译的时候,如果遇到以下报错:

1
{"errors":[{"component":"general","formattedMessage":"* Line 1, Column 1\n Syntax error: value, object or array expected.\n* Line 1, Column 2\n Extra non-whitespace after JSON value.\n","message":"* Line 1, Column 1\n Syntax error: value, object or array expected.\n* Line 1, Column 2\n Extra non-whitespace after JSON value.\n","severity":"error","type":"JSONError"}]}

这个是因为 solc 的版本不对,我们的代码中的版本是 ^0.4.0 ,而安装的 solc 的版本为 ^0.5.7 。应该用一样的版本。

代码中的版本改为^0.5.7,即pragma solidity ^0.5.7;。运行后,报:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
assert.js:350
throw err;
^
AssertionError [ERR_ASSERTION]: Invalid callback specified.
at wrapCallback (/data/eth-contract/node_modules/solc/wrapper.js:16:5)
at runWithReadCallback (/data/eth-contract/node_modules/solc/wrapper.js:42:26)
at compileStandard (/data/eth-contract/node_modules/solc/wrapper.js:83:14)
at Object.compileStandardWrapper (/data/eth-contract/node_modules/solc/wrapper.js:90:14)
at Object.<anonymous> (/data/eth-contract/src/index.js:8:28)
at Module._compile (internal/modules/cjs/loader.js:701:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
at Module.load (internal/modules/cjs/loader.js:600:32)
at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
at Function.Module._load (internal/modules/cjs/loader.js:531:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:754:12)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)

参考 https://stackoverflow.com/questions/53353167/npm-solc-assertionerror-err-assertion-invalid-callback-specified 后,如下操作:

1
2
3
npm uninstall -g solc
npm uninstall solc
npm install solc@0.4.25

然后将代码中的版本号改为:pragma solidity ^0.4.25;

完整源码

index.js:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
const Web3 = require('web3');
const fs = require("fs");
const solc = require('solc');
let web3;
if (typeof web3 !== 'undefined') {
web3 = new Web3(web3.currentProvider);
} else {
// set the provider you want from Web3.providers
web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}
//编译合约
let source = fs.readFileSync('Calc.sol', 'UTF-8').toString();
let calcCompiled = solc.compile(source);
//得到合约对象
let jsonInterface = calcCompiled['contracts'][':Calc']['interface'];
//获得abi
let abi = JSON.parse(jsonInterface);
//获取合约的代码
let bytecode = calcCompiled['contracts'][':Calc']['bytecode']
//得到合约对象
const calcContract = new web3.eth.Contract(abi,null,{
data: '0x'+bytecode,
defaultGas:'4700000'
});
//部署者的地址,当前取默认账户的第一个地址
let deployeAddr = web3.eth.accounts[0];
//部署合约
calcContract.deploy().send({
from: deployeAddr
})
.on('error', (error) => {
console.error(error)
})
.on('transactionHash', (transactionHash) => {
console.log("transactionHash :" + transactionHash)
})
.on('receipt', (receipt) => {
console.log("receipt:")
console.log(receipt)
})
.on('confirmation', (confirmationNumber, receipt) => {
console.log("confirmationNumber:"+confirmationNumber)
}).then((newContractInstance) => {
console.log(newContractInstance)
console.log(newContractInstance.options.address) // instance with the new contract address
});

Calc.sol:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pragma solidity ^0.4.25;
contract Calc{
/*区块链存储*/
uint count;
/*执行会写入数据,所以需要`transaction`的方式执行。*/
function add(uint a, uint b) returns(uint){
count++;
return a + b;
}
/*执行不会写入数据,所以允许`call`的方式执行。*/
function getCount() constant returns (uint){
return count;
}
}

package.json:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"name": "eth-contract",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"solc": "^0.4.25",
"web3": "^1.0.0-beta.52"
}
}

参考