Solidity的Truffle框架实战(手把手)

前置工作:

1. 创建工程目录

在你想放工程的任何位置,创建一个文件夹truffleTest,来做为你的工程根目录。

$ mkdir -p /Users/admin/develop/blockchain_workspace/truffleTest

2. 初始化框架

进入到工程根目录下(现在应该是个空目录),并执行下述命令。

$ cd /Users/admin/develop/blockchain_workspace/truffleTest
$ truffle init

正确执行后,我们将得到下面这样的目录结构:

目录结构简单说明如下:

  • app/ - 你的应用文件运行的默认目录。这里面包括推荐的javascript文件和css样式文件目录,但你可以完全决定如何使用这些目录。
  • contract/ - Truffle默认的合约文件存放地址。
  • migrations/ - 存放发布脚本文件
  • test/ - 用来测试应用和合约的测试文件
  • truffle.js - Truffle的配置文件

相关详细说明,详见:初始化Truffle

3.放入自己的合约

删除./contract目录下的自带demo合约,切记不要删除./contract/Migrations.sol合约,它是Truffle用来帮助部署的。

$ cd /Users/admin/develop/blockchain_workspace/truffleTest/contracts

$ rm ConvertLib.sol MetaCoin.sol

./contract目录下创建一个自己的合约文件Greeter.sol

pragma solidity ^0.4.0;

contract Greeter         
{
    address creator;     
    string greeting;     

    function Greeter(string _greeting) public   
    {
        creator = msg.sender;
        greeting = _greeting;
    }

    function greet() constant returns (string)          
    {
        return greeting;
    }
    
    function setGreeting(string _newgreeting) 
    {
        greeting = _newgreeting;
    }
    
     /**********
     Standard kill() function to recover funds 
     **********/
    
    function kill()
    { 
        if (msg.sender == creator)
            suicide(creator);  // kills this contract and sends remaining funds back to creator
    }

}

代码来自fiveDogIt的一段入门代码05_greeter.sol

4. 修改发布脚本

./migrations/2_deploy_contracts.js下的内容由:

module.exports = function(deployer) {
  deployer.deploy(ConvertLib);
  deployer.autolink();
  deployer.deploy(MetaCoin);
};

修改为:

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

目的是去掉原有自带的Demo部署流程,修改为要部署的合约。修改完后,记得保存,不然发布时会报错,找不到相关合约。详细发布流程参考:部署(migrate)

5. 编译

进入到工程根目录./truffleTest目录下,进行编译:

$ truffle compile
Compiling Greeter.sol...

Writing artifacts to ./build/contracts

6. 启动你的客户端

启动之前安装好的EthereumJS RPC客户端。

$ testrpc

EthereumJS TestRPC v3.0.3

Available Accounts
==================

Private Keys
==================

HD Wallet
==================
Mnemonic:      degree debate income mask fiber issue album diet unfair police race car
Base HD Path:  m/44'/60'/0'/0/{account_index}

Listening on localhost:8545

7. 部署合约(migrate)

部署合约到网络上:

$ truffle migrate
Running migration: 2_deploy_contracts.js
  Deploying Greeter...
  Greeter: 0xe66038995cf64b14da96d26cbe1c96d30dec0e95
Saving successful migration to network...
Saving artifacts...

备注

  • 如果报错出现了一些你之前编译部署过,但你已经不需要的合约,可以用truffle migrate --reset来重置部署,但可能根据情况,你需要更新移植版本号,来管理不同的版本,详见部署(migrate)

  • 若误删Truffle自带用来部署的合约./contracts/Migrations.sol,会出现下述报错,需要补回到./contract目录,重初始化一次得到。

$ truffle migrate
Running migration: 1_initial_migration.js
/Users/admin/develop/blockchain_workspace/truffleTest/migrations/1_initial_migration.js:2
  deployer.deploy(Migrations);
                  ^

ReferenceError: Migrations is not defined
    at module.exports (/Users/admin/develop/blockchain_workspace/truffleTest/migrations/1_initial_migration.js:2:19)
    at /usr/local/lib/node_modules/truffle/lib/migrate.js:109:7
    at /usr/local/lib/node_modules/truffle/lib/require.js:82:7
    at tryToString (fs.js:425:3)
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:412:12)

8. 看一下效果

我们使用truffle console功能在控制台与合约交互,来看下效果。

$ truffle console
truffle(default)> Greeter.deployed().setGreeting("Hello world!");
'0xf6a00b4466c9ab38d7eb60dc9f8d15f5f1e500e24ea91bd9e28f6233bad08aed'
truffle(default)> Greeter.deployed().greet.call();
'Hello world!'
truffle(default)>
  • 在console中为简单需要,与使用直接使用代码方式在返回结果处理上有一点点差异,参见控制台
  • 要直接使用代码与合约交互,参见合约交互
  • 控制台内,可以通过声明变量来减少输入的内容,比如var g = Greeter.deployed();g.greet();。更多详见控制台

常见报错

  • 以太坊客户端连接配置不正确,或未正常启动时。
$ truffle console
/usr/local/lib/node_modules/truffle/lib/repl.js:25
    if (err) return done(err);
                    ^

ReferenceError: done is not defined
    at /usr/local/lib/node_modules/truffle/lib/repl.js:25:21
    at /usr/local/lib/node_modules/truffle/lib/repl.js:57:21
    at /usr/local/lib/node_modules/truffle/lib/contracts.js:46:25
    at /usr/local/lib/node_modules/truffle/node_modules/web3/lib/web3/property.js:119:13
    at /usr/local/lib/node_modules/truffle/node_modules/web3/lib/web3/requestmanager.js:82:20
    at exports.XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/node_modules/web3/lib/web3/httppro
vider.js:114:13)
    at exports.XMLHttpRequest.dispatchEvent (/usr/local/lib/node_modules/truffle/node_modules/xmlhttprequest/lib/XMLHttpRequest.
js:591:25)
    at setState (/usr/local/lib/node_modules/truffle/node_modules/xmlhttprequest/lib/XMLHttpRequest.js:610:14)
    at exports.XMLHttpRequest.handleError (/usr/local/lib/node_modules/truffle/node_modules/xmlhttprequest/lib/XMLHttpRequest.js
:532:5)
    at ClientRequest.errorHandler (/usr/local/lib/node_modules/truffle/node_modules/xmlhttprequest/lib/XMLHttpRequest.js:459:14)
    at emitOne (events.js:96:13)
    at ClientRequest.emit (events.js:188:7)
    at Socket.socketErrorListener (_http_client.js:309:9)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
    at emitErrorNT (net.js:1281:8)
  • 若合约未进行部署就进行调用,可能出现下述报错:
truffle(default)> Greeter.deployed().setGreeting("Hello world!");
Error: Cannot find deployed address: Greeter not deployed or address not set.
    at Function.Contract.deployed (/Users/admin/develop/blockchain_workspace/truffleTest/build/contracts/Greeter.sol.js:311:1
3)
    at evalmachine.<anonymous>:1:-53

    at ContextifyScript.Script.runInContext (vm.js:37:29)
    at Object.exports.runInContext (vm.js:69:17)
    at TruffleInterpreter.interpret (/usr/local/lib/node_modules/truffle/lib/repl.js:99:17)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.onLine (repl.js:513:10)
    at emitOne (events.js:96:13)
    at REPLServer.emit (events.js:188:7)
  • 部署时填合约名称有误,本应该写为deployer.deploy(IntegerLiteral);,却写成了deployer.deploy("IntegerLiteral");
  Deploying undefined...
Error encountered, bailing. Network state unknown. Review successful transactions manually.
TypeError: Cannot read property 'apply' of undefined
    at /usr/local/lib/node_modules/truffle/lib/deployer.js:62:28
    at process._tickDomainCallback (internal/process/next_tick.js:129:7)

处于某些特定的环境下,可以看到评论框,欢迎留言交流^_^。