1. 安装 solc 环境
在Ubuntu下安装solc:
$ sudo apt-get install -y software-properties-common
$ sudo add-apt-repository -y ppa:ethereum/ethereum
$ sudo apt-get update
$ sudo apt-get install -y solc
安装完成后,用如下命令查看solc是否安装好:
$ solc --version
2. 编译智能合约
测试代码(Storage.sol):
pragma solidity ^0.4.10;
contract Storage {
uint256 storedData;
function set(uint256 data) public {
storedData = data;
}
function get() public constant returns (uint256) {
return storedData;
}
}
编译:
echo "var storageOutput=`solc --optimize --combined-json abi,bin,interface Storage.sol`" > storage.js
编译后赋值给你了变量 storageOutput。
查看编译结果文件(storage.js)内容:
var storageOutput = {
"contracts": {
"Storage.sol:Storage": {
"abi": "[{\"constant\":false,\"inputs\":[{\"name\":\"data\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]",
"bin": "608060405234801561001057600080fd5b5060bf8061001f6000396000f30060806040526004361060485763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166360fe47b18114604d5780636d4ce63c146064575b600080fd5b348015605857600080fd5b5060626004356088565b005b348015606f57600080fd5b506076608d565b60408051918252519081900360200190f35b600055565b600054905600a165627a7a723058208157aff69edee57dc9d12d47289d96cfe21fa1e318d916bf9bf3d85da0e5d0ff0029"
}
},
"version": "0.4.24+commit.e67f0147.Linux.g++"
}
其中有2个主要部分:
- abi
ABI(Application Binary Interface)为合约的接口说明,当合约被编译后,那么它的接口就确定了。
- bin
合约被编译后的二进制内容。
3. 发布
首先确认geth已经启动,并已经登录到了geth console
(1)加载之前生成的storage.js文件
> loadScript('/路径/storage.js')
加载js文件后,其中的变量 storageOutput 就可以引用了,查看一下:
> storageOutput
{
contracts: {
Storage.sol:Storage: {
abi: "[{\"constant\":false,\"inputs\":[{\"name\":\"data\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]",
bin: "608060405234801561001057600080fd5b5060bf8061001f6000396000f30060806040526004361060485763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166360fe47b18114604d5780636d4ce63c146064575b600080fd5b348015605857600080fd5b5060626004356088565b005b348015606f57600080fd5b506076608d565b60408051918252519081900360200190f35b600055565b600054905600a165627a7a723058208157aff69edee57dc9d12d47289d96cfe21fa1e318d916bf9bf3d85da0e5d0ff0029"
}
},
version: "0.4.24+commit.e67f0147.Linux.g++"
}
就是智能合约的编译结果。
Storage.sol:Storage 下面有2个key,abi 和 bin,之后要分别用到,为了使用方便,把他们赋值为2个变量:
> var storageContractAbi = storageOutput.contracts['Storage.sol:Storage'].abi
undefined
> var storageContract = eth.contract(JSON.parse(storageContractAbi))
undefined
> var storageBinCode = "0x" + storageOutput.contracts['Storage.sol:Storage'].bin
undefined
(2)部署
先要解锁账户:
> personal.unlockAccount(eth.accounts[0])
Unlock account 0xf090551f59e907a73c76123377e373cd76da449b
Passphrase:
true
发送部署合约的交易:
> var deployTransationObject = { from: eth.accounts[0], data: storageBinCode, gas: 1000000 };
undefined
> var storageInstance = storageContract.new(deployTransationObject)
undefined
此时网络中有一个待处理的交易:
> txpool.status
{
pending: 1,
queued: 0
}
> txpool.inspect.pending
{
0xE0DDcb2abC5da896764202A6e6Cd9aC937D3A946: {
0: "contract creation: 0 wei + 1000000 gas × 18000000000 wei"
}
}
开启挖矿,使这笔交易成功写入区块中:
> miner.start(1);admin.sleepBlocks(1);miner.stop();
true
查看部署结果:
> storageInstance
{
abi: [{
constant: false,
inputs: [{...}],
name: "set",
outputs: [],
payable: false,
stateMutability: "nonpayable",
type: "function"
}, {
constant: true,
inputs: [],
name: "get",
outputs: [{...}],
payable: false,
stateMutability: "view",
type: "function"
}],
address: "0x8829cb81c61a4c553fe757422a1dee3fdbef7694",
transactionHash: "0xc70efd32fb60c2a74d4a0ac3402c0fe7d97c09121ea45dc47f2d2707c25b93bb",
allEvents: function(),
get: function(),
set: function()
}
其中的 transactionHash 是合约的交易地址。
查看交易详情:
> eth.getTransactionReceipt(storageInstance.transactionHash);
{
blockHash: "0x2bc825af0e96a5ea64dbd6a191773b05db8966e784e72fd0b44b58727e0efec4",
blockNumber: 2973,
contractAddress: "0x8829cb81c61a4c553fe757422a1dee3fdbef7694",
cumulativeGasUsed: 71631,
from: "0xe0ddcb2abc5da896764202a6e6cd9ac937d3a946",
gasUsed: 71631,
logs: [],
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
root: "0x5167b657140527b8dfa28c634946ca539c0d54955d5883d20d403bfa7129f3ea",
to: null,
transactionHash: "0xc70efd32fb60c2a74d4a0ac3402c0fe7d97c09121ea45dc47f2d2707c25b93bb",
transactionIndex: 0
}
其中的 contractAddress 是合约地址,赋值到变量:
> var storageAddress = eth.getTransactionReceipt(storageInstance.transactionHash).contractAddress
undefined
> storageAddress
"0x8829cb81c61a4c553fe757422a1dee3fdbef7694"
4. 调用合约
(1)获取合约
通过合约地址获取合约:
> var storage = storageContract.at(storageAddress);
undefined
> storage
{
abi: [{
constant: false,
inputs: [{...}],
name: "set",
outputs: [],
payable: false,
stateMutability: "nonpayable",
type: "function"
}, {
constant: true,
inputs: [],
name: "get",
outputs: [{...}],
payable: false,
stateMutability: "view",
type: "function"
}],
address: "0x8829cb81c61a4c553fe757422a1dee3fdbef7694",
transactionHash: null,
allEvents: function(),
get: function(),
set: function()
}
(2)发送一条合约调用交易
> storage.set.sendTransaction(42, {from: eth.accounts[1], gas: 1000000})
"0xec3f97caac33fbbc2e73dadd88e93265814b65cd4f24d7067f9efaf792d49695"
此时网络中有一个待处理的交易:
> txpool.status
{
pending: 1,
queued: 0
}
> txpool.inspect.pending
{
0xE0DDcb2abC5da896764202A6e6Cd9aC937D3A946: {
1: "0x8829cB81c61a4C553FE757422A1DeE3fDBef7694: 0 wei + 1000000 gas × 18000000000 wei"
}
}
(3)挖矿 使交易生效
> miner.start(1);admin.sleepBlocks(1);miner.stop();
true
(4)调用合约查看结果
> storage.get.call()
42
至此,智能合约的部署流程就完成了。