Truffle初探和踩坑笔记
本文最后更新于 4 年前,部分内容可能不适合当前所有情况,仅供参考。
一个刚入门的 Truffle DEMO 和学习笔记,能找到的教程都好老,记录一版踩坑笔记,后面遇到类似的问题可以快速处理,啃的 Truffle 的英文文档,国内的翻译文档都太老了,都快速找到的停留在 2019 年之前,实在没法看。
官方文档:Truffle Document
模板库:Truffle Boxes
Truffle 的模板库有点类似于 GitHub 仓库的 template 功能,你可以根据你的技术选型,在初始化 Truffle 项目的时候,选择合适的模板创建项目,比如基于 React / Vue / Vyper 等等,再去做调整。
了解概念
开始搞事情之前,先了解几个新概念,我估计大部分人应该还是跟我一样,刚接触的时候都是一脸懵逼。
Truffle 是一个开发智能合约的工具,也可以用来做 DAPP ,这两个概念,引用别的地方的说明大概了解一下:
智能合约 —— 可以简单理解为脚本,用来处理各种业务逻辑
DAPP —— 包含完整的智能合约 + 用户 UI 交互界面,载体可以是 Android APP/ iOS APP/ WEB APP ,只要主要逻辑和数据在区块链上就可以
至于怎么把数据和界面连接起来,后面了解了再补充,先记录一下前期的一些学习体验问题。
目前最知名的区块链游戏体验:Axie Infinity
安装问题
需要全局安装,但理论上第一次安装会得到好几屏幕的报错信息……
# 全局安装 Truffle
yarn global add truffle
因为在 Node 基础上还需要 Python 和 C++ 编译器……
不过其实我之前都有装过,看了报错都是 gyp 相关的,更新了 gyp 就可以了。
| 依赖环境 | 下载地址 |
|---|---|
| C++ | Visual Studio |
| Python | node-gyp |
然后再次全局安装 Truffle 就可以了,如果可以正确查询到版本号,说明安装成功了。
# 查询当前的 Truffle 版本
truffle -v
VS Code 配置
点击安装 solidity 语言高亮和语法补全功能支持。
项目初始化
直接执行初始化命令 truffle init 只得到了一个空项目,前期建议先按照官方文档 Quick Start 里面的建议,先用官方推荐的 MetaCoin 项目模板来学习:
# 创建并进入 DEMO 项目文件夹
mkdir truffle-demo && cd truffle-demo
# 通过模板创建一个 Truffle 项目
truffle unbox metacoin
初始化后的项目结构:
truffle-demo
│
│ # Solidity 合约目录
├─contracts
│
│ # 部署脚本目录
├─migrations
│
│ # 测试脚本目录
├─test
│
│ # Truffle 配置文件
└─truffle-config.js
配置文件
和其他前端项目一样,都有一个统一的项目配置文件 truffle-config.js ,这个看文档按需要的配就可以了。
常用命令
| 命令 | 作用 |
|---|---|
| truffle compile | 编译成 JSON 文件 |
| truffle test | 运行 JavaScript 和 Solidity 测试 |
| truffle develop | 调试个人区块链(命令行) |
| truffle console | 调试个人区块链(GUI) |
| truffle publish | 将包发布到以太坊包注册表 |
完整命令参见:Commands
使用 GUI 调试
develop 命令默认基于命令行,可以下载 Ganache 通过 GUI 来调试。
下载和安装后,需要修改项目的 truffle-config.js 文件:
module.exports = {
// ...
networks: {
development: {
host: '127.0.0.1',
port: 7545,
network_id: '*',
},
},
// ...
}
然后启动 Ganache ,点击 "Quick Start" ,就可以运行个人区块链了。

在命令行运行 truffle console 可以进入 GUI 情况下的调试命令状态(等价于命令行情况的 truffle develop)。
解决单元测试异常
在实际体验中发现,如果你在刚刚的 使用 GUI 调试 环节直接配置了 networks 之后,会发现无法再执行 truffle test 了(当然,执行 truffle develop 是没问题的,因为它等价于使用 Ganache)……
控制台会出现如下报错:
λ truffle test
> Something went wrong while attempting to connect to the network at http://127.0.0.1:7545. Check your network configuration.
Could not connect to your Ethereum client with the following parameters:
- host > 127.0.0.1
- port > 7545
- network_id > *
Please check that your Ethereum client:
- is running
- is accepting RPC connections (i.e., "--rpc" or "--http" option is used in geth)
- is accessible over the network
- is properly configured in your Truffle configuration file (truffle-config.js)
Truffle v5.4.14 (core: 5.4.14)
Node v16.1.0
然后你把 truffle-config.js 里的 networks 注释掉,会发现其实又可以了,就很迷……
解决方法一
在 GitHub 的 Issue 区查了也有人遇到一样的情况,所以很快有了这个解决方法:
- 重新启动 Ganache ,点击 "New Workspace" ,进入配置:

- 点击 “Add Project” ,进入到你的 truffle 项目文件夹,把项目的
truffle-config.js添加到工作区,然后点击右上角的 “Start” 或者 “Restart” 启动运行。
在启动 Ganache 的时候,运行 truffle test 就不会出现网络问题了(下次启动 GUI 的时候,选择工作区的配置启动连接,就可以对应的给你的项目开启测试支持了)。

解决方法二
由于方法一要基于 GUI 才能解决这个问题,那如果以后跑在服务器上面,没有 GUI 可以用咋办?观察了一下控制台,在没有配置 networks 选项的时候,执行测试命令时,使用的网络是不一样的:
配置 networks 前:
λ truffle test
Using network 'test'.
配置 networks 后:
λ truffle test
Using network 'development'.
为什么会出现这个情况?官方文档也没有说明,得去看一下仓库相关的代码了,看看有没有门路……
按照一般的大型开源项目的习惯,在 GitHub 仓库里找到了 commands 相关的文件,其中 test 命令是位于 truffle/packages/core/lib/commands/test/index.js ,这里可以看到测试命令的运行规则是:
-
有配置了
networks.development就优先按这个配置启动测试工作 -
如果没有的话,会创建一个
networks.test的选项,并先通过Develop.connectOrStart启动连接开发环境再启动测试工作
所以我们另外一个解决方式就是:
- 先开启 develop 环境
λ truffle develop
Truffle Develop started at http://127.0.0.1:9545/
- 然后在 develop 环境下运行测试命令(此时不需要再补 truffle 前缀了),就可以正常运行了
truffle(develop)> test
Using network 'develop'.
Compiling your contracts...
===========================
项目构建
虽然直接执行 truffle build 可以完成一个最基本的构建行为。
其他常见问题
一些刚上手可能遇到的问题和解决方案。
由于官方 DEMO 的上次实际更新是 1 年前(最新更新只是无关痛痒的注释修改),所以为了可持续发展,Solidity 的语言版本始终选择较新的 0.8+ ,而不是默认的 0.5+ ,默认版本可落后太多了。
版本号报错
初始化后,打开 .sol 文件时, VS Code 会报下面这样的问题:
Source file requires different compiler version (current compiler is 0.8.6+commit.11564f7e.Emscripten.clang) - note that nightly builds are considered to be strictly less than the released version
因为模板项目的版本可能比较老,跟不上当前的编译器版本,所以根据提示的版本号,手动更新到对应版本就可以了,也可以在 Solidity 的 GitHub 仓库查看最新版本号。
- pragma solidity >=0.4.25 <0.7.0;
+ pragma solidity >=0.4.25 <=0.8.6;
或者是下面这种(个人比较推荐):
- pragma solidity >=0.4.25 <0.7.0;
+ pragma solidity ^0.8.6;
这个是 Solidity 语言的强制要求,为了避免智能合约在编译过程中出现兼容问题,在 soliditylang 的官方文档有说明 version-pragma
具体的版本管理方式,比如 >= 也可以用 ^ 符号代替版本兼容范围,和 Node 的 package.json 的版本管理是一样的。
构造函数的可见性被忽略
这个报错是在上面那个版本号报错问题,解决了之后出现的:
Visibility for constructor is ignored. If you want the contract to be non-deployable, making it "abstract" is sufficient.
这个是 Solidity 语言在 v0.7.0 的更新(CHANGLOG)
由于模板原本是 <0.7.0 ,使用的是低于 0.7 版本,所以没有出现这个报错,我们改成了 ^0.8.6 ,所以出现了这个问题。
只需要移除掉 constructor 的可见性就可以了:
contract Migrations {
// ...
- constructor() public {
+ constructor() {
// ...
}
// ...
}
缺少构造函数可见性
接上一个问题,移除了 constructor 的可见性,又会报缺少可见性的问题(韩红听了都想打人.jpg?x-oss-process=image/interlace,1):
SyntaxError: No visibility specified. Did you intend to add "public"?
这是因为编译器使用的默认版本比较低(0.5.16),而我们用的是 0.8+ 了,版本之间不兼容,所以导致编译出错。
可以在 truffle-config 里统一修改,指定编译版本范围和我们的文件里保持一致。
module.exports = {
compilers: {
solc: {
version: '^0.8.6',
},
},
}
导入依赖报错
比如在测试文件里,会导入 Truffle 自身的依赖:
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
此时执行测试命令是成功的,但是在 VS Code 会报诸如下面的错误:
Source "truffle/Assert.sol" not found: File import callback not supported
因为出现的问题只存在于 VS Code ,所以可以确认是语法插件的问题,后面在插件仓库的 Issue #193 找到了原因。
不过好像当前无法解决,所以目前只能是人肉忽视,强迫症也没办法……
功能不影响测试和编译,不是大问题。