准备

确保安装好了 Truffle Framework 和 Ganache CLI.

$ sudo npm install -g truffle
$ sudo npm install -g ganache-cli

开始

// SPDX-License-Identifier: MIT
pragma solidity > 0.4.21;contract Storage {mapping (string => string) private _store;function addData(string memory key, string memory value) public {require(bytes(_store[key]).length == 0);_store[key] = value;}function removeData(string memory key) public returns (string memory) {require(bytes(_store[key]).length != 0);string memory prev = _store[key];delete _store[key];return prev;}function changeData(string memory key, string memory newValue) public {require(bytes(_store[key]).length != 0);_store[key] = newValue;}}

solidity 0.5.0版本更新后,string后面要加上memory,否则编译会报错。

初始的迁移(Migrations)文件及部署规则

你可以能已经看到了在运行 truffle init 时生成的 Migrations.sol1_initial_migration.js

初始迁移合约一般不需要修改,他们是跟踪部署在区块链上的地址。当然也可以按照自己的需要修改 Migrations.sol 合约文件,进行一些高级的迁移管理,但需要保留truffle init命令创建的接口。

1_initial_migration.js 迁移文件,仅仅是说明如何把 Migrations.sol 合约部署到对应的链上。

1_initial_migration.js 迁移文件名,前面的序号,代表着 truffle migrate 运行迁移文件的顺序,1 表示第一个运行的迁移文件(从 1 开始)。 我们可以创建其他的迁移文件: 2_mycontract_migration.js ,在每个合约部署完成,Truffle 会把迁移序号保存到 Migrations 合约的 last_completed_migration

假设 migrations 就这两个迁移文件,truffle migrate运行时实际会发生 4 笔交易:

运行 1_initial_migration.js 进行部署
把序号 1 写入到合约 Migrations
运行 2_mycontract_migration.js 进行部署
把序号 2 写入到合约Migrations
last_completed_migration 表示的是最后部署的迁移,之后再加入其它的迁移文件:3_yourcontract.js 时, 运行truffle migrate时 Truffle 会首先读取 last_completed_migration 状态变量,参看之前部署到了哪些,再部署比 last_completed_migration 序号大的(所有)迁移文件,这样就可以保证不会重复部署。

注意,如果修改一个已有的合约,需要重新部署的话,直接运行 truffle migrate 是不会自动部署的,需要新加(或修改)一个更高序号的迁移文件,再运行 truffle migrate

truffle migrate 可以接一个 -f 序号 来强制从一个序号开始执行迁移(此时会忽略 last_completed_migration的值)。 例如: truffle migrate -f 2 会从第 2 个迁移文件开始部署。

迁移的相关数据

编写迁移文件

有了这些知识,让我们写下我们的第一个迁移文件 2_deploy_contracts.js, 代码如下:

// 获取对应的合约文件
var Storage = artifacts.require("./Storage.sol");// JavaScript export
module.exports = function(deployer) {// deployer 是用来部署// 部署deployer.deploy(Storage);
}

编写迁移就这么简单。

为了运行迁移脚本,请在终端中运行以下命令:

truffle migrate

不过这时候,会得到一个错误:

Error: No network specified. Cannot determine current network.

意思是 Truffle 找不到要部署到的网络,这时可以在命令行终端打开一个新的 tab 运行 ganache-cli 来启动一个模拟的测试区块链,启动后,有会类似输出:

/TruffleTest$ ganache-cli
Ganache CLI v6.12.2 (ganache-core: 2.13.2)Available Accounts
==================
(0) 0x36eC0bC604780Da01da74fdc21062090342422F0 (100 ETH)
(1) 0x5df8Ff0fC05Fa2d0eDE36a14c22958652b5e2396 (100 ETH)
(2) 0xEB20b6e8844A32c50F1149Df54f6AAC55754b248 (100 ETH)
(3) 0x8Bb575F18d54dc570449E14A3A453555628e597F (100 ETH)
(4) 0xf29Bae551395fd286345518262A197950Ffb3903 (100 ETH)
(5) 0xEfd420BB71682725fCEf27a48D88dfc04d20c171 (100 ETH)
(6) 0xC07026932a7C29C3505Ec28baf2c372177849f8a (100 ETH)
(7) 0x4d219b1490B21849BFdADC071B18E761863B9AB1 (100 ETH)
(8) 0xF33e7CeaA8825c90cAFb332EA3A0448fFEE242E7 (100 ETH)
(9) 0xd0Ffeb7caA16025e713EabF1761a9bb431406322 (100 ETH)Private Keys
==================
(0) 0x627e7ad2299bf54679de34746714d4559b7dd463d4c869d37a540d8f0f00fba4
(1) 0x0fb839122b11abe05bb8783578a74d0a1ac11ea314b200050b3e394ab3e6119c
(2) 0x51a4f0d22d1ecad211a580944152f03b8ea7fdf13b5e22def7fbec17bb0750bb
(3) 0x8d95d6d02882d591beddaa46a8f59910db588b7ef3c5cc43ee58dd9b67fc93ac
(4) 0x9dd25620de22ce96616aa933066a2f240f09819beed9cb611e0004034fc61bff
(5) 0x5e4d89ce7885cb5f645eee49a8b844c29edb4447b0e7bfa9449583a412e8aa06
(6) 0x79d5edde2f9cf0c2e0d572cfc74ee2b6b2efe4883bcb9d095f27bfd72cc106c2
(7) 0xd9c62a643dc16531a4e22c50491af696f30a029422d9170cd2776ac6f8303621
(8) 0x9e0d415bb50dbc5f095a001f0a642bc069560cbc37b229b0d2960c90719dc664
(9) 0xb214a0f61c14119b47decdfb59124cb2f6ffe33960ac2af08b45a52da6e766bfHD Wallet
==================
Mnemonic:      entire exhaust spoon client ladder used harsh hobby cabbage swing cave where
Base HD Path:  m/44'/60'/0'/0/{account_index}Gas Price
==================
20000000000Gas Limit
==================
6721975Call Gas Limit
==================
9007199254740991Listening on 127.0.0.1:8545

现在已经建立了一个私有区块链,它运行在localhost:8545上。

现在让我们配置 Truffle 以便部署合约到该网络。
打开 truffle-config.js 文件,加入以下内容:

module.exports = {networks: {development: {host: "127.0.0.1",port: 8545,network_id: "*"}}
};

上面配置的含义是把编译的合约部署到 localhost:8545 所在的网络上。

现在运行 truffle migrate , 得到以下输出:

/TruffleTest$ truffle migrateCompiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.Starting migrations...
======================
> Network name:    'development'
> Network id:      1628492486749
> Block gas limit: 6721975 (0x6691b7)1_initial_migration.js
======================Deploying 'Migrations'----------------------> transaction hash:    0x8a16df1dde1da9624236320f31505e1149b1401ea3229347f830fe074690f8d7> Blocks: 0            Seconds: 0> contract address:    0xeaFd135174544015f10edCC4C38494f2967EC72D> block number:        1> block timestamp:     1628492566> account:             0x36eC0bC604780Da01da74fdc21062090342422F0> balance:             99.99616114> gas used:            191943 (0x2edc7)> gas price:           20 gwei> value sent:          0 ETH> total cost:          0.00383886 ETH> Saving migration to chain.> Saving artifacts-------------------------------------> Total cost:          0.00383886 ETH2_deploy_contracts.js
=====================Deploying 'Storage'-------------------> transaction hash:    0x6c34134d752cf425413d27fe1d102a05afb0e684655f6d5826cf4efa60648202> Blocks: 0            Seconds: 0> contract address:    0x7c91Ba1Fa7395B94909021Fe186fc172F0b1a71D> block number:        3> block timestamp:     1628492566> account:             0x36eC0bC604780Da01da74fdc21062090342422F0> balance:             99.98386434> gas used:            572502 (0x8bc56)> gas price:           20 gwei> value sent:          0 ETH> total cost:          0.01145004 ETH> Saving migration to chain.> Saving artifacts-------------------------------------> Total cost:          0.01145004 ETHSummary
=======
> Total deployments:   2
> Final cost:          0.0152889 ETH

可以看到truffle migrate部署合约时使用的账户是 ganache-cli 预置的10个账户的第一个账户: 0x36eC0bC604780Da01da74fdc21062090342422F0

Truffle 将合约迁移到网络并保存了构件(artifacts)。 在构建目录(build/contracts/)的 Storage.json文件中,通过检查 networks 对象来检查它是否正确。 您应该看到类似以下内容:

  "networks": {"1628492486749": {"events": {},"links": {},"address": "0x7c91Ba1Fa7395B94909021Fe186fc172F0b1a71D","transactionHash": "0x6c34134d752cf425413d27fe1d102a05afb0e684655f6d5826cf4efa60648202"}},

1628492486749 是网络的 ID,以太坊网络主网和测试网都有固定的 ID(主网是 1)。
address 是部署合约的地址。
transactionHash 是部署合约的交易hash。

在后面会看到如何使用。

部署多合约

Truffle 迁移的真正亮点是能进行多个合约的编译、部署和跟踪(几乎所有区块链项目都是这样)。

迁移文件不仅允许我们使用单个命令部署多个合约,还允许我们调用合约的函数,如获取这些函数的返回值并将其传递给后续合约。

我们在 contracts 目录下,添加一个新合约 InfoManager.sol, 代码如下:

pragma solidity >0.4.21;import "./Storage.sol";contract InfoManager {Storage private _dataStore;uint private _lastAdded;constructor(Storage dataStore) public {_dataStore = dataStore;}function addData(string memory key, string memory value) public {require((now - 1 days) > _lastAdded);_dataStore.addData(key, value);}}

可以看出,InfoManager 依赖 Storage 合约,不仅如此,InfoManager的构造函数还需要 Storage 合约作为参数。

重新修改一下 2_deploy_contracts.js 让它可以完成 InfoManager 的部署:

var Storage = artifacts.require("./Storage.sol");
var InfoManager = artifacts.require("./InfoManager.sol");module.exports = function(deployer) {// 部署 Storagedeployer.deploy(Storage)// 等待、直到合约部署完成.then(() => Storage.deployed())// 传递 Storage 合约地址,部署 InfoManager 合约.then(() => deployer.deploy(InfoManager, Storage.address));
}

部署的语法是:

...
deployer.deploy(`ContractName`, [`constructor params`]) // 返回一个 promise
...

因为 deploy(...) 返回一个 promise, 我们可以按自己喜欢的方式处理它,不过要注意的是在部署文件里,还不支持 async

我们还可以在部署合约后自定义调用函数。例如,迁移还可以这样:

deployer.deploy(Storage).then(() => Storage.deployed()).then((instance) => {instance.addData("Hello", "world")}).then(() => deployer.deploy(InfoManager, Storage.address));

这样在部署 InfoManager 之前,先给Storage 添加一条数据。

这个技巧很有用,因为有时相互依赖的合约可能需要在构造函数的之外写入。

根据网络进行部署

还可以根据所处的网络不同,进行不同的部署。这对于在开发阶段使用模拟链的数据而在主网上线时使用已部署的主网合约作为输入参数到合约中都非常有用。

通过导出函数 module.exports 扩展一个参数 network

module.exports = function(deployer, network) {if (network == "live") {// do one thing} else if (network == "development") {// do other thing}
}

选择账号进行部署

module.exports 默认函数还可以公开一个账号参数,这些账号是以太坊节点或钱包provider “暴露” 出来的,看看下面的例子:

module.exports = function(deployer, network, accounts) {var defaultAccount;if (network == "live") {defaultAccount = accounts[0]} else {defaultAccount = accounts[1]}
}

链接库

你还可以通过 deployer.link(...) 连接已经存在(部署)的库:

...
deployer.deploy(MyLibrary);
deployer.link(MyLibrary, MyContract);
deployer.deploy(MyContract);
...

结论

通过使用上面的这些技术,可以把大部分区块链部署工作自动化,并减少开发去中心化应用程序涉及的大量重复工作。

相关内容:
TypeError: Data location must be “memory“ for parameter in function, but none was given.

Truffle在ganache-cli部署合约相关推荐

  1. 以太坊开发(二)使用Ganache CLI在私有链上搭建智能合约

    以太坊开发(二)使用Ganache CLI在私有链上搭建智能合约 在上一篇文章中,我们使用Truffle自带的客户端Truffle Develop,在私有链上搭建并运行了官方提供的WebPack智能合 ...

  2. Truffle - 2 利用Truffle编写、测试智能合约并将其部署到不同的测试网络

    2 利用Truffle编写.测试智能合约并将其部署到不同的测试网络 2.1创建项目 建一个文件夹 mkdir truffle-project truffle init //初始化qinjianquan ...

  3. 以太坊Dapp开发通过truffle部署合约

    以太坊Dapp开发通过truffle部署合约 Truffle是一个非常流行 DApp 开发框架,他可以帮我们处理掉大量无关紧要的小事情,让我们可以迅速开始写代码-编译-部署-测试-打包DApp这个流程 ...

  4. 四:调用部署在ganache的智能合约

    四:调用部署在ganache的智能合约 文章目录 四:调用部署在ganache的智能合约 实验目的 实验原理 开始条件 实验过程 实验步骤 相关官方知识库 下一章内容: 如果朋友有代码,工具,使用流程 ...

  5. 使用ganache-cli和truffle构建以太坊智能合约,以实现“基于哈希锁定的跨链技术”为例

    目录 配置以太坊开发环境 部署智能合约 调用智能合约 配置以太坊开发环境 系统与工具的版本:Ubuntu 21.04 npm 7.5.2 Ganache CLI v6.12.2 (ganache-co ...

  6. 以太坊开发(一)——Truffle和Ganache

    Truffle是目前最流行的以太坊开发框架,采用JavaScript编写,支持智能合约的编译.部署和测试. 一.安装Truffle 1. 首先安装Truffle依赖的NodeJS: curl -sL ...

  7. OpenZeppelin集成Truffle编写健壮安全的合约

    原文:http://truffleframework.com/tutorials/robust-smart-contracts-with-openzeppelin 因为智能合约往往涉及金钱,保证Sol ...

  8. 【区块链】以太坊truffle+web3+ganache简单实践

    以太坊truffle+web3+ganache简单实践 安装 帮助文档 结构 代码 solidity代码 html 注意 安装 下载最新版nodejs npm install -g truffle 下 ...

  9. 前端工作笔记-Nginx安装及vue cli部署

    目录 Linux中Nginx安装 vue cli部署 Linux中Nginx安装 这里找了一台Linux机器: tar –zxvf xxxxx.gz 换root来搞 ./configure make ...

最新文章

  1. AI科普微视频丨深度学习如何帮助自动驾驶
  2. java8 collect 类型转换_java8新特性之list转换
  3. Linux下MySql数据库常用操作
  4. matlab条形图添加误差线_在Excel图表中添加误差线和对误差线进行设置的技巧
  5. 13 款 JavaScript 模板引擎
  6. BZOJ4516: [Sdoi2016]生成魔咒
  7. ruby的optparse使用小记
  8. 音视频开发(39)---语音增强
  9. Linux对I/O端口资源的管理(5)
  10. 申请一个公网ip多少钱_申请1个条形码多少钱?小作坊如何申请条形码?
  11. 基于JAVA_JSP电子书下载系统
  12. VB2010中的MediaPlayer控件在哪?
  13. 7.CCNA第七天-探索数据转发
  14. 第十八期 Amesim视频教程热交换器建模仿真专题
  15. FFmpeg无损转换ts为mp4
  16. SpringMVC 406状态码
  17. 微型计算机原理中的mov,微机原理(判断题)(指令正误)
  18. ibm服务器硬盘raid检测,IBM 3650 服务器做的RAID5,两块硬盘亮黄灯,但是系统正常,更换...
  19. python检测按键按下_如何检测按键是否被按下?
  20. C#实现自定义打印文字和图片

热门文章

  1. java将中文Url转换为浏览器识别的编码
  2. php ppt转视频教程,如何制作ppt转换视频新手教程操作指南
  3. HTML5+CSS3 鼠标悬停3D立体图片效果
  4. 2010年,哪些智能手机很热门?
  5. Python生成词云图,TIIDF方法文本挖掘: 词频统计,词云图
  6. 用 WinGrub 引导Linux安装详述[转]
  7. 武汉公安携手九州云,织就荆楚平安天网
  8. oracle 五笔码函数,如何根据单元格汉字自动生成拼音码和五笔码
  9. 让Yahoo(雅虎)1G邮箱POP的配置方法
  10. 【日本动漫新番尝鲜】机动战士高达OO 第二季