Code Monkey home page Code Monkey logo

buidler-deploy's Introduction

buidler

buidler-deploy

A Plugin For Deployments

Buidler Deployment Plugin.

What

This buidler plugin add a mechanism to deploy contract to various network, keeping track of them and replicate the same environment for testing.

On top of that it adds a mechanism to add names to addresses so test and deployment script can be reconfigured by simply changing the address a name points to, allowing different configuration per network.

Installation

npm install buidler-deploy

And add the following statement to your buidler.config.js:

usePlugin('buidler-deploy');

Tasks

This plugin adds the deploy task to Buidler

This tasks will be executing scripts in the deploy folder and save contract deployments

Environment extensions

This plugin extends the Buidler Runtime Environment by adding 2 fields

  • namedAccounts that is an object where keys are names and value are addresses. It is parsed from the namedAccounts configuration (see Configuration)
  • deployments which contains functions to access past deployment or save new one, as well as helpers functions

Configuration

namedAccounts

This plugin extends the BuidlerConfig's object with an optional namedAccounts field.

namedAccounts allow you to associate names to addresses and have them configured per chain. This allow you to have meaningful name in your tests while the addresses matches to multi sig in real network for example

{
    namedAccounts: {
        deployer: {
            default: 0, // here this will by default take the first account as deployer
            4: '0xffffeffffff', // but for rinkeby it will be a specific address
        },
        feeCollector:{
            default: 1, // here this will by default take the second account as feeCollector (so in the test this will be a different account that the deployer)
            1: '0xffffeaaa', // on the mainnet the feeCollector could be a multi sig
            4: '0xaaaeffffff', // on rinkeby it could be another account
        }
    }
}

paths

It also add fields to BuidlerConfig's ProjectPaths object

Here is an example showing the default values :

{
    paths: {
        deploy: 'deploy',
        deployments: 'deployments'
    }
}

Usage

deploy

buidler deploy --network <networkName>

This is a new task that the plugin add. As the name suggests it deploy contracts. To be exact it will look for files in the folder deploy or whatever was configured in paths.deploy

It will scan for file in alphabetical order and execute them in turn.

  • it will require each of these file and execute the exported function with the BRE as argument

An example of a deploy script :

module.exports = async ({getNamedAccounts, deployments}) => {
    const {deployIfDifferent, log} = deployments;
    const {deployer} = await getNamedAccounts();

    let contract = await deployments.get('GenericMetaTxProcessor');
    if (!contract) {
        const deployResult = await deployIfDifferent(['data'], "GenericMetaTxProcessor",  {from: deployer, gas: 4000000}, "GenericMetaTxProcessor");
        contract = await deployments.get('GenericMetaTxProcessor');
        if(deployResult.newlyDeployed) {
            log(`GenericMetaTxProcessor deployed at ${contract.address} for ${deployResult.receipt.gasUsed}`);
        }
    }
}

As you can see the BRE passed in has 2 new fields :

  • getNamedAccounts a function that return a promise to an object where keys are names and value are addresses. It is parsed from the namedAccounts configuration (see namedAccounts)
  • deployments which contains functions to access past deployment or save new one, as well as helpers functions

Note that running buidler deploy without network will use the default network. If the default network is an internal ganache or buidlerevm then nothing will happen as a result but this can be used to ensure the deployment is without issues.

test

buidler test

The test task is like normal except that names are resolved and past deployment are loaded.

test can then use the bre.deployments.fixture function to run the deployment for the test and snapshot it so test do not need to perform the all deploy flow, they simply reuse the snapshot for every test (this leverage evm_snapshot and evm_revert provided by both buidlerevm and ganache). You can for example set them in a beaforeEach

You can also specify to run a subset of the deploy scripts by specifying a tag or an array of tag

A tag is simply a string value, that deploy script can advertise. (see tags and dependencies)

Here is an example of a test :

const { deployments } = require('@nomiclabs/buidler');

describe("Token", () => {
    beforeEach(async () => {
      await deployments.fixture();
    })
    it("testing 1 2 3", async function() {
      const Token = await deployments.get('Token'); // Token is available because Token is a dependency of ERC721BidSale deploy script
      console.log(Token.address);
      const ERC721BidSale = await deployments.get('ERC721BidSale');
      console.log({ERC721BidSale});
    });
});

node

buidler node

The node command is updated so that now when the node is serving, all contract are already deployed.

It also add an argument --export that allow you to specify a destination file where the info about the contracts deployed is written. Your webapp can then access all contracts information.

Note: for now, you have to use buidler listen instead of buidler node as buidler does not let plugin add options to existing task yet.

run

buidler run <script>

The run command is also updated in that now when the script run it has access to contract deployment and can easily act on them via helpers functions

Here is an example of script that run can support

const bre = require('@nomiclabs/buidler');
const { deployments, getNamedAccounts } = bre;

(async() => {
    console.log(await deployments.all())
    console.log({namedAccounts: await getNamedAccounts()});
})()

You can also run it directly from the command line as usual.

compile

buidler compile

The compile command is also updated so that you could potentially have the compiler do different thing depending on the deployed contract. Like for example you might want to inject the address of a deployed contract in the bytecode for efficiency reason. This is not yet enable in any way though.

deploy scripts tags and dependencies

These following paragraphs were written before the deployments.fixture function was implemented and while it is possible to run a subset of the deploy scripts via run this is now mostly useful for partial deployment, in script for example as tests can now benefit from an even faster method via deployments.fixture

When you run test, you want to replicate the same set of contract that will be deployed without having to copy the deployment procedure. That is why the test have access to bre.deployments.run function to be able to easily setup the contracts for testing. Now though, for efficiency reason it would be nice if you could only deploy the necessary contract for a particular test.

To help doing that, deploy script can setup tags and dependencies.

tags represent what the deploy script act on. In general it will be a single string value, the name of the contract it deploy or modify

Then if another deploy script have such tag as dependency, then when this latter deploy script have a specific tag and that tag is requested, the dependency will be executed first.

Here is an example of 2 deploy scripts :

module.exports = async ({getNamedAccounts, deployments}) => {
    const {deployIfDifferent, log} = deployments;
    const namedAccounts = await getNamedAccounts();
    const {deployer} = namedAccounts;
    const deployResult = await deployIfDifferent('data', 'Token', {from: deployer}, 'Token');
    if (deployResult.newlyDeployed) {
        log(`contract Token deployed at ${deployResult.contract.address} using ${deployResult.receipt.gasUsed} gas`);
    }
}
module.exports.tags = ['Token'];
module.exports = async function({getNamedAccounts, deployments}) {
    const {deployIfDifferent, log} = deployments;
    const namedAccounts = await getNamedAccounts();
    const {deployer} = namedAccounts;
    const Token = await deployments.get('Token');
    const deployResult = await deployIfDifferent('data', 'ERC721BidSale', {from: deployer}, 'ERC721BidSale', Token.address, 1, 3600);
    if (deployResult.newlyDeployed) {
        log(`contract ERC721BidSale deployed at ${deployResult.contract.address} using ${deployResult.receipt.gasUsed} gas`);
    }
};
module.exports.tags = ['ERC721BidSale'];
module.exports.dependencies = ['Token'];

As you can see the second one depends on the first. This is because the second depends on a tag that the first script register as using.

With that when bre.deployments.run is executed as follow :

bre.deployments.run(['ERC721BidSale'])

then both script will be run, ensuring ERC721BidSale is ready

buidler-deploy's People

Contributors

wighawag avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.