Deploy contracts programmatically using the CLI

shark0der asked on Telegram

Is there a way to implement a deployment script?
My project has multiple contracts that depend on each other so I need to set them up in a specific order

In this specific case it’s an upgradable contract. I’d like to know how to cover both cases (regular deploy) though

We can deploy contracts programmatically, though please note that this doesn’t register the instances created in any project files.

It is just a way to deploy, so we can’t use the CLI to interact with the contracts after deploying.

Deploy upgradeable contracts programmatically

To deploy an upgradeable contract we can use the ProxyAdminProject as shown in the Upgrading Contracts Programmatically Learn guide documentation.

The following example script deploys the Box contract as an upgradeable contract.

Box.sol

Box contract (from https://docs.openzeppelin.com/learn/developing-smart-contracts#setting-up-a-solidity-project)

// contracts/Box.sol
pragma solidity ^0.5.0;

contract Box {
    uint256 private value;

    // Emitted when the stored value changes
    event ValueChanged(uint256 newValue);

    // Stores a new value in the contract
    function store(uint256 newValue) public {
        value = newValue;
        emit ValueChanged(newValue);
    }

    // Reads the last stored value
    function retrieve() public view returns (uint256) {
        return value;
    }
}

deployUpgradeable.js

// src/deployUpgradeable.js
const Web3 = require('web3');
const { ZWeb3, Contracts, ProxyAdminProject } = require('@openzeppelin/upgrades')

async function main() {
  // Set up web3 object, connected to the local development network, initialize the Upgrades library
  const web3 = new Web3('http://localhost:8545');
  ZWeb3.initialize(web3.currentProvider)

  const [from] = await ZWeb3.eth.getAccounts();
  const project = new ProxyAdminProject('MyProject', null, null, { from, gas: 1e6, gasPrice: 1e9 });

  const Box = Contracts.getFromLocal('Box');
  const box = await project.createProxy(Box);

  await box.methods.store(42).send({ from: from });
  console.log('Box value:', (await box.methods.retrieve().call({ from: from })).toString());

}

main();

Run deploy

$ node src/deployUpgradeable.js
Box value: 42

Deploy regular contracts programmatically

To deploy a regular contract we can just use deploy (web3) or new (truffle) (See Contract Loader - Usage. The Interacting Programmatically Learn guide shows how to interact programmatically (though it doesn’t show the deployment).

deployRegular.js

// src/deployRegular.js
const Web3 = require('web3');
const { setupLoader } = require('@openzeppelin/contract-loader');

async function main() {
  // Set up web3 object, connected to the local development network, and a contract loader
  const web3 = new Web3('http://localhost:8545');
  const loader = setupLoader({ provider: web3 }).web3;

  const [from] = await web3.eth.getAccounts();

  // Set up a web3 contract, using the contract loader
  const Box = loader.fromArtifact('Box');
  const box = await Box.deploy().send({ from: from});

  await box.methods.store(23).send({ from: from });
  console.log('Box value:', (await box.methods.retrieve().call({ from: from })).toString());
}

main();

Run deploy

$ node src/deployRegular.js
Box value: 23