Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

[WIP] V5 release notes #1129

Closed
wants to merge 12 commits into from
Closed

[WIP] V5 release notes #1129

wants to merge 12 commits into from

Conversation

cgewecke
Copy link
Contributor

@cgewecke cgewecke commented Jul 20, 2018

DO NOT MERGE - this is here so people can do review stuff to it if they want to.
Good day! We're pleased to announce the first beta release of Truffle v5. With this release, we're excited to bring you some new features and improvements that will make your life easier.

What's included, you ask? Well, get ready to use whatever Solidity version you want (Truffle will even automatically download it for you.) Or how about an improved migrations system, which dry-runs by default and provides lots of information to understand what is going right or wrong. Maybe you've been waiting for Web3.js 1.0. Perhaps you're sick of typing .then() and want to use await in the console. Truffle v5 has all of this, and more!

If you're as excited as we are and can't wait, here's how to upgrade:

npm uninstall -g truffle
npm install -g truffle@beta

Or keep reading for more information!

Release Contents

Bring your own compiler

It's now possible to have Truffle compile with:

  • any solc-js version listed at solc-bin. Specify the one you want and Truffle will get it for you.
  • a natively compiled solc binary (you'll need to install this yourself, links to help below).
  • dockerized solc from one of images published here. (You'll also need to pull down the docker image yourself but it's really easy.)

List available versions at the command line

$ truffle compile --list                   # Recent stable releases from solc-bin (JS)
$ truffle compile --list prereleases       # Recent prereleases from solc-bin (JS)
$ truffle compile --list docker            # Recent docker tags from hub.docker.com
$ truffle compile --list releases --all    # Complete list of stable releases.

Specify a solcjs version

Set the compilers solc version key to the one you'd like. Truffle will fetch it from the solc-bin server and cache it in your local evironment.

module.exports = {
  networks: {
    ... etc ...
  },
  compilers: {
     solc: {
       version: <string>  // ex:  "0.4.20". (Default: Truffle's installed solc)
     }
  }
};

Advanced

  • docker
  • native binary
  • path/to/solc
  • solc settings

Docker images should be installed locally by running:

$ docker pull ethereum/solc:0.4.22  // Example image

truffle.js

// Native binary
compilers: {
  solc: {
    version: "native"
  }
}

// Docker
compilers: {
  solc: {
    version: "0.4.22",   // Any published image name
    docker: true
  }
}

// Relative or absolute path to an npm installed solc-js
compilers: {
  solc: {
    version: "/Users/axic/.nvm/versions/node/v8.9.4/lib/node_modules/solc"
  }
}

// Optimization and EVM version settings
compilers: {
  solc: {
    settings: {
      optimizer: {
        enabled: true, // Default: false
        runs: 1000     // Default: 200
      },
      evmVersion: "homestead"  // Default: "byzantium"
    }
  }
}

Speed comparison

Docker and native binary compilers process large contract sets faster than solcjs. If you're just compiling a few contracts at a time, the speedup isn't significant relative to the overhead of running a command (see below). The first time Truffle uses a docker version there's a small delay as it caches the solc version string and a solcjs companion compiler. All subsequent runs should be at full speed.

Times to truffle compile on a MacBook Air 1.8GHz, Node 8.11.1

Project # files solcjs docker bin
truffle/metacoin-box 3 4.4s 4.4s 4.7s
gnosis/pm-contracts 34 21.7s 10.9s 10.2s
zeppelin-solidity 107 36.7s 11.7s 11.1s

For help installing a natively built compiler, see the Solidity docs here.

Contract Profiling

Truffle has always tried figure out which contracts changed recently and compile the smallest set necessary (with varying degrees of success). It now does this reliably so you may benefit from setting up an npm convenience script that looks like this:

"test": "truffle compile && truffle test"

Many thanks to the Solidity team for making all of the above possible and for their helpful advice over the last year. 🙌 🙌

🐇 🐇 Web3.js 1.0 🐇 🐇

truffle-contract now uses Web3.js 1.0 under the hood. It's nice! The error handling (especially the parameter checking) is really good. And there's lots of new work happening over there - ENS support is being added and EthPrize is funding an API to make contract packages published to EthPM easily available as well.

We've tried to minimize the inconvenience involved in transitioning an existing test suite from Web3 0.x to 1.0. Unfortunately there are some breaking changes due to differences in the way Web3 1.0 formats outputs (see chart below).

The biggest of these is that truffle-contract now returns numbers as BN by default instead of BigNumber. This is necessary - BigNumber doesn't have the precision required by the EVM. The number libraries share some methods (notably .toNumber()) but their arithmetic operations are quite different.

Important: If you receive a number directly from Web3 (e.g. not from a truffle-contract instance) you'll get a string. Luckily there's a helpful BN conversion method in the Web3 utils.

const stringBalance = await web3.eth.getBalance('0xabc..');
const bnBalance = web3.utils.toBN(stringBalance);

Helpful Resources

  • Web3 1.0's documentation. Well worth taking a look - lots of differences in their new API.
  • EthWork's bn-chai library: BN helpers for your tests. (💡 ProTip courtesy elenadimitrova)

⚠️ Breaking Changes ⚠️

Category v4 (Web3 0.0) v5 (Web3 1.0)
addresses (return value) lower-case check-summed (mixed-case)
numbers (return value) BigNumber BN (configurable)
tuples (return value) Array Object w/ named & indexed keys
.contract (underlying Web3 abstraction) same as now completely different
.at (TruffleContract method) sync / then-able async

🍨 Features 🍨

Methods / .new have an EventEmitter interface and return a promise.

const example = await artifacts.require("Example").deployed();

example
  .setValue(45)
  .on('transactionHash', hash => {} )
  .on('receipt', receipt => {})
  .on('error', error => {})
  .on('confirmation', (num, receipt) => {} )
  .then( receipt => {} )

Events have an EventEmitter interface

example
  .ExampleEvent()
  .on('data', event => ... etc ... )

example
  .ExampleEvent()
  .once('data', event => ... etc ... )

Reason strings!! Find out the reason.

Solidity

require(msg.sender == owner, 'not authorized');

Javascript

try {
  await example.transferToSelf({from: nonOwner})
} catch (err) {
  assert(err.reason === 'not authorized');
  assert(err.message.includes('not authorized');
}

Overloaded Solidity methods (credit to @rudolfix and @mcdee)

example.methods['setValue(uint256)'](123);
example.methods['setValue(uint256,uint256)'](11,55);

Configure number return format

As mentioned above - truffle-contract now returns BN. We've made this configurable so if you have an existing test suite you'd prefer to gradually transition from BigNumber to BN, it's possible to configure a contract's number format as below.

// Choices are:  `["BigNumber", "BN", "String"].
const Example = artifacts.require('Example');
Example.numberFormat = 'BigNumber';

Call methods at any block using the defaultBlock parameter.

const oldBlock = 777;
const valueInThePast = await example.getBalance("0xabc..545", oldBlock);

Automated fueling for method calls and deployments.

Example.autoGas = true;   // Defaults to true
Example.gasMultiplier(1.5) // Defaults to 1.25
const instance = await Example.new();
await instance.callExpensiveMethod();

Contract deployments & transactions allowed to take as long as they take

Example.timeoutBlocks = 10000;
const example = await Example.new(1);
// Later....
await example.setValue(5)

Gas estimation for .new

const deploymentCost = await Example.new.estimateGas();

Config

To take advantage of the confirmations listener and to hear Events using .on or .once, you'll need to enable websockets in your network config as below.

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

🐦 🐦 New Migrations 🐦 🐦

Deploying contracts to public networks is hard ... 🙂 The topic dominates our 10 most visited GitHub issues. On the bright side, those discussion threads are a rich trove of advice and brilliant insight from experienced Truffle users. V5 includes a rewrite of the migrations command that tries to integrate all their hard won knowledge into an easier to use deployment manager.

Features

  • Improved error messaging. If Truffle can guess why a deployment failed it tells you and suggests some possible solutions.
  • More information about what's going on as you deploy, including cost summaries and real-time status updates about how long transactions have been pending. (See GIF below)
  • Improved dry run deployment simulations. This feature has had it's kinks worked out and now runs automatically if you're deploying to a known public network. You can also use the --interactive flag at the command line to get a prompt between your dry run and real deployment.
  • Configure the number of block confirmations to wait between deployments. This is helpful when deploying to Infura because their load balancer sometimes executes back-to-back transactions out of sequence and noncing can go awry.
  • Specify how many blocks to wait before timing out a pending deployment. Web3 hardcodes this value at 50 blocks which can be a problem if you're trying to deploy large contracts at the lower end of the gas price range.
  • A deployer interface that works seamlessly with ES6 async/await syntax. (Also backward compatible with Truffle V4's then-able pattern.)

⚠️ Important ⚠️ If you're using truffle-hdwallet-provider with Truffle v5 you must install the Web3 1.0 enabled version:

$ npm install --save truffle-hdwallet-provider@web3-one

Configuration and use

Example network config

ropsten: {
  provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io`),
  network_id: 3,
  gas: 5500000,           // Default gas to send per transaction
  gasPrice: 10000000000,  // 10 gwei (default: 20 gwei)
  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 )
},

Example Migration using async / await

const One = artifacts.require("One");
const Two = artifacts.require("Two");

module.exports = async function(deployer) {
  await deployer.deploy(One);

  const one = await One.deployed();
  const value = await one.value();

  await deployer.deploy(Two, value);
};

Deploying to Rinkeby...

migrate-rinkeby

More migrations improvements are coming soon....

  • cag from Gnosis has written a really nice addition to the Migrations module that will automatically deploy contract dependencies you've installed with npm along with your own contracts.
  • Under the hood, the migrations command is now completely evented and managed by a reporter module. Those hooks will be exposed so anyone can write a UI for it and hopefully you'll be plugging into ever more sophisticated deployment script managers soon. Work on the default UI to make it more interactive and colorful is ongoing.

Even More!

truffle-console now supports async/await

A small but decisive improvement that should make the console much easier to use.
Example

truffle(development)> let instance = await MetaCoin.deployed()
truffle(development)> let accounts = await web3.eth.getAccounts()
truffle(development)> let balance = await instance.getBalanceInEth(accounts[0])
truffle(development)> balance.toNumber()
20000
truffle(development)>

External compiler support

For more advanced use cases, let's say your smart contract development workflow involves more than just compiling Solidity contracts. Maybe you're writing eWASM precompiles or making a two-dimensional delegatecall proxy. Or maybe you would just rather use @pubkey's solidity-cli instead of Truffle's solc configuration.

This is now supported by adding a compilers.external object to your Truffle config:

{
  /* ... */

  compilers: {
    /* ... */

    external: {
      command: "./compile-contracts",
      targets: [{
        /* compilation output */
      }]
    }
  }

  /* ... */
}

When you run truffle compile, Truffle will run the configured command and look for contract artifacts specified by targets.

This new configuration supports two main use cases:

  • Your compilation command outputs Truffle JSON artifacts directly
  • Your compilation command outputs individual parts of an artifact, and you want Truffle to generate the artifacts for you.

Credit to @axic for the idea and for helping to hone our requirements as we implemented it. Thank you!

Target generated artifacts

If your compilation command generates artifacts directly, or generates output that contains all the information for an artifact, configure a target as follows:

{
  compilers: {
    external: {
      command: "./compile-contracts",
      targets: [{
        path: "./path/to/artifacts/*.json"
      }]
    }
  }
}

Truffle will expand the glob (*) and find all .json files in the listed path and copy those over as artifacts in the build/contracts/ directory.

Post-processing artifacts

The above use case might not be sufficient for all use cases. You can configure your target to run an arbitrary post-processing command:

{
  compilers: {
    external: {
      command: "./compile-contracts",
      targets: [{
        path: "./path/to/preprocessed-artifacts/*.json",
        command: "./process-artifact"
      }]
    }
  }
}

This will run ./process-artifact for each matched .json file, piping the contents of that file as stdin. Your ./process-artifact command is then expected to output a complete Truffle artifact as stdout.

Want to provide the path as a filename instead? Add stdin: false to your target configuration.

Target individual artifact properties

The other way to configure your external compilation is to specify the individual properties of your contracts and have Truffle generate the artifacts itself:

{
  compilers: {
    external: {
      command: "./compile-contracts",
      targets: [{
        properties: {
          contractName: "MyContract",
          /* other literal properties */
        },
        fileProperties: {
          abi: "./output/contract.abi",
          bytecode: "./output/contract.bytecode",
          /* other properties encoded in output files */
        }
      }]
    }
  }
}

Specify properties and/or fileProperties, and Truffle will look for those values when building the artifacts.

These two approaches aim to provide flexibility, aiming to meet whatever your compilation needs may be.

Debugger mapping support

Mappings are now supported in truffle-debugger. Truffle will keep track of known mapping keys and let you inspect your contract's mapping variables with the v command. What's more, this means you can inspect mappings of structs and structs of mappings, etc.!

Acknowledgements

We'd like to extend a huge thank you to our community, our users, and our contributors, who have all been instrumental in helping us get this this point. We hope you enjoy this beta and all of Truffle's new features.

Please let us know if you find any problems or have any suggestions for making this release better. 🙇

@rudolfix
Copy link

I hope there's a trick to still have BigNumbers returned in case of numbers

@cgewecke
Copy link
Contributor Author

@rudolfix So far the only trick I have is making strings have a toNumber method by overloading the String prototype. PR pending.

What do you advise?

@cgewecke
Copy link
Contributor Author

cgewecke commented Jul 20, 2018

I think I'm going to look at chai-bignumber and see if there's some trick I can steal from that
I think I'm just going to return BigNumber BN for now . . .

@cgewecke cgewecke requested review from gnidan and tcoulter August 9, 2018 01:06
@cgewecke
Copy link
Contributor Author

cgewecke commented Aug 9, 2018

@gnidan @tcoulter This might be too much detail but here's a first draft of the beta release notes.

@gnidan gnidan mentioned this pull request Aug 9, 2018
7 tasks
Copy link
Contributor

@gnidan gnidan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fabulous @cgewecke!

Here's some notes that are mostly polish-level things. Let me know what I can help out with, so you don't have to implement all my pedantry yourself.

release.md Outdated

## 1. All SOLC.

It's now possible to have truffle compile with:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Truffle

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The all capped now.

release.md Outdated
⚠️ **Early draft. Details subject to change.** ⚠️

# 🐘 🐘 V5 🐘 🐘 🐘

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(just a reminder: we'll need a preamble.)

release.md Outdated

# 🐘 🐘 V5 🐘 🐘 🐘

## 1. All SOLC.
Copy link
Contributor

@gnidan gnidan Aug 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove the indexes for these headers, and instead have a table of contents at the top. There's a lot here. It'd be nice to lay it all out upfront.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah very good idea!!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put a small TOC in but it doesn't scroll - not sure if it's because it's in a comment or the links are bad. Probably need to work on this in the release context.

release.md Outdated
```

### Advanced:
+ docker
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note for full release: this a great list of things we'll have to remember to document. Making an issue for full-relesae checklist #1176 so we can add stuff as we think of it.

"test": "truffle compile && truffle test"
```

Many thanks to the Solidity team for making all of the above possible and for their helpful advice over the last year. 🙌 🙌
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I second this ------------------------------------------^

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That second pair of hands is yours!

release.md Outdated

### Methods / `.new` have an EventEmitter interface *and* return a promise.
```javascript
example
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these examples, I think it's helpful to include a line above:

const example = await artifacts.require("Example").deployed();

Well, maybe not, because that kind of clashes with the .then() syntax we're showing off.

Wait, is this now possible?:

let receipt = await example
  .setValue(123)
  .on('transactionHash', hash => {})
  /* ... */
  .on('confirmation', (num, receipt) => {} )

Anyway, my point is that it's probably worth showing a more complete example so there's literally no guesswork.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm. Yeah I could go either way - I think I had it as you've shown it originally but when I looked at the web3 docs they used the then which seemed clearer.

Like there's also a weird temporal thing about lines above happening before lines below. In the receipt example - receipt resolves after the txHash fires and that seemed weird to me.

Am I crazy lol?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the require.

```javascript
example
.ExampleEvent()
.on('data', event => ... etc ... )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I am reading this, I am getting giddy.

assert(err.reason === 'not authorized');
assert(err.message.includes('not authorized');
}
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be broken up:

Solidity:

require(msg.sender == owner, 'not authorized');

Javascript:

try {
  await example.transferToSelf({from: nonOwner})
} catch (err) {
  assert(err.reason === 'not authorized');
  assert(err.message.includes('not authorized');
}

Maybe not bold?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's much better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

release.md Outdated
```

### Configure format of number return values
As mentioned above - `truffle-contract` now returns BN. We've made this configurable so if you have an existing test suite you'd prefer to gradually transition from BigNumber to BN, it's possible to configure a contract's number format as below.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BigNumber.js etc.

Maybe these should be links; or maybe we should just make sure everything gets linked at least once.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

truffle(development)> balance.toNumber()
20000
truffle(development)>
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll likely need:

  • Contributing section / Call for feedback to get everything perfect for the full release
  • Thank you to our awesome community
  • Installation instructions

![migrate-rinkeby](https://user-images.githubusercontent.com/7332026/43867960-3499922c-9b20-11e8-8553-589308a6cd61.gif)

**More migrations improvements are coming soon...**.
+ cag from Gnosis has written a really nice addition to the Migrations module that will automatically deploy contract dependencies you've installed with `npm` along with your own contracts.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh missed this: we should @cag him.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - and there's one for elena as well above - didn't want to actually at them for the draft but definitely try make sure we don't forget this.

@gnidan
Copy link
Contributor

gnidan commented Aug 9, 2018

General thought on naming:

I like v5 better than V5, even when it's on its own. Do you have strong opinions on the matter?

@cgewecke
Copy link
Contributor Author

cgewecke commented Aug 9, 2018

@gnidan Please just edit at will - whatever changes you want to make are good. I'll go through your suggestions though and fix those up. Thanks for reviewing :)

@cgewecke
Copy link
Contributor Author

Have ended up mixing v5 / V5. There are some cases (like headings and where it appears at the beginning of a sentence where the lower case looks weird to me but please change this to whatever you prefer.

Web3 is referred to initially as Web3.js and afterwards Web3 (I think the .js is overkill at certain point)

@tcoulter
Copy link
Contributor

In the release notes, you have this:

// Relative or absolute path to an npm installed solc-js
compilers: {
  solc: {
    version: "/Users/axic/.nvm/versions/node/v8.9.4/lib/node_modules/solc"
  }
}

We probably shouldn't encourage the use of absolute paths here, and we might want to remove support for absolute paths here entirely. If an absolute path is stored in the truffle.js file, it will make working as a team complicated as that path won't be available on a different computer or OS.

@tcoulter
Copy link
Contributor

PS: Love the emojis. 👏 💃 🌮

@cgewecke
Copy link
Contributor Author

@tcoulter Ok cool, I'll change that example to something 'workspacey'.

@gnidan
Copy link
Contributor

gnidan commented Aug 21, 2018

This is released!

@gnidan gnidan closed this Aug 21, 2018
@gnidan gnidan deleted the release-notes branch August 21, 2018 19:32
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants