Truffle 启动样例

Truffle很友好,当读者第一次运行Truffle的时候,可以什么参数也不指定,创建一个空白项目,或者 Truffle 代为下载一个模板示例来作为基础进行开发。Truffle官方和社区都共同开发了一些样例,这些样例称之为Truffle Boxes ,就和圣诞节礼物一样,一打开盒子就已经是完整的示例。我们首先通过一个名为MetaCoin的项目来了解一下Truffle的工程目录结构。

下载样例

初始化目录,下载 MetaCoin模板项目:

$ mkdir truffle-project
$ cd truffle-project
$ truffle unbox metacoin

Note

Truffle 稳定版本已经去除了truffle init <模板名> 的启动方式,执行 truffle init 会得到一个空白的基础项目;若要下载某模板项目,请使用 truffle unbox <模板名>来进行。

至此我们得到了一个模板项目,它的组织结构如下:

truffle-project/
├── contracts
│   ├── ConvertLib.sol
│   ├── MetaCoin.sol
│   └── Migrations.sol
├── migrations
│   ├── 1_initial_migration.js
│   └── 2_deploy_contracts.js
├── test
│   ├── TestMetacoin.sol
│   └── metacoin.js
├── truffle-config.js
└── truffle.js

3 directories, 9 files
每个目录具体解释如下。
  • contracts目录包含了主要的合约代码,示例中包含了MetaCoin.sol(主要合约),ConvertLib.sol (库文件)和部署时记录地址的合约 Migration.sol。
  • migrations目录包含了两个部署文件,先会部署Migration.sol, 再会链接ConvertLib.sol与MetaCoin.sol部署到链上,两者顺序不可颠倒。代码中aritfacts.require()函数相当于node.js中的require()函数,指明了我们希望引用哪个合约的抽象。这个引用名必须与合约中的类名相同。
  • test目录包含了两种不同的测试文件,智能合约可以通过sol结尾的合约进行测试写作,也可以通过js文件写作,两者功能几乎一致,笔者在开发组多时,考虑到语言的通用性与灵活程度,平时一直使用js的格式书写测试。Truffle的测试都是Mocha测试框架格式的语法。
  • truffle-config.js和truffle.js都保存了控制truffle行为定义的全局变量,当想调换测试网络时,可以编辑truffle.js指定网络和端口。

编译项目

有了目录和源文件,我们来尝试编译部署一下合约。

$ truffle compile
Compiling ./contracts/ConvertLib.sol...
Compiling ./contracts/MetaCoin.sol...
Compiling ./contracts/Migrations.sol...
Writing artifacts to ./build/contracts

Truffle将contracts目录下的合约都编译了一遍,之后将输出结果放入到了./build/文件夹下方,build 文件夹内都是特殊格式的 artifacts,相对应智能合约的 ABI 信息。每次Truffle在跑 compile 命令的时候,都会创建或者复写这个文件夹,所以修改 build 文件夹的内容是徒劳的,再次编译后,新的改动就会覆盖旧文件。

如果启动 --all 参数会强制从头编译所有的合约,无论新旧。

$ truffle compile --all

部署项目到 Ganache

编译完成后,我们可以将合约部署到网络上。

$ truffle migrate

此时可能读者电脑上会报一个错说:没有指定以太坊网络,的确,我们应该先启动 Ganache 测试节点。

$ ganache-cli

然后将 truffle.js 文件修改为如下样式,指定测试的网络。

module.exports = {
  networks: {
      development: {
          host: "localhost",
          port: 8545,
          network_id: "*" // 匹配任何的network id
      }
  }
};

再次运行truffle migrate 就不会出错了,控制台输出如下。

Using network 'development'.

Running migration: 1_initial_migration.js
  Deploying Migrations...
  ... 0x3d5fe2cd860c64d465a0fae3908e2de889ba56f4ebd683653f6d23c0eee55761
  Migrations: 0x67b19c3ce017b7b75c4ca1d0b06bd17ec8d31df0
Saving successful migration to network...
  ... 0xc8829afea94774a85e708608ca631758096e3c9005ab08f5209911ed41cc7c3c
Saving artifacts...
Running migration: 2_deploy_contracts.js
  Deploying ConvertLib...
  ... 0x4bc21a0a4df9507b71d1e3cbce199d1eb967b37346156e005bc53c3afd868231
  ConvertLib: 0xbf46ec73895ef7f9bfe52f508bd5041dd3746978
  Linking ConvertLib to MetaCoin
  Deploying MetaCoin...
  ... 0x3326d829e6968d4bb5128f49a0fde951c4d1ed2c8b0bfa4ecaf221fcea38c865
  MetaCoin: 0x7a054ef9375731b2d41beb5cce1336ccebb16d3c
Saving successful migration to network...
  ... 0x6e4d273dee78e6f807a9958ce24ec717d9081083dacfbf24fadf5880368ae6b1
Saving artifacts...

测试项目

在合约部署到测试网上之后,我们可以运行一系列预定义的测试,例如 /test/metacoin.js文件所指定的Mocha测试就可以运行起来,Mocha测试框架配合 Chai 的断言库非常有利于智能合约的测试。以下是运行示例项目的测试结果。

$ truffle test
Using network 'development'.

Compiling ./contracts/ConvertLib.sol...
Compiling ./contracts/MetaCoin.sol...
Compiling ./test/TestMetacoin.sol...
Compiling truffle/Assert.sol...
Compiling truffle/DeployedAddresses.sol...


  TestMetacoin
    ✓ testInitialBalanceUsingDeployedContract (81ms)
    ✓ testInitialBalanceWithNewMetaCoin (91ms)

  Contract: MetaCoin
    ✓ should put 10000 MetaCoin in the first account
    ✓ should call a function that depends on a linked library (41ms)
    ✓ should send coin correctly (107ms)


  5 passing (946ms)

让我们暂时把MetaCoin项目放一边。我们需要从头开始建立一个自己的合约项目。较为合适举例的就是ERC20数字资产合约。作为2017-2018年以太坊上最火热的Dapp应用之一,ERC20数字资产合约承载了 ...