add upgradable instance factory and needed architecture

This commit is contained in:
Ricardo Guilherme Schmidt 2018-02-28 01:36:48 -03:00
commit b3025a5d80
5 changed files with 158 additions and 0 deletions

View File

@ -0,0 +1,35 @@
pragma solidity ^0.4.17;
/**
* @title DelegatedCall
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
* @dev Abstract contract that delegates calls by `delegated` modifier to result of `targetDelegatedCall()`
* Important to avoid overwriting wrong storage pointers is that never define storage to this contract
*/
contract DelegatedCall {
/**
* @dev delegates the call of this function
*/
modifier delegated {
//require successfull delegate call to remote `_target()`
require(targetDelegatedCall().delegatecall(msg.data));
assembly {
let outSize := returndatasize
let outDataPtr := mload(0x40) //load memory
returndatacopy(outDataPtr, 0, outSize) //copy last return into pointer
return(outDataPtr, outSize)
}
assert(false); //should never reach here
_; //never will execute local logic
}
/**
* @dev defines the address for delegation of calls
*/
function targetDelegatedCall()
internal
constant
returns(address);
}

View File

@ -0,0 +1,45 @@
pragma solidity ^0.4.17;
import "../common/Controlled.sol";
contract Factory is Controlled {
event NewKernel(address newKernel, bytes infohash);
struct Version {
uint256 blockNumber;
uint256 timestamp;
address kernel;
bytes infohash;
}
mapping (address => uint256) versionMap;
Version[] versionLog;
uint256 latestUpdate;
address latestKernel;
function Factory(address _kernel, bytes _infohash)
public
{
_setKernel(_kernel, _infohash);
}
function setKernel(address _kernel, bytes _infohash)
external
onlyController
{
_setKernel(_kernel, _infohash);
}
function _setKernel(address _kernel, bytes _infohash)
internal
{
require(_kernel != latestKernel);
versionMap[_kernel] = versionLog.length;
versionLog.push(Version({blockNumber: block.number, timestamp: block.timestamp, kernel: _kernel, infohash: _infohash}));
latestUpdate = block.timestamp;
latestKernel = _kernel;
NewKernel(_kernel, _infohash);
}
}

View File

@ -0,0 +1,38 @@
pragma solidity ^0.4.17;
import "./InstanceStorage.sol";
import "./DelegatedCall.sol";
/**
* @title Instance
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
* @dev Contract that forward everything through delegatecall to defined kernel
*/
contract Instance is InstanceStorage, DelegatedCall {
function Instance(address _kernel) public {
kernel = _kernel;
}
/**
* @dev delegatecall everything (but declared functions) to `_target()`
* @notice Verify `kernel()` code to predict behavior
*/
function () external delegated {
//all goes to kernel
}
/**
* @dev returns kernel if kernel that is configured
* @return kernel address
*/
function targetDelegatedCall()
internal
constant
returns(address)
{
return kernel;
}
}

View File

@ -0,0 +1,15 @@
pragma solidity ^0.4.17;
/**
* @title InstanceStorage
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
* @dev Defines kernel vars that Kernel contract share with Instance.
* Important to avoid overwriting wrong storage pointers is that
* InstanceStorage should be always the first contract at heritance.
*/
contract InstanceStorage {
// protected zone start (InstanceStorage vars)
address public kernel;
// protected zone end
}

View File

@ -0,0 +1,25 @@
pragma solidity ^0.4.17;
import "./Instance.sol";
/**
* @title UpdatableInstance
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
* @dev Contract that can be updated by a call from itself.
*/
contract UpdatableInstance is Instance {
function UpdatableInstance(address _kernel)
Instance(_kernel)
public
{
}
function updateUpdatableInstance(address _kernel) external {
require(msg.sender == address(this));
kernel = _kernel;
}
}