Solidity的Truffle框架实战(手把手)
前置工作:
- 安装Solidity的开发框架Truffle,参见:Truffle框架安装
- 安装开发客户端,参见: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)
处于某些特定的环境下,可以看到评论框,欢迎留言交流^_^。