3

I've got a contract that I'd like to be able to create a copy of the same contract, then have the child be able to retrieve data from the parent. When I try to compile the following, which is a simplified version of what I'm trying to make:

contract Example {

    uint256 num;
    address parent;

    function Example(uint256 _num, address _parent) {
        num = _num;
        parent = _parent;
    }

    function createChild() {
        uint256 childNum = num + 1;
        Example child = new Example(childNum, this);
    }

    function getNumber() constant returns (uint256) {
        return num;
    }

    function getParentNumber() constant returns (uint256) {
        Example e = Example(parent);
        return e.getNumber();
    }

}

...the solidity compiler understandably complains:

example.sol:15:25: Error: Circular reference for contract creation (cannot create instance of derived or same contract).
        Example child = new Example(childNum, this);

This matches what the docs say will happen: http://solidity.readthedocs.io/en/develop/contracts.html#multiple-inheritance-and-linearization

So it makes sense that I can't do it that way. But is there a (preferably clean) way to accomplish a contract creating a contract with the same code as itself, then call methods on it and get data back?

  • Why do you need to have a contract create itself? Usually it's better to use a "factory" contract, which can then create sub-contracts – Tjaden Hess Oct 4 '16 at 0:35
  • Thank, that makes sense. Then I still have the problem of calling back to the parent, but I guess I can do this: pastebin.com/vdntJAUn – Edmund Edgar Oct 4 '16 at 0:56
4

Have a look at this inline assembly example. It takes the code out of an address:

pragma solidity ^0.4.0;

library GetCode {
    function at(address _addr) returns (bytes o_code) {
        assembly {
            // retrieve the size of the code, this needs assembly
            let size := extcodesize(_addr)
            // allocate output byte array - this could also be done without assembly
            // by using o_code = new bytes(size)
            o_code := mload(0x40)
            // new "memory end" including padding
            mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
            // store length in memory
            mstore(o_code, size)
            // actually retrieve the code, this needs assembly
            extcodecopy(_addr, add(o_code, 0x20), 0, size)
        }
    }
}

I am not too sure what you can do at this stage, though, since it lacks the constructor...

| improve this answer | |
4

The DAO (with the USD 50 million bug), is a good example of a contract being able to create copies of itself using a factory.

Here's the factory contract:

contract DAO_Creator {
    function createDAO(
        address _curator,
        uint _proposalDeposit,
        uint _minTokensToCreate,
        uint _closingTime
    ) returns (DAO _newDAO) {

        return new DAO(
            _curator,
            DAO_Creator(this),
            _proposalDeposit,
            _minTokensToCreate,
            _closingTime,
            msg.sender
        );
    }
}

And here's the code that created the new child DAOs:

contract DAO is DAOInterface, Token, TokenCreation {

    ...
    function splitDAO(
        uint _proposalID,
        address _newCurator
    ) noEther onlyTokenholders returns (bool _success) {
        ...
        p.splitData[0].newDAO = createNewDAO(_newCurator);
        ...
    }

    ...
    function createNewDAO(address _newCurator) internal returns (DAO _newDAO) {
        NewCurator(_newCurator);
        return daoCreator.createDAO(_newCurator, 0, 0, now + splitExecutionPeriod);
    }
    ...
}

There was the means to transfer ethers and tokens from the parent contract to the child contract via the parent's splitDAO(...) method (this was exploited by the DAO hacker).

You should be able to design your contract so you can execute methods in the child contract that refers back to the parent contract.

| improve this answer | |
1

I wrote an article on how to get around this on medium.

https://medium.com/@kylebryant_28277/subverting-the-circular-reference-error-in-solidity-f7167bf9fdb

Basically you need to create two new contracts, one that makes a new contract of the type you want, and an abstract contract of that one. I call these the Maker and Supplier contracts. Give it a read :)!

pragma solidity ^0.4.17;

contract VotethComment {

    string public comment;
    string public nickname;
    address public author;
    address[] public votethComments;
    address votethCommentMaker;

    constructor(string _comment, string _nickname, address _author, address _votethCommentMaker) public {
        comment = _comment;
        nickname = _nickname;
        author = _author;
        votethCommentMaker = _votethCommentMaker;
    }

    function addComment(string _comment, string _nickname) public {
        VotethCommentSupplier votethCommentSupplier = VotethCommentSupplier(votethCommentMaker);
        votethComments.push(votethCommentSupplier.makeComment(_comment, _nickname, msg.sender));
    }
}

contract VotethCommentSupplier {
   function makeComment(string _comment, string _nickname, address _author) public returns(address);
}

contract VotethCommentMaker {
    function makeComment(string _comment, string _nickname, address _author) public returns(address) {
        return new VotethComment(_comment, _nickname, _author, this);
    }
}
| improve this answer | |
  • it would be better to have the code as string rather than an image. – mirg May 16 '18 at 3:15
  • 1
    Changed it to code – Kyle May 16 '18 at 3:50
1

You can make something like this.

contract ObjectFactory{

    function createObject() returns(address){
        Object subObject = new Object();
        return subObject;
    }

}    
contract Object{
    function createSubObject(ObjectFactory factory) returns(address) {
        address objectAddress = factory.createObject();
        return ObjectAddress; 
    }
}

This code will make Object contract creates sub contract of type Object, and ObjectAddress shall returns the address of the newly created Object.

Note that ObjectFactory factory can be treated like a normal address.

| improve this answer | |
1

It is possible for a contract to deploy a copy of itself using inline assembly:

function _autoDeploy () internal returns (address copy) {
    bytes memory initCode = hex'58333b90818180333cf3';

    assembly {
        let encoded_data := add(0x20, initCode)
        let encoded_size := mload(initCode)
        copy := create(0, encoded_data, encoded_size)
    }
}

The initCode makes use of the extcodecopy opcode, which copies the code of the calling contract to the address of the new contract. A consequence of this deployment method is that the constructor is not called, and any variable assignments that are outside of a function are ignored.

I have published a repository and NPM package with an implementation of this deployment process: https://github.com/ItsNickBarry/solidity-auto-deployer

| improve this answer | |

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.