reorg
This commit is contained in:
commit
fade1238b3
|
@ -0,0 +1,35 @@
|
||||||
|
pragma solidity ^0.4.21;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
view
|
||||||
|
returns(address);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
pragma solidity ^0.4.17;
|
||||||
|
|
||||||
|
import "../common/Controlled.sol";
|
||||||
|
|
||||||
|
contract Factory is Controlled {
|
||||||
|
|
||||||
|
event NewKernel(address newKernel, bytes32 codeHash);
|
||||||
|
|
||||||
|
struct Version {
|
||||||
|
uint256 blockNumber;
|
||||||
|
uint256 timestamp;
|
||||||
|
address kernel;
|
||||||
|
bytes32 codeHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapping (address => uint256) versionMap;
|
||||||
|
|
||||||
|
Version[] versionLog;
|
||||||
|
uint256 latestUpdate;
|
||||||
|
address latestKernel;
|
||||||
|
|
||||||
|
function Factory(address _kernel)
|
||||||
|
public
|
||||||
|
{
|
||||||
|
_setKernel(_kernel);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setKernel(address _kernel)
|
||||||
|
external
|
||||||
|
onlyController
|
||||||
|
{
|
||||||
|
_setKernel(_kernel);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVersion(uint256 index)
|
||||||
|
public
|
||||||
|
view
|
||||||
|
returns(
|
||||||
|
uint256 blockNumber,
|
||||||
|
uint256 timestamp,
|
||||||
|
address kernel,
|
||||||
|
bytes32 codeHash
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
versionLog[index].blockNumber,
|
||||||
|
versionLog[index].timestamp,
|
||||||
|
versionLog[index].kernel,
|
||||||
|
versionLog[index].codeHash
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCodeHash(address _addr)
|
||||||
|
public
|
||||||
|
view
|
||||||
|
returns (bytes32 codeHash)
|
||||||
|
{
|
||||||
|
bytes memory o_code;
|
||||||
|
uint size;
|
||||||
|
assembly {
|
||||||
|
// retrieve the size of the code, this needs assembly
|
||||||
|
size := extcodesize(_addr)
|
||||||
|
}
|
||||||
|
require (size > 0);
|
||||||
|
assembly {
|
||||||
|
// allocate output byte array - this could also be done without assembly
|
||||||
|
// by using o_code = new bytes(size)
|
||||||
|
o_code := mload(0x40)
|
||||||
|
// new "memory end" including padding
|
||||||
|
mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
|
||||||
|
// store length in memory
|
||||||
|
mstore(o_code, size)
|
||||||
|
// actually retrieve the code, this needs assembly
|
||||||
|
extcodecopy(_addr, add(o_code, 0x20), 0, size)
|
||||||
|
}
|
||||||
|
codeHash = keccak256(o_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _setKernel(address _kernel)
|
||||||
|
internal
|
||||||
|
{
|
||||||
|
require(_kernel != latestKernel);
|
||||||
|
bytes32 _codeHash = getCodeHash(_kernel);
|
||||||
|
versionMap[_kernel] = versionLog.length;
|
||||||
|
versionLog.push(Version({blockNumber: block.number, timestamp: block.timestamp, kernel: _kernel, codeHash: _codeHash}));
|
||||||
|
latestUpdate = block.timestamp;
|
||||||
|
latestKernel = _kernel;
|
||||||
|
emit NewKernel(_kernel, _codeHash);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
pragma solidity ^0.4.21;
|
||||||
|
|
||||||
|
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
|
||||||
|
view
|
||||||
|
returns(address)
|
||||||
|
{
|
||||||
|
return kernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
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 {
|
||||||
|
|
||||||
|
event InstanceUpdated(address oldKernel, address newKernel);
|
||||||
|
|
||||||
|
function UpdatableInstance(address _kernel)
|
||||||
|
Instance(_kernel)
|
||||||
|
public
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUpdatableInstance(address _kernel) external {
|
||||||
|
require(msg.sender == address(this));
|
||||||
|
InstanceUpdated(kernel, _kernel);
|
||||||
|
kernel = _kernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue