目录结构
-
contracts/
: Solidity合约目录 -
migrations/
: 部署脚本文件目录 -
test/
: 测试脚本目录,参考 如何测试合约于应用? -
truffle-config.js
: Truffle 配置文件
合约编译
合约文件目录
所有合约都位于项目的 contracts/
目录中。 由于合约是用Solidity语言编写的,所有包含合约的文件都将具有 .sol
文件扩展名。 相关的 Solidity 库也将有一个.sol
扩展名。
使用truffle init
命令创建的空 Truffle 工程会生成一个用于部署的Migrations.sol
合约文件。 如果我们使用 Truffle Box 来创建工程,则会有多个合约文件。
编译命令
要编译Truffle项目里的合约,请切换到项目工程所在根目录,然后在终端中键入以下内容:
truffle compile
首次运行时,将编译所有合约。 在后续运行中,Truffle将仅编译自上次编译以来有更改的合约。 如果我们想覆盖此行为,可以使用 --all
选项运行上面的命令。
构建工件 Artifacts
注解
译者注:Artifacts 主要是指编译的目标(或目标文件),因为中文中有时会使用”工件“,为了避免理解问题,大部分会保留英文词 Artifacts。
编译的目标文件 Artifacts 将放在 build/contracts/
目录中,相对于项目根目录(如果该目录不存在,将创建该目录。)
这些 Artifacts 是Truffle内部工作的组成部分,它们在成功部署应用程序中起着重要作用。 我们不应编辑这些文件,因为这些文件将被合约编译和部署覆盖。
引入合约依赖文件
我们可以使用Solidity的 import 命令声明合约依赖文件。 Truffle 将以正确的顺序编译合约,并确保将所有依赖文件发送给编译器。 可以通过两种方式指定依赖关系:
通过文件名导入依赖文件
要从单独的文件导入合约,请将以下代码添加到Solidity源文件中:
import “./AnotherContract.sol”;
这将导入 AnotherContract.sol
中的所有合约,这里 AnotherContract.sol
是在当前编写的合约目录下。
Solidity 还有其他的导入语法,可以参考Solidity文档:导入源文件 了解更多。
从外部包导入合约
Truffle支持通过EthPM和NPM安装的依赖。 可使用以下语法把依赖导入合约:
import “somepackage/SomeContract.sol”;
这里,somepackage
表示通过EthPM或NPM安装的包,SomeContract.sol
表示该包提供的Solidity源文件。
请注意,在搜索从NPM安装的软件包之前,Truffle将首先从EthPM搜索已安装的软件包,因此在极少数情况下会出现命名冲突,将使用通过EthPM安装的软件包。
有关如何使用Truffle软件包管理功能的更多信息,请参阅Truffle EthPM和NPM文档。
合约部署
注解
译者注:Migrations 直译”迁移“,当作为一个名词时,有时指的是用来部署的脚本文件,称之为迁移文件,作为动词会翻译成部署,请读者了解。
迁移脚本(JavaScript文件)可帮助我们将合约部署到以太坊网络。 这些文件负责暂存我们的部署任务,并且假设我们的部署需求会随着时间的推移而发生变化。 随着项目的发展,我们将创建新的迁移脚本,以进一步推动区块链的发展。 先前运行的部署记录通过特殊的 Migrations
迁移合约记录在链上,详细信息如下。
部署命令
要运行部署,请运行以下命令:
$ truffle migrate
这将部署在项目的 migrations
目录中的所有迁移文件。 最简单的迁移只是一组管理部署脚本。 如果我们的迁移先前已成功运行,则 truffle migrate
将从上次运行的迁移开始执行,仅运行新创建的迁移。 如果不存在新的迁移,truffle migrate
将不会执行任何操作。 我们可以使用 --reset
选项从头开始运行所有迁移。 对于本地测试,确保在执行 migrate
之前安装并运行了 Ganache等 测试区块链。
脚本文件
一个简单的迁移文件,如文件名:4_example_migration.js
:
var MyContract = artifacts.require(“XlbContract”);
module.exports = function(deployer) {
// 部署步骤
deployer.deploy(MyContract);
};
请注意,文件名以数字为前缀,后缀为描述。 编号前缀是必需的,以便记录迁移是否成功运行。 后缀纯粹是为了人类的可读性和理解力。
注解
译者注:编号 还有记录 运行迁移文件顺序的作用。
artifacts.require()
在迁移开始时,我们通过 artifacts.require()
方法告诉 Truffle 我们想要与哪些合约进行交互。 这个方法类似于Node的 require
,但在我们的例子中,它特别返回了一个 合约抽象 contract abstraction,我们可以在其余的部署脚本中使用它。 指定的名称应与该源文件中的合约定义的名称相匹配。 不传递源文件的文件名,因为文件可以包含多个合约。
考虑这个示例,其中在同一源文件中指定了两个合约:
文件名: ./contracts/Contracts.sol
contract ContractOne {
// …
}
contract ContractTwo {
// …
}
通过 artifacts.require()
引入 ContractTwo
的语句像下面这样:
var ContractTwo = artifacts.require(“ContractTwo”);
也可以引入两个合约,语句如下:
var ContractOne = artifacts.require(“ContractOne”);
var ContractTwo = artifacts.require(“ContractTwo”);
module.exports
所有迁移都必须通过 module.exports
语法导出函数。 每次迁移导出的函数都应该接受 deployer
对象作为其第一个参数。 此对象通过为部署智能合约提供清晰的语法以及执行部署职责(例如保存已部署的 artifacts 供以后使用)。 deployer
对象是用于暂存部署任务最主要接口,其API在本页底部描述。
我们的迁移功能也可以接受其他参数。 请参阅以下示例。
初始化迁移功能
Truffle要求我们有迁移合约(Migrations 合约)才能使用迁移功能。 此合约必须包含特定的接口,但我们可以随意编辑此合约。 对于大多数项目,此合约最初将作为第一个迁移文件进行部署,不会再次更新。 在使用truffle init
创建新项目时,我们也会默认收到此合约。
文件: contracts/Migrations.sol
pragma solidity >=0.4.8 <0.6.0;
contract Migrations {
address public owner;
// A function with the signature last_completed_migration()
, returning a uint, is required.
uint public last_completed_migration;
modifier restricted() {
if (msg.sender == owner) _;
}
function Migrations() {
owner = msg.sender;
}
// A function with the signature setCompleted(uint)
is required.
function setCompleted(uint completed) restricted {
last_completed_migration = completed;
}
function upgrade(address new_address) restricted {
Migrations upgraded = Migrations(new_address);
upgraded.setCompleted(last_completed_migration);
}
}
我们必须在第一次迁移中部署此合约才能利用迁移功能。 为此,需要创建以下迁移脚本文件:
文件名: migrations/1_initial_migration.js
var Migrations = artifacts.require(“Migrations”);
module.exports = function(deployer) {
// 任务就是 部署迁移合约
deployer.deploy(Migrations);
};
这里,我们可以使用增加的编号前缀创建新的迁移,以部署其他合约并执行更多的部署步骤。
部署程序 Deployer
我们的迁移文件将用于部署程序 deployer 来(分阶段)部署任务。 因此,我们可以同步编写部署任务,它们将以正确的顺序执行:
// Stage deploying A before B
deployer.deploy(A);
deployer.deploy(B);
或者,部署程序上的每个函数可以使用 Promise,等待上一个任务执行的部署任务完成之后执行(进入一个部署队列):
// Deploy A, then deploy B, passing in A’s newly deployed address
deployer.deploy(A).then(function() {
return deployer.deploy(B, A.address);
});
如果你发现更清晰语法也可以为部署编写为单个 promise 链, 部署API将在本页底部讨论。
考虑网络
可以根据网络条件,条件性地运行部署。 这是一项高级功能,因此请在继续之前先参阅网络 部分。
要有条件地运行部署步骤,在编写迁移时,加入第二个参数 network
, 例如:
module.exports = function(deployer, network) {
if (network == “live”) {
// Do something specific to the network named “live”.
} else {
// Perform a different step otherwise.
}
}
可用账号
迁移也会通过我们的以太坊客户端和 Web3 provider 提供给我们的帐户列表,供我们在部署期间使用。 下面和 从web3.eth.getAccounts()
返回的完全相同的帐户列表。
module.exports = function(deployer, network, accounts) {
// Use the accounts within your migrations.
}
部署程序接口 Deployer API
部署程序包含许多可用于简化迁移的功能。
deployer.deploy(contract, args…, options)
部署合约可以通过使用指定合约对象
和可选的合约构造函数的参数
来进行合约部署。对于单个合约很有用,DApp只存在此合约的一个实例。 它将在部署之后设置合约地址(即Contract.address
将等于新部署的地址),并且它将覆盖任何先前存储的地址。
注解
译者注:上面的段落的第一句 有一点拗口, 其意思是:传给 deploy 函数的可选参数 会传递给智能合约的构造函数,看下面的例子就很容易理解。
我们也可以选择传递一组合约或一组数组,以加快多个合约的部署。另外,最后一个参数是一个可选对象,它可以包含名为overwrite
的键以及其他交易参数如 gas
和from
。如果overwrite
设置为false
,则部署程序如果发现之前已经部署了该合约,则不会再次部署该合约。这对于由外部依赖提供合约地址的某些情况下很有用。
注意,在调用deploy
之前,我们需要首先部署和链接合约所依赖的库。有关详细信息,请参阅下面的链接
功能。
有关详细信息,请参阅truffle-contract 文档。
通过下面示例会更好理解 deploy 方法:
// 部署没有构造函数的合约
deployer.deploy(A);
// 部署合约 并使用一些参数传递给合约的构造函数。
deployer.deploy(A, arg1, arg2, ...);
// 如果合约部署过,不会覆盖
deployer.deploy(A, {overwrite: false});
// 设置gasLimit 和部署合约的账号
deployer.deploy(A, {gas: 4612388, from: "0x...."});
// 部署多个合约,一些包含参数,另一些没有。
// 这比编写三个`deployer.deploy()`语句更快,因为部署者可以作为单个批处理请求执行部署。
deployer.deploy([
[A, arg1, arg2, ...],
B,
[C, arg1]
]);
// 外部依赖示例:
//对于此示例,我们的依赖在部署到线上网络时提供了一个地址,但是没有为测试和开发等任何其他网络提供地址。
//当我们部署到线上网络时,我们希望它使用该地址,但在测试和开发中,我们需要部署自己的版本。 我们可以简单地使用`overwrite`键来代替编写一堆条件。
deployer.deploy(SomeDependency, {overwrite: false});
deployer.link(library, destinations)
将已部署的库链接到合约或多个合约。 参数 destinations
可以是单个合约,也可以是多个合约的数组。 如果目的(即参数指定的)合约中有不依赖于链接的库,则合约将被忽略。
示例:
// 部署库LibA,然后将LibA链接到合约B,然后部署B.
deployer.deploy(LibA);
deployer.link(LibA, B);
deployer.deploy(B);
// 链接 LibA 到多个合约
deployer.link(LibA, [B, C, D]);
deployer.then(function() {…})
就像 promise 一样,可运行任意部署步骤。 使用此选项可在迁移期间调用特定的合约函数,以添加,编辑和重新组织合约数据。
示例:
var a, b;
deployer.then(function() {
// 创建一个新版本的 A
return A.new();
}).then(function(instance) {
a = instance;
// 获取部署的 B 实例
return B.deployed();
}).then(function(instance) {
b = instance;
// 通过B的setA()函数在B上设置A的新实例地址
return b.setA(a.address);
});
与合约进行交互
介绍
如果我们为了与合约进行(测试)交互而向每次都向以太坊网络进行原始请求,我们很快就会意识到编写这些请求是笨重而繁琐的。 同样,我们可能会发现管理每个请求的状态是 复杂的。 幸运的是,Truffle为我们处理这种复杂性,使我们与合约的互动变得轻而易举。
数据的读和写
以太坊网络区分将数据写入网络和从网络读取数据,在编写应用程序我们需要关注这个区别。 通常,写入数据称为交易 transaction,而读取数据称为 调用 call。 交易
和调用
的处理方式是截然不同的,下面介绍:
交易 Transactions
交易
从改变了网络的状态。 交易
可以像 发送 Ether 到一个帐户一样简单,也可以像执行合约函数或向网络部署新合约一样复杂。 交易
的特征是它写入(或更改)数据。 一个交易
需要耗费以太运行,称为 “gas”,交易
同样需要(较长)时间来处理。 当我们通过交易
执行合约的函数时,我们无法接收该函数的返回值,因为交易不会立即处理。 通常,通过交易执行的函数不会返回值,仅仅是返回一个交易ID。 可总结交易
的特征如下:
-
消耗Gas 费用(以太)
-
会更改网络状态
-
不会立即执行(需要等待网络矿工打包)
-
没有执行返回值(只是一个交易ID)。
调用 Calls
调用
则不同,调用
依然可以在网络上执行合约代码,但不会永久更改任何数据(如状态变量)。 调用
的特征是读取数据。 当我们通过调用
执行合约函数时,我们可以立刻获取到返回值。 可总结调用Call
的特点:
-
免费(不消耗 Gas)
-
不改变网络状态
-
立即执行
-
有返回值
选择使用 交易
还是调用
关键是看 读取数据 还是需要写入数据。
什么是合约抽象
合约抽象( Contract abstraction)是从 Javascript 与以太坊合约交互的基础和黄油。 简单说,合约抽象是一种代码封装,让我们可以轻松地与合约进行交互,从而让我们忘记在引擎盖下执行的引擎和齿轮。 Truffle 通过truffle-contract模块使用合约抽象,下面会介绍。
在这里,我们通过一个例子 metacoin
,来介绍合约抽象的作用,通过Truffle Boxes,执行truffle unbox metacoin
使用MetaCoin合约,下面合约代码:
pragma solidity >=0.4.25 <0.6.0;
import “./ConvertLib.sol”;
//这只是一个类似Coin 合约的简单例子,并不是一个标准代币合约
// 常见Token合约可参考:https://github.com/ConsenSys/Tokens
contract MetaCoin {
mapping (address => uint) balances;
event Transfer(address indexed _from, address indexed _to, uint256 _value);
constructor() public {
balances[tx.origin] = 10000;
}
function sendCoin(address receiver, uint amount) public returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Transfer(msg.sender, receiver, amount);
return true;
}
function getBalanceInEth(address addr) public view returns(uint){
return ConvertLib.convert(getBalance(addr),2);
}
function getBalance(address addr) public view returns(uint) {
return balances[addr];
}
}
注解
译者注: 这段代码其实有点旧了(不过并不影响本节要表达的意思), 现在Solidity 升级到 0.5 以上,应该在合约里显示的标明合约是否修改状态。
除了构造函数之外,这个合约还有三个方法(sendCoin
,getBalanceInEth
和getBalance
),这三种方法都可以作为交易
或调用
来执行。
现在让我们来看看Truffle为我们提供的名为 “MetaCoin” 的 Javascript 对象,它可以在Truffle控制台访问,如:
truffle(develop)> let instance = await MetaCoin.deployed()
truffle(develop)> instance
// outputs:
//
// Contract
// - address: “0xa9f441a487754e6b27ba044a5a8eb2eec77f6b92”
// - allEvents: ()
// - getBalance: ()
// - getBalanceInEth: ()
// - sendCoin: ()
// …
注意: 合约抽象包含与合约中完全相同的函数。 它还包含一个指向 MetaCoin合约 部署版本的地址。
执行合约函数
使用合约抽象,我们可以轻松地在以太坊网络上执行合约函数。
执行交易Transactions
我们可以执行MetaCoin合约上的三个函数。 如果我们分析每一个函数,会发现sendCoin
是唯一一个会改变网络状态的函数。 sendCoin
的作用是从一个帐户“发送”一些 Meta coins 到另一个帐户,这个变化是需要持续保存的。
当调用sendCoin
时,我们需要它作为一个交易
执行。 如在下面的示例中,使用交易
调用的方式从一个帐户向另一个帐户发送10个币:
truffle(develop)> let accounts = await web3.eth.getAccounts()
truffle(develop)> instance.sendCoin(accounts[1], 10, {from: accounts[0]})
以上代码有一些有趣的事情:
-
我们直接调用了
抽象合约
的sendCoin
函数。 它默认使用交易
的方式去执行,而不是使用调用
。 -
我们还用一个对象作为第三个参数传递给
sendCoin
函数。 注意,在 Solidity 合约中的sendCoin
函数没有第三个参数。 这是一个特殊对象,它始终可以作为最后一个参数传递给函数,该函数允许我们编辑有关交易
的特定信息。 在这里,我们设置了from
地址,确保此交易来自accounts [0]
。
执行调用 call
继续使用MetaCoin,注意getBalance
函数是从网络读取数据的理想选择。 它不需要进行任何更改,因为它只返回地址参数的 MetaCoin 余额。 让我们试一试:
truffle(develop)> let balance = await instance.getBalance(accounts[0])
truffle(develop)> balance.toNumber()
调用会得到返回值。 注意,由于以太坊网络可以处理非常大的数字,我们会得到一个BigNum 对象,然后将其转换为数字。
注解
这里返回值转换为数字,因为在此示例中数字很小。 但是如果尝试转换大于 Javascript 支持的最大整数的 BigNum(简写:BN),可能会遇到错误或无法预期的行为。
处理交易结果
当我们进行交易
时,我们会得到一个result
对象,它为我们提供了大量有关交易
的信息。
truffle(develop)> let result = await contract.sendCoin(accounts[1], 10, {from: accounts[0]})
truffle(develop)> result
具体来说,我们将获得以下内容:
-
result.tx
(string) - 交易哈希 hash -
result.logs
(array) - 解码过的事件 (日志) -
result.receipt
(object) - 交易收据 receipt(包括使用的gas)
想了解更多,可参阅truffle-contract
包中的README。
捕获事件 events
通过捕获合约触发的事件,可以更深入地了解合约正在做什么。 处理事件的最简单方法是处理交易结果result
对象中包含的logs
数组。
如果我们显式输出第一个日志条目,我们可以看到 sendCoin
函数触发事件(Transfer(msg.sender,receiver,amount);
)的细节:
truffle(develop)> result.logs[0]
{ logIndex: 0,
transactionIndex: 0,
transactionHash: ‘0x3b33960e99416f687b983d4a6bb628d38bf7855c6249e71d0d16c7930a588cb2’,
blockHash: ‘0xe36787063e114a763469e7dabc7aa57545e67eb2c395a1e6784988ac065fdd59’,
blockNumber: 8,
address: ‘0x6891Ac4E2EF3dA9bc88C96fEDbC9eA4d6D88F768’,
type: ‘mined’,
id: ‘log_3181e274’,
event: ‘Transfer’,
args:
Result {
‘0’: ‘0x8128880DC48cde7e471EF6b99d3877357bb93f01’,
‘1’: ‘0x12B6971f6eb35dD138a03Bd6cBdf9Fc9b9a87d7e’,
‘2’: <BN: a>,
length: 3,
_from: ‘0x8128880DC48cde7e471EF6b99d3877357bb93f01’,
_to: ‘0x12B6971f6eb35dD138a03Bd6cBdf9Fc9b9a87d7e’,
_value: <BN: a> } }
部署新合约
在上述所有情况中,我们一直在使用已经部署的合约抽象。 还可以使用.new()
函数把自己版本的合约部署到网络:
truffle(develop)> let newInstance = await MetaCoin.new()
truffle(develop)> newInstance.address
‘0x64307b67314b584b1E3Be606255bd683C835A876’
指定合约地址
如果我们已有合约的地址,则可以在该地址上创建新的抽象。
let specificInstance = await MetaCoin.at(“0x1234…”);
给合约发送以太
可以简单的把 Ether 直接发送给合约地址,或是触发合约的Fallback 函数。有两种方式:
- 方法1:通过
instance.sendTransaction()
将交易直接发送到合约。 它像执行所有可用的合约实例函数一样有效,并且和web3.eth.sendTransaction
功能相同,但没有回调。 如果没有指定,目标地址to
值将自动填入。
instance.sendTransaction({…}).then(function(result) {
// Same transaction result object as above.
});
- 方法2:还可以直接调用
send
:
instance.send(web3.toWei(1, “ether”)).then(function(result) {
// Same result object as above.
});
使用控制台
有时,以交互方式处理合约以进行测试和调试,或手动执行事务是件好事。Truffle 为您提供了两种简单的方法,可以通过交互式控制台执行此操作,您的合同可用且随时可用。
-
Truffle 控制台:连接到任何以太坊客户端的基本交互式控制台
-
Truffle Develop:一个交互式控制台,也生成了一个开发区块链
为什么有两个控制台?
拥有两个不同的控制台可让您选择最适合您需求的工具。
使用松露控制台的原因:
-
您有一个已经在使用的客户端,例如 Ganache 或 geth
-
您想迁移到测试网(或主以太坊网络)
-
您想要使用特定的助记符或帐户列表
使用Truffle Develop的理由:
-
您正在测试您的项目,但无意立即部署
-
您不需要使用特定帐户(并且可以使用默认开发帐户)
-
您不想安装和管理单独的区块链客户端
次序
所有命令都要求您位于项目文件夹中。你不需要在根。
登录控制台
要启动控制台,请执行以下操作:
truffle console
这将查找配置中调用的网络定义,并连接到该定义(如果可用)。您可以使用该选项覆盖此选项或自定义网络设置。有关详细信息,请参阅“网络”部分以及命令参考。development``--network <name>``development
加载控制台时,您将立即看到以下提示:
truffle(development)>
这表示您正在使用网络在 Truffle 控制台中运行。development
登录Develop控制台
要启动 Truffle Develop:
truffle develop
默认情况下,这将在端口本地生成一个开发区块链。如果您已经有一个会话正在运行,它将连接到该开发区块链。9545``truffle develop
加载 Truffle Develop 时,您将看到以下内容:
Truffle Develop started at http://localhost:9545/
Accounts:
(0) 0x627306090abab3a6e1400e9345bc60c78a8bef57
(1) 0xf17f52151ebef6c7334fad080c5704d77216b732
(2) 0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef
(3) 0x821aea9a577a9b44299b9c15c88cf3087f3b5544
(4) 0x0d1d4e623d10f9fba5db95830f7d3839406c6af2
(5) 0x2932b7a2355d6fecc4b5c0b6bd44cc31df247a2e
(6) 0x2191ef87e392377ec08e7c08eb105ef5448eced5
(7) 0x0f4f2ac550a1b4e2280d04c21cea7ebd822934b5
(8) 0x6330a553fc93768f612722bb8c2ec78ac90b3bbc
(9) 0x5aeda56215b167893e80b4fe645ba6d5bab767de
Private Keys:
(0) c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3
(1) ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f
(2) 0dbbe8e4ae425a6d2687f1a7e3ba17bc98c673636790f1b8ad91193c05875ef1
(3) c88b703fb08cbea894b6aeff5a544fb92e78a18e19814cd85da83b71f772aa6c
(4) 388c684f0ba1ef5017716adb5d21a053ea8e90277d0868337519f97bede61418
(5) 659cbb0e2411a44db63778987b1e22153c086a95eb6b18bdf89de078917abc63
(6) 82d052c865f5763aad42add438569276c00d3d88a2d062d36b2bae914d58b8c8
(7) aa3680d5d48a8283413f7a108367c7299ca73f553735860a87b08f39395618b7
(8) 0f62d96d6675f32685bbdb8ac13cda7c23436f63efbb9d07700d8669ff12b7c4
(9) 8d5366123cb560bb606379f90a0bfd4769eecc0557f1b362dcae9012b548b1e5
Mnemonic: candy maple cake sugar pudding cream honey rich smooth crumble sweet treat
This shows you the addresses, private keys, and mnemonic for this particular blockchain.
Note: When you run truffle develop
for the first time, Truffle will generate a random mnemonic that will persist for you and you alone. If you want to use a different mnemonic or set of addresses, we recommend using Ganache.
Warning: Remember to never use any of these addresses or the mnemonic on the mainnet. This is for development only.
配置 Truffle Develop
You can configure to use any of the available ganache-core options and configurable network settings.truffle develop
For example:
module.exports = {
/* … rest of config */
networks: {
/* … other networks */
develop: {
port: 8545,
network_id: 20,
accounts: 5,
defaultEtherBalance: 500,
blockTime: 3
}
}
};
功能
Truffle Develop 和控制台都提供了 Truffle 命令行工具中提供的大部分功能。例如,您可以在控制台中键入,它将被解释为您在命令行上运行的相同。migrate --reset``truffle migrate --reset
此外,Truffle Develop 和控制台都具有以下功能:
-
您所有编译的合同都可用并可供使用。
-
在每个命令(如 )之后,将重新预配您的协定,以便您可以立即开始使用新分配的地址和二进制文件。
migrate --reset
-
该库可用,并设置为连接到您的以太坊客户端。
web3
可用命令
-
build
-
compile
-
create
-
debug
-
deploy
-
exec
-
help
-
install
-
migrate
-
networks
-
opcode
-
publish
-
run
-
test
-
version
如果 Truffle 命令不可用,那是因为它与现有项目无关(例如,)或没有意义(例如,或)。init``develop``console
有关详细信息,请参阅完整的命令参考。