From bc40451e910208e07f4c6453379df06c01fecc6b Mon Sep 17 00:00:00 2001 From: Sowmayjain Date: Tue, 19 Mar 2019 02:44:58 +0530 Subject: [PATCH] Updated and standardised the contracts. --- contracts/ProxyRegistry.sol | 62 ++++++++++--- contracts/UserProxy.sol | 172 +++++++++++++++++++++++++++++------- 2 files changed, 188 insertions(+), 46 deletions(-) diff --git a/contracts/ProxyRegistry.sol b/contracts/ProxyRegistry.sol index e468e08..77289ba 100644 --- a/contracts/ProxyRegistry.sol +++ b/contracts/ProxyRegistry.sol @@ -3,29 +3,63 @@ pragma solidity ^0.5.0; import "./UserProxy.sol"; -contract ProxyRegistry { - event Created(address indexed sender, address indexed owner, address proxy); - mapping(address => UserProxy) public proxies; - address public logicProxyAddr; +// checking if the logic proxy is authorised +contract SystemAdmin { - constructor(address logicProxyAddr_) public { - logicProxyAddr = logicProxyAddr_; + address public logicProxyAddr; + + modifier isAdmin() { + require(msg.sender == getAdmin(), "permission-denied"); + _; } - function build(uint activeDays) public returns (UserProxy proxy) { - proxy = build(msg.sender, activeDays); + function getAdmin() internal view returns (address) { + AddressRegistryInterface registry = AddressRegistryInterface(logicProxyAddr); + return registry.getAddress("admin"); + } + +} + + +contract ProxyRegistry is SystemAdmin { + + event Created(address indexed sender, address indexed owner, address proxy); + + mapping(address => UserProxy) public proxies; + bool public guardianEnabled; + + constructor(address _logicProxyAddr) public { + logicProxyAddr = _logicProxyAddr; + } + + function build() public returns (UserProxy proxy) { + proxy = build(msg.sender); } // deploys a new proxy instance and sets custom owner of proxy - function build(address owner, uint activeDays) public returns (UserProxy proxy) { + function build(address owner) public returns (UserProxy proxy) { require( - proxies[owner] == UserProxy(0) || proxies[owner].owner() != owner, + proxies[owner] == UserProxy(0) || proxies[owner].owner() != owner, "multiple-proxy-per-user-not-allowed" ); // Not allow new proxy if the user already has one and remains being the owner - - proxy = new UserProxy(logicProxyAddr, activeDays); + proxy = new UserProxy(owner, logicProxyAddr); emit Created(msg.sender, owner, address(proxy)); - proxy.setOwner(owner); proxies[owner] = proxy; } -} + + // msg.sender should always be proxies created via this contract for successful execution + function updateProxyRecord(address currentOwner, address nextOwner) public { + require(msg.sender == address(proxies[currentOwner]), "invalid-proxy-or-owner"); + proxies[nextOwner] = proxies[currentOwner]; + proxies[currentOwner] = UserProxy(0); + } + + function enableGuardian() public isAdmin { + guardianEnabled = true; + } + + function disableGuardian() public isAdmin { + guardianEnabled = false; + } + +} \ No newline at end of file diff --git a/contracts/UserProxy.sol b/contracts/UserProxy.sol index 485cc3e..f5b04c9 100644 --- a/contracts/UserProxy.sol +++ b/contracts/UserProxy.sol @@ -9,48 +9,99 @@ library SafeMath { } } +/** + * @title ProxyRegistry Interface + */ +interface ProxyRegistryInterface { + function updateProxyRecord(address currentOwner, address nextOwner) external; + function guardianEnabled() external returns (bool); +} -contract UserAuth { +/** + * @title AddressRegistryInterface Interface + */ +interface AddressRegistryInterface { + function getLogic(address logicAddr) external view returns (bool); + function getAddress(string calldata name) external view returns(address); +} + + +/** + * @title Proxy Record + */ +contract ProxyRecord { + + address public proxyContract; + + /** + * @dev this updates the internal proxy ownership on "proxy registry" contract + * @param currentOwner is the current owner + * @param nextOwner is the new assigned owner + */ + function setProxyRecordOwner(address currentOwner, address nextOwner) internal { + ProxyRegistryInterface initCall = ProxyRegistryInterface(proxyContract); + initCall.updateProxyRecord(currentOwner, nextOwner); + } + +} + +/** + * @title User Auth + */ +contract UserAuth is ProxyRecord { using SafeMath for uint; using SafeMath for uint256; - event LogSetOwner(address indexed owner, bool isGuardian); - event LogSetGuardian(address indexed guardian); - - mapping(uint => address) public guardians; + event LogSetOwner(address indexed owner, address setter); + event LogSetPendingOwner(address indexed pendingOwner, address setter); address public owner; - uint public lastActivity; // timestamp - // guardians can set owner after owner stay inactive for certain period - uint public activePeriod; // timestamp + address public pendingOwner; + uint public claimOnwershipTime; // 7 days + /** + * @dev defines the "proxy registry" contract and sets the owner + */ constructor() public { + proxyContract = msg.sender; owner = msg.sender; - emit LogSetOwner(msg.sender, false); + emit LogSetOwner(owner, msg.sender); } + /** + * @dev Throws if not called by owner or contract itself + */ modifier auth { require(isAuth(msg.sender), "permission-denied"); _; } - function setOwner(address owner_) public auth { - owner = owner_; - emit LogSetOwner(owner, false); + /** + * @dev sets the "pending owner" + * @param nextOwner is the assigned "pending owner" + */ + function setPendingOwner(address nextOwner) public auth { + require(block.timestamp > claimOnwershipTime, "owner-is-still-pending"); + pendingOwner = nextOwner; + claimOnwershipTime = block.timestamp.add(7 days); + emit LogSetPendingOwner(nextOwner, msg.sender); } - function setOwnerViaGuardian(address owner_, uint num) public { - require(msg.sender == guardians[num], "permission-denied"); - require(block.timestamp > lastActivity.add(activePeriod), "active-period-not-over"); - owner = owner_; - emit LogSetOwner(owner, true); - } - - function setGuardian(uint num, address guardian_) public auth { - require(num > 0 && num < 6, "guardians-cant-exceed-five"); - guardians[num] = guardian_; - emit LogSetGuardian(guardian_); + /** + * @dev sets "pending owner" as real owner + * Throws if called before 7 day after assigning "pending owner" + */ + function setOwner() public { + require(pendingOwner != address(0), "no-pending-address"); + setProxyRecordOwner(owner, pendingOwner); + owner = pendingOwner; + pendingOwner = address(0); + emit LogSetOwner(owner, msg.sender); } + /** + * @dev checks if called by owner or contract itself + * @param src is the address initiating the call + */ function isAuth(address src) internal view returns (bool) { if (src == address(this)) { return true; @@ -60,9 +111,69 @@ contract UserAuth { return false; } } + } +/** + * @title User Guardians + */ +contract UserGuardian is UserAuth { + event LogSetGuardian(address indexed guardian); + event LogNewActivePeriod(uint newActivePeriod); + event LogSetOwnerViaGuardian(address nextOwner, address indexed guardian); + + mapping(uint => address) public guardians; + uint public lastActivity; // time when called "execute" last time + uint public activePeriod; // the period over lastActivity when guardians have no rights + + /** + * @dev Throws if guardians not enabled by system admin + */ + modifier guard() { + ProxyRegistryInterface initCall = ProxyRegistryInterface(proxyContract); + require(initCall.guardianEnabled()); + _; + } + + /** + * @dev guardians can set "owner" after owner stay inactive for minimum "activePeriod" + * @param nextOwner is the new owner + * @param num is the assigned guardian number + */ + function setOwnerViaGuardian(address nextOwner, uint num) public guard { + require(msg.sender == guardians[num], "permission-denied"); + require(block.timestamp > lastActivity.add(activePeriod), "active-period-not-over"); + owner = nextOwner; + emit LogSetOwnerViaGuardian(nextOwner, guardians[num]); + } + + /** + * @dev sets the guardian with assigned number (upto 3) + * @param num is the guardian assigned number + * @param _guardian is the new guardian address + */ + function setGuardian(uint num, address _guardian) public auth guard { + require(num > 0 && num < 4, "guardians-cant-exceed-three"); + guardians[num] = _guardian; + emit LogSetGuardian(_guardian); + } + + /** + * @dev sets the guardian with assigned number (upto 3) + * @param num is the guardian assigned number + * @param _guardian is the new guardian address + */ + function updateActivePeriod(uint _activePeriod) public auth guard { + activePeriod = _activePeriod; + emit LogNewActivePeriod(_activePeriod); + } + +} + +/** + * @dev logging the execute events + */ contract UserNote { event LogNote( bytes4 indexed sig, @@ -93,27 +204,23 @@ contract UserNote { } -interface AddressRegistry { - function getLogic(address logicAddr) external view returns (bool); -} - - // checking if the logic proxy is authorised contract UserLogic { address public logicProxyAddr; function isLogicAuthorised(address logicAddr) internal view returns (bool) { - AddressRegistry logicProxy = AddressRegistry(logicProxyAddr); + AddressRegistryInterface logicProxy = AddressRegistryInterface(logicProxyAddr); return logicProxy.getLogic(logicAddr); } } +contract UserProxy is UserGuardian, UserNote, UserLogic { -contract UserProxy is UserAuth, UserNote, UserLogic { - constructor(address _logicProxyAddr, uint _activePeriod) public { + constructor(address _owner, address _logicProxyAddr) public { logicProxyAddr = _logicProxyAddr; lastActivity = block.timestamp; - activePeriod = _activePeriod; + activePeriod = 30 days; // default and changeable + owner = _owner; } function() external payable {} @@ -139,4 +246,5 @@ contract UserProxy is UserAuth, UserNote, UserLogic { } } } + }