Deploying contracts with truffle

Using truffle makes deploying contracts simply a matter of configuration, though the configuration is not always obvious. See below for information on truffle configuration.

Truffle v4 gives poor, or sometimes no error messages. Example.

Truffle v5* does a lot better with providing logging information and error messages. (The beta was just released at the time of writing.)

$ ./node_modules/.bin/truffle migrate --network kovan --interactive

Starting migrations...
======================
> Network name:    'kovan'
> Network id:      5
> Block gas limit: 8000000


1_initial_migration.js
======================

   Deploying 'Migrations'
   ----------------------
Error:  *** Deployment Failed ***

"Migrations" could not deploy due to insufficient funds
   * Account:  0x8B17899958A31f140F5E0104a34Fe9091744f4B7
   * Balance:  0 wei
   * Message:  Insufficient funds. The account you tried to send transaction from does not have enough funds. Required 147000000 and got: 0.
   * Try:
      + Using an adequately funded account
      + If you are using a local Geth node, verify that your node is synced.

    at /Users/andrewstewart/Code/magmo/rps-poc/truffle/node_modules/truffle/build/webpack:/packages/truffle-deployer/src/deployment.js:361:1
    at process._tickCallback (internal/process/next_tick.js:68:7)

To install and use truffle v5 (as a developer dependency)

npm install -D truffle@beta
// you'll need to update truffle-hdwallet-provider as well
npm install -D truffle-hdwallet-provider@web3-one

//usage:
./node_modules/.bin/truffle [command]

Truffle configuration

Truffle looks for configuration settings in truffle.js (apparently truffle-config.js on Windows?).

To deploy to a local development network, for testing purposes, ensure that either ganache or ganache-cli is running, and that the "development" network is configured. If truffle migrate is not passed a specific network, then development is used by default.

// truffle.js
module.exports = {
  networks: {
    development: {
      host: '127.0.0.1', // localhost
      port: 8545, // default port for ganache-cli
      network_id: '*', // match any network
      gas: 300000,
      gasPrice: 21,
    },
  }
}

To deploy to a public network, you need to either provide a connection to a local ethereum node (eg. running with geth or parity) or a "custom provider".

Syncing an ethereum node consumes a lot of disk space, and is impractical for development TODO: explore light ethereum clients.

Configuring a custom provider is a good, lightweight solution. Infura seems to work well, and is easy to configure:

// truffle.js
var HDWalletProvider = require("truffle-hdwallet-provider");
require('dotenv').config()

module.exports = {
  networks: {
    ropsten: {
      provider: () => new HDWalletProvider(process.env.MNENOMIC, "https://ropsten.infura.io/v3/" + process.env.INFURA_API_KEY),
      network_id: 3,
      gas: 4000000,
      gasPrice: 21,
    },
  }
}
// usage: truffle migrate --network ropsten

The mnenomic, stored in ${TRUFFLE_ROOT_FOLDER}/.env, generates keys according to BIP39. I used Ian Coleman's generator. Be sure to set the coin to Ethereum. By default, truffle sends transactions from the first account generated by this mnemonic, so ensure that this account has a balance on whichever network you're using (see below). This can be overruled by passing the index of the address you want to use to the provider HDWalletProvider constructor.

Test networks

Infura offers endpoints for MAINNET, the network which actually holds value, as well as three testnets: Ropsten, Rinkeby and Kovan.

Kovan seems to be the most user-friendly of the 3, with it being very simple to request "kether" (kovan-ether) via a faucet, and having fast transactions.

In comparison, this transaction on the Ropsten has been pending for over 2 hours, as of the time of writing. (This shouldn't be normal.)

See here for a brief comparison of the test networks.

Last updated