一、创建项目根目录
mkdir -p /home/simon/project/ColorBayDemo
cd /home/simon/project/ColorBayDemo
二、项目初始化
truffle init
三、创建智能合约
在根目录下的contracts
文件夹下新建一文件ColorBay.sol
,代码如下:
pragma solidity ^0.4.17;
contract ColorBay {
function calculate(uint a, uint b) public pure returns (uint) { #计算a与b的乘积
return a * b;
}
}
注意:public修饰符应该写在任何自定义修饰符前;pure修饰器表示不需要去获取我们的状态变量
四、编译合约
truffle develop
#省略显示账号列表信息
> compile
Compiling ./contracts/ColorBay.sol...
Compiling ./contracts/Migrations.sol...
Writing artifacts to ./build/contracts
五、合约单元测试
打开官方开发文档 http://truffleframework.com/docs/getting_started/solidity-tests,将EXAMPLE栏的代码复制到新建文件TestColorBay.sol
中,并修改成如下:
pragma solidity ^0.4.17;
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/ColorBay.sol";
contract TestColorBay {
function testCalculateIsRight() {
ColorBay colorbay = ColorBay(DeployedAddresses.ColorBay());
Assert.equal(colorbay.calculate(3, 4), 12, "3 * 4 should be 12"); #如果要测试返回失败时的效果,将12改成任意错误数字,如120
}
}
执行测试命令:
> test
# 返回成功时的效果:
Using network 'develop'.
Compiling ./contracts/ColorBay.sol...
Compiling ./test/TestColorBay.sol...
Compiling truffle/Assert.sol...
Compiling truffle/DeployedAddresses.sol...
#省略中间警告信息
TestColorBay
✓ testCalculateIsRight (146ms)
1 passing (1s)
如果要测试返回失败时的效果,将TestColorBay.sol
中一行Assert.equal(colorbay.calculate(3, 4), 12, "3 * 4 should be 12");
修改成Assert.equal(colorbay.calculate(3, 4), 120, "3 * 4 should be 12");
,在控制台中再次执行test
命令,返回信息如下:
# 返回失败时的效果:
Using network 'develop'.
Compiling ./contracts/ColorBay.sol...
Compiling ./test/TestColorBay.sol...
Compiling truffle/Assert.sol...
Compiling truffle/DeployedAddresses.sol...
#省略中间警告信息
TestColorBay
1) testCalculateIsRight
Events emitted during test:
---------------------------
TestEvent(result: , message: 3 * 4 should be 12 (Tested: 12, Against: 120))
---------------------------
0 passing (950ms)
1 failing
1) TestColorBay testCalculateIsRight:
Error: 3 * 4 should be 12 (Tested: 12, Against: 120)
at /usr/lib/node_modules/truffle/build/webpack:/~/truffle-core/lib/testing/soliditytest.js:61:1
at Array.forEach (native)
at processResult (/usr/lib/node_modules/truffle/build/webpack:/~/truffle-core/lib/testing/soliditytest.js:59:1)
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
1
六、新建发布脚本
在项目根目录下的文件夹migrations
下,新建文件2_deploy_colorbay.js
, 编写如下代码:
var ColorBay = artifacts.require("./ColorBay.sol");
module.exports = function(deployer) {
deployer.deploy(ColorBay); #注意,如果合约的构造函数需要传递参数,从第二个位置开始增加参数
};
七、移植部署合约
> migrate #如果需要重新移植,加--reset选项
Using network 'develop'.
Running migration: 1_initial_migration.js
Deploying Migrations...
... 0xcae8151fa504661038bcc80ee6f80e3ebc5aa55cb91f7b809d0ef084958ffa4f
Migrations: 0x2a504b5e7ec284aca5b6f49716611237239f0b97
Saving successful migration to network...
... 0xad16ddf12b1be2f43938221b5fd7dfa05dae1c6da09776f16f25b2e4a7f4cedc
Saving artifacts...
Running migration: 2_deploy_colorbay.js
Deploying ColorBay...
... 0x5302dfc1537dfe40b1df44a873810f27b4c9f5692c55d46a14127ef1b645f980
ColorBay: 0x2eca6fcfef74e2c8d03fbaf0ff6712314c9bd58b #此处为合约地址
Saving successful migration to network...
... 0x05d263b8571d786abcca55bf0248d2b0185697ae076b19bf3403015a7ada9f6b
Saving artifacts...
八、测试合约部署是否成功
truffle(develop)> web3.eth.getCode('0x2eca6fcfef74e2c8d03fbaf0ff6712314c9bd58b');
'0x606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680638dfa4363146044575b600080fd5b3415604e57600080fd5b606b60048080359060200190919080359060200190919050506081565b6040518082815260200191505060405180910390f35b60008183029050929150505600a165627a7a72305820d9c655b8112892366b8577e059f3210d2aaef10bb3e8038f15861c4de2628f4f0029'
将返回的合约字节码与项目根目录下build/contracts/ColorBay.json
中的键bytecode
的值对比,如果一致,说明合约部署成功!
九、调用合约
> var colorbay;
undefined
> colorbay = ColorBay.deployed().then(instance => colorbay = instance); #创建一个ColorBay合约实例colorbay
#返回信息如下:
TruffleContract {
constructor:
{ [Function: TruffleContract]
_static_methods:
{ setProvider: [Function: setProvider],
new: [Function: new],
at: [Function: at],
deployed: [Function: deployed],
defaults: [Function: defaults],
hasNetwork: [Function: hasNetwork],
isDeployed: [Function: isDeployed],
detectNetwork: [Function: detectNetwork],
setNetwork: [Function: setNetwork],
resetAddress: [Function: resetAddress],
link: [Function: link],
clone: [Function: clone],
addProp: [Function: addProp],
toJSON: [Function: toJSON] },
_properties:
{ contract_name: [Object],
contractName: [Object],
abi: [Object],
network: [Function: network],
networks: [Function: networks],
address: [Object],
transactionHash: [Object],
links: [Function: links],
events: [Function: events],
binary: [Function: binary],
deployedBinary: [Function: deployedBinary],
unlinked_binary: [Object],
bytecode: [Object],
deployedBytecode: [Object],
sourceMap: [Object],
deployedSourceMap: [Object],
source: [Object],
sourcePath: [Object],
legacyAST: [Object],
ast: [Object],
compiler: [Object],
schema_version: [Function: schema_version],
schemaVersion: [Function: schemaVersion],
updated_at: [Function: updated_at],
updatedAt: [Function: updatedAt] },
_property_values: {},
_json:
{ contractName: 'ColorBay',
abi: [Object],
bytecode: '0x6060604052341561000f57600080fd5b60ba8061001d6000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680638dfa4363146044575b600080fd5b3415604e57600080fd5b606b60048080359060200190919080359060200190919050506081565b6040518082815260200191505060405180910390f35b60008183029050929150505600a165627a7a72305820d9c655b8112892366b8577e059f3210d2aaef10bb3e8038f15861c4de2628f4f0029',
deployedBytecode: '0x606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680638dfa4363146044575b600080fd5b3415604e57600080fd5b606b60048080359060200190919080359060200190919050506081565b6040518082815260200191505060405180910390f35b60008183029050929150505600a165627a7a72305820d9c655b8112892366b8577e059f3210d2aaef10bb3e8038f15861c4de2628f4f0029',
sourceMap: '28:121:0:-;;;;;;;;;;;;;;;;;',
deployedSourceMap: '28:121:0:-;;;;;;;;;;;;;;;;;;;;;;;;53:93;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;109:4;137:1;133;:5;126:12;;53:93;;;;:::o',
source: 'pragma solidity ^0.4.17;\r\n\r\ncontract ColorBay {\r\n function calculate(uint a, uint b) public pure returns (uint) {\r\n return a * b;\r\n }\r\n}\r\n',
sourcePath: '/home/simon/project/ColorBayDemo/contracts/ColorBay.sol',
ast: [Object],
legacyAST: [Object],
compiler: [Object],
networks: [Object],
schemaVersion: '2.0.0',
updatedAt: '2018-04-16T15:09:48.351Z' },
setProvider: [Function: bound setProvider],
new: [Function: bound new],
at: [Function: bound at],
deployed: [Function: bound deployed],
defaults: [Function: bound defaults],
hasNetwork: [Function: bound hasNetwork],
isDeployed: [Function: bound isDeployed],
detectNetwork: [Function: bound detectNetwork],
setNetwork: [Function: bound setNetwork],
resetAddress: [Function: bound resetAddress],
link: [Function: bound link],
clone: [Function: bound clone],
addProp: [Function: bound addProp],
toJSON: [Function: bound toJSON],
web3:
Web3 {
_requestManager: [Object],
currentProvider: [Object],
eth: [Object],
db: [Object],
shh: [Object],
net: [Object],
personal: [Object],
bzz: [Object],
settings: [Object],
version: [Object],
providers: [Object],
_extend: [Object] },
class_defaults:
{ from: '0x627306090abab3a6e1400e9345bc60c78a8bef57',
gas: 6721975,
gasPrice: 100000000000 },
currentProvider:
HttpProvider {
host: 'http://127.0.0.1:9545/',
timeout: 0,
user: undefined,
password: undefined,
headers: undefined,
send: [Function],
sendAsync: [Function],
_alreadyWrapped: true },
network_id: '4447' },
abi:
[ { constant: true,
inputs: [Object],
name: 'calculate',
outputs: [Object],
payable: false,
stateMutability: 'pure',
type: 'function' } ],
contract:
Contract {
_eth:
Eth {
_requestManager: [Object],
getBalance: [Object],
getStorageAt: [Object],
getCode: [Object],
getBlock: [Object],
getUncle: [Object],
getCompilers: [Object],
getBlockTransactionCount: [Object],
getBlockUncleCount: [Object],
getTransaction: [Object],
getTransactionFromBlock: [Object],
getTransactionReceipt: [Object],
getTransactionCount: [Object],
call: [Object],
estimateGas: [Object],
sendRawTransaction: [Object],
signTransaction: [Object],
sendTransaction: [Object],
sign: [Object],
compile: [Object],
submitWork: [Object],
getWork: [Object],
coinbase: [Getter],
getCoinbase: [Object],
mining: [Getter],
getMining: [Object],
hashrate: [Getter],
getHashrate: [Object],
syncing: [Getter],
getSyncing: [Object],
gasPrice: [Getter],
getGasPrice: [Object],
accounts: [Getter],
getAccounts: [Object],
blockNumber: [Getter],
getBlockNumber: [Object],
protocolVersion: [Getter],
getProtocolVersion: [Object],
iban: [Object],
sendIBANTransaction: [Function: bound transfer] },
transactionHash: null,
address: '0x2eca6fcfef74e2c8d03fbaf0ff6712314c9bd58b',
abi: [ [Object] ],
calculate:
{ [Function: bound ]
request: [Function: bound ],
call: [Function: bound ],
sendTransaction: [Function: bound ],
estimateGas: [Function: bound ],
getData: [Function: bound ],
'uint256,uint256': [Circular] },
allEvents: [Function: bound ] },
calculate:
{ [Function]
call: [Function],
sendTransaction: [Function],
request: [Function: bound ],
estimateGas: [Function] },
sendTransaction: [Function],
send: [Function],
allEvents: [Function: bound ],
address: '0x2eca6fcfef74e2c8d03fbaf0ff6712314c9bd58b',
transactionHash: null }
> colorbay.calculate(3, 4); #调用合约方法
{ [String: '12'] s: 1, e: 1, c: [ 12 ] }
十、总结
与上一篇文章《【以太坊开发】Truffle框架实战(一)》相比,本篇是直接在truffle控制台中操作,省去了第五步配置测试网络一节。在开发过程中,需要熟练掌握以上流程并快速排查出错误。