From b3025a5d80e179c242c11486d392bc0fe30caa87 Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Wed, 28 Feb 2018 01:36:48 -0300 Subject: [PATCH 1/4] add upgradable instance factory and needed architecture --- contracts/deploy/DelegatedCall.sol | 35 ++++++++++++++++++++ contracts/deploy/Factory.sol | 45 ++++++++++++++++++++++++++ contracts/deploy/Instance.sol | 38 ++++++++++++++++++++++ contracts/deploy/InstanceStorage.sol | 15 +++++++++ contracts/deploy/UpdatableInstance.sol | 25 ++++++++++++++ 5 files changed, 158 insertions(+) create mode 100644 contracts/deploy/DelegatedCall.sol create mode 100644 contracts/deploy/Factory.sol create mode 100644 contracts/deploy/Instance.sol create mode 100644 contracts/deploy/InstanceStorage.sol create mode 100644 contracts/deploy/UpdatableInstance.sol diff --git a/contracts/deploy/DelegatedCall.sol b/contracts/deploy/DelegatedCall.sol new file mode 100644 index 0000000..0526c76 --- /dev/null +++ b/contracts/deploy/DelegatedCall.sol @@ -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); + +} diff --git a/contracts/deploy/Factory.sol b/contracts/deploy/Factory.sol new file mode 100644 index 0000000..19975d5 --- /dev/null +++ b/contracts/deploy/Factory.sol @@ -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); + } + +} \ No newline at end of file diff --git a/contracts/deploy/Instance.sol b/contracts/deploy/Instance.sol new file mode 100644 index 0000000..96c18d8 --- /dev/null +++ b/contracts/deploy/Instance.sol @@ -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; + } + + +} \ No newline at end of file diff --git a/contracts/deploy/InstanceStorage.sol b/contracts/deploy/InstanceStorage.sol new file mode 100644 index 0000000..ba84f64 --- /dev/null +++ b/contracts/deploy/InstanceStorage.sol @@ -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 +} \ No newline at end of file diff --git a/contracts/deploy/UpdatableInstance.sol b/contracts/deploy/UpdatableInstance.sol new file mode 100644 index 0000000..550df8d --- /dev/null +++ b/contracts/deploy/UpdatableInstance.sol @@ -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; + } + +} \ No newline at end of file From d4b98d1186ff50f7d8bfff7612d795285a365f6d Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Wed, 28 Feb 2018 11:47:59 -0400 Subject: [PATCH 2/4] - Added event to inform of an identity instance upgrade - Added test units for Identity factory and its kernel upgrading --- contracts/deploy/UpdatableInstance.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/deploy/UpdatableInstance.sol b/contracts/deploy/UpdatableInstance.sol index 550df8d..60f6d0a 100644 --- a/contracts/deploy/UpdatableInstance.sol +++ b/contracts/deploy/UpdatableInstance.sol @@ -10,6 +10,8 @@ import "./Instance.sol"; */ contract UpdatableInstance is Instance { + event InstanceUpdated(address oldKernel, address newKernel); + function UpdatableInstance(address _kernel) Instance(_kernel) public @@ -19,6 +21,7 @@ contract UpdatableInstance is Instance { function updateUpdatableInstance(address _kernel) external { require(msg.sender == address(this)); + InstanceUpdated(kernel, _kernel); kernel = _kernel; } From 213e76d3a5f9bc1ac3aca11c12d5d4c7795c1cff Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Wed, 28 Feb 2018 14:52:32 -0400 Subject: [PATCH 3/4] Linting to reduce problems in IDE --- contracts/deploy/Instance.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/deploy/Instance.sol b/contracts/deploy/Instance.sol index 96c18d8..f9d60cb 100644 --- a/contracts/deploy/Instance.sol +++ b/contracts/deploy/Instance.sol @@ -3,6 +3,7 @@ pragma solidity ^0.4.17; import "./InstanceStorage.sol"; import "./DelegatedCall.sol"; + /** * @title Instance * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH) From 5466aeed49f5b618e7fe7b2e6b72018a407bcbad Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Tue, 13 Mar 2018 13:52:44 -0400 Subject: [PATCH 4/4] Changed name to function, and added view to Factory --- contracts/deploy/Factory.sol | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/contracts/deploy/Factory.sol b/contracts/deploy/Factory.sol index 19975d5..f63bf71 100644 --- a/contracts/deploy/Factory.sol +++ b/contracts/deploy/Factory.sol @@ -31,6 +31,18 @@ contract Factory is Controlled { _setKernel(_kernel, _infohash); } + function getVersion(uint256 index) public view + returns(uint256 blockNumber, + uint256 timestamp, + address kernel, + bytes infohash) + { + return (versionLog[index].blockNumber, + versionLog[index].timestamp, + versionLog[index].kernel, + versionLog[index].infohash); + } + function _setKernel(address _kernel, bytes _infohash) internal {