41

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?

2 Answers 2

35

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.

10
  • 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, 2017 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, 2017 at 5:37
  • 7
    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[]? Mar 22, 2018 at 9:24
  • 8
    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. Mar 22, 2018 at 12:35
  • 3
    The return value with the new contract address on newCookie() can't be accessed by the caller though right? The function will be a transaction call which will result in a receipt object.
    – Interition
    Aug 24, 2018 at 7:37
1

For accessing the method I created a new function and did it like this

function getCookieFlavor(address cookie) public view returns(string){
    return Cookie(cookie).getFlavor();
}

just pass in the address of the cookie which is already created.

1
  • 1
    For anyone who comes across this, one can access the deployed contracts (the Cookies) directly if they have the ABI (either JSON ABI or an Interface), and they know the address of the instance, which they can get from the Hub. Aug 19, 2020 at 5:04

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.