It's a common pattern to use a hub/factory contract to create multiple instances of a standard contract.

It's also common to require a way to enumerate the addresses of the created contracts.

Is there a simple minimal example of a good approach?

up vote 21 down vote accepted

Here's a simple hub (Bakery) that deploys contracts (Cookie) from a template and keeps track of the contracts created.

Note that Cookie is part of the source file so Bakery can "see it" during compilation. Cookie's ByteCode will become part of Bakery so the new Cookie() invocation knows what to do.

Deploy the hub/factory (Bakery). It's not necessary to deploy the template (Cookie). You can create as many of the latter as needed by calling a function in the former.

pragma solidity ^0.4.8;

contract Bakery {

  // index of created contracts

  address[] public contracts;

  // useful to know the row count in contracts index

  function getContractCount() 
    public
    constant
    returns(uint contractCount)
  {
    return contracts.length;
  }

  // deploy a new contract

  function newCookie()
    public
    returns(address newContract)
  {
    Cookie c = new Cookie();
    contracts.push(c);
    return c;
  }
}


contract Cookie {

  // suppose the deployed contract has a purpose

  function getFlavor()
    public
    constant
    returns (string flavor)
  {
    return "mmm ... chocolate chip";
  }    
}

If you need more functionality in the index (e.g. is 0x123 a contract?) consider more feature-complete storage patterns: Are there well-solved and simple storage patterns for Solidity?

Hope it helps.

  • 1
    For 5 seconds I was confused by the erroneous thought that an Ethereum contract could be identified via an HTTP protocol cookie. In classic OO programming terms your Bakery is a singleton factory and the method newCookie() creates a new instance of a contract of type Cookie. – camelCase Dec 14 '17 at 11:02
  • @Rob are there any concerns with the contracts array getting very large (say, millions or tens-of-millions addresses)? – Andy Hin Dec 25 '17 at 5:37
  • Its economically constrained, not technically constrained. The pattern will scale as large as one can afford to pay for writes. The key thing is the gas cost is consistent at any scale. – Rob Hitchens B9lab Dec 25 '17 at 6:28
  • 1
    I don't understand the type paradigm here. How come c is both a Cookie and an address? It's created as the former but stored in an array (and returned) as the latter. Why isn't contracts an array of Cookie[] instead of address[]? – Teleporting Goat Mar 22 at 9:24
  • 2
    Good questions. Q1: c is a Cookie, which is a contract and contracts are directly convertible to addresses. The newer compiler wants to see that explicitly, like return address(c);. We're using an array of address as a list of keys we can use to discover the rest which is more economical than an array of large objects. – Rob Hitchens B9lab Mar 22 at 12:35

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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