From bc40451e910208e07f4c6453379df06c01fecc6b Mon Sep 17 00:00:00 2001 From: Sowmayjain Date: Tue, 19 Mar 2019 02:44:58 +0530 Subject: [PATCH 1/6] 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 { } } } + } From 1ffa90ade8fdab4d593db43073783420a854cdb9 Mon Sep 17 00:00:00 2001 From: Sowmayjain Date: Tue, 19 Mar 2019 03:19:39 +0530 Subject: [PATCH 2/6] added more comments. --- contracts/ProxyRegistry.sol | 31 ++++++++++++++----- contracts/UserProxy.sol | 62 ++++++++++++++++++++++++++++--------- 2 files changed, 71 insertions(+), 22 deletions(-) diff --git a/contracts/ProxyRegistry.sol b/contracts/ProxyRegistry.sol index 77289ba..18d357d 100644 --- a/contracts/ProxyRegistry.sol +++ b/contracts/ProxyRegistry.sol @@ -6,15 +6,18 @@ import "./UserProxy.sol"; // checking if the logic proxy is authorised contract SystemAdmin { - address public logicProxyAddr; + address public addrRegistry; modifier isAdmin() { require(msg.sender == getAdmin(), "permission-denied"); _; } + /** + * @dev get the system admin + */ function getAdmin() internal view returns (address) { - AddressRegistryInterface registry = AddressRegistryInterface(logicProxyAddr); + AddressRegistryInterface registry = AddressRegistryInterface(addrRegistry); return registry.getAddress("admin"); } @@ -28,36 +31,50 @@ contract ProxyRegistry is SystemAdmin { mapping(address => UserProxy) public proxies; bool public guardianEnabled; - constructor(address _logicProxyAddr) public { - logicProxyAddr = _logicProxyAddr; + constructor(address _addrRegistry) public { + addrRegistry = _addrRegistry; } + /** + * @dev deploys a new proxy instance and sets msg.sender as owner of proxy + */ function build() public returns (UserProxy proxy) { proxy = build(msg.sender); } - // deploys a new proxy instance and sets custom owner of proxy + /** + * @dev deploys a new proxy instance and sets custom owner of proxy + */ function build(address owner) public returns (UserProxy proxy) { require( 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(owner, logicProxyAddr); + proxy = new UserProxy(owner, addrRegistry); emit Created(msg.sender, owner, address(proxy)); proxies[owner] = proxy; } - // msg.sender should always be proxies created via this contract for successful execution + /** + * @dev update the proxy record whenever owner changed on any proxy + * Throws if msg.sender is not a proxy contract created via this contract + */ 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); } + /** + * @dev enable guardian in overall system + */ function enableGuardian() public isAdmin { guardianEnabled = true; } + /** + * @dev disable guardian in overall system + */ function disableGuardian() public isAdmin { guardianEnabled = false; } diff --git a/contracts/UserProxy.sol b/contracts/UserProxy.sol index f5b04c9..cbc30b3 100644 --- a/contracts/UserProxy.sol +++ b/contracts/UserProxy.sol @@ -31,7 +31,7 @@ interface AddressRegistryInterface { */ contract ProxyRecord { - address public proxyContract; + address public proxyRegistryContract; /** * @dev this updates the internal proxy ownership on "proxy registry" contract @@ -39,7 +39,7 @@ contract ProxyRecord { * @param nextOwner is the new assigned owner */ function setProxyRecordOwner(address currentOwner, address nextOwner) internal { - ProxyRegistryInterface initCall = ProxyRegistryInterface(proxyContract); + ProxyRegistryInterface initCall = ProxyRegistryInterface(proxyRegistryContract); initCall.updateProxyRecord(currentOwner, nextOwner); } @@ -62,9 +62,7 @@ contract UserAuth is ProxyRecord { * @dev defines the "proxy registry" contract and sets the owner */ constructor() public { - proxyContract = msg.sender; - owner = msg.sender; - emit LogSetOwner(owner, msg.sender); + proxyRegistryContract = msg.sender; } /** @@ -131,7 +129,7 @@ contract UserGuardian is UserAuth { * @dev Throws if guardians not enabled by system admin */ modifier guard() { - ProxyRegistryInterface initCall = ProxyRegistryInterface(proxyContract); + ProxyRegistryInterface initCall = ProxyRegistryInterface(proxyRegistryContract); require(initCall.guardianEnabled()); _; } @@ -161,8 +159,7 @@ contract UserGuardian is UserAuth { /** * @dev sets the guardian with assigned number (upto 3) - * @param num is the guardian assigned number - * @param _guardian is the new guardian address + * @param _activePeriod is the period when guardians have no rights to dethrone the owner */ function updateActivePeriod(uint _activePeriod) public auth guard { activePeriod = _activePeriod; @@ -204,31 +201,66 @@ contract UserNote { } -// checking if the logic proxy is authorised +/** + * @title User Proxy Logic + */ contract UserLogic { - address public logicProxyAddr; + address public logicRegistryAddr; + + /** + * @param logicAddr is the logic proxy contract address + * @return the true boolean for logic proxy if authorised otherwise false + */ function isLogicAuthorised(address logicAddr) internal view returns (bool) { - AddressRegistryInterface logicProxy = AddressRegistryInterface(logicProxyAddr); + AddressRegistryInterface logicProxy = AddressRegistryInterface(logicRegistryAddr); return logicProxy.getLogic(logicAddr); } + } contract UserProxy is UserGuardian, UserNote, UserLogic { - constructor(address _owner, address _logicProxyAddr) public { - logicProxyAddr = _logicProxyAddr; + event LogExecute(address target, uint srcNum, uint sessionNum); + + /** + * @dev sets the "address registry", owner's last activity, owner's active period and initial owner + * @param _owner initial owner of the contract + * @param _logicRegistryAddr address registry address which have logic proxy registry + */ + constructor(address _owner, address _logicRegistryAddr) public { + logicRegistryAddr = _logicRegistryAddr; + owner = _owner; lastActivity = block.timestamp; activePeriod = 30 days; // default and changeable - owner = _owner; } function() external payable {} - function execute(address _target, bytes memory _data) public payable auth note returns (bytes memory response) { + /** + * @dev execute authorised calls via delegate call + * @param _target logic proxy address + * @param _data delegate call data + * @param srcNum to find the source + * @param sessionNum to find the session + */ + function execute( + address _target, + bytes memory _data, + uint srcNum, + uint sessionNum + ) + public + payable + auth + note + returns (bytes memory response) + { require(_target != address(0), "user-proxy-target-address-required"); require(isLogicAuthorised(_target), "logic-proxy-address-not-allowed"); lastActivity = block.timestamp; + emit LogExecute(_target, srcNum, sessionNum); + // call contract in current context assembly { let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 0) From 46dd5a0583a316ef5aa5975bd66e0fc81e0c4f11 Mon Sep 17 00:00:00 2001 From: Sowmayjain Date: Tue, 19 Mar 2019 03:27:24 +0530 Subject: [PATCH 3/6] added comment in AddressRegistry --- contracts/AddressRegistry.sol | 40 +++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/contracts/AddressRegistry.sol b/contracts/AddressRegistry.sol index eb100e8..84e0cc7 100644 --- a/contracts/AddressRegistry.sol +++ b/contracts/AddressRegistry.sol @@ -2,9 +2,9 @@ pragma solidity ^0.5.0; contract AddressRegistry { - event AddressSet(string name, address addr); - event DefaultLogicSet(address logicAddr); - event LogicSet(address logicAddr, bool isLogic); + event LogSetAddress(string name, address addr); + event LogSetDefaultLogic(address logicAddr); + event LogSetLogic(address logicAddr, bool isLogic); mapping(bytes32 => address) registry; mapping(address => bool) public defaultLogicProxies; @@ -15,28 +15,35 @@ contract AddressRegistry { registry[keccak256(abi.encodePacked("owner"))] = msg.sender; } + /** + * @dev get the address from system registry + */ function getAddress(string memory name) public view returns(address) { return registry[keccak256(abi.encodePacked(name))]; } + /** + * @dev set new address in system registry + */ function setAddress(string memory name, address addr) public { require( msg.sender == getAddress("admin") || msg.sender == getAddress("owner"), - "Permission Denied" + "permission-denied" ); registry[keccak256(abi.encodePacked(name))] = addr; - emit AddressSet(name, addr); + emit LogSetAddress(name, addr); } modifier isAdmin() { - require( - msg.sender == getAddress("admin"), - "Permission Denied" - ); + require(msg.sender == getAddress("admin"), "permission-denied"); _; } + /** + * @dev get the boolean of the logic proxy contract + * @param logicAddr is the logic proxy address + */ function getLogic(address logicAddr) public view returns (bool) { if (defaultLogicProxies[logicAddr]) { return true; @@ -47,16 +54,23 @@ contract AddressRegistry { } } + /** + * @dev this sets the default logic proxy to true + * @param logicAddr is the default logic proxy address + */ function setDefaultLogic(address logicAddr) public isAdmin { - require(msg.sender == getAddress("admin"), "Permission Denied"); defaultLogicProxies[logicAddr] = true; - emit DefaultLogicSet(logicAddr); + emit LogSetDefaultLogic(logicAddr); } + /** + * @dev this updates the boolean of the logic proxy + * @param logicAddr is the logic proxy address + * @param isLogic is the boolean to set for the logic proxy + */ function setLogic(address logicAddr, bool isLogic) public isAdmin { - require(msg.sender == getAddress("admin"), "Permission Denied"); logicProxies[logicAddr] = true; - emit LogicSet(logicAddr, isLogic); + emit LogSetLogic(logicAddr, isLogic); } } \ No newline at end of file From 8350d1f74cfe71e11749b3e0f64b4b580e1599be Mon Sep 17 00:00:00 2001 From: Sowmayjain Date: Tue, 19 Mar 2019 03:42:36 +0530 Subject: [PATCH 4/6] added grace period in UserProxy. --- contracts/UserProxy.sol | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/contracts/UserProxy.sol b/contracts/UserProxy.sol index cbc30b3..9cddd6b 100644 --- a/contracts/UserProxy.sol +++ b/contracts/UserProxy.sol @@ -56,13 +56,15 @@ contract UserAuth is ProxyRecord { event LogSetPendingOwner(address indexed pendingOwner, address setter); address public owner; address public pendingOwner; - uint public claimOnwershipTime; // 7 days + uint public claimOnwershipTime; // now + 7 days + uint public gracePeriod; // to set the new owner /** * @dev defines the "proxy registry" contract and sets the owner */ constructor() public { proxyRegistryContract = msg.sender; + gracePeriod = 3 days; } /** @@ -74,11 +76,12 @@ contract UserAuth is ProxyRecord { } /** - * @dev sets the "pending owner" + * @dev sets the "pending owner" and provide 3 days grace period to set the new owner via setOwner() + * Throws if called before 10 (i.e. 7 + 3) day after assigning "pending owner" * @param nextOwner is the assigned "pending owner" */ function setPendingOwner(address nextOwner) public auth { - require(block.timestamp > claimOnwershipTime, "owner-is-still-pending"); + require(block.timestamp > claimOnwershipTime.add(gracePeriod), "owner-is-still-pending"); pendingOwner = nextOwner; claimOnwershipTime = block.timestamp.add(7 days); emit LogSetPendingOwner(nextOwner, msg.sender); @@ -86,10 +89,12 @@ contract UserAuth is ProxyRecord { /** * @dev sets "pending owner" as real owner + * Throws if no "pending owner" * Throws if called before 7 day after assigning "pending owner" */ function setOwner() public { require(pendingOwner != address(0), "no-pending-address"); + require(block.timestamp > claimOnwershipTime, "owner-is-still-pending"); setProxyRecordOwner(owner, pendingOwner); owner = pendingOwner; pendingOwner = address(0); From 04eb343142800ed08dc321b7067c54382cf174d5 Mon Sep 17 00:00:00 2001 From: Sowmayjain Date: Tue, 19 Mar 2019 04:09:43 +0530 Subject: [PATCH 5/6] Merged all the registries. --- contracts/ProxyRegistry.sol | 82 ------------------- .../{AddressRegistry.sol => Registry.sol} | 69 +++++++++++++++- contracts/{UserProxy.sol => UserWallet.sol} | 70 ++++++++-------- 3 files changed, 98 insertions(+), 123 deletions(-) delete mode 100644 contracts/ProxyRegistry.sol rename contracts/{AddressRegistry.sol => Registry.sol} (57%) rename contracts/{UserProxy.sol => UserWallet.sol} (89%) diff --git a/contracts/ProxyRegistry.sol b/contracts/ProxyRegistry.sol deleted file mode 100644 index 18d357d..0000000 --- a/contracts/ProxyRegistry.sol +++ /dev/null @@ -1,82 +0,0 @@ -pragma solidity ^0.5.0; - -import "./UserProxy.sol"; - - -// checking if the logic proxy is authorised -contract SystemAdmin { - - address public addrRegistry; - - modifier isAdmin() { - require(msg.sender == getAdmin(), "permission-denied"); - _; - } - - /** - * @dev get the system admin - */ - function getAdmin() internal view returns (address) { - AddressRegistryInterface registry = AddressRegistryInterface(addrRegistry); - 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 _addrRegistry) public { - addrRegistry = _addrRegistry; - } - - /** - * @dev deploys a new proxy instance and sets msg.sender as owner of proxy - */ - function build() public returns (UserProxy proxy) { - proxy = build(msg.sender); - } - - /** - * @dev deploys a new proxy instance and sets custom owner of proxy - */ - function build(address owner) public returns (UserProxy proxy) { - require( - 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(owner, addrRegistry); - emit Created(msg.sender, owner, address(proxy)); - proxies[owner] = proxy; - } - - /** - * @dev update the proxy record whenever owner changed on any proxy - * Throws if msg.sender is not a proxy contract created via this contract - */ - 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); - } - - /** - * @dev enable guardian in overall system - */ - function enableGuardian() public isAdmin { - guardianEnabled = true; - } - - /** - * @dev disable guardian in overall system - */ - function disableGuardian() public isAdmin { - guardianEnabled = false; - } - -} \ No newline at end of file diff --git a/contracts/AddressRegistry.sol b/contracts/Registry.sol similarity index 57% rename from contracts/AddressRegistry.sol rename to contracts/Registry.sol index 84e0cc7..437a99a 100644 --- a/contracts/AddressRegistry.sol +++ b/contracts/Registry.sol @@ -1,14 +1,12 @@ pragma solidity ^0.5.0; +import "./UserWallet.sol"; + contract AddressRegistry { event LogSetAddress(string name, address addr); - event LogSetDefaultLogic(address logicAddr); - event LogSetLogic(address logicAddr, bool isLogic); mapping(bytes32 => address) registry; - mapping(address => bool) public defaultLogicProxies; - mapping(address => bool) public logicProxies; constructor() public { registry[keccak256(abi.encodePacked("admin"))] = msg.sender; @@ -40,6 +38,17 @@ contract AddressRegistry { _; } +} + + +contract LogicRegistry is AddressRegistry { + + event LogSetDefaultLogic(address logicAddr); + event LogSetLogic(address logicAddr, bool isLogic); + + mapping(address => bool) public defaultLogicProxies; + mapping(address => bool) public logicProxies; + /** * @dev get the boolean of the logic proxy contract * @param logicAddr is the logic proxy address @@ -73,4 +82,56 @@ contract AddressRegistry { emit LogSetLogic(logicAddr, isLogic); } +} + + +contract ProxyRegistry is LogicRegistry { + + event Created(address indexed sender, address indexed owner, address proxy); + + mapping(address => UserWallet) public proxies; + bool public guardianEnabled; + + /** + * @dev deploys a new proxy instance and sets msg.sender as owner of proxy + */ + function build() public returns (UserWallet proxy) { + proxy = build(msg.sender); + } + + /** + * @dev deploys a new proxy instance and sets custom owner of proxy + * Throws if the owner already have a UserWallet + */ + function build(address owner) public returns (UserWallet proxy) { + require(proxies[owner] == UserWallet(0), "multiple-proxy-per-user-not-allowed"); + proxy = new UserWallet(owner); + emit Created(msg.sender, owner, address(proxy)); + proxies[owner] = proxy; + } + + /** + * @dev update the proxy record whenever owner changed on any proxy + * Throws if msg.sender is not a proxy contract created via this contract + */ + function updateProxyRecord(address currentOwner, address nextOwner) public { + require(msg.sender == address(proxies[currentOwner]), "invalid-proxy-or-owner"); + proxies[nextOwner] = proxies[currentOwner]; + proxies[currentOwner] = UserWallet(0); + } + + /** + * @dev enable guardian in overall system + */ + function enableGuardian() public isAdmin { + guardianEnabled = true; + } + + /** + * @dev disable guardian in overall system + */ + function disableGuardian() public isAdmin { + guardianEnabled = false; + } + } \ No newline at end of file diff --git a/contracts/UserProxy.sol b/contracts/UserWallet.sol similarity index 89% rename from contracts/UserProxy.sol rename to contracts/UserWallet.sol index 9cddd6b..ad1a2f1 100644 --- a/contracts/UserProxy.sol +++ b/contracts/UserWallet.sol @@ -1,6 +1,9 @@ pragma solidity ^0.5.0; +/** + * @dev because math is not safe + */ library SafeMath { function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; @@ -9,46 +12,53 @@ library SafeMath { } } -/** - * @title ProxyRegistry Interface - */ -interface ProxyRegistryInterface { - function updateProxyRecord(address currentOwner, address nextOwner) external; - function guardianEnabled() external returns (bool); -} /** * @title AddressRegistryInterface Interface */ interface AddressRegistryInterface { function getLogic(address logicAddr) external view returns (bool); - function getAddress(string calldata name) external view returns(address); + function updateProxyRecord(address currentOwner, address nextOwner) external; + function guardianEnabled() external returns (bool); } /** - * @title Proxy Record + * @title Address Record */ -contract ProxyRecord { - - address public proxyRegistryContract; +contract AddressRecord { + + /** + * @dev address registry of system, logic and proxy addresses + */ + address public registry; /** - * @dev this updates the internal proxy ownership on "proxy registry" contract + * @dev this updates the internal proxy ownership on "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(proxyRegistryContract); + AddressRegistryInterface initCall = AddressRegistryInterface(registry); initCall.updateProxyRecord(currentOwner, nextOwner); } + /** + * @param logicAddr is the logic proxy contract address + * @return the true boolean for logic proxy if authorised otherwise false + */ + function isLogicAuthorised(address logicAddr) internal view returns (bool) { + AddressRegistryInterface logicProxy = AddressRegistryInterface(registry); + return logicProxy.getLogic(logicAddr); + } + } + /** * @title User Auth */ -contract UserAuth is ProxyRecord { +contract UserAuth is AddressRecord { using SafeMath for uint; using SafeMath for uint256; @@ -63,7 +73,6 @@ contract UserAuth is ProxyRecord { * @dev defines the "proxy registry" contract and sets the owner */ constructor() public { - proxyRegistryContract = msg.sender; gracePeriod = 3 days; } @@ -117,6 +126,7 @@ contract UserAuth is ProxyRecord { } + /** * @title User Guardians */ @@ -134,8 +144,8 @@ contract UserGuardian is UserAuth { * @dev Throws if guardians not enabled by system admin */ modifier guard() { - ProxyRegistryInterface initCall = ProxyRegistryInterface(proxyRegistryContract); - require(initCall.guardianEnabled()); + AddressRegistryInterface initCall = AddressRegistryInterface(registry); + require(initCall.guardianEnabled(), "guardian-not-enabled"); _; } @@ -173,6 +183,7 @@ contract UserGuardian is UserAuth { } + /** * @dev logging the execute events */ @@ -207,24 +218,9 @@ contract UserNote { /** - * @title User Proxy Logic + * @title User Owned Contract Wallet */ -contract UserLogic { - address public logicRegistryAddr; - - /** - * @param logicAddr is the logic proxy contract address - * @return the true boolean for logic proxy if authorised otherwise false - */ - function isLogicAuthorised(address logicAddr) internal view returns (bool) { - AddressRegistryInterface logicProxy = AddressRegistryInterface(logicRegistryAddr); - return logicProxy.getLogic(logicAddr); - } - -} - - -contract UserProxy is UserGuardian, UserNote, UserLogic { +contract UserWallet is UserGuardian, UserNote { event LogExecute(address target, uint srcNum, uint sessionNum); @@ -233,8 +229,8 @@ contract UserProxy is UserGuardian, UserNote, UserLogic { * @param _owner initial owner of the contract * @param _logicRegistryAddr address registry address which have logic proxy registry */ - constructor(address _owner, address _logicRegistryAddr) public { - logicRegistryAddr = _logicRegistryAddr; + constructor(address _owner) public { + registry = msg.sender; owner = _owner; lastActivity = block.timestamp; activePeriod = 30 days; // default and changeable From 2e3a95be3240ba4bda17fa4a928f8c1c1ffe8139 Mon Sep 17 00:00:00 2001 From: Sowmayjain Date: Tue, 19 Mar 2019 04:11:14 +0530 Subject: [PATCH 6/6] added comments in registry. --- contracts/Registry.sol | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/contracts/Registry.sol b/contracts/Registry.sol index 437a99a..9866078 100644 --- a/contracts/Registry.sol +++ b/contracts/Registry.sol @@ -3,6 +3,9 @@ pragma solidity ^0.5.0; import "./UserWallet.sol"; +/** + * @title Address Registry + */ contract AddressRegistry { event LogSetAddress(string name, address addr); @@ -41,6 +44,9 @@ contract AddressRegistry { } +/** + * @title Logic Registry + */ contract LogicRegistry is AddressRegistry { event LogSetDefaultLogic(address logicAddr); @@ -85,6 +91,9 @@ contract LogicRegistry is AddressRegistry { } +/** + * @title User Wallet Registry + */ contract ProxyRegistry is LogicRegistry { event Created(address indexed sender, address indexed owner, address proxy);