[Ethereum] truffle migrate: How to deploy a contract whose constructor takes a parameter

contract-deploymentsoliditytruffletruffle-migration

I'm using Truffle Version 4 to develop a simple smart contract and am stuck on something I think reflects a very basic misunderstanding that I just can't get my head around.

Here's my simple contract, in contracts/BaconSupplier.sol

contract BaconMaker {
    address public pig;
    address public owner;

    function BaconMaker(address _pig) public {
        require(_pig != 0x0);
        owner = msg.sender;
        pig = _pig;
    }
}

And my deployment migration, in migrations/2_deploy_contracts.js

const BaconMaker = artifacts.require('./BaconMaker.sol')

module.exports = (deployer) => {
  deployer.deploy(BaconMaker)
}

I run truffle develop to enter the standard Truffle development environment, then

compile

=> compiles just fine

Compiling ./contracts/BaconMaker.sol...
Compiling ./contracts/Migrations.sol...
Writing artifacts to ./build/contracts

then

migrate

Running migration: 1_initial_migration.js
  Deploying Migrations...
  ... 0x9e8257089a048815b4593a87ae5ae22af7dab80f74c07a98a0cf0a2ba08234a1
  Migrations: 0xee08e5e6643952b3cb22642d2a04a2992141eddd
Saving successful migration to network...
  ... 0x9845c22c3db695912cb4958c9f8071b9a2ac8853b226367c3f969a0f54510fe9
Saving artifacts...
Running migration: 2_deploy_contracts.js
  Deploying BaconMaker...
  ... 0xdcb442cda2621bbcd648813a567f70761746fb583a502746670f63a558a9a5e8
Error encountered, bailing. Network state unknown. Review successful transactions manually.
Error: VM Exception while processing transaction: invalid opcode

If I remove the line require(_pig != 0x0); however then the migration runs fine, which implies to me that the migration process is actually attempting to create an instance of the BaconMaker contract.

I guess I don't really understand what the migrations are doing here or what's actually happening with deployment.

The longer term aim is that there would be a Farm contract that maintains a record of its own pigs and for each pig there is an associated BaconMaker (ignore the logic of this for now, I'm just using pigs and BaconMakers here in place of the actual contracts being developed.)

So the Farm contract would look like

import './BaconMaker.sol';

contract Farm {
    address public owner;
    mapping(address => bool) public pigs;
    BaconMaker[] public baconMakers;

    function Farm() {
        owner = msg.sender;
    }

    function addPig(address pig) external {
        require(pig != 0x0);
        require(msg.sender == owner);
        pigs[pig] = true;
        BaconMaker baconMaker = new BaconMaker(pig);
        baconMakers.push(baconMaker);
    }

}

In this case do I actually need to deploy the BaconMaker contract during the migration, or will it be deployed for me when addPig is called?

If not then how do I deploy the BaconMaker contract in the migration stage?

Best Answer

You can add the constructor parameters as extra arguments to the deploy() call

const BaconMaker = artifacts.require('./BaconMaker.sol')

module.exports = (deployer, network, accounts) => {
  const userAddress = accounts[3];
  deployer.deploy(BaconMaker, userAddress)
}

In your case since Farm will create BaconMaker on demand, you do not have to deploy BaconMaker from the deploy scripts.

There's no general solution that fit all situations. Sometimes you create a single contract that will deploy child contracts. Also you can deploy several contracts and add them to a register after deployment, so they can communicate with each other.

A single contract is easiest, but you are bound by the block gas limit. Having several contracts is more complex because it no easy to communicate between them and you have to be more careful with the organization.

Related Topic