2

What is best practice on deploying a contract called within another contract with web3.js?

I have previously gone under the assumption that the contracts must be mined separately, and the caller must explcitly be told about the address of the callee?

Let's say we have this:

pragma solidity ^0.4.11;

contract Sub {
    bytes32 one;
    function set(bytes32 _one) {
        one = _one;
    }
    function get() constant returns(bytes32) {
        return one;
    }
}

contract Main {
    struct Data {   
        bytes32 one;
        Sub two;
    }
    Data public d;
    function set(bytes32 _main, bytes32 _sub) returns (uint) {
        Sub s = new Sub();
        s.set(_sub);
        d.one = _main;
        d.two = s;
    }
    function getBoth() constant returns (bytes32, bytes32) {
        return (d.one, d.two.get());
    }
}

Using remix this yields two deploy code snippets where there is no explicit mention of the sub contract in the main deployment:

var browser_main_sol_mainContract = web3.eth.contract([{"constant":true,"inputs":[],"name":"d","outputs":[{"name":"one","type":"bytes32"},{"name":"two","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"getBoth","outputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_main","type":"bytes32"},{"name":"_sub","type":"bytes32"}],"name":"set","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"}]);
var browser_main_sol_main = browser_main_sol_mainContract.new(
   {
     from: web3.eth.accounts[0], 
     data: '0x6060604052341561000f57600080fd5b5b61046c8061001f6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680638a054ac21461005457806393affe51146100b8578063f71f7a25146100f8575b600080fd5b341561005f57600080fd5b610067610140565b6040518083600019166000191681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390f35b34156100c357600080fd5b6100cb610172565b60405180836000191660001916815260200182600019166000191681526020019250505060405180910390f35b341561010357600080fd5b61012a6004808035600019169060200190919080356000191690602001909190505061022f565b6040518082815260200191505060405180910390f35b60008060000154908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082565b6000806000800154600060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636d4ce63c6000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b151561020b57600080fd5b6102c65a03f1151561021c57600080fd5b50505060405180519050915091505b9091565b60008061023a610335565b604051809103906000f080151561025057600080fd5b90508073ffffffffffffffffffffffffffffffffffffffff1663db80813f846040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050600060405180830381600087803b15156102c857600080fd5b6102c65a03f115156102d957600080fd5b5050508360008001816000191690555080600060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5092915050565b60405160fc806103458339019056006060604052341561000f57600080fd5b5b60de8061001e6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636d4ce63c146047578063db80813f146075575b600080fd5b3415605157600080fd5b60576099565b60405180826000191660001916815260200191505060405180910390f35b3415607f57600080fd5b609760048080356000191690602001909190505060a3565b005b6000805490505b90565b80600081600019169055505b505600a165627a7a72305820a90f2381ccf91722255d4c49830ceb62cbf40dadd61270f2ddd16ce3e4b07aa70029a165627a7a72305820a78d823b4ea6c0d1aa519c352389992a7606efec11c0524ddab42dfc44227fba0029', 
     gas: '4700000'
   }, function (e, contract){
    console.log(e, contract);
    if (typeof contract.address !== 'undefined') {
         console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
    }
 })

However, searching for the sha3 digest 6d4ce63c of the get() method in the bytecode of main matches twice. That suggests to me that it matches the call and the method itself, and thus the code of sub is embedded in the bytecode for main, and the need for an extra reference in the deployment seems unnecessary?

0

I would recommend splitting the two contracts into two separate files and then import Sub.sol in the file Main.sol.

You could deploy either contract and hence Remix gives you two deploy code snippets. E.g. the Sub contract could be a standalone contract that is deployed at some point and then later on you deploy the Main contract and make it interact with your Sub contract. In your particular example there is no need to separately deploy the Sub contract as you instantiate it in the Main contract. You could, however also think about inheriting Main from Sub, or you could deploy an instance of Sub separately, and store its address in Main. The latter might be useful if you have a lot of Main instances that could all use the same Sub contract, in this way the deploy bytecode of Main would get smaller (and hence cheaper to deploy).

0

Where do you want to deploy the contract to ? In memory VM, testnet or Mainnet?

For testnet or mainnet you can deploy using Truffle and to split your contracts into different files - then link them in your 2_deploy_contracts.js. This will auto-magically ensure that the referenced methods call each other:

Sub.sol

pragma solidity ^0.4.11;

contract Sub {
 bytes32 one;
 function set(bytes32 _one) {
    one = _one;
 }

 function get() constant returns(bytes32) {
     return one;
 } 
}

Main.sol

pragma solidity ^0.4.11; 
import "./Sub.sol";"

contract Main {
    struct Data {   
        bytes32 one;
        Sub two;
    }
    Data public d;
    function set(bytes32 _main, bytes32 _sub) returns (uint) {
        Sub s = new Sub();
        s.set(_sub);
        d.one = _main;
        d.two = s;
    }
    function getBoth() constant returns (bytes32, bytes32) {
        return (d.one, d.two.get());
    }
}

2_deploy_contracts.js

var Sub = artifacts.require("./Sub.sol");
var Main = artifacts.require("./Main.sol");

module.exports = function(deployer) {
  deployer.deploy(Sub);
  deployer.link(Sub, Main);
  deployer.deploy(Main);
}
deployer.deploy(); 
};

More at:

http://truffleframework.com/docs/getting_started/migrations

I would also recommend using pragma solidity ^0.4.23; Lot's of nice changes in the newer version.

Hope this helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.