2

How can I create multiple contracts of Contract X using the new key word. I am getting an error that says cannot create instance of the same contract type. Is there a way around it ...

I would like to create a chain of contracts of the same type that point to each other.

2
  • Just curious. From a pragmatic standpoint, what is advantageous about contract copying itself (versus summing a factory to do it) and what is meant by pointing forward, backward. Sounds like an ordered index. Some insight into the purpose of these constraints might yield a cleaner pattern. Commented Apr 17, 2018 at 23:42
  • when a factory creates all the contracts .. it is more centralized.. the factory manages all the other children.. where as I wanted to create a chain of contracts which are independent and thus make it less centralized. In my case as well, there are ether deposits based on certain conditions.. the factory method would make one contract hold all the ether which is not quite a good design
    – Haya Raed
    Commented Apr 18, 2018 at 11:23

4 Answers 4

3

For a contract to be able to create another contract, it needs the bytecode of the contract that is to be created. When a product creates a new product, that new product has to have the byte code of product as well and so on. The bytecode of products would be infinitly large.

You could create a factory contract, which contains the logic for creating new contracts, like this:

pragma solidity ^0.4.22;

contract Factory{
    function createNewProduct(Product _reference) public returns (Product) {
        Product p = new Product(_reference, this);
        return p;
    }
}

contract Product {
    Factory public factory;
    Product public reference;

    function Product(Product _reference, Factory _factory){
        reference = _reference;
        factory = _factory;
    }

    function haveFactoryCreateProductWithReferenceToThis() public {
        emit ProductCreated(factory.createNewProduct(this));
    }

    event ProductCreated(Product indexed product);
}

To deploy, first create the factory, then create a product (X) with reference "0x0". After that, you can create new products using the function haveFactoryCreateProductWithReferenceToThis

4
  • I want a way for Product to create another Product .. where the first Product is the Parent to the child Product which will then be a parent to the next child Product and so on ... so it is a chain of Products .. rather than a Factory that generates the products ...
    – Haya Raed
    Commented Apr 17, 2018 at 13:52
  • 1
    That's not possible. For a contract to be able to create another contract, it needs the bytecode of the contract that is to be created. When a product creates a new product, that new product has to have the byte code of product as well and so on. The bytecode of products would be infinitly large.
    – Henk
    Commented Apr 17, 2018 at 13:55
  • 1
    As stated, a contract cannot create an instance of itself, or a contract derived from itself. You must have a factory contract that does the creation, and then can call the controlled contracts.
    – supakaity
    Commented Apr 17, 2018 at 14:02
  • 1
    @henkiedoodle can you post your comment as part of the answer to choose it as the right answer.
    – Haya Raed
    Commented Apr 18, 2018 at 12:10
1

Circular creation.

The following is an example of creating a circular group of items.

In this example you would:

  • create a new Factory
  • check factory.head.next == factory.head
  • call factory.add(factory.head)
  • check factory.head.next is a new Item
  • check factory.head.next.next == factory.head

Code:

pragma solidity ^0.4.22;

contract Item {
    Item public next;
    address owner;

    constructor(Item _next) public {
        owner = msg.sender;
        if (_next == Item(0)) {
            next = this;
        } else {
            next = _next;
        }
    }

    function addNew(Item item) public {
        require(msg.sender == owner);
        next = item;
    }
}

contract Factory {
    Item public head;

    constructor() public {
        head = new Item(Item(0));
    }

    function add(Item _to) public {
        Item link = _to.next();
        Item next = new Item(link);
        _to.addNew(next);
    }
}
1

Self Replication / Cloning using Assembly:

Of course you can if you really want to!

Make sure to read holiman's gist if you want to understand the assembly.


pragma solidity ^0.4.22;

// @mickys - based on https://gist.github.com/holiman/069de8d056a531575d2b786df3345665 
contract Replicator {

  address public parent;

  function replicate() public returns(address) {
      address childAddress = clone(address(this));
      Replicator child = Replicator(childAddress);
      child.setParent(address(this));
      return child;
  }

  function setParent(address addr) public {
      parent = addr;
  }

  function clone(address a) public returns(address)  {
    address retval;
    assembly{
        mstore(0x0, or (0x5880730000000000000000000000000000000000000000803b80938091923cF3 ,mul(a,0x1000000000000000000)))
        retval := create(0,0, 32)
    }
    return retval;
 }
}

Cheers!

1

Please try this:

   struct Project {
        string name;
        uint256 funds;
        uint256 available;
        address project;
        bool active;
    }

    mapping(address => Project) projects;
    address[] projectAddresses;

    function createProject(string name, uint amount) public {
        StandardToken token = new ProjectToken(name, amount);
        projectAddresses.push(token);
        projects[token] = Project(name, amount, amount, token, true);
    }
1
  • Here new contracts of type ProjectToken are created from another contract of a different type which works perfectly. But imagine you are in ProjectToken and trying to create another ProjectToken contract that points to the previous contract and so on. A chain of ProjectToken contracts rather than a factory that generates ProjectToken contracts
    – Haya Raed
    Commented Apr 17, 2018 at 13:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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