From 29cdc8527fcca26f0ee2c8ff0a0fbb6a01e0d511 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Fri, 21 Feb 2020 20:00:48 +0100 Subject: [PATCH] add factory and proxy contracts --- contracts/GiftBucketFactory.sol | 25 ++++++++++++++++++++ contracts/Proxy.sol | 42 +++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 contracts/GiftBucketFactory.sol create mode 100644 contracts/Proxy.sol diff --git a/contracts/GiftBucketFactory.sol b/contracts/GiftBucketFactory.sol new file mode 100644 index 0000000..7f8f526 --- /dev/null +++ b/contracts/GiftBucketFactory.sol @@ -0,0 +1,25 @@ +pragma solidity ^0.6.1; + +import "./GiftBucket.sol"; +import "./Proxy.sol"; + +contract GiftBucketFactory { + GiftBucket public GiftBucketImplementation; + + event Created(address indexed gifter, address indexed bucket); + + constructor() public { + GiftBucketImplementation = new GiftBucket(address(0), block.timestamp + 1); + } + + function create(address _tokenAddress, uint256 _expirationTime) public returns (address) { + address p = address(new Proxy("", address(GiftBucketImplementation))); + + GiftBucket g = GiftBucket(p); + g.initialize(_tokenAddress, _expirationTime, msg.sender); + + emit Created(msg.sender, address(p)); + + return address(p); + } +} diff --git a/contracts/Proxy.sol b/contracts/Proxy.sol new file mode 100644 index 0000000..b90e19e --- /dev/null +++ b/contracts/Proxy.sol @@ -0,0 +1,42 @@ +pragma solidity ^0.6.1; + +contract Proxy { + /** + * @param constructData Constructor input data for initializing the proxy + * @param contractLogic Address of the contract used as implementation logic for the proxy + */ + constructor(bytes memory constructData, address contractLogic) public { + // save the code address + assembly { // solium-disable-line + sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, contractLogic) + } + + if (constructData.length == 0) { + return; + } + + (bool success,) = contractLogic.delegatecall(constructData); // solium-disable-line + require(success, "Construction failed"); + } + + /** + * @dev Fallback function allowing to perform a delegatecall to the given implementation. + * This function will return whatever the implementation call returns + */ + fallback() external payable { + assembly { // solium-disable-line + let contractLogic := sload(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7) + calldatacopy(0x0, 0x0, calldatasize()) + let success := delegatecall(sub(gas(), 10000), contractLogic, 0x0, calldatasize(), 0, 0) + let retSz := returndatasize() + returndatacopy(0, 0, retSz) + switch success + case 0 { + revert(0, retSz) + } + default { + return(0, retSz) + } + } + } +}