因为官定版本的 solidity 实在编译安装太费力了,放弃,改用 Truffle。

直接用 npm 安装:

1
npm install -g truffle

创建新目录,初始化新目录:

1
2
3
mkdir myproject
cd myproject
truffle init

修改配置文件 truffle.js:

1
2
3
4
5
6
7
8
9
10
 module.exports = {
networks: {
development: {
host: "localhost",
port: 8545,
network_id: "*", // Match any network id
gas: 500000
}
}
};

生成必须的智能合约源码和迁移脚本:

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
55
56
57
58
pragma solidity ^0.4.15;


contract Calc {

/* 合约的创建者,可以在外部调用 owner() 来获取当前合约的创建者 */
address public owner;

/* 区块链存储 */
uint public count;

/* Event 是基于 log 的,写 event 类似于 写 log,外部的观察者通过过滤日志来读取事件 */
event AddEvent(
address contractOwner,
address transactionSender,
uint a,
uint b,
uint256 result
);

// This contract only defines a modifier but does not use
// it - it will be used in derived contracts.
// The function body is inserted where the special symbol
// "_;" in the definition of a modifier appears.
// This means that if the owner calls this function, the
// function is executed and otherwise, an exception is
// thrown.
modifier onlyOwner {
require(msg.sender == owner);
_;
}

/* 构造函数的写法 */
function Calc() public { owner = msg.sender; }

/* 执行会写入数据,所以需要`transaction`的方式执行。 */
function add(uint a, uint b) public onlyOwner returns(uint) {
count++;
uint c = realAdd(a, b);
AddEvent(
//多行的参数只有这样写才没有警告
owner,
msg.sender,
a, b, c
);
return c;
}

/* 只有高版本的编译器才支持 pure 函数,这个 Vscode 插件不支持 */
function realAdd(uint a, uint b) returns (uint) {
return a + b;
}

/* 执行不会写入数据,所以允许`call`的方式执行。 */
function getCount() public onlyOwner constant returns (uint) {
return count;
}
}

迁移脚本

1
2
3
4
var Calc = artifacts.require("./Calc.sol");
module.exports = function(deployer) {
deployer.deploy(Calc);
};

目录下已然有了示例用的 contract 和 migration 文件,接下来:

1
2
3
4
5
6
7
8
9
10
11
truffle compile
truffle migrate --reset
# 或者。这两个命令都会直接导致 compile。
truffle deploy --reset
Deploying Migrations...
... 0x25edbfb37d3fe1f8fc642771e3070c4342723f29f19d2751c482bae957a4d98e
Migrations: 0x194750fba19f4813cc8df2b6f1028290d4e1bd5b
# Migrations 就是合约的类型,后面跟的 0x194750fba19f4813cc8df2b6f1028290d4e1bd5b 就是当前的合约账户。

Saving successful migration to network...
... 0x5d44a65dd1f470c1a38b20f33dcff96a7d3ce27b1dffa1ab474d47a7f33a210a

如果 migrate 失败,可能需要先解锁账户,

1
2
3
4
5
6
7
geth attach http://localhost:8545

#在 geth 实例运行期间永久解锁某个账户
personal.unlockAccount(eth.accounts[0], "123456", 0)

# 或者考虑:
geth --unlock bbb --password 123456

并且把配置文件中的 gas 调高点,不知道还有多少 gas 余额的时候,可以考虑用:

1
eth.getBlock("pending").gasLimit

进入 console:

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
truffle console

#console

truffle(development)> Calc.
Calc.__defineGetter__ Calc.__defineSetter__ Calc.__lookupGetter__ Calc.__lookupSetter__ Calc.__proto__ Calc.constructor Calc.hasOwnProperty Calc.isPrototypeOf Calc.propertyIsEnumerable Calc.toLocaleString
Calc.toString Calc.valueOf

Calc.apply Calc.arguments Calc.bind Calc.call Calc.caller Calc.length Calc.name

Calc._json Calc._properties Calc._property_values Calc._static_methods Calc.abi Calc.addProp Calc.address Calc.ast Calc.at Calc.binary
Calc.bytecode Calc.class_defaults Calc.clone Calc.compiler Calc.contractName Calc.contract_name Calc.currentProvider Calc.defaults Calc.deployed Calc.deployedBinary
Calc.deployedBytecode Calc.deployedSourceMap Calc.detectNetwork Calc.events Calc.hasNetwork Calc.isDeployed Calc.link Calc.links Calc.network Calc.network_id
Calc.networks Calc.new Calc.prototype Calc.resetAddress Calc.schemaVersion Calc.schema_version Calc.setNetwork Calc.setProvider Calc.source Calc.sourceMap
Calc.sourcePath Calc.toJSON Calc.unlinked_binary Calc.updatedAt Calc.updated_at Calc.web3

#合约对象相关的信息

#查看部署的信息
Calc.defaults()

#获取当前抽象实例的信息,除此之外,还有 at(), new()方法用不同的方式来获取其他实例。
Migrations.deployed()

# 因为这个 deployed() 的返回值被 promise 化了,所以一切都应该按照回调来考虑
var a;
# 准备一个可赋值的变量,用 then 来赋值。
Calc.deployed().then(function(instance) { a = instance})

# 生成可复用的 abi 字符串。记得在使用时去掉单引号。
JSON.stringify(a.abi)

a.owner();

# 返回一个事务对象

truffle(development)> a.realAdd(11, 2)
{ tx: '0xcd5e32ee51a3289272660ad154e7057d25b972f65633d6c8bbe64ba9795ee062',
receipt:
{ blockHash: '0x6e1960bab1b3cb3f3f0b877a799f3561c23c2345d129efca339d8e3bdc9f6ca7',
blockNumber: 15886,
contractAddress: null,
cumulativeGasUsed: 22009,
from: 'bbb',
gasUsed: 22009,
logs: [],
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
root: '0x2f405095a81a2a59dc2ba47a37e21d4f1ef839d64fe92c00c9bc18e2af7f1898',
to: '0x50361da49a229247381c8d920853aa5560f8608c',
transactionHash: '0xcd5e32ee51a3289272660ad154e7057d25b972f65633d6c8bbe64ba9795ee062',
transactionIndex: 0 },
logs: [] }
truffle(development)> { tx: '0xf493659cbbc3202236e8876fe8b2908760c9393fcdbcafe6d33c0a3e78220493',
receipt:
{ blockHash: '0x6e1960bab1b3cb3f3f0b877a799f3561c23c2345d129efca339d8e3bdc9f6ca7',
blockNumber: 15886,
contractAddress: null,
cumulativeGasUsed: 44018,
from: 'bbb',
gasUsed: 22009,
logs: [],
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
root: '0x4b437a56092089c92564ca3255555b306ca0ab703b460287aa05ff79e12daeb1',
to: '0x50361da49a229247381c8d920853aa5560f8608c',
transactionHash: '0xf493659cbbc3202236e8876fe8b2908760c9393fcdbcafe6d33c0a3e78220493',
transactionIndex: 1 },
logs: [] }

# 直接用 call 调用

a.realAdd.call(11, 2)
BigNumber { s: 1, e: 1, c: [ 13 ] }

a.add.call(1, 2)
BigNumber { s: 1, e: 0, c: [ 3 ] }

# 事务调用
a.add.sendTransaction(1, 2, {from: 'bbb'})

# 查看预估的 gas 消耗
a.add.estimateGas()

退出 console:

1
.exit

使用来查看所有通过 Truffle 部署的代码:

1
truffle network