0xTrustTryEP

Just do it, deeply...

Follow me on GitHub

Truffle编译部署合约

write by donaldhan, 2020-05-19 10:01

引言

去年Facebook创世人扎克伯格关于libra听证会的中国威胁论,习主席发表了全民学习区块链的中央指导精神,一时间区块链成为了党员必须学习的知识。想到区块链,我们一般会想到比特币,以太坊,EOS,火币,BT,OKX,钱包,合约、挖矿、发币,去中心话,不可篡改,溯源,区块链金融,公有链,私有链,联盟链,联邦学习,共识机制,算力,矿机,矿产,区块链交易,DAG,EVM,加密算法,块高。你是否和我一样,一头雾水,对区块链没有一个全局的知识。我们可以通过一些区块链数据,对区块链可以有个系统的认知。如果想要学习区块链相关的技术,我们可以看一下比特币白皮书,以太坊白皮书 想要原汁原味的可以对应的官网去看。想要深入学习区块链技术,我们可以试着将创建一个区块链,体验一个挖矿,发币,写智能合约,调用合约,上链,读取连上的交易数据。今天我们先从创建一个本地以太坊区块链,使用truffle box,常见一个简单的DAPP,体验一下,合约的编译部署,和在区块链上相关的提现。

目录

相关工具准备

统一使用npm管理相关包,我们npm及node版本如下:

node, npm

PS F:\github\solidity-demo> node -v
v10.15.3
PS F:\github\solidity-demo> npm -v
6.4.1

vs code

我使用的ide是vscode,为了编写合约需要添加solidity相关的插件:

  • solidity0.0.46
  • solidity extended 3.0.2
  • solidity debugger 0.2.1

truffle框架

Truffle 是一个开发工具体系, 用于以太坊平台的开发, 测试和断言. 旨在让以太坊平台开发者更轻松的编写程序. 使用 Truffle, 你可以获得以下功能:

  • 内置只能合约编译, 集成, 部署与二进制文件管理
  • 合约自动化测试加速开发进程.
  • 可扩展的脚本化部署框架.
  • 使用网络管理功能可以管理任意数量的公网 & 私网的部署.
  • 使用EthPM & NPM做包依赖管理, 基于 ERC190 标准.
  • 可交互命令行控制台, 可以直接运行命令与合约交互.
  • 基于配置的编译过程, 支持强集成. Configurable build pipeline with support for tight integration.
  • 外部脚本运行器在 Truffle 环境下执行本地脚本.

ganache

ganache(前身testRPC)可以快速启动一个个人版以太坊区块链, 方便通过操作控制区块链来运行测试, 执行命令, 检查状态; 首先在ganache,直接安装即可。

安装完成后,我们可以创建一个新的工程或者直接快捷启动新工程方式:

ganache_init

面板说明:

ACCOUNTS:区块链账户面板
  MNEMONIC ?(助记词)
  camera venture feel cash bread market carbon olympic dawn route flavor poet
BLOCKS:区块信息面板
TRANSACTIONS:交易
CONTRACTS:合约
EVENTS:时间
LOGS:日志

SEARCH FOR BLOCK NUMBERS OR TX HASHES:根据区块编号,和交易hash搜索,区块和交易
CURRENT BLOCK 5:当前区块数
GAS PRICE 20000000000:燃机价格(gwei)
GAS LIMIT 6721975:交易燃气上限
HARDFORK PETERSBURG:硬分叉分支
NETWORK ID 5777:网络id,部署合约是会用到
RPC SERVER HTTP://127.0.0.1:7545:RCP服务地址,,部署合约是会用到
MINING STATUS AUTOMINING:自动挖矿
WORKSPACE QUICKSTART:工程名称 

通过右上角ICON,我们可以保护工作空间配置,切换,以及设置工作空间

ganache_config

设置工作空间说明:

WORKSPACE:工作空间配置
  WORKSPACE NAME(工作空间名)
    Quickstart A friendly name for this workspace.
  TRUFFLE PROJECTS(工作空间配置,关键truffle项目的配置文件)
    F:\github\solidity-demo\truffle-config.js
SERVER:服务器配置
  HOSTNAME The server will accept RPC connections on the following host and port.:RCP主机
  PORT NUMBER :RPC端口
    7545
  NETWORK ID(Internal blockchain identifier of Ganache server.)
    5777
  AUTOMINE(Process transactions instantaneously.):是否开启自动挖矿
  ERROR ON TRANSACTION FAILURE:如果开启,当交易失败,抛出一个错误;如果关闭,只能通过交易接受这的状态来判断。关闭将会是ganache想其他以太坊客户端一样,处理失败的交易。
ACCOUNTS & KEYS:区块链账户配置(初始化使用)

  ACCOUNT DEFAULT BALANCE: The starting balance for accounts, in Ether.
    100
 
  TOTAL ACCOUNTS TO GENERATE:Total number of Accounts to create and pre-fund.
    10
  
  AUTOGENERATE HD MNEMONIC:自动生成助记词,否则自己填写
    enable:Turn on to automatically generate a new mnemonic and account addresses on each run.

    camera venture feel cash bread market carbon olympic dawn route flavor poet
    note: this mnemonic is not secure; don't use it on a public blockchain.
    Enter the Mnemonic you wish to use.

  LOCK ACCOUNTS
    disable:If enabled, accounts will be locked on startup.

CHAIN: 链相关配置
  GAS:燃气设置(以太坊的合理燃气值可以参考 https://ethgasstation.info/)
    GAS LIMIT
      6721975
      Maximum amount of gas available to each block and transaction. Leave blank for default.
    GAS PRICE
      20000000000 
      The price of each unit of gas, in WEI. Leave blank for default.

HARDFORK:硬分叉分支
  HARDFORK
    Petersburg
  The hardfork to use. Default is Petersburg.
ADVANCED:高级配置
  LOGGING
  LOG FILE DIRECTORY
    F:\github\solidity-demo\log
    Path to a directory to save the timestamped log files. A separate file will be generated everytime you restart Ganache. It is recommended to create a directory just for these logs.
  VERBOSE LOGS
    Verbose Logs:Increase the log output.
  ANALYTICS
    GOOGLE ANALYTICS
    We use Google Analytics to track Ganache usage. This information helps us gain more insight into how Ganache is used. This tracking is anonymous. We do not track personally identifiable information, account data or private keys.
  Note: This setting is global and will persist between workspaces.
ABOUT
CANCEL
RESTART

修改配置后,需要保存配置,同时重启后,方能生效,重启过后,将是一个全新的个人版以太坊区块链。

我使用的直接快捷启动新工程方式,设置WORKSPACE关联truffle工程 ganache-link-truffle-project

然后保存,重新启动工程。这是我们已经可以在ganache的contact中看到没有编译的合约;

ganache_contact

我们也可以使用ganache-cli模式,可以更清楚的理解区块链底层的操作;当前我使用的是ganache,有兴趣可以 亲测一下ganache-cli模式。

具体准备完毕,我们来撸起袖子,骚起来。

创建truffle工程

我们使用truffle box来,快速创建一个工程。

通过以下命令,可以拉取truffle box

mkdir solidity-demo
cd solidity-demo
truffle init

init,实际初始化的也是unbox,也可以通过

truffle unbox metacoin

truffle box命令打开一个truffle box(可以理解为相关合约demo) metacoin; truffle盒子包含一些有用的模块,solidity合约和lib,及前端view等。所有的box都是一个简单dapps项目,更多参见:

文件目标及配置说明

https://github.com/truffle-box/metacoin-box 我们首先将metaCoin拉到本地,仓库下有一下几个文件夹:

  • contracts/: 存储 Solidity 智能合约目录,含ConvertLib.sol MetaCoin.sol Migrations.sol
  • migrations/: 存储 部署脚本文件目录
  • test/: 存储 项目和智能合约测试用例目录
  • truffle.js: Truffle 配置文件

注意配置文件中有ganache的信息:,

 ganache: {
      host: "127.0.0.1", // Localhost (default: none)
      port: 7545, // Standard Ethereum port (default: none)
      network_id: "5777", // Any network (default: none)
}

以及环境配置

 development: {
        host: "127.0.0.1",
        port: 9545,
        // network_id: "4777" 
        network_id: "*" // Match any network id
}

默认我们使用的是development;

我们也可以配置更高级的属性,公有链,私有链环境

    // Another network with more advanced options...高级属性
    // advanced: {
      // port: 8777,             // Custom port
      // network_id: 1342,       // Custom network
      // gas: 8500000,           // Gas sent with each transaction (default: ~6700000)
      // gasPrice: 20000000000,  // 20 gwei (in wei) (default: 100 gwei)
      // from: <address>,        // Account to send txs from (default: accounts[0])
      // websockets: true        // Enable EventEmitter interface for web3 (default: false)
    // },

    // Useful for deploying to a public network. 公有链
    // NB: It's important to wrap the provider as a function.
    // ropsten: {
      // provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`),
      // network_id: 3,       // Ropsten's id
      // gas: 5500000,        // Ropsten has a lower block limit than mainnet
      // confirmations: 2,    // # of confs to wait between deployments. (default: 0)
      // timeoutBlocks: 200,  // # of blocks before a deployment times out  (minimum/default: 50)
      // skipDryRun: true     // Skip dry run before migrations? (default: false for public nets )
    // },

    // Useful for private networks 私有链
    // private: {
      // provider: () => new HDWalletProvider(mnemonic, `https://network.io`),
      // network_id: 2111,   // This network is yours, in the cloud.
      // production: true    // Treats this network as if it was a public net. (default: false)
    // }
  }

编译合约

在终端使用如下 truffle compile 命令,编译合约

PS F:\github\solidity-demo> truffle compile

Compiling your contracts...
===========================
> Compiling .\contracts\ConvertLib.sol
> Compiling .\contracts\MetaCoin.sol
> Artifacts written to F:\github\solidity-demo\build\contracts
> Compiled successfully using:
   - solc: 0.5.8+commit.23d335f2.Emscripten.clang

编译将生成对应的工件文件存储在相对于该项目的根路径的 build/contracts/ 文件夹中. (文件夹不存在将自动创建). 这些工件是 Truffle 进行后面工作的核心, 在后续部署应用的时候也非常有用. 该文件无需手动编辑, 重新执行编译命令会覆盖原文件.

这个时候,从ganache的contact中编译好的合约这是已经可以部署了,已经可以在ganace的contact中看到。 ganache_contact

use the ganace client, can brower the account, blocks, transactions, contact, events.

这个时候我们已经可以,部署合约了,使用命令 truffle migrate 部署合约

部署合约

PS F:\github\solidity-demo> truffle migrate

Compiling your contracts...
===========================
> Compiling .\contracts\ConvertLib.sol
> Artifacts written to F:\github\solidity-demo\build\contracts
> Compiled successfully using:
   - solc: 0.5.8+commit.23d335f2.Emscripten.clang

<!-- 开始部署 -->
Starting migrations...
======================
> Network name:    'development'
> Network id:      5777
> Block gas limit: 0x6691b7

<!-- 部署Migrations合约 -->
1_initial_migration.js
======================

<!-- 部署合约信息(校验地址,合约地址,块高,生成区块的时间,账户地址,账户余额,消耗gas,gas价格,发生的交易值,总共消耗的ETH) -->
   Replacing 'Migrations'
   ----------------------
   > transaction hash:    0xf5ae6f20fbc4e298604a2ef11e0c1304a70618fca6f29a671b049a444f72174b
   > Blocks: 0            Seconds: 0
   > contract address:    0x173Fb7636A8EC88E902de1c77f152F69e58d9856
   > block number:        1
   > block timestamp:     1581931602
   > account:             0x209F9f4F4f38a8b966f905F90f451F235136420C
   > balance:             99.99477214
   > gas used:            261393
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.00522786 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:          0.00522786 ETH


<!-- 部署ConvertLib -->
2_deploy_contracts.js
=====================

   Replacing 'ConvertLib'
   ----------------------
   > transaction hash:    0x3a40e512d3fe9c3b624a4164f3d0cfb70ee3374654545ac174f8e3aa1fd8c586
   > Blocks: 0            Seconds: 0
   > contract address:    0x73b516ab48Eb24ee42C7E092Cf1E00473B0eaEA3
   > block number:        3
   > block timestamp:     1581931603
   > account:             0x209F9f4F4f38a8b966f905F90f451F235136420C
   > balance:             99.99185922
   > gas used:            103623
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.00207246 ETH

<!-- 关联ConvertLib -> MetaCoin, 并部署MetaCoin -->
   Linking
   -------
   * Contract: MetaCoin <--> Library: ConvertLib (at address: 0x73b516ab48Eb24ee42C7E092Cf1E00473B0eaEA3)

   Replacing 'MetaCoin'
   --------------------
   > transaction hash:    0xfd5fbb7b4af182feee9c5773055af098a22dfe0df1f8b60a963a6f94e8f90eb5
   > Blocks: 0            Seconds: 0
   > contract address:    0x42e2A31b636e8f1D099d76F2b6319905FEf02067
   > block number:        4
   > block timestamp:     1581931603
   > account:             0x209F9f4F4f38a8b966f905F90f451F235136420C
   > balance:             99.98509352
   > gas used:            338285
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.0067657 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:          0.00883816 ETH


Summary
=======
> Total deployments:   3
> Final cost:          0.01406602 ETH

PS F:\github\solidity-demo>

这个时候,合约已经部署并且有了合约地址: ganache_contact_compile

同时新生成5个区块 ganache_block 其中0区块,即是创世纪区块。

产生5个交易

ganache_transactions 这里为什么已3个创建合约2个调用合约? 项目中,总共有3个合约如下; Migrations.sol,ConvertLib.sol,MetaCoin.sol; 在部署合约的过程,5个交易如下:

  1. 首先使用1_initial_migration.js创建合约Migrations.sol; migrations_contact_create 交易说明:
    TX 0xf5ae6f20fbc4e298604a2ef11e0c1304a70618fca6f29a671b049a444f72174b:交易地址
    SENDER ADDRESS 0x209F9f4F4f38a8b966f905F90f451F235136420C:部署合约账户地址
    CONTRACT CREATION:创建合约
    VALUE 0.00 ETH:交易额
    GAS USED 261393:消耗燃气
    GAS PRICE 20000000000:燃气价格
    GAS LIMIT 6721975:燃气限制(如果创建交易的过程中,超过燃气值,交易失败,但部署的过程燃气值不会退回)
    MINED IN BLOCK 1:在区块1中挖得
    TX DATA: 交易数据
    EVENTS:事件
    
  2. 合约Migrations.sol部署完毕 migrations_contact_create_finish

交易说明

TX 0xcec5b221f177cc892aba017f2a7f26d116c5144ca8e307ed65c4560450ca9855
SENDER ADDRESS 0x209F9f4F4f38a8b966f905F90f451F235136420C:调用合约账户地址
TO CONTRACT ADDRESS 0x173Fb7636A8EC88E902de1c77f152F69e58d9856:被调用合约
CONTRACT CALL:调用合约
VALUE 0.00 ETH
GAS USED 42023
GAS PRICE 20000000000
GAS LIMIT 6721975
MINED IN BLOCK 2:在区块2中挖得
TX DATA
CONTRACT:被调用的合约信息
  CONTRACT Migrations:被调用合约
  ADDRESS 0x173Fb7636A8EC88E902de1c77f152F69e58d9856:被调用合约地址
  FUNCTION setCompleted(completed: uint256):被调用的合约操作
  INPUTS 1 :入参
EVENTS
  1. 调用2_deploy_contracts.js部署ConvertLib合约; convertLib_contact_create

  2. 调用2_deploy_contracts.js部署MetaCoin合约; metacoin_contact_create

  3. 部署ConvertLib.sol,MetaCoin.sol完毕; convertLib_metacoin_contact_create_finish

从上面可以看出,部署合约使用的都是同一个账户: SENDER ADDRESS 0x209F9f4F4f38a8b966f905F90f451F235136420C

这个账户就是初始化10个账户中的0号账户,accounts[0]:

ganache_migrations_account

在整个部署合约的过程中,使用账号0,大概消耗了0.014ETH。

在部署过程中,每个交易对应一个区块,我们来看一下,5个区块的信息 ganache_block 我们只看两个,其他几个类似

block_create_contact 区块说明:

BLOCK 1:区块编号
GAS USED 261393
GAS LIMIT 6721975
MINED ON 2020-02-17 17:26:42:挖矿成功时间
BLOCK HASH 0x72f8b6ba3ee4852ef61fa82379559624139dd6833d87d1e0d353d676542fe92c:区块地址
TX HASH 0xf5ae6f20fbc4e298604a2ef11e0c1304a70618fca6f29a671b049a444f72174b:交易地址
CONTRACT CREATION:创建合约
FROM ADDRESS 0x209F9f4F4f38a8b966f905F90f451F235136420C:创建合约账户
CREATED CONTRACT ADDRESS 0x173Fb7636A8EC88E902de1c77f152F69e58d9856:合约地址
GAS USED 261393
VALUE 0

区块3,4类似,都是创建合约区块;

block_call_contact 区块说明:

BLOCK 2
GAS USED 42023
GAS LIMIT 6721975
MINED ON 2020-02-17 17:26:42
BLOCK HASH 0x12f09b7a991a34c482bb01b7cef587137ddf03cb9326cc07ab594f96eba0a1d9
TX HASH 0xcec5b221f177cc892aba017f2a7f26d116c5144ca8e307ed65c4560450ca9855
CONTRACT CALL:调用合约
FROM ADDRESS 0x209F9f4F4f38a8b966f905F90f451F235136420C
TO CONTRACT ADDRESS Migrations:被调用合约
GAS USED 42023
VALUE 0

区块5类似,都是调用合约区块;

我们再来看一下部署后的合约信息

ganache_contact_compile

  • Migrations合约 migrations_contact

具体合约信息如下:

Migrations:合约基本信息 ADDRESS:合约地址 0x173Fb7636A8EC88E902de1c77f152F69e58d9856 BALANCE 0.00 ETH CREATION TX:合约创建时的交易地址 0xeCD1E4A721aC083ed8B1a2f2b393f887Ee3Cdf3430d8238273d91304Be36b140 STORAGE:合约相关数据

{2 items last_completed_migration:uint2 owner:address”0x209F9f4F4f38a8b966 …” } TRANSACTIONS:合约上产生的交易信息 TX HASH 0x723fc2b2be939cc9e0ec50436bbc9b1941971985103bb16257dbdaf722078d58 CONTRACT CALL FROM ADDRESS 0x209F9f4F4f38a8b966f905F90f451F235136420C TO CONTRACT ADDRESS Migrations GAS USED 27023 VALUE 0 EVENTS:合约相关的事件 NO EVENTS 合约明细上我们可以看出,合约详情中包括基本信息(合约地址,账户余额,合约创建时的交易地址),合约相关数据,合约上产生的交易信息,合约相关的事件。

再来简单看一下其他两个合约

  • ConvertLib合约 convertlib_contract

  • MetaCoin合约 metacoin_contact

总结

我们首先简单罗列了区块链合约开发相关的工具(npm,ide:vscode,ganache:以太坊区块链)。使用ganache我们可以快速启动一个个人版以太坊区块链, 方便通过操作控制区块链来运行测试, 执行命令, 检查区块链相关的状态;通过ganache我们可以简单的管理区块链账户、区块、交易、合约、事件及日志。同时我们可以使用ganache的设置区块相关的配置,比如初始化账户,账户金额,是否锁定账户,配置RCP地址和端口,上链配置(燃气值,燃气价格),以及通过工作空间配置,将ganache和truffle工程关联起来,一般将truffle工程中的合约部署到,ganache创建的本地区块链上。在了解了以太坊客户端ganache使用之后,我们使用truffle box创建了最基础的metacoin, 使用truffle的相关命令,编译,以及部署了相关合约,并根据使用Ganache客户端,对合约的编译,和部署进行了分析。针对合约,一个交易主要包含 交易地址、部署合约账户地址、合约操作(创建合约、调用合约),交易额(针对转账),消耗燃气,燃气价格 ,燃气限制(如果创建交易的过程中,超过燃气值,交易失败,但部署的过程燃气值不会退回),关联区块,交易数据及事件等信息。针对合约,一个区块主要包含,区块编号,消耗燃气,燃气限制,区块形成时间,区块地址,交易地址 交易类型(创建合约、调用合约),创建合约账户,合约地址,交易额(针对转账)。合约详情中包括基本信息(合约地址,账户余额,合约创建时的交易地址),合约相关数据,合约上产生的交易信息,合约相关的事件。

编译单个合约

PS F:\github\solidity-demo> truffle compile .\contracts\MetaCoin.sol

Compiling your contracts...
===========================
> Compiling .\contracts\ConvertLib.sol
> Artifacts written to F:\github\solidity-demo\build\contracts
> Compiled successfully using:
   - solc: 0.5.8+commit.23d335f2.Emscripten.clang

PS F:\github\solidity-demo>

部署脚本

1_initial_migration.js

const Migrations = artifacts.require("Migrations");

module.exports = function(deployer) {
  //部署Migrations合约
  deployer.deploy(Migrations);
};

2_deploy_contracts.js

const ConvertLib = artifacts.require("ConvertLib");
const MetaCoin = artifacts.require("MetaCoin");

module.exports = function(deployer) {
  //部署合约ConvertLib
  deployer.deploy(ConvertLib);
  //关联合约ConvertLib,到MetaCoin
 /*  因为在MetaCoin中,有引用ConvertLib合约 
 import "./ConvertLib.sol";
 */
  deployer.link(ConvertLib, MetaCoin);
  //部署MetaCoin合约
  deployer.deploy(MetaCoin);
};

相关问题

The network id specified in the truffle config (4447) does not match the one returned by the network (5777)

$ truffle test ./test/metacoin.js
Error: The network id specified in the truffle config (4447) does not match the one returned by the network (5777).  Ensure that both the network and the provider are properly configured.
    at Object.detectAndSetNetworkId (C:\Users\hanshaoqing\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\truffle-environment\environment.js:94:1)
    at process._tickCallback (internal/process/next_tick.js:68:7)
Truffle v5.0.30 (core: 5.0.30)
Node v10.15.3

如果遇见上面的问题,是有与运行单元测试用例的时候,无法连接ETH网络节点,这时,只需要在truffle.js文件中配置如下:

networks: {
    // Useful for testing. The `development` name is special - truffle uses it by default
    // if it's defined here and no other network is specified at the command line.
    // You should run a client (like ganache-cli, geth or parity) in a separate terminal
    // tab if you use this network and you must also set the `host`, `port` and `network_id`
    // options below to some value.
      ganache: {
      host: "127.0.0.1", // Localhost (default: none)
      port: 7545, // Standard Ethereum port (default: none)
      network_id: "5777", // Any network (default: none)
      },
      development: {
        host: "127.0.0.1",
        port: 9545,
        // network_id: "4777" 
        network_id: "*" // Match any network id
      }
    //
    // development: {
    //  host: "127.0.0.1",     // Localhost (default: none)
    //  port: 8545,            // Standard Ethereum port (default: none)
    //  network_id: "*",       // Any network (default: none)
    // },

    // Another network with more advanced options...
    // advanced: {
      // port: 8777,             // Custom port
      // network_id: 1342,       // Custom network
      // gas: 8500000,           // Gas sent with each transaction (default: ~6700000)
      // gasPrice: 20000000000,  // 20 gwei (in wei) (default: 100 gwei)
      // from: <address>,        // Account to send txs from (default: accounts[0])
      // websockets: true        // Enable EventEmitter interface for web3 (default: false)
    // },

    // Useful for deploying to a public network.
    // NB: It's important to wrap the provider as a function.
    // ropsten: {
      // provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`),
      // network_id: 3,       // Ropsten's id
      // gas: 5500000,        // Ropsten has a lower block limit than mainnet
      // confirmations: 2,    // # of confs to wait between deployments. (default: 0)
      // timeoutBlocks: 200,  // # of blocks before a deployment times out  (minimum/default: 50)
      // skipDryRun: true     // Skip dry run before migrations? (default: false for public nets )
    // },

    // Useful for private networks
    // private: {
      // provider: () => new HDWalletProvider(mnemonic, `https://network.io`),
      // network_id: 2111,   // This network is yours, in the cloud.
      // production: true    // Treats this network as if it was a public net. (default: false)
    // }
  },

  // Set default mocha options here, use special reporters etc.
  mocha: {
    // timeout: 100000
  }

即可,具体原因是由于network_id不匹配导致的;

修改

   development: {
        host: "127.0.0.1",
        port: 9545,
        network_id: "4777" 
      }

如下

   development: {
        host: "127.0.0.1",
        port: 9545,
        // network_id: "4777" 
        network_id: "*" // Match any network id
      }

使用ganache报如下错误(Error: EPERM: operation not permitted, rename )

Error: EPERM: operation not permitted, rename 'C:\Users\hanshaoqing\AppData\Roaming\Ganache\workspaces\wise-home\Settings.2736138938' ->
'C:\Users\hanshaoqing\AppData\Roaming\Ganache\workspaces\wise-home\Settings'
    at Object.fs.renameSync (fs.js:772:18)
    at writeFileSync (C:\Program Files\WindowsApps\Ganache_2.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\node_modules\write-file-atomic\index.js:124:8)
    at LocalStorage.setItem (C:\Program Files\WindowsApps\Ganache_2.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\node_modules\node-localstorage\LocalStorage.js:188:7)
    at JsonStorage.setToStorage (C:\Program Files\WindowsApps\Ganache_2.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\src\main\types\json\JsonStorage.js:72:20)
    at JsonStorage.set (C:\Program Files\WindowsApps\Ganache_2.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\src\main\types\json\JsonStorage.js:78:12)
    at WorkspaceSettings.set (C:\Program Files\WindowsApps\Ganache_2.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\src\main\types\settings\Settings.js:89:21)
    at Workspace.saveAs (C:\Program Files\WindowsApps\Ganache_2.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\src\main\types\workspaces\Workspace.js:91:21)
    at EventEmitter.<anonymous> (C:\Program Files\WindowsApps\Ganache_2.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\src\main\main.js:532:24)
    at Generator.next (<anonymous>)
    at step (C:\Program Files\WindowsApps\Ganache_2.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\src\main\main.js:71:191)
    at C:\Program Files\WindowsApps\Ganache_2.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\src\main\main.js:71:361
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

这个是由于,可能是由于我装ganache-cli和web3失败导致到

npm install ganache-cli web3@0.20.2

这个ganache bug,当前还没有好的解决办法. 可以参考如下链接:

https://github.com/trufflesuite/ganache/issues/1466

https://stackoverflow.com/questions/39293636/npm-err-error-eperm-operation-not-permitted-rename

反正我是没有解决(!!!)

Could not connect to your Ethereum client

PS F:\github\solidity-demo> truffle migrate

Compiling your contracts...
===========================
> Compiling .\contracts\ConvertLib.sol
> Artifacts written to F:\github\solidity-demo\build\contracts
> Compiled successfully using:
   - solc: 0.5.8+commit.23d335f2.Emscripten.clang


Could not connect to your Ethereum client with the following parameters:
    - host       > 127.0.0.1
    - port       > 9545
    - network_id > *
Please check that your Ethereum client:
    - is running
    - is accepting RPC connections (i.e., "--rpc" option is used in geth)
    - is accessible over the network
    - is properly configured in your Truffle configuration file (truffle-config.js)

Truffle v5.0.30 (core: 5.0.30)
Node v10.15.3
PS F:\github\solidity-demo>

从上面可以看出,主要是因为部署环境配置的端口和ganache的端口不一致导致的,配置一致即可;ganache的默认端口为7545。 ganache_server_port 修改配置

  development: {
        host: "127.0.0.1",
        port: 9545,
        // network_id: "4777" 
        network_id: "*" // Match any network id
      }

development: {
        host: "127.0.0.1",
        // port: 9545,
        port: 7545,
        // network_id: "4777" 
        network_id: "*" // Match any network id
}