Migrating from Truffle to Buidler

And why you should probably keep both.

Why Buidler?

Proper debugging is a pain with Truffle. Events are way too difficult to use as logging and they don't even work for reverted transactions (when you would need them most). Buidler gives you a console.log for your contracts which is a game changer. And you'll also get stack traces within your contracts.

Gone are the days where you have to guess the revert line in your contracts.

Gone are the days of trying to figure out the content of variables during runtime, just console.log them.

debugging meme

How to add Buidler

Alright, so you want to start using Buidler in your Truffle project? You don't actually have to restart from scratch as buidler has a plugin that allows you to keep your current setup. First let's install the required packages.

npm install @nomiclabs/buidler @nomiclabs/buidler-truffle5 --save-dev

Create a buidler.config.js file in the root of your project and add usePlugin("@nomiclabs/buidler-truffle5"); to the start:

usePlugin("@nomiclabs/buidler-truffle5");

module.exports = {};

Now you have two options, you either change all your existing tests to avoid using .deployed() functions as they don't work with Buidler. Or better, you simply create a fixture file which helps Buidler to support .deployed() calls. Then you won't need any changes to your existing tests.

If you want to add the fixtures, create a test/truffle-fixture.js file.

This Truffle migration file:

const MyContract = artifacts.require("MyContract");
const MyLib = artifacts.require("MyLib");

module.exports = function(deployer) {
  deployer.deploy(MyLib);
  deployer.link(MyLib, MyContract);
  deployer.deploy(MyContract);

  // do all other migration stuff if required
};

Becomes this Buidler truffle-fixture file:

const MyContract = artifacts.require("MyContract");
const MyLib = artifacts.require("MyLib");

module.exports = function(deployer) {
  const myLib = await MyLib.new();
  MyLib.setAsDeployed(myLib);
  MyContract.link(myLib);
  const myContract = await MyContract.new();
  MyContract.setAsDeployed(myContract);

  // do all other migration stuff if required
};

If you want to use the web3 instance in your tests, you only have to install a few more packages:

npm install @nomiclabs/buidler-web3 web3 --save-dev

That's it. Happy buidling! Use the command npx buidler test to run tests via Buidler.

Stack traces will now be shown within your contracts. And you may now import the console.log file using import "@nomiclabs/buidler/console.sol";

Running tests inside VS Code

If you are using VS Code, you can install the Mocha Test Explorer. Simply add a .mocharc.json file to your root:

{
  "require": ["@nomiclabs/buidler/register"],
  "timeout": 20000,
  "recursive": "test"
}
inline tests
debugger

That's all. You'll now be able to run individual tests directly within your editor and you'll bet a test explorer, see image above.

And you'll also be able to debug tests directly with breakpoints, see image on the left.

The case for keeping Truffle

Now do we need Truffle still? In most cases I would say keep it for two reasons:

  1. Deployments
  2. Plugins

Technically Buidler now has a deployment plugin, the buidler-deploy plugin. However it's very new, less powerful than Truffle and more steps required to make it work.

Buidler also has a wide range of plugins. But once again, those plugins are mostly cloned from the respective Truffle plugins and so they are often behind in terms of features and bugs. And some plugins only exists for Truffle. For those reasons I would just recommend keeping them both and you'll have the best of both worlds.


Markus Waas

Solidity Developer

More great blog posts from Markus Waas

© 2024 Solidity Dev Studio. All rights reserved.

This website is powered by Scrivito, the next generation React CMS.