Skip to content

Instantly share code, notes, and snippets.

@3esmit
Last active March 17, 2017 22:05
Show Gist options
  • Save 3esmit/2a22a4bd813303b9efeb0e5375844bfa to your computer and use it in GitHub Desktop.
Save 3esmit/2a22a4bd813303b9efeb0e5375844bfa to your computer and use it in GitHub Desktop.

Contract Factory Library

Reason

There is no easy way to split contracts into deploys, currently this is the way I found:

  1. create interface of contract and interface of factory;
  2. move logic to a Factory;
  3. interface creation and return address of contract being created;
  4. add factory interface variable;
  5. add at constructor the assignment of that address;
  6. replace myContract = new MyContract(); to the logic exemplified in needNewExternalContract()
import "MyFactoryI.sol";

contract UsesFactory{
//(...)
    MyFactoryI myFactoryI;
    Database db;
    function UsesFactory(address factory){
        myFactoryI = MyFactoryI(factory);
        db = new Database();
    }
        
    function needNewMyContract(int arg1, int arg2, int arg3, int arg4) internal returns (MyContractI) {
        db.newTempAddress("newMyContract()"); //
        iFactoryVar.delegatecall("newMyContract(int,int,int,int)",db,arg1,arg2,arg3,arg4);
        address contractCreated = db.getTempAddress("newMyContract()"); //
        MyContractI myContract = MyContractI(contractCreated);
        return myContract;
    } 
//(...)   
}

The example above is of the current implementation, how I've implemented in my App to make a class use a factory. If you want the real code used in a functional contract:

This current method is a overload of code for a simple task in most of popular programming languages and is very likely to have bad implementations that are not detected by compiler, but will throw when called.
This is another implementation that uses libraries as helper to access particular contracts

Desired Behavior

Based on the already implemented transparent delegatecall in library functions:

  1. move contract code inside library scope;
  2. replace new instances to MyLibrary.MyContract myContract = new MyLibrary.MyContract(arg1,arg2,arg3,arg4);
    The current behavior would internally delegate call of a factory function built in library and would give the address of new contract:
function newMyContract(int arg1,int arg2,int arg3,int arg4) internal returns (address){  
  return new MyContract(arg1,arg2,arg3,arg4);  
}  
  1. Compiler will include those contracts to library code or deploys and calculate their nonces;
  2. Compiler will craft delegate calls to contracts using the library contract;
  3. Sources that uses that libraries, solc will check if function exists in the library contract interface.

Alternative Solution

  1. Contracts are placed normally after library scope.
  2. Create a factory function, such as:
function newMyContract(int arg1,int arg2,int arg3,int arg4) internal returns (address){  
  return new MyContract(arg1,arg2,arg3,arg4);  
}  
  1. On deploy, library deploys the contracts at its constructor
  2. solc precalculates the resulting nonces from the contracts and set them as addresses in constants
  3. delegatecalls goes to addresses in this constants
  4. other contract calls myContract = Library.newMyContract(arg1,arg2,arg3,arg4);
  5. solidity don't include the contact code generated by library, instead uses delegatecall, that ends up in contract deployed by library.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment