Last active
October 6, 2018 06:20
-
-
Save cmditch/e0d97f60cdbd42a75655ab4a0f1767b6 to your computer and use it in GitHub Desktop.
Revisions
-
cmditch renamed this gist
Oct 6, 2018 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
cmditch created this gist
Oct 6, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,127 @@ pragma solidity ^0.4.24; // All of this is confirmed working within remix, and geth, but freezes up hevm. // See here for testing with `hevm` and `dapp test` ///////////////////////////// // Start of proxy contract // contract Proxyable { address masterCopy; } contract Proxy is Proxyable { /// @dev Constructor function sets address of master copy contract. /// @param _masterCopy Master copy address. constructor(address _masterCopy) public { require(_masterCopy != 0); masterCopy = _masterCopy; } /// @dev Fallback function forwards all transactions and returns all received return data. function () external payable { assembly { let masterCopy := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff) calldatacopy(0, 0, calldatasize()) let success := delegatecall(sub(gas, 703), masterCopy, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) switch success case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } } // // End of proxy contract ///////////////////////////// /* Say we have a very fat contract, and we want to save money by using a proxy. Say also, this fat contract needs to ocassionally spawn off another fat contract. HEVM seems to play fine with a single proxy, but creating a proxy within a proxy seems problematic. */ contract Foo is Proxyable { event FooInitialized(uint lifeMeaning); bool public initialized; uint public lifeMeaning; address public masterCopy; function initialize(uint lifeMeaning_) public { require(!initialized, "already initialized"); lifeMeaning = lifeMeaning_; initialized = true; emit FooInitialized(lifeMeaning_); } } // Foo is the second/inner proxy, or proxy within proxy. Foo's just return some number. contract FooFactory { event FooCreatedFromFactory(address foo); address fooMasterCopy; constructor(address fooMasterCopy_) public { fooMasterCopy = fooMasterCopy_; } function create(uint lifeMeaning_) public returns (Foo foo) { foo = Foo(new Proxy(fooMasterCopy)); foo.initialize(lifeMeaning_); emit FooCreatedFromFactory(foo); } } // Bar is the first/outer proxy, it gets a FooFactory to create Foo's. contract Bar is Proxyable { event FooCreatedFromBar(address foo); bool public initialized; FooFactory public fooFactory; function initialize(FooFactory fooFactory_) public { require(!initialized, "already initialized"); fooFactory = fooFactory_; initialized = true; } function createFoo(uint lifeMeaning_) public returns (Foo foo) { foo = fooFactory.create(lifeMeaning_); emit FooCreatedFromBar(address(foo)); } } // BarFactory is where all the magic begins. contract BarFactory { event BarCreatedFromBarFactory(address bar); FooFactory fooFactory; Bar masterBar; constructor() public { Foo fooMasterCopy = new Foo(); fooFactory = new FooFactory(fooMasterCopy); masterBar = new Bar(); } function create() public returns (Bar bar) { bar = Bar(new Proxy(masterBar)); bar.initialize(fooFactory); emit BarCreatedFromBarFactory(bar); } }