咸鱼

咸鱼是以盐腌渍后,晒干的鱼

0%

6.0、基于truffle部署HelloWorld合约到私链

后来发现 文档翻译系列-Truffle框架 文章,摘录:

Truffle是针对基于以太坊的Solidity语言的一套开发框架。本身基于Javascript。

Truffle官方文档-英文
Truffle官方文档-中文版
Truffle中文文档-深入浅出区块链

依赖环境

  • nodejs
  • npm

启动 ganache-cli 或者 ganache-gui

1
2
#本文采用 cli
$ ganache-cli

安装truffle环境

1
2
$ npm install -g solc-js
$ npm install -g truffle

指定版本

1
2
$ npm install -g solc-js@0.5.0
$ npm install -g truffle@5.0.24

** 注意:在Ubuntu下安装truffle** ,很容易出现 Error: EACCES: permission denied,怎么修改文件的目录权限都不行,这个是npm的错误,可以增加以下参数执行:

1
$ sudo npm install -g truffle@5.0.24 --unsafe-perm=true --allow-root
1
2
3
4
$ truffle version
Truffle v5.0.24 (core: 5.0.24)
Solidity v0.5.0 (solc-js)
Node v8.10.0

初始化项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ mkdir demo
$ cd demo
$ truffle init
Downloading...
Unpacking...
Setting up...
Unbox successful. Sweet!

Commands:
Compile: truffle compile
Migrate: truffle migrate
Test contracts: truffle test

$ tree
.
├── contracts
│   └── Migrations.sol
├── migrations
│   └── 1_initial_migration.js
├── test
├── truffle-config.js
└── truffle.js

3 directories, 4 files

配置

配置使用本地的 ganache-cli 测试网络

truffle.js

1
2
3
4
5
6
7
8
9
10
module.exports = {
networks: {
development: {
host: 'localhost',
port: '8545', //cli默认端口是8545,gui默认7545
network_id: '*' // Match any network id
}
}
};

可以配置多个网络

编写合约代码

Hello.sol

1
2
3
4
5
6
7
8
9
10
11
pragma solidity ^0.4.17;

contract Hello{

function sayhello() public constant returns (string name){
return ("Hello World");
}
function add(uint a,uint b) public returns (uint c){
return a + b;
}
}

1_initial_migration.js 配置编译部署合约

1
2
3
4
5
6
7
8
9
10
var Migrations = artifacts.require("./Migrations.sol");

var Hello = artifacts.require("./Hello.sol");


module.exports = function(deployer) {
deployer.deploy(Migrations);
deployer.deploy(Hello);
};

编译和部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ truffle compile
$ truffle migrate

Using network 'development'.

Running migration: 1_initial_migration.js
Deploying Migrations...
... 0x430463c5f02367d3c00a0eb3facab3be1578aadcb770858e0ce767818fb6485a
Migrations: 0xcb5f27c8d6f01dba2fef4444b0b838aa8af5288a
Deploying Hello...
... 0xf9316b965d67db613c6c85fff4cfa647701db396648ef3a1f9ce76b4c05c7b7e
Hello: 0x13369cf35bb4b60bb1bbd35f4413729d56490a6d
Saving successful migration to network...
... 0x5af709894fad67a85f766f8ec61ad6377d4c62cd5c058b4e49d201d3b59fadaa
Saving artifacts...

ganache-cli 控制台的log(发生了2笔交易。):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
eth_sendTransaction

Transaction: 0xf9316b965d67db613c6c85fff4cfa647701db396648ef3a1f9ce76b4c05c7b7e
Contract created: 0x13369cf35bb4b60bb1bbd35f4413729d56490a6d
Gas usage: 162663
Block Number: 7
Block Time: Tue May 15 2018 17:32:11 GMT+0800 (中国标准时间)

eth_newBlockFilter
eth_getFilterChanges
eth_getTransactionReceipt
eth_getCode
eth_uninstallFilter
eth_sendTransaction

Transaction: 0x5af709894fad67a85f766f8ec61ad6377d4c62cd5c058b4e49d201d3b59fadaa
Gas usage: 42008
Block Number: 8
Block Time: Tue May 15 2018 17:32:11 GMT+0800 (中国标准时间)

eth_getTransactionReceipt

成功之后,build/contracts目录下都是json文件,它就是合约的元数据,我们要与合约进行交互就是用到其中的abi和address。

修改合约

编译过的合约,如果版本没变,不会再次migrate,所以修改合约代码要重新 migrate。

truffle migrate --reset

测试

1
2
3
$ truffle test
Using network 'development'.
0 passing (1ms)

ganache-cli 控制台的log:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  Transaction: 0xd72b2538ee2e7770a7d3695cc233908c16d0eb9c96be9aab69d31a837238d4f6
Contract created: 0xbf3f89e5e3635467a899f86b532ba8d4329a9d5a
Gas usage: 277462
Block Number: 4
Block Time: Tue May 15 2018 16:24:06 GMT+0800 (中国标准时间)

eth_newBlockFilter
eth_getFilterChanges
eth_getTransactionReceipt
eth_getCode
eth_uninstallFilter
eth_sendTransaction

Transaction: 0xcf3ed3d31914eb20ba731646abe4b6c025316332aa487924922fad1eee9b52c3
Gas usage: 42008
Block Number: 5
Block Time: Tue May 15 2018 16:24:06 GMT+0800 (中国标准时间)

用truffle控制台与合约函数交互

合约部署好了,就用使用它,调用他的函数
以下操作参考了这篇文章

1
Hello.deployed().then(instance => contract = instance)

Hello.deployed().then 语句来取得 Hello 合约的 Instance (实例),并存到 contract 变量中,以方便后续的调用。

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
$ truffle console

truffle(development)> Hello.deployed().then(instance => contract = instance)

...
...
很多打印
...
...
truffle(development)> contract.sayhello()

'Hello World'

truffle(development)>
truffle(development)> contract.add(1,44)

{ tx: '0x00724f11eaafd9eaa52315fb752aa935e75bad6c6a9ea654449874036dee23fc',
receipt:
{ transactionHash: '0x00724f11eaafd9eaa52315fb752aa935e75bad6c6a9ea654449874036dee23fc',
transactionIndex: 0,
blockHash: '0x31025dac9c6dc90aa1559e37002b174b15e86301cdab64607ba4f55e32234b7a',
blockNumber: 10,
gasUsed: 21976,
cumulativeGasUsed: 21976,
contractAddress: null,
logs: [],
status: '0x01',
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' },
logs: [] }

通常来说,写数据被称作交易(transaction),读数据被称作调用(call)

  • sayhello() 方法返回字符,不需要 gas(call) 。
  • add() 方法会改变数据在区块链上的状态,需要花费 gas (transaction);

扩展

官方的示例项目:宠物商店
官方的示例项目:宠物商店(中文翻译)
官方的示例项目:宠物商店(中文翻译:旧)