【以太坊开发】Truffle框架实战(二)

一、创建项目根目录

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: <indexed>, 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控制台中操作,省去了第五步配置测试网络一节。在开发过程中,需要熟练掌握以上流程并快速排查出错误。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容