直接在geth
的控制台通过solc
进行编译部署的示例已经很多了,比如这篇博客,此处不再赘述。
本文主要演示怎样通过truffle部署以太坊智能合约。truffle是一个以太坊智能合约开发框架,它会帮你做很多琐碎的事情,安装使用都很简单
npm install -g truffle
mkdir test
cd test
truffle init #初始化
初如化后test目录下会创建如下的目录和文件
app build contracts migrations test truffle.js
contracts 就是合约存储的目录,默认情况下已经帮你创建好了几个文件, 可以不用管
ConvertLib.sol MetaCoin.sol Migrations.sol
在contracts目录下面新建一个合约 Test.sol,内容如下
pragma solidity ^0.4.2;
contract Test {
function multiply(uint a) returns(uint d) {
return a * 7;
}
}
合约内容很简单,就是输入一个整数,返回 它乘以7的结果
在truffle.js里面添加rpc配置信息,我这里是搭的私有链,添加后配置信息如下(更多配置请参照官方文档)
module.exports = {
build: {
"index.html": "index.html",
"app.js": [
"javascripts/app.js"
],
"app.css": [
"stylesheets/app.css"
],
"images/": "images/"
},
rpc: {
host: "localhost",
port: 8545
},
networks: {
"staging": {
network_id: 999, // custom private network
host:"localhost",
port: 8545
},
}
};
这里只需要发布 Test
这一个合约, 修改migrations/1_initial_migration.js 如下, 并删除 migrations/2_initial_migration.js
module.exports = function(deployer) {
deployer.deploy(Test);
};
打开一个新的终端,打开geth
./geth --identity "newEth" --rpc --rpccorsdomain "*" --datadir "./cdata" --port 30303 --rpcapi "db,eth,net,web3" --networkid 999 console
注意这里的 networkid 和上面的truffle.js 里面的配置要一样,端口号默认是 8545,所以可以不用指定
如果已经有账户了,可以不用再创建,但是要保证账户里面资产不为0 ,否则发布的时候会报错。可以通过挖矿的方式让账户获得奖励。创建账户和挖矿的过程 不再赘述,可以 戳这里解锁账户,很重要,不然后部署合约的时候会报错
personal.unlockAccount('0xa04ab66a12291b53496a60df57aae8eebb6d8398', "123456", 10000)
如上,第二个参数是创建账户时设置的密码,第三个参数是解锁时间,因为是开发环境上自己搭的私有链,可以把时间设的长一点
在编写合约的那个终端下执行 truffle compile
编译,然后再执行 truffle migrate
, 如果没有报错会显示如下
Running migration: 1_initial_migration.js
Deploying Test...
如上,表示正在发布。geth的控制台也会有一条提示信息,如下
> I1202 20:09:46.354075 internal/ethapi/api.go:1045] Tx(0x218db3d2c2665ed3a264139316b9744223df30cac4498539f1be3ac3e6e01317) created: 0xbf6080eaae18a6eb4d9d3b9ef08a8bdf02e3caa8
这个时候合约正在部署,geth 控制台执行 如下
> txpool.status
{
pending: 1,
queued: 0
}
可以看到,有一个交易在等待确认,需要继续挖矿,把交易打包到下一个区块
miner.start()
好了,耐心等待下一个区块被挖出来吧! 成功后部署合约的终端会显示如下
Running migration: 1_initial_migration.js
Deploying Test...
Test: 0xbf6080eaae18a6eb4d9d3b9ef08a8bdf02e3caa8
Saving successful migration to network...
Test 后面那串就是合约被存储的地址
a)、查看abi (abi, application binary interface)vim build/contracts/Test.sol.js
找到下面这段
Contract.all_networks = {
"default": {
"abi": [
{
"constant": false,
"inputs": [
{
"name": "a",
"type": "uint256"
}
],
"name": "multiply",
"outputs": [
{
"name": "d",
"type": "uint256"
}
],
"payable": false,
"type": "function"
}
],
"unlinked_binary": "0x606060405260388060106000396000f3606060405260e060020a6000350463c6888fa18114601c575b6002565b3460025760076004350260408051918252519081900360200190f3",
"events": {},
"updated_at": 1480738754835,
"address": "0xbf6080eaae18a6eb4d9d3b9ef08a8bdf02e3caa8",
"links": {}
}
};
b)、把abi取出来在线压缩, 并在geth终端 赋值给abi变量
> abi = [{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"payable":false,"type":"function"}]
[{
constant: false,
inputs: [{
name: "a",
type: "uint256"
}],
name: "multiply",
outputs: [{
name: "d",
type: "uint256"
}],
payable: false,
type: "function"
}]
c)、创建合约实例
> test = eth.contract(abi).at('0xbf6080eaae18a6eb4d9d3b9ef08a8bdf02e3caa8')
上面的地址就是合约存储的地址d)、调用
> test.multiply.call(3)
21