From a882448a3c1a5ba9341f92da240f070d37103a9e Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Fri, 18 Sep 2020 14:21:32 +0200 Subject: [PATCH 01/12] Move contracts into a dedicated folder --- ICommonUtilities.sol | 12 -- IDoubleProxy.sol | 11 -- IERC721.sol | 7 -- IERC721Receiver.sol | 5 - IMVDFunctionalitiesManager.sol | 33 ------ LICENSE | 2 +- .../CommonUtilities.sol | 0 DoubleProxy.sol => contracts/DoubleProxy.sol | 0 .../Functionality.sol | 0 contracts/ICommonUtilities.sol | 57 +++++++++ contracts/IDoubleProxy.sol | 46 +++++++ IERC20.sol => contracts/IERC20.sol | 0 contracts/IERC721.sol | 18 +++ contracts/IERC721Receiver.sol | 11 ++ contracts/IMVDFunctionalitiesManager.sol | 112 ++++++++++++++++++ .../IMVDFunctionalityModelsManager.sol | 0 .../IMVDFunctionalityProposal.sol | 0 .../IMVDFunctionalityProposalManager.sol | 0 IMVDProxy.sol => contracts/IMVDProxy.sol | 0 IMVDWallet.sol => contracts/IMVDWallet.sol | 0 .../IStateHolder.sol | 0 .../IVotingToken.sol | 0 .../MVDFunctionalitiesManager.sol | 0 .../MVDFunctionalityModelsManager.sol | 0 .../MVDFunctionalityProposal.sol | 0 .../MVDFunctionalityProposalManager.sol | 0 MVDProxy.sol => contracts/MVDProxy.sol | 0 MVDWallet.sol => contracts/MVDWallet.sol | 0 StateHolder.sol => contracts/StateHolder.sol | 0 VotingToken.sol => contracts/VotingToken.sol | 0 30 files changed, 245 insertions(+), 69 deletions(-) delete mode 100644 ICommonUtilities.sol delete mode 100644 IDoubleProxy.sol delete mode 100644 IERC721.sol delete mode 100644 IERC721Receiver.sol delete mode 100644 IMVDFunctionalitiesManager.sol rename CommonUtilities.sol => contracts/CommonUtilities.sol (100%) rename DoubleProxy.sol => contracts/DoubleProxy.sol (100%) rename Functionality.sol => contracts/Functionality.sol (100%) create mode 100644 contracts/ICommonUtilities.sol create mode 100644 contracts/IDoubleProxy.sol rename IERC20.sol => contracts/IERC20.sol (100%) create mode 100644 contracts/IERC721.sol create mode 100644 contracts/IERC721Receiver.sol create mode 100644 contracts/IMVDFunctionalitiesManager.sol rename IMVDFunctionalityModelsManager.sol => contracts/IMVDFunctionalityModelsManager.sol (100%) rename IMVDFunctionalityProposal.sol => contracts/IMVDFunctionalityProposal.sol (100%) rename IMVDFunctionalityProposalManager.sol => contracts/IMVDFunctionalityProposalManager.sol (100%) rename IMVDProxy.sol => contracts/IMVDProxy.sol (100%) rename IMVDWallet.sol => contracts/IMVDWallet.sol (100%) rename IStateHolder.sol => contracts/IStateHolder.sol (100%) rename IVotingToken.sol => contracts/IVotingToken.sol (100%) rename MVDFunctionalitiesManager.sol => contracts/MVDFunctionalitiesManager.sol (100%) rename MVDFunctionalityModelsManager.sol => contracts/MVDFunctionalityModelsManager.sol (100%) rename MVDFunctionalityProposal.sol => contracts/MVDFunctionalityProposal.sol (100%) rename MVDFunctionalityProposalManager.sol => contracts/MVDFunctionalityProposalManager.sol (100%) rename MVDProxy.sol => contracts/MVDProxy.sol (100%) rename MVDWallet.sol => contracts/MVDWallet.sol (100%) rename StateHolder.sol => contracts/StateHolder.sol (100%) rename VotingToken.sol => contracts/VotingToken.sol (100%) diff --git a/ICommonUtilities.sol b/ICommonUtilities.sol deleted file mode 100644 index 7c86a7a..0000000 --- a/ICommonUtilities.sol +++ /dev/null @@ -1,12 +0,0 @@ -pragma solidity ^0.6.0; - -interface ICommonUtilities { - function toString(address _addr) external pure returns(string memory); - function toString(uint _i) external pure returns(string memory); - function toUint256(bytes calldata bs) external pure returns(uint256 x); - function toAddress(bytes calldata b) external pure returns (address addr); - function compareStrings(string calldata a, string calldata b) external pure returns(bool); - function getFirstJSONPart(address sourceLocation, uint256 sourceLocationId, address location) external pure returns(bytes memory); - function formatReturnAbiParametersArray(string calldata m) external pure returns(string memory); - function toLowerCase(string calldata str) external pure returns(string memory); -} \ No newline at end of file diff --git a/IDoubleProxy.sol b/IDoubleProxy.sol deleted file mode 100644 index 3e96465..0000000 --- a/IDoubleProxy.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma solidity ^0.6.0; - -interface IDoubleProxy { - function init(address[] calldata proxies, address currentProxy) external; - function proxy() external view returns(address); - function setProxy() external; - function isProxy(address) external view returns(bool); - function proxiesLength() external view returns(uint256); - function proxies(uint256 start, uint256 offset) external view returns(address[] memory); - function proxies() external view returns(address[] memory); -} \ No newline at end of file diff --git a/IERC721.sol b/IERC721.sol deleted file mode 100644 index 913b8bb..0000000 --- a/IERC721.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma solidity ^0.6.0; - -interface IERC721 { - function ownerOf(uint256 _tokenId) external view returns (address); - function transferFrom(address _from, address _to, uint256 _tokenId) external payable; - function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; -} \ No newline at end of file diff --git a/IERC721Receiver.sol b/IERC721Receiver.sol deleted file mode 100644 index 62d698e..0000000 --- a/IERC721Receiver.sol +++ /dev/null @@ -1,5 +0,0 @@ -pragma solidity ^0.6.0; - -interface IERC721Receiver { - function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4); -} \ No newline at end of file diff --git a/IMVDFunctionalitiesManager.sol b/IMVDFunctionalitiesManager.sol deleted file mode 100644 index 5948cf1..0000000 --- a/IMVDFunctionalitiesManager.sol +++ /dev/null @@ -1,33 +0,0 @@ -pragma solidity ^0.6.0; - -interface IMVDFunctionalitiesManager { - - function getProxy() external view returns (address); - function setProxy() external; - - function init(address sourceLocation, - uint256 getMinimumBlockNumberSourceLocationId, address getMinimumBlockNumberFunctionalityAddress, - uint256 getEmergencyMinimumBlockNumberSourceLocationId, address getEmergencyMinimumBlockNumberFunctionalityAddress, - uint256 getEmergencySurveyStakingSourceLocationId, address getEmergencySurveyStakingFunctionalityAddress, - uint256 checkVoteResultSourceLocationId, address checkVoteResultFunctionalityAddress) external; - - function addFunctionality(string calldata codeName, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string calldata methodSignature, string calldata returnAbiParametersArray, bool isInternal, bool needsSender) external; - function addFunctionality(string calldata codeName, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string calldata methodSignature, string calldata returnAbiParametersArray, bool isInternal, bool needsSender, uint256 position) external; - function removeFunctionality(string calldata codeName) external returns(bool removed, uint256 position); - function isValidFunctionality(address functionality) external view returns(bool); - function isAuthorizedFunctionality(address functionality) external view returns(bool); - function setCallingContext(address location) external returns(bool); - function clearCallingContext() external; - function getFunctionalityData(string calldata codeName) external view returns(address, uint256, string memory, address, uint256); - function hasFunctionality(string calldata codeName) external view returns(bool); - function getFunctionalitiesAmount() external view returns(uint256); - function functionalitiesToJSON() external view returns(string memory); - function functionalitiesToJSON(uint256 start, uint256 l) external view returns(string memory functionsJSONArray); - function functionalityNames() external view returns(string memory); - function functionalityNames(uint256 start, uint256 l) external view returns(string memory functionsJSONArray); - function functionalityToJSON(string calldata codeName) external view returns(string memory); - - function preConditionCheck(string calldata codeName, bytes calldata data, uint8 submitable, address sender, uint256 value) external view returns(address location, bytes memory payload); - - function setupFunctionality(address proposalAddress) external returns (bool); -} \ No newline at end of file diff --git a/LICENSE b/LICENSE index e2e7f6c..85dc429 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Robe +Copyright (c) 2020 Robe Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/CommonUtilities.sol b/contracts/CommonUtilities.sol similarity index 100% rename from CommonUtilities.sol rename to contracts/CommonUtilities.sol diff --git a/DoubleProxy.sol b/contracts/DoubleProxy.sol similarity index 100% rename from DoubleProxy.sol rename to contracts/DoubleProxy.sol diff --git a/Functionality.sol b/contracts/Functionality.sol similarity index 100% rename from Functionality.sol rename to contracts/Functionality.sol diff --git a/contracts/ICommonUtilities.sol b/contracts/ICommonUtilities.sol new file mode 100644 index 0000000..2a7ea96 --- /dev/null +++ b/contracts/ICommonUtilities.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.7.0; + +/** + * @title Common Utilities + * @dev Collection of simple utilities + */ +interface ICommonUtilities { + /** + * @dev Convert address to string + */ + function toString(address _addr) external pure returns (string memory); + + /** + * @dev Convert uint to string + */ + function toString(uint256 _i) external pure returns (string memory); + + /** + * @dev Convert bytes address to uint + */ + function toUint256(bytes calldata bs) external pure returns (uint256 x); + + /** + * @dev Convert bytes address to address + */ + function toAddress(bytes calldata b) external pure returns (address addr); + + /** + * @dev Compare to strings + */ + function compareStrings(string calldata a, string calldata b) + external + pure + returns (bool); + + // DOCUMENT + function getFirstJSONPart( + address sourceLocation, + uint256 sourceLocationId, + address location + ) external pure returns (bytes memory); + + // DOCUMENT + function formatReturnAbiParametersArray(string calldata m) + external + pure + returns (string memory); + + /** + * @dev Convert a string to lowercase + */ + function toLowerCase(string calldata str) + external + pure + returns (string memory); +} diff --git a/contracts/IDoubleProxy.sol b/contracts/IDoubleProxy.sol new file mode 100644 index 0000000..cad8e1b --- /dev/null +++ b/contracts/IDoubleProxy.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.7.0; + +/** + * @title Double Proxy Interface + * @dev + * + */ +interface IDoubleProxy { + /** + * @dev Initializer logic used during the constructor call + * @param proxies Array of address of the old proxies, only used in legacy scenarios. Can be left empty. + * @param currentProxy Address of the current proxy + */ + function init(address[] calldata proxies, address currentProxy) external; + + /** + * @dev GET the proxy + */ + function proxy() external view returns (address); + + /** + * @dev SET the proxy + */ + function setProxy() external; + + /** + * @dev Check if the address is or has been a proxy + */ + function isProxy(address) external view returns (bool); + + /** + * @dev GET the number of proxies + */ + function proxiesLength() external view returns (uint256); + + /** + * @dev Retrieve a portion of the proxies + */ + function proxies(uint256 start, uint256 offset) + external + view + returns (address[] memory); + + function proxies() external view returns (address[] memory); +} diff --git a/IERC20.sol b/contracts/IERC20.sol similarity index 100% rename from IERC20.sol rename to contracts/IERC20.sol diff --git a/contracts/IERC721.sol b/contracts/IERC721.sol new file mode 100644 index 0000000..b28f9aa --- /dev/null +++ b/contracts/IERC721.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.6.0; + +interface IERC721 { + function ownerOf(uint256 _tokenId) external view returns (address); + + function transferFrom( + address _from, + address _to, + uint256 _tokenId + ) external payable; + + function safeTransferFrom( + address from, + address to, + uint256 tokenId, + bytes calldata data + ) external; +} diff --git a/contracts/IERC721Receiver.sol b/contracts/IERC721Receiver.sol new file mode 100644 index 0000000..8e44a4b --- /dev/null +++ b/contracts/IERC721Receiver.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.6.0; + +interface IERC721Receiver { + function onERC721Received( + address operator, + address from, + uint256 tokenId, + bytes calldata data + ) external returns (bytes4); +} diff --git a/contracts/IMVDFunctionalitiesManager.sol b/contracts/IMVDFunctionalitiesManager.sol new file mode 100644 index 0000000..eb32d8b --- /dev/null +++ b/contracts/IMVDFunctionalitiesManager.sol @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.6.0; + +interface IMVDFunctionalitiesManager { + function getProxy() external view returns (address); + + function setProxy() external; + + function init( + address sourceLocation, + uint256 getMinimumBlockNumberSourceLocationId, + address getMinimumBlockNumberFunctionalityAddress, + uint256 getEmergencyMinimumBlockNumberSourceLocationId, + address getEmergencyMinimumBlockNumberFunctionalityAddress, + uint256 getEmergencySurveyStakingSourceLocationId, + address getEmergencySurveyStakingFunctionalityAddress, + uint256 checkVoteResultSourceLocationId, + address checkVoteResultFunctionalityAddress + ) external; + + function addFunctionality( + string calldata codeName, + address sourceLocation, + uint256 sourceLocationId, + address location, + bool submitable, + string calldata methodSignature, + string calldata returnAbiParametersArray, + bool isInternal, + bool needsSender + ) external; + + function addFunctionality( + string calldata codeName, + address sourceLocation, + uint256 sourceLocationId, + address location, + bool submitable, + string calldata methodSignature, + string calldata returnAbiParametersArray, + bool isInternal, + bool needsSender, + uint256 position + ) external; + + function removeFunctionality(string calldata codeName) + external + returns (bool removed, uint256 position); + + function isValidFunctionality(address functionality) + external + view + returns (bool); + + function isAuthorizedFunctionality(address functionality) + external + view + returns (bool); + + function setCallingContext(address location) external returns (bool); + + function clearCallingContext() external; + + function getFunctionalityData(string calldata codeName) + external + view + returns ( + address, + uint256, + string memory, + address, + uint256 + ); + + function hasFunctionality(string calldata codeName) + external + view + returns (bool); + + function getFunctionalitiesAmount() external view returns (uint256); + + function functionalitiesToJSON() external view returns (string memory); + + function functionalitiesToJSON(uint256 start, uint256 l) + external + view + returns (string memory functionsJSONArray); + + function functionalityNames() external view returns (string memory); + + function functionalityNames(uint256 start, uint256 l) + external + view + returns (string memory functionsJSONArray); + + function functionalityToJSON(string calldata codeName) + external + view + returns (string memory); + + function preConditionCheck( + string calldata codeName, + bytes calldata data, + uint8 submitable, + address sender, + uint256 value + ) external view returns (address location, bytes memory payload); + + function setupFunctionality(address proposalAddress) + external + returns (bool); +} diff --git a/IMVDFunctionalityModelsManager.sol b/contracts/IMVDFunctionalityModelsManager.sol similarity index 100% rename from IMVDFunctionalityModelsManager.sol rename to contracts/IMVDFunctionalityModelsManager.sol diff --git a/IMVDFunctionalityProposal.sol b/contracts/IMVDFunctionalityProposal.sol similarity index 100% rename from IMVDFunctionalityProposal.sol rename to contracts/IMVDFunctionalityProposal.sol diff --git a/IMVDFunctionalityProposalManager.sol b/contracts/IMVDFunctionalityProposalManager.sol similarity index 100% rename from IMVDFunctionalityProposalManager.sol rename to contracts/IMVDFunctionalityProposalManager.sol diff --git a/IMVDProxy.sol b/contracts/IMVDProxy.sol similarity index 100% rename from IMVDProxy.sol rename to contracts/IMVDProxy.sol diff --git a/IMVDWallet.sol b/contracts/IMVDWallet.sol similarity index 100% rename from IMVDWallet.sol rename to contracts/IMVDWallet.sol diff --git a/IStateHolder.sol b/contracts/IStateHolder.sol similarity index 100% rename from IStateHolder.sol rename to contracts/IStateHolder.sol diff --git a/IVotingToken.sol b/contracts/IVotingToken.sol similarity index 100% rename from IVotingToken.sol rename to contracts/IVotingToken.sol diff --git a/MVDFunctionalitiesManager.sol b/contracts/MVDFunctionalitiesManager.sol similarity index 100% rename from MVDFunctionalitiesManager.sol rename to contracts/MVDFunctionalitiesManager.sol diff --git a/MVDFunctionalityModelsManager.sol b/contracts/MVDFunctionalityModelsManager.sol similarity index 100% rename from MVDFunctionalityModelsManager.sol rename to contracts/MVDFunctionalityModelsManager.sol diff --git a/MVDFunctionalityProposal.sol b/contracts/MVDFunctionalityProposal.sol similarity index 100% rename from MVDFunctionalityProposal.sol rename to contracts/MVDFunctionalityProposal.sol diff --git a/MVDFunctionalityProposalManager.sol b/contracts/MVDFunctionalityProposalManager.sol similarity index 100% rename from MVDFunctionalityProposalManager.sol rename to contracts/MVDFunctionalityProposalManager.sol diff --git a/MVDProxy.sol b/contracts/MVDProxy.sol similarity index 100% rename from MVDProxy.sol rename to contracts/MVDProxy.sol diff --git a/MVDWallet.sol b/contracts/MVDWallet.sol similarity index 100% rename from MVDWallet.sol rename to contracts/MVDWallet.sol diff --git a/StateHolder.sol b/contracts/StateHolder.sol similarity index 100% rename from StateHolder.sol rename to contracts/StateHolder.sol diff --git a/VotingToken.sol b/contracts/VotingToken.sol similarity index 100% rename from VotingToken.sol rename to contracts/VotingToken.sol From bde15e817fbb87e1b494f1a207f98af66e45cde8 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Fri, 18 Sep 2020 17:24:45 +0200 Subject: [PATCH 02/12] WIP: Add Natspec --- contracts/CommonUtilities.sol | 107 ++-- contracts/DoubleProxy.sol | 45 +- contracts/Functionality.sol | 6 +- contracts/IDoubleProxy.sol | 1 + contracts/IMVDFunctionalitiesManager.sol | 105 +++- contracts/IMVDFunctionalityModelsManager.sol | 23 +- contracts/IMVDFunctionalityProposal.sol | 184 ++++++- .../IMVDFunctionalityProposalManager.sol | 15 +- contracts/IMVDProxy.sol | 169 +++++- contracts/MVDFunctionalitiesManager.sol | 475 +++++++++++++---- contracts/MVDFunctionalityModelsManager.sol | 263 +++++++-- contracts/MVDFunctionalityProposal.sol | 329 ++++++++---- contracts/MVDProxy.sol | 502 ++++++++++++++---- 13 files changed, 1737 insertions(+), 487 deletions(-) diff --git a/contracts/CommonUtilities.sol b/contracts/CommonUtilities.sol index 111f1b7..235bf38 100644 --- a/contracts/CommonUtilities.sol +++ b/contracts/CommonUtilities.sol @@ -1,92 +1,129 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; import "./ICommonUtilities.sol"; contract CommonUtilities is ICommonUtilities { - - function toString(address _addr) public override pure returns(string memory) { + function toString(address _addr) + public + override + pure + returns (string memory) + { bytes32 value = bytes32(uint256(_addr)); bytes memory alphabet = "0123456789abcdef"; bytes memory str = new bytes(42); - str[0] = '0'; - str[1] = 'x'; - for (uint i = 0; i < 20; i++) { - str[2+i*2] = alphabet[uint(uint8(value[i + 12] >> 4))]; - str[3+i*2] = alphabet[uint(uint8(value[i + 12] & 0x0f))]; + str[0] = "0"; + str[1] = "x"; + for (uint256 i = 0; i < 20; i++) { + str[2 + i * 2] = alphabet[uint256(uint8(value[i + 12] >> 4))]; + str[3 + i * 2] = alphabet[uint256(uint8(value[i + 12] & 0x0f))]; } return string(str); } - function toString(uint _i) public override pure returns(string memory) { + function toString(uint256 _i) public override pure returns (string memory) { if (_i == 0) { return "0"; } - uint j = _i; - uint len; + uint256 j = _i; + uint256 len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); - uint k = len - 1; + uint256 k = len - 1; while (_i != 0) { - bstr[k--] = byte(uint8(48 + _i % 10)); + bstr[k--] = bytes1(uint8(48 + (_i % 10))); _i /= 10; } return string(bstr); } - function toUint256(bytes memory bs) public override pure returns(uint256 x) { - if(bs.length >= 32) { + function toUint256(bytes memory bs) + public + override + pure + returns (uint256 x) + { + if (bs.length >= 32) { assembly { x := mload(add(bs, add(0x20, 0))) } } } - function toAddress(bytes memory b) public override pure returns (address addr) { - if(b.length > 0) { + function toAddress(bytes memory b) + public + override + pure + returns (address addr) + { + if (b.length > 0) { assembly { - addr := mload(add(b,20)) + addr := mload(add(b, 20)) } } } - function compareStrings(string memory a, string memory b) public override pure returns(bool) { + function compareStrings(string memory a, string memory b) + public + override + pure + returns (bool) + { return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b)); } - function getFirstJSONPart(address sourceLocation, uint256 sourceLocationId, address location) public override pure returns(bytes memory) { - return abi.encodePacked( - '"sourceLocation":"', - toString(sourceLocation), - '","sourceLocationId":', - toString(sourceLocationId), - ',"location":"', - toString(location) - ); + function getFirstJSONPart( + address sourceLocation, + uint256 sourceLocationId, + address location + ) public override pure returns (bytes memory) { + return + abi.encodePacked( + '"sourceLocation":"', + toString(sourceLocation), + '","sourceLocationId":', + toString(sourceLocationId), + ',"location":"', + toString(location) + ); } - function formatReturnAbiParametersArray(string memory m) public override pure returns(string memory) { + function formatReturnAbiParametersArray(string memory m) + public + override + pure + returns (string memory) + { bytes memory b = bytes(m); - if(b.length < 2) { + if (b.length < 2) { return "[]"; } - if(b[0] != bytes1("[")) { + if (b[0] != bytes1("[")) { return "[]"; } - if(b[b.length - 1] != bytes1("]")) { + if (b[b.length - 1] != bytes1("]")) { return "[]"; } return m; } - function toLowerCase(string memory str) public override pure returns(string memory) { + function toLowerCase(string memory str) + public + override + pure + returns (string memory) + { bytes memory bStr = bytes(str); - for (uint i = 0; i < bStr.length; i++) { - bStr[i] = bStr[i] >= 0x41 && bStr[i] <= 0x5A ? bytes1(uint8(bStr[i]) + 0x20) : bStr[i]; + for (uint256 i = 0; i < bStr.length; i++) { + bStr[i] = bStr[i] >= 0x41 && bStr[i] <= 0x5A + ? bytes1(uint8(bStr[i]) + 0x20) + : bStr[i]; } return string(bStr); } -} \ No newline at end of file +} diff --git a/contracts/DoubleProxy.sol b/contracts/DoubleProxy.sol index e791b39..e9fb192 100644 --- a/contracts/DoubleProxy.sol +++ b/contracts/DoubleProxy.sol @@ -1,9 +1,9 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; import "./IDoubleProxy.sol"; contract DoubleProxy is IDoubleProxy { - address private _proxy; mapping(address => bool) private _isProxy; @@ -14,57 +14,70 @@ contract DoubleProxy is IDoubleProxy { init(proxies, currentProxy); } - function init(address[] memory proxies, address currentProxy) public override { + function init(address[] memory proxies, address currentProxy) + public + override + { require(_proxies.length == 0, "Init already called!"); - for(uint256 i = 0; i < proxies.length; i++) { - if(proxies[i] != address(0)) { + for (uint256 i = 0; i < proxies.length; i++) { + if (proxies[i] != address(0)) { _proxies.push(proxies[i]); _isProxy[proxies[i]] = true; } } - if(currentProxy != address(0)) { + if (currentProxy != address(0)) { _proxy = currentProxy; - if(!_isProxy[currentProxy]) { + if (!_isProxy[currentProxy]) { _proxies.push(currentProxy); _isProxy[currentProxy] = true; } } } - function proxy() public override view returns(address) { + function proxy() public override view returns (address) { return _proxy; } function setProxy() public override { - require(_proxy == address(0) || _proxy == msg.sender, _proxy != address(0) ? "Proxy already set!" : "Only Proxy can toggle itself!"); - _proxy = _proxy == address(0) ? msg.sender : address(0); - if(_proxy != address(0) && !_isProxy[_proxy]) { + require( + _proxy == address(0) || _proxy == msg.sender, + _proxy != address(0) + ? "Proxy already set!" + : "Only Proxy can toggle itself!" + ); + _proxy = _proxy == address(0) ? msg.sender : address(0); + if (_proxy != address(0) && !_isProxy[_proxy]) { _proxies.push(_proxy); _isProxy[_proxy] = true; } } - function isProxy(address addr) public override view returns(bool) { + function isProxy(address addr) public override view returns (bool) { return _isProxy[addr]; } - function proxiesLength() public override view returns(uint256) { + function proxiesLength() public override view returns (uint256) { return _proxies.length; } - function proxies() public override view returns(address[] memory) { + function proxies() public override view returns (address[] memory) { return proxies(0, _proxies.length); } - function proxies(uint256 start, uint256 offset) public override view returns(address[] memory out) { + function proxies(uint256 start, uint256 offset) + public + override + view + returns (address[] memory out) + { require(start < _proxies.length, "Invalid start"); uint256 length = offset > _proxies.length ? _proxies.length : offset; out = new address[](length); length += start; length = length > _proxies.length ? _proxies.length : length; uint256 pos = 0; - for(uint256 i = start; i < length; i++) { + for (uint256 i = start; i < length; i++) { out[pos++] = _proxies[i]; } } -} \ No newline at end of file +} diff --git a/contracts/Functionality.sol b/contracts/Functionality.sol index 450e525..18add87 100644 --- a/contracts/Functionality.sol +++ b/contracts/Functionality.sol @@ -1,11 +1,13 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; +// DOCUMENT struct Functionality { string codeName; address sourceLocation; uint256 sourceLocationId; address location; - bool submitable; + bool submittable; string methodSignature; string returnAbiParametersArray; bool isInternal; @@ -13,4 +15,4 @@ struct Functionality { address proposalAddress; bool active; uint256 position; -} \ No newline at end of file +} diff --git a/contracts/IDoubleProxy.sol b/contracts/IDoubleProxy.sol index cad8e1b..b5e5fc4 100644 --- a/contracts/IDoubleProxy.sol +++ b/contracts/IDoubleProxy.sol @@ -42,5 +42,6 @@ interface IDoubleProxy { view returns (address[] memory); + // DOCUMENT function proxies() external view returns (address[] memory); } diff --git a/contracts/IMVDFunctionalitiesManager.sol b/contracts/IMVDFunctionalitiesManager.sol index eb32d8b..f613d1a 100644 --- a/contracts/IMVDFunctionalitiesManager.sol +++ b/contracts/IMVDFunctionalitiesManager.sol @@ -1,11 +1,37 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.6.0; +/** + * @title Interface for the Functionalities Manager + * @dev + */ interface IMVDFunctionalitiesManager { + /** + * @dev GET the proxy + */ function getProxy() external view returns (address); + /** + * @dev SET the proxy + */ function setProxy() external; + /** + * @dev Initializer logic used during the constructor call + * @param sourceLocation ROBE location of the source code + * @param getMinimumBlockNumberSourceLocationId ROBE id + * @param getMinimumBlockNumberFunctionalityAddress Address of the Functionality that controls + * the block duration of regular proposals + * @param getEmergencyMinimumBlockNumberSourceLocationId ROBE id + * @param getEmergencyMinimumBlockNumberFunctionalityAddress Address for the Functionality that controls + * the block duration of emergency proposals + * @param getEmergencySurveyStakingSourceLocationId ROBE id + * @param getEmergencySurveyStakingFunctionalityAddress Address for the Functionality that controls the + * minimum amount of vote to be staked in order to start an Emergency Proposal + * @param checkVoteResultSourceLocationId ROBE id + * @param checkVoteResultFunctionalityAddress Address for the Functionality that controls the + * check for determining if a Proposal was successful or it failed + */ function init( address sourceLocation, uint256 getMinimumBlockNumberSourceLocationId, @@ -18,24 +44,51 @@ interface IMVDFunctionalitiesManager { address checkVoteResultFunctionalityAddress ) external; + // DOCUMENT + /** + * @dev Add a functionality to the Functionalities Manager + * @param codeName + * @param sourceLocation + * @param sourceLocationId + * @param location + * @param submittable + * @param methodSignature + * @param returnAbiParametersArray + * @param isInternal + * @param needsSender + */ function addFunctionality( string calldata codeName, address sourceLocation, uint256 sourceLocationId, address location, - bool submitable, + bool submittable, string calldata methodSignature, string calldata returnAbiParametersArray, bool isInternal, bool needsSender ) external; + // DOCUMENT + /** + * @dev Replace a Functionality in the Functionalities Manager + * @param codeName + * @param sourceLocation + * @param sourceLocationId + * @param location + * @param submittable + * @param methodSignature + * @param returnAbiParametersArray + * @param isInternal + * @param needsSender + * @param position Position of the Functionality to replace + */ function addFunctionality( string calldata codeName, address sourceLocation, uint256 sourceLocationId, address location, - bool submitable, + bool submittable, string calldata methodSignature, string calldata returnAbiParametersArray, bool isInternal, @@ -43,24 +96,43 @@ interface IMVDFunctionalitiesManager { uint256 position ) external; + /** + * @dev Remove a Functionality from the Functionalities Manager + * @param codeName ID of the Functionality to remove + * @return removed Boolean flag representing the success status of the operation + * @return position Position of the removed functionality + */ function removeFunctionality(string calldata codeName) external returns (bool removed, uint256 position); + /** + * @dev Check that the Functionality is a valid one + * @param functionality Functionality to be checked + * @return valid Boolean flag indicating the validity of the Functionality + */ function isValidFunctionality(address functionality) external view - returns (bool); + returns (bool valid); + /** + * @dev Check that the Functionality is an authorized one + * @param functionality Functionality to be checked + * @return valid Boolean flag indicating the authorization status of the Functionality + */ function isAuthorizedFunctionality(address functionality) external view - returns (bool); + returns (bool success); + // DOCUMENT function setCallingContext(address location) external returns (bool); + // DOCUMENT function clearCallingContext() external; + // DOCUMENT function getFunctionalityData(string calldata codeName) external view @@ -72,40 +144,61 @@ interface IMVDFunctionalitiesManager { uint256 ); + /** + * @dev Check that the FunctionalitiesManager has a specific Functionality + * @param codeName ID of the Functionality to be checked + * @return output Boolean flag indicating wether the Functionalities Manager has the given Functionality. + */ function hasFunctionality(string calldata codeName) external view - returns (bool); + returns (bool output); + /** + * @dev GET the amount of functionalities present in the Functionalities Manager + */ function getFunctionalitiesAmount() external view returns (uint256); + // DOCUMENT function functionalitiesToJSON() external view returns (string memory); + // DOCUMENT function functionalitiesToJSON(uint256 start, uint256 l) external view returns (string memory functionsJSONArray); + /** + * @dev GET all Functionalities Names (IDs) + */ function functionalityNames() external view returns (string memory); + /** + * @dev GET all Functionalities Names (IDs) in a portion of the array + */ function functionalityNames(uint256 start, uint256 l) external view returns (string memory functionsJSONArray); + /** + * @dev Given a Functionality ID return its JSON encoded version + */ function functionalityToJSON(string calldata codeName) external view returns (string memory); + // DOCUMENT function preConditionCheck( string calldata codeName, bytes calldata data, - uint8 submitable, + uint8 submittable, address sender, uint256 value ) external view returns (address location, bytes memory payload); + // DOCUMENT function setupFunctionality(address proposalAddress) external returns (bool); diff --git a/contracts/IMVDFunctionalityModelsManager.sol b/contracts/IMVDFunctionalityModelsManager.sol index 4e0c27d..f03bd91 100644 --- a/contracts/IMVDFunctionalityModelsManager.sol +++ b/contracts/IMVDFunctionalityModelsManager.sol @@ -1,6 +1,25 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; +/** + * @title Functionalities Models Manager + * @dev Well Known Functionalities are "special" Fnctionalities must be implemented according to + * a specific pattern. Well Known Functionalities can be found in the implementation of this Interface. + */ interface IMVDFunctionalityModelsManager { function init() external; - function checkWellKnownFunctionalities(string calldata codeName, bool submitable, string calldata methodSignature, string calldata returnAbiParametersArray, bool isInternal, bool needsSender, string calldata replaces) external view; -} \ No newline at end of file + + /** + * @dev Check Well Known Functionalities. If the check fails it will raise its own errors. + * // DOCUMENT + */ + function checkWellKnownFunctionalities( + string calldata codeName, + bool submittable, + string calldata methodSignature, + string calldata returnAbiParametersArray, + bool isInternal, + bool needsSender, + string calldata replaces + ) external view; +} diff --git a/contracts/IMVDFunctionalityProposal.sol b/contracts/IMVDFunctionalityProposal.sol index 9040423..316d836 100644 --- a/contracts/IMVDFunctionalityProposal.sol +++ b/contracts/IMVDFunctionalityProposal.sol @@ -1,43 +1,175 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; +/** + * @title Interface for Proposal + * @dev Proposals are the defacto heart of the protocol since they allow voting token holders potentially + * alter all of the logic of a DFO and even extend it via custom logic. + */ interface IMVDFunctionalityProposal { + /** + * @dev Functionality Initializer + * @param codeName String ID of the Functionality + * @param location // DOCUMENTATION + * @param methodSignature + * @param returnAbiParameters + * @param replaces + * @param proxy + */ + function init( + string calldata codeName, + address location, + string calldata methodSignature, + string calldata returnAbiParametersArray, + string calldata replaces, + address proxy + ) external; + + /** + * @dev set the collateral attributes of the proposal + * @param emergency // DOCUMENTATION + * @param sourceLocation + * @param sourceLocationId + * @param submittable + * @param isInternal + * @param needsSender + * @param proposer + * @param votesHardCap + */ + function setCollateralData( + bool emergency, + address sourceLocation, + uint256 sourceLocationId, + bool submittable, + bool isInternal, + bool needsSender, + address proposer, + uint256 votesHardCap + ) external; + + /** + * @dev GET the Proxy address + */ + function getProxy() external view returns (address); + + /** + * @dev GET the Proposal Functionality string ID + */ + function getCodeName() external view returns (string memory); + + /** + * @dev GET the boolean flag indicating wether the Proposal is an Emergency Proposal + */ + function isEmergency() external view returns (bool); + + /** + * @dev GET the ROBE source location + */ + function getSourceLocation() external view returns (address); + + /** + * @dev // DOCUMENT + */ + function getSourceLocationId() external view returns (uint256); + + // DOCUMENTATION + function getLocation() external view returns (address); + + // DOCUMENTATION + function issubmittable() external view returns (bool); + + // DOCUMENTATION + function getMethodSignature() external view returns (string memory); + + // DOCUMENTATION + function getReturnAbiParametersArray() + external + view + returns (string memory); + + // DOCUMENTATION + function isInternal() external view returns (bool); + + // DOCUMENTATION + function needsSender() external view returns (bool); + + /** + * @dev GET the ROBE source location + */ + function getReplaces() external view returns (string memory); + + /** + * @dev GET the ROBE source location + */ + function getProposer() external view returns (address); + + /** + * @dev GET the ROBE source location + */ + function getSurveyEndBlock() external view returns (uint256); + + /** + * @dev GET the ROBE source location + */ + function getSurveyDuration() external view returns (uint256); + + /** + * @dev Check that the HardCap has been reached + */ + function isVotesHardCapReached() external view returns (bool); + + /** + * @dev GET the HardCap value + */ + function getVotesHardCapToReach() external view returns (uint256); + + /** + * @dev GET the json representation of the Functionality + */ + function toJSON() external view returns (string memory); + + /** + * @dev GET the current status of the voting + * @param addr // DOCUMENT + * @return accept Amount of YES votes + * @return refuse Amount of NO votes + */ + function getVote(address addr) + external + view + returns (uint256 accept, uint256 refuse); + + /** + * @dev // DOCUMENT + */ + function getVotes() external view returns (uint256, uint256); - function init(string calldata codeName, address location, string calldata methodSignature, string calldata returnAbiParametersArray, string calldata replaces, address proxy) external; - function setCollateralData(bool emergency, address sourceLocation, uint256 sourceLocationId, bool submitable, bool isInternal, bool needsSender, address proposer, uint256 votesHardCap) external; - - function getProxy() external view returns(address); - function getCodeName() external view returns(string memory); - function isEmergency() external view returns(bool); - function getSourceLocation() external view returns(address); - function getSourceLocationId() external view returns(uint256); - function getLocation() external view returns(address); - function isSubmitable() external view returns(bool); - function getMethodSignature() external view returns(string memory); - function getReturnAbiParametersArray() external view returns(string memory); - function isInternal() external view returns(bool); - function needsSender() external view returns(bool); - function getReplaces() external view returns(string memory); - function getProposer() external view returns(address); - function getSurveyEndBlock() external view returns(uint256); - function getSurveyDuration() external view returns(uint256); - function isVotesHardCapReached() external view returns(bool); - function getVotesHardCapToReach() external view returns(uint256); - function toJSON() external view returns(string memory); - function getVote(address addr) external view returns(uint256 accept, uint256 refuse); - function getVotes() external view returns(uint256, uint256); function start() external; + function disable() external; - function isDisabled() external view returns(bool); - function isTerminated() external view returns(bool); + + function isDisabled() external view returns (bool); + + function isTerminated() external view returns (bool); + function accept(uint256 amount) external; + function retireAccept(uint256 amount) external; + function moveToAccept(uint256 amount) external; + function refuse(uint256 amount) external; + function retireRefuse(uint256 amount) external; + function moveToRefuse(uint256 amount) external; + function retireAll() external; + function withdraw() external; + function terminate() external; + function set() external; event Accept(address indexed voter, uint256 amount); @@ -47,4 +179,4 @@ interface IMVDFunctionalityProposal { event RetireRefuse(address indexed voter, uint256 amount); event MoveToRefuse(address indexed voter, uint256 amount); event RetireAll(address indexed voter, uint256 amount); -} \ No newline at end of file +} diff --git a/contracts/IMVDFunctionalityProposalManager.sol b/contracts/IMVDFunctionalityProposalManager.sol index d38bd5b..1645b73 100644 --- a/contracts/IMVDFunctionalityProposalManager.sol +++ b/contracts/IMVDFunctionalityProposalManager.sol @@ -1,9 +1,20 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; interface IMVDFunctionalityProposalManager { - function newProposal(string calldata codeName, address location, string calldata methodSignature, string calldata returnAbiParametersArray, string calldata replaces) external returns(address); + function newProposal( + string calldata codeName, + address location, + string calldata methodSignature, + string calldata returnAbiParametersArray, + string calldata replaces + ) external returns (address); + function checkProposal(address proposalAddress) external; + function getProxy() external view returns (address); + function setProxy() external; + function isValidProposal(address proposal) external view returns (bool); -} \ No newline at end of file +} diff --git a/contracts/IMVDProxy.sol b/contracts/IMVDProxy.sol index bf84ff0..46f6bc0 100644 --- a/contracts/IMVDProxy.sol +++ b/contracts/IMVDProxy.sol @@ -1,42 +1,159 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; interface IMVDProxy { + function init( + address votingTokenAddress, + address functionalityProposalManagerAddress, + address stateHolderAddress, + address functionalityModelsManagerAddress, + address functionalitiesManagerAddress, + address walletAddress, + address doubleProxyAddress + ) external; + + function getDelegates() external view returns (address[] memory); + + function getToken() external view returns (address); + + function getMVDFunctionalityProposalManagerAddress() + external + view + returns (address); + + function getStateHolderAddress() external view returns (address); + + function getMVDFunctionalityModelsManagerAddress() + external + view + returns (address); + + function getMVDFunctionalitiesManagerAddress() + external + view + returns (address); + + function getMVDWalletAddress() external view returns (address); + + function getDoubleProxyAddress() external view returns (address); + + function setDelegate(uint256 position, address newAddress) + external + returns (address oldAddress); + + function changeProxy(address newAddress, bytes calldata initPayload) + external; - function init(address votingTokenAddress, address functionalityProposalManagerAddress, address stateHolderAddress, address functionalityModelsManagerAddress, address functionalitiesManagerAddress, address walletAddress, address doubleProxyAddress) external; - - function getDelegates() external view returns(address[] memory); - function getToken() external view returns(address); - function getMVDFunctionalityProposalManagerAddress() external view returns(address); - function getStateHolderAddress() external view returns(address); - function getMVDFunctionalityModelsManagerAddress() external view returns(address); - function getMVDFunctionalitiesManagerAddress() external view returns(address); - function getMVDWalletAddress() external view returns(address); - function getDoubleProxyAddress() external view returns(address); - function setDelegate(uint256 position, address newAddress) external returns(address oldAddress); - function changeProxy(address newAddress, bytes calldata initPayload) external; function isValidProposal(address proposal) external view returns (bool); - function isAuthorizedFunctionality(address functionality) external view returns(bool); - function newProposal(string calldata codeName, bool emergency, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string calldata methodSignature, string calldata returnParametersJSONArray, bool isInternal, bool needsSender, string calldata replaces) external returns(address proposalAddress); + + function isAuthorizedFunctionality(address functionality) + external + view + returns (bool); + + function newProposal( + string calldata codeName, + bool emergency, + address sourceLocation, + uint256 sourceLocationId, + address location, + bool submittable, + string calldata methodSignature, + string calldata returnParametersJSONArray, + bool isInternal, + bool needsSender, + string calldata replaces + ) external returns (address proposalAddress); + function startProposal(address proposalAddress) external; + function disableProposal(address proposalAddress) external; - function transfer(address receiver, uint256 value, address token) external; - function transfer721(address receiver, uint256 tokenId, bytes calldata data, bool safe, address token) external; - function flushToWallet(address tokenAddress, bool is721, uint256 tokenId) external; + + function transfer( + address receiver, + uint256 value, + address token + ) external; + + function transfer721( + address receiver, + uint256 tokenId, + bytes calldata data, + bool safe, + address token + ) external; + + function flushToWallet( + address tokenAddress, + bool is721, + uint256 tokenId + ) external; + function setProposal() external; - function read(string calldata codeName, bytes calldata data) external view returns(bytes memory returnData); - function submit(string calldata codeName, bytes calldata data) external payable returns(bytes memory returnData); - function callFromManager(address location, bytes calldata payload) external returns(bool, bytes memory); - function emitFromManager(string calldata codeName, address proposal, string calldata replaced, address replacedSourceLocation, uint256 replacedSourceLocationId, address location, bool submitable, string calldata methodSignature, bool isInternal, bool needsSender, address proposalAddress) external; - function emitEvent(string calldata eventSignature, bytes calldata firstIndex, bytes calldata secondIndex, bytes calldata data) external; + function read(string calldata codeName, bytes calldata data) + external + view + returns (bytes memory returnData); + + function submit(string calldata codeName, bytes calldata data) + external + payable + returns (bytes memory returnData); + + function callFromManager(address location, bytes calldata payload) + external + returns (bool, bytes memory); + + function emitFromManager( + string calldata codeName, + address proposal, + string calldata replaced, + address replacedSourceLocation, + uint256 replacedSourceLocationId, + address location, + bool submittable, + string calldata methodSignature, + bool isInternal, + bool needsSender, + address proposalAddress + ) external; + + function emitEvent( + string calldata eventSignature, + bytes calldata firstIndex, + bytes calldata secondIndex, + bytes calldata data + ) external; event ProxyChanged(address indexed newAddress); - event DelegateChanged(uint256 position, address indexed oldAddress, address indexed newAddress); + event DelegateChanged( + uint256 position, + address indexed oldAddress, + address indexed newAddress + ); event Proposal(address proposal); event ProposalCheck(address indexed proposal); event ProposalSet(address indexed proposal, bool success); - event FunctionalitySet(string codeName, address indexed proposal, string replaced, address replacedSourceLocation, uint256 replacedSourceLocationId, address indexed replacedLocation, bool replacedWasSubmitable, string replacedMethodSignature, bool replacedWasInternal, bool replacedNeededSender, address indexed replacedProposal); + event FunctionalitySet( + string codeName, + address indexed proposal, + string replaced, + address replacedSourceLocation, + uint256 replacedSourceLocationId, + address indexed replacedLocation, + bool replacedWassubmittable, + string replacedMethodSignature, + bool replacedWasInternal, + bool replacedNeededSender, + address indexed replacedProposal + ); - event Event(string indexed key, bytes32 indexed firstIndex, bytes32 indexed secondIndex, bytes data); -} \ No newline at end of file + event Event( + string indexed key, + bytes32 indexed firstIndex, + bytes32 indexed secondIndex, + bytes data + ); +} diff --git a/contracts/MVDFunctionalitiesManager.sol b/contracts/MVDFunctionalitiesManager.sol index a86f0de..fa4af7a 100644 --- a/contracts/MVDFunctionalitiesManager.sol +++ b/contracts/MVDFunctionalitiesManager.sol @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; import "./IMVDFunctionalitiesManager.sol"; @@ -6,8 +7,10 @@ import "./IMVDProxy.sol"; import "./IMVDFunctionalityProposal.sol"; import "./Functionality.sol"; -contract MVDFunctionalitiesManager is IMVDFunctionalitiesManager, CommonUtilities { - +contract MVDFunctionalitiesManager is + IMVDFunctionalitiesManager, + CommonUtilities +{ address private _proxy; Functionality[] private _functionalities; @@ -20,27 +23,44 @@ contract MVDFunctionalitiesManager is IMVDFunctionalitiesManager, CommonUtilitie address private _callingContext; - constructor(address sourceLocation, - uint256 getMinimumBlockNumberSourceLocationId, address getMinimumBlockNumberFunctionalityAddress, - uint256 getEmergencyMinimumBlockNumberSourceLocationId, address getEmergencyMinimumBlockNumberFunctionalityAddress, - uint256 getEmergencySurveyStakingSourceLocationId, address getEmergencySurveyStakingFunctionalityAddress, - uint256 checkVoteResultSourceLocationId, address checkVoteResultFunctionalityAddress) public { - if(getMinimumBlockNumberFunctionalityAddress == address(0)) { + constructor( + address sourceLocation, + uint256 getMinimumBlockNumberSourceLocationId, + address getMinimumBlockNumberFunctionalityAddress, + uint256 getEmergencyMinimumBlockNumberSourceLocationId, + address getEmergencyMinimumBlockNumberFunctionalityAddress, + uint256 getEmergencySurveyStakingSourceLocationId, + address getEmergencySurveyStakingFunctionalityAddress, + uint256 checkVoteResultSourceLocationId, + address checkVoteResultFunctionalityAddress + ) public { + if (getMinimumBlockNumberFunctionalityAddress == address(0)) { return; } - init(sourceLocation, - getMinimumBlockNumberSourceLocationId, getMinimumBlockNumberFunctionalityAddress, - getEmergencyMinimumBlockNumberSourceLocationId, getEmergencyMinimumBlockNumberFunctionalityAddress, - getEmergencySurveyStakingSourceLocationId, getEmergencySurveyStakingFunctionalityAddress, - checkVoteResultSourceLocationId, checkVoteResultFunctionalityAddress); + init( + sourceLocation, + getMinimumBlockNumberSourceLocationId, + getMinimumBlockNumberFunctionalityAddress, + getEmergencyMinimumBlockNumberSourceLocationId, + getEmergencyMinimumBlockNumberFunctionalityAddress, + getEmergencySurveyStakingSourceLocationId, + getEmergencySurveyStakingFunctionalityAddress, + checkVoteResultSourceLocationId, + checkVoteResultFunctionalityAddress + ); } - function init(address sourceLocation, - uint256 getMinimumBlockNumberSourceLocationId, address getMinimumBlockNumberFunctionalityAddress, - uint256 getEmergencyMinimumBlockNumberSourceLocationId, address getEmergencyMinimumBlockNumberFunctionalityAddress, - uint256 getEmergencySurveyStakingSourceLocationId, address getEmergencySurveyStakingFunctionalityAddress, - uint256 checkVoteResultSourceLocationId, address checkVoteResultFunctionalityAddress) public override { - + function init( + address sourceLocation, + uint256 getMinimumBlockNumberSourceLocationId, + address getMinimumBlockNumberFunctionalityAddress, + uint256 getEmergencyMinimumBlockNumberSourceLocationId, + address getEmergencyMinimumBlockNumberFunctionalityAddress, + uint256 getEmergencySurveyStakingSourceLocationId, + address getEmergencySurveyStakingFunctionalityAddress, + uint256 checkVoteResultSourceLocationId, + address checkVoteResultFunctionalityAddress + ) public override { require(_functionalitiesAmount == 0, "Init already called!"); addFunctionality( @@ -92,18 +112,53 @@ contract MVDFunctionalitiesManager is IMVDFunctionalitiesManager, CommonUtilitie ); } - function addFunctionality(string memory codeName, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string memory methodSignature, string memory returnAbiParametersArray, bool isInternal, bool needsSender) public override { - addFunctionality(codeName, sourceLocation, sourceLocationId, location, submitable, methodSignature, returnAbiParametersArray, isInternal, needsSender, _functionalities.length); + function addFunctionality( + string memory codeName, + address sourceLocation, + uint256 sourceLocationId, + address location, + bool submittable, + string memory methodSignature, + string memory returnAbiParametersArray, + bool isInternal, + bool needsSender + ) public override { + addFunctionality( + codeName, + sourceLocation, + sourceLocationId, + location, + submittable, + methodSignature, + returnAbiParametersArray, + isInternal, + needsSender, + _functionalities.length + ); } - function addFunctionality(string memory codeName, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string memory methodSignature, string memory returnAbiParametersArray, bool isInternal, bool needsSender, uint256 position) public override { - require(_proxy == address(0) || _callingContext == msg.sender, "Unauthorized call!"); + function addFunctionality( + string memory codeName, + address sourceLocation, + uint256 sourceLocationId, + address location, + bool submittable, + string memory methodSignature, + string memory returnAbiParametersArray, + bool isInternal, + bool needsSender, + uint256 position + ) public override { + require( + _proxy == address(0) || _callingContext == msg.sender, + "Unauthorized call!" + ); Functionality memory functionality = Functionality( codeName, sourceLocation, sourceLocationId, location, - submitable, + submittable, methodSignature, returnAbiParametersArray, isInternal, @@ -112,7 +167,7 @@ contract MVDFunctionalitiesManager is IMVDFunctionalitiesManager, CommonUtilitie true, position ); - if(position >= _functionalities.length) { + if (position >= _functionalities.length) { _functionalities.push(functionality); } else { removeFunctionality(_functionalities[position].codeName); @@ -123,167 +178,332 @@ contract MVDFunctionalitiesManager is IMVDFunctionalitiesManager, CommonUtilitie _indexes[codeName] = position; } - function removeFunctionality(string memory codeName) public override returns(bool removed, uint256 position) { - require(_proxy == address(0) || _callingContext == msg.sender, "Unauthorized call!"); - Functionality storage functionality = _functionalities[_indexes[codeName]]; + function removeFunctionality(string memory codeName) + public + override + returns (bool removed, uint256 position) + { + require( + _proxy == address(0) || _callingContext == msg.sender, + "Unauthorized call!" + ); + + + Functionality storage functionality + = _functionalities[_indexes[codeName]]; position = functionality.position; - if(compareStrings(codeName, functionality.codeName) && functionality.active) { + if ( + compareStrings(codeName, functionality.codeName) && + functionality.active + ) { functionality.active = false; - _functionalityCount[functionality.location] = _functionalityCount[functionality.location] - 1; + _functionalityCount[functionality.location] = + _functionalityCount[functionality.location] - + 1; _functionalitiesAmount--; removed = true; } } - function preConditionCheck(string memory codeName, bytes memory data, uint8 submitable, address sender, uint256 value) public override view returns(address location, bytes memory payload) { - Functionality memory functionality = _functionalities[_indexes[codeName]]; - - require(compareStrings(codeName, functionality.codeName) && functionality.active, "Unauthorized functionality"); + function preConditionCheck( + string memory codeName, + bytes memory data, + uint8 submittable, + address sender, + uint256 value + ) public override view returns (address location, bytes memory payload) { + + Functionality memory functionality + = _functionalities[_indexes[codeName]]; + + require( + compareStrings(codeName, functionality.codeName) && + functionality.active, + "Unauthorized functionality" + ); - require(submitable == (functionality.submitable ? 1 : 0), "Functionality called in the wrong context!"); + require( + submittable == (functionality.submittable ? 1 : 0), + "Functionality called in the wrong context!" + ); - require(functionality.isInternal ? _functionalityCount[sender] > 0 || _callingContext == sender : true, "Internal functionalities can be called from other functionalities only!"); + require( + functionality.isInternal + ? _functionalityCount[sender] > 0 || _callingContext == sender + : true, + "Internal functionalities can be called from other functionalities only!" + ); location = functionality.location; - if(functionality.needsSender) { - require(data.length >= (submitable == 1 ? 64 : 32), "Insufficient space in data payload"); + if (functionality.needsSender) { + require( + data.length >= (submittable == 1 ? 64 : 32), + "Insufficient space in data payload" + ); assembly { mstore(add(data, 0x20), sender) - switch iszero(submitable) case 0 { - mstore(add(data, 0x40), value) - } + switch iszero(submittable) + case 0 { + mstore(add(data, 0x40), value) + } } } - payload = abi.encodePacked(bytes4(keccak256(bytes(functionality.methodSignature))), data); + payload = abi.encodePacked( + bytes4(keccak256(bytes(functionality.methodSignature))), + data + ); } - function getFunctionalitiesAmount() public override view returns(uint256) { + function getFunctionalitiesAmount() public override view returns (uint256) { return _functionalitiesAmount; } - function isValidFunctionality(address functionality) public override view returns(bool) { + function isValidFunctionality(address functionality) + public + override + view + returns (bool) + { return _functionalityCount[functionality] > 0; } - function isAuthorizedFunctionality(address functionality) public override view returns(bool) { - return _callingContext != address(0) && (_functionalityCount[functionality] > 0 || _callingContext == functionality); + function isAuthorizedFunctionality(address functionality) + public + override + view + returns (bool) + { + return + _callingContext != address(0) && + (_functionalityCount[functionality] > 0 || + _callingContext == functionality); } - function getFunctionalityData(string memory codeName) public override view returns(address, uint256, string memory, address, uint256) { - Functionality memory functionality = _functionalities[_indexes[codeName]]; - return (compareStrings(codeName, functionality.codeName) && functionality.active ? functionality.location : address(0), functionality.position, functionality.methodSignature, functionality.sourceLocation, functionality.sourceLocationId); + function getFunctionalityData(string memory codeName) + public + override + view + returns ( + address, + uint256, + string memory, + address, + uint256 + ) + { + + Functionality memory functionality + = _functionalities[_indexes[codeName]]; + return ( + compareStrings(codeName, functionality.codeName) && + functionality.active + ? functionality.location + : address(0), + functionality.position, + functionality.methodSignature, + functionality.sourceLocation, + functionality.sourceLocationId + ); } - function hasFunctionality(string memory codeName) public override view returns(bool) { - Functionality memory functionality = _functionalities[_indexes[codeName]]; - return compareStrings(codeName, functionality.codeName) && functionality.active; + function hasFunctionality(string memory codeName) + public + override + view + returns (bool) + { + + Functionality memory functionality + = _functionalities[_indexes[codeName]]; + return + compareStrings(codeName, functionality.codeName) && + functionality.active; } - function functionalitiesToJSON() public override view returns(string memory) { + function functionalitiesToJSON() + public + override + view + returns (string memory) + { return functionalitiesToJSON(0, _functionalities.length); } - function functionalitiesToJSON(uint256 start, uint256 l) public override view returns(string memory functionsJSONArray) { + function functionalitiesToJSON(uint256 start, uint256 l) + public + override + view + returns (string memory functionsJSONArray) + { uint256 length = start + l; functionsJSONArray = "["; - for(uint256 i = start; i < length; i++) { - functionsJSONArray = !_functionalities[i].active ? functionsJSONArray : string(abi.encodePacked(functionsJSONArray, toJSON(_functionalities[i]), i == length - (_functionalities[i].active ? 1 : 0) ? "" : ",")); + for (uint256 i = start; i < length; i++) { + functionsJSONArray = !_functionalities[i].active + ? functionsJSONArray + : string( + abi.encodePacked( + functionsJSONArray, + toJSON(_functionalities[i]), + i == length - (_functionalities[i].active ? 1 : 0) + ? "" + : "," + ) + ); length += _functionalities[i].active ? 0 : 1; - length = length > _functionalities.length ? _functionalities.length : length; + length = length > _functionalities.length + ? _functionalities.length + : length; } functionsJSONArray = string(abi.encodePacked(functionsJSONArray, "]")); } - function functionalityNames() public override view returns(string memory) { + function functionalityNames() public override view returns (string memory) { return functionalityNames(0, _functionalities.length); } - function functionalityNames(uint256 start, uint256 l) public override view returns(string memory functionsJSONArray) { + function functionalityNames(uint256 start, uint256 l) + public + override + view + returns (string memory functionsJSONArray) + { uint256 length = start + l; functionsJSONArray = "["; - for(uint256 i = start; i < length; i++) { - functionsJSONArray = !_functionalities[i].active ? functionsJSONArray : string(abi.encodePacked(functionsJSONArray, '"', _functionalities[i].codeName, '"', i == length - (_functionalities[i].active ? 1 : 0) ? "" : ",")); + for (uint256 i = start; i < length; i++) { + functionsJSONArray = !_functionalities[i].active + ? functionsJSONArray + : string( + abi.encodePacked( + functionsJSONArray, + '"', + _functionalities[i].codeName, + '"', + i == length - (_functionalities[i].active ? 1 : 0) + ? "" + : "," + ) + ); length += _functionalities[i].active ? 0 : 1; - length = length > _functionalities.length ? _functionalities.length : length; + length = length > _functionalities.length + ? _functionalities.length + : length; } functionsJSONArray = string(abi.encodePacked(functionsJSONArray, "]")); } - function functionalityToJSON(string memory codeName) public override view returns(string memory) { + function functionalityToJSON(string memory codeName) + public + override + view + returns (string memory) + { return string(toJSON(_functionalities[_indexes[codeName]])); } - function toJSON(Functionality memory func) private pure returns(bytes memory) { - return abi.encodePacked( - '{', - getFirstJSONPart(func.sourceLocation, func.sourceLocationId, func.location), - '","submitable":', - func.submitable ? "true" : "false", - ',"isInternal":', - func.isInternal ? "true" : "false", - ',"needsSender":', - func.needsSender ? "true" : "false", - ',"proposalAddress":"', - toString(func.proposalAddress), - '","codeName":"', - func.codeName, - '","methodSignature":"', - func.methodSignature, - '","returnAbiParametersArray":', - formatReturnAbiParametersArray(func.returnAbiParametersArray), - ',"position":', - toString(func.position), - '}' - ); + function toJSON(Functionality memory func) + private + pure + returns (bytes memory) + { + return + abi.encodePacked( + "{", + getFirstJSONPart( + func.sourceLocation, + func.sourceLocationId, + func.location + ), + '","submittable":', + func.submittable ? "true" : "false", + ',"isInternal":', + func.isInternal ? "true" : "false", + ',"needsSender":', + func.needsSender ? "true" : "false", + ',"proposalAddress":"', + toString(func.proposalAddress), + '","codeName":"', + func.codeName, + '","methodSignature":"', + func.methodSignature, + '","returnAbiParametersArray":', + formatReturnAbiParametersArray(func.returnAbiParametersArray), + ',"position":', + toString(func.position), + "}" + ); } - function getProxy() public override view returns(address) { + function getProxy() public override view returns (address) { return _proxy; } function setProxy() public override { require(_functionalitiesAmount != 0, "Init not called!"); - require(_proxy == address(0) || _proxy == msg.sender, _proxy != address(0) ? "Proxy already set!" : "Only Proxy can toggle itself!"); - _proxy = _proxy == address(0) ? msg.sender : address(0); + require( + _proxy == address(0) || _proxy == msg.sender, + _proxy != address(0) + ? "Proxy already set!" + : "Only Proxy can toggle itself!" + ); + _proxy = _proxy == address(0) ? msg.sender : address(0); } - function setupFunctionality(address proposalAddress) public override returns(bool result) { - + function setupFunctionality(address proposalAddress) + public + override + returns (bool result) + { require(_proxy == msg.sender, "Only Proxy can call This!"); - IMVDFunctionalityProposal proposal = IMVDFunctionalityProposal(proposalAddress); + IMVDFunctionalityProposal proposal = IMVDFunctionalityProposal( + proposalAddress + ); string memory codeName = proposal.getCodeName(); bool hasCodeName = !compareStrings(codeName, ""); string memory replaces = proposal.getReplaces(); bool hasReplaces = !compareStrings(replaces, ""); - if(!hasCodeName && !hasReplaces) { - (result,) = IMVDProxy(_proxy).callFromManager(_callingContext = proposal.getLocation(), abi.encodeWithSignature("callOneTime(address)", proposalAddress)); + if (!hasCodeName && !hasReplaces) { + (result, ) = IMVDProxy(_proxy).callFromManager( + _callingContext = proposal.getLocation(), + abi.encodeWithSignature("callOneTime(address)", proposalAddress) + ); _callingContext = address(0); return result; } - Functionality memory replacedFunctionality = _functionalities[_indexes[replaces]]; - uint256 position = hasReplaces ? replacedFunctionality.position : _functionalities.length; - if(hasReplaces) { - (result,) = IMVDProxy(_proxy).callFromManager(_callingContext = replacedFunctionality.location, abi.encodeWithSignature("onStop(address)", proposalAddress)); + Functionality memory replacedFunctionality + = _functionalities[_indexes[replaces]]; + uint256 position = hasReplaces + ? replacedFunctionality.position + : _functionalities.length; + + if (hasReplaces) { + (result, ) = IMVDProxy(_proxy).callFromManager( + _callingContext = replacedFunctionality.location, + abi.encodeWithSignature("onStop(address)", proposalAddress) + ); _callingContext = address(0); - if(!result) { + if (!result) { revert("onStop failed!"); } } - replacedFunctionality.active = hasReplaces ? false : replacedFunctionality.active; + replacedFunctionality.active = hasReplaces + ? false + : replacedFunctionality.active; _functionalitiesAmount -= hasReplaces ? 1 : 0; - _functionalityCount[replacedFunctionality.location] = _functionalityCount[replacedFunctionality.location] - (hasReplaces ? 1 : 0); + _functionalityCount[replacedFunctionality.location] = + _functionalityCount[replacedFunctionality.location] - + (hasReplaces ? 1 : 0); - if(hasReplaces) { + if (hasReplaces) { _functionalities[position] = replacedFunctionality; } @@ -292,7 +512,7 @@ contract MVDFunctionalitiesManager is IMVDFunctionalitiesManager, CommonUtilitie proposal.getSourceLocation(), proposal.getSourceLocationId(), proposal.getLocation(), - proposal.isSubmitable(), + proposal.issubmittable(), proposal.getMethodSignature(), proposal.getReturnAbiParametersArray(), proposal.isInternal(), @@ -304,37 +524,64 @@ contract MVDFunctionalitiesManager is IMVDFunctionalitiesManager, CommonUtilitie _functionalitiesAmount += hasCodeName ? 1 : 0; - if(hasCodeName && position == _functionalities.length) { + if (hasCodeName && position == _functionalities.length) { _functionalities.push(newFunctionality); - } else if(hasCodeName) { + } else if (hasCodeName) { _functionalities[position] = newFunctionality; } _indexes[codeName] = hasCodeName ? position : 0; - _functionalityCount[newFunctionality.location] = _functionalityCount[newFunctionality.location] + (hasCodeName ? 1 : 0); - - if(hasCodeName) { - (result,) = IMVDProxy(_proxy).callFromManager(_callingContext = newFunctionality.location, abi.encodeWithSignature("onStart(address,address)", proposalAddress, hasReplaces ? replacedFunctionality.location : address(0))); + _functionalityCount[newFunctionality.location] = + _functionalityCount[newFunctionality.location] + + (hasCodeName ? 1 : 0); + + if (hasCodeName) { + (result, ) = IMVDProxy(_proxy).callFromManager( + _callingContext = newFunctionality.location, + abi.encodeWithSignature( + "onStart(address,address)", + proposalAddress, + hasReplaces ? replacedFunctionality.location : address(0) + ) + ); _callingContext = address(0); - if(!result) { + if (!result) { revert("onStart failed!"); } } - if(hasCodeName || hasReplaces) { - IMVDProxy(_proxy).emitFromManager(hasCodeName ? codeName : "", proposalAddress, hasReplaces ? replacedFunctionality.codeName : "", hasReplaces ? replacedFunctionality.sourceLocation : address(0), hasReplaces ? replacedFunctionality.sourceLocationId : 0, hasReplaces ? replacedFunctionality.location : address(0), hasReplaces ? replacedFunctionality.submitable : false, hasReplaces ? replacedFunctionality.methodSignature : "", hasReplaces ? replacedFunctionality.isInternal : false, hasReplaces ? replacedFunctionality.needsSender : false, hasReplaces ? replacedFunctionality.proposalAddress : address(0)); + if (hasCodeName || hasReplaces) { + IMVDProxy(_proxy).emitFromManager( + hasCodeName ? codeName : "", + proposalAddress, + hasReplaces ? replacedFunctionality.codeName : "", + hasReplaces ? replacedFunctionality.sourceLocation : address(0), + hasReplaces ? replacedFunctionality.sourceLocationId : 0, + hasReplaces ? replacedFunctionality.location : address(0), + hasReplaces ? replacedFunctionality.submittable : false, + hasReplaces ? replacedFunctionality.methodSignature : "", + hasReplaces ? replacedFunctionality.isInternal : false, + hasReplaces ? replacedFunctionality.needsSender : false, + hasReplaces ? replacedFunctionality.proposalAddress : address(0) + ); } _callingContext = address(0); return true; } - function setCallingContext(address location) public override returns(bool changed) { + function setCallingContext(address location) + public + override + returns (bool changed) + { require(msg.sender == _proxy, "Unauthorized Access"); - _callingContext = (changed = _callingContext == address(0)) ? location : _callingContext; + _callingContext = (changed = _callingContext == address(0)) + ? location + : _callingContext; } function clearCallingContext() public override { require(msg.sender == _proxy, "Unauthorized Access"); _callingContext = address(0); } -} \ No newline at end of file +} diff --git a/contracts/MVDFunctionalityModelsManager.sol b/contracts/MVDFunctionalityModelsManager.sol index 4e24ce6..2659a44 100644 --- a/contracts/MVDFunctionalityModelsManager.sol +++ b/contracts/MVDFunctionalityModelsManager.sol @@ -4,7 +4,6 @@ import "./IMVDFunctionalityModelsManager.sol"; import "./Functionality.sol"; contract MVDFunctionalityModelsManager is IMVDFunctionalityModelsManager { - mapping(string => Functionality) private _wellKnownFunctionalityModels; constructor() public { @@ -12,50 +11,236 @@ contract MVDFunctionalityModelsManager is IMVDFunctionalityModelsManager { } function init() public override { - - require(compareStrings("", _wellKnownFunctionalityModels["getMinimumBlockNumberForSurvey"].codeName), "Init already called!"); - - _wellKnownFunctionalityModels["getMinimumBlockNumberForSurvey"] = Functionality("getMinimumBlockNumberForSurvey", address(0), 0, address(0), false, "getMinimumBlockNumberForSurvey()", '["uint256"]', false, false, address(0), true, 0); - - _wellKnownFunctionalityModels["getMinimumBlockNumberForEmergencySurvey"] = Functionality("getMinimumBlockNumberForEmergencySurvey", address(0), 0, address(0), false, "getMinimumBlockNumberForEmergencySurvey()", '["uint256"]', false, false, address(0), true, 0); - - _wellKnownFunctionalityModels["getEmergencySurveyStaking"] = Functionality("getEmergencySurveyStaking", address(0), 0, address(0), false, "getEmergencySurveyStaking()", '["uint256"]', false, false, address(0), true, 0); - - _wellKnownFunctionalityModels["checkSurveyResult"] = Functionality("checkSurveyResult", address(0), 0, address(0), false, "checkSurveyResult(address)", '["bool"]', false, false, address(0), true, 0); - - _wellKnownFunctionalityModels["getVotesHardCap"] = Functionality("getVotesHardCap", address(0), 0, address(0), false, "getVotesHardCap()", '["uint256"]', false, false, address(0), false, 0); - - _wellKnownFunctionalityModels["onNewProposal"] = Functionality("onNewProposal", address(0), 0, address(0), true, "onNewProposal(address)", '[]', false, false, address(0), false, 0); - - _wellKnownFunctionalityModels["startProposal"] = Functionality("startProposal", address(0), 0, address(0), true, "startProposal(address,uint256,address)", '[]', false, true, address(0), false, 0); - - _wellKnownFunctionalityModels["disableProposal"] = Functionality("disableProposal", address(0), 0, address(0), true, "disableProposal(address,uint256,address)", '[]', false, true, address(0), false, 0); - - _wellKnownFunctionalityModels["proposalEnd"] = Functionality("proposalEnd", address(0), 0, address(0), true, "proposalEnd(address,bool)", "[]", false, false, address(0), false, 0); + require( + compareStrings( + "", + _wellKnownFunctionalityModels["getMinimumBlockNumberForSurvey"] + .codeName + ), + "Init already called!" + ); + + _wellKnownFunctionalityModels["getMinimumBlockNumberForSurvey"] = Functionality( + "getMinimumBlockNumberForSurvey", + address(0), + 0, + address(0), + false, + "getMinimumBlockNumberForSurvey()", + '["uint256"]', + false, + false, + address(0), + true, + 0 + ); + + _wellKnownFunctionalityModels["getMinimumBlockNumberForEmergencySurvey"] = Functionality( + "getMinimumBlockNumberForEmergencySurvey", + address(0), + 0, + address(0), + false, + "getMinimumBlockNumberForEmergencySurvey()", + '["uint256"]', + false, + false, + address(0), + true, + 0 + ); + + _wellKnownFunctionalityModels["getEmergencySurveyStaking"] = Functionality( + "getEmergencySurveyStaking", + address(0), + 0, + address(0), + false, + "getEmergencySurveyStaking()", + '["uint256"]', + false, + false, + address(0), + true, + 0 + ); + + _wellKnownFunctionalityModels["checkSurveyResult"] = Functionality( + "checkSurveyResult", + address(0), + 0, + address(0), + false, + "checkSurveyResult(address)", + '["bool"]', + false, + false, + address(0), + true, + 0 + ); + + _wellKnownFunctionalityModels["getVotesHardCap"] = Functionality( + "getVotesHardCap", + address(0), + 0, + address(0), + false, + "getVotesHardCap()", + '["uint256"]', + false, + false, + address(0), + false, + 0 + ); + + _wellKnownFunctionalityModels["onNewProposal"] = Functionality( + "onNewProposal", + address(0), + 0, + address(0), + true, + "onNewProposal(address)", + "[]", + false, + false, + address(0), + false, + 0 + ); + + _wellKnownFunctionalityModels["startProposal"] = Functionality( + "startProposal", + address(0), + 0, + address(0), + true, + "startProposal(address,uint256,address)", + "[]", + false, + true, + address(0), + false, + 0 + ); + + _wellKnownFunctionalityModels["disableProposal"] = Functionality( + "disableProposal", + address(0), + 0, + address(0), + true, + "disableProposal(address,uint256,address)", + "[]", + false, + true, + address(0), + false, + 0 + ); + + _wellKnownFunctionalityModels["proposalEnd"] = Functionality( + "proposalEnd", + address(0), + 0, + address(0), + true, + "proposalEnd(address,bool)", + "[]", + false, + false, + address(0), + false, + 0 + ); } - function checkWellKnownFunctionalities(string memory codeName, bool submitable, string memory methodSignature, string memory returnAbiParametersArray, - bool isInternal, bool needsSender, string memory replaces) public override view { - - if(compareStrings(codeName, "") && compareStrings(replaces, "")) { + function checkWellKnownFunctionalities( + string memory codeName, + bool submittable, + string memory methodSignature, + string memory returnAbiParametersArray, + bool isInternal, + bool needsSender, + string memory replaces + ) public override view { + if (compareStrings(codeName, "") && compareStrings(replaces, "")) { return; } - bool codeNameIsWellKnown = compareStrings(codeName, _wellKnownFunctionalityModels[string(codeName)].codeName); - Functionality memory wellKnownFunctionality = _wellKnownFunctionalityModels[string(codeName)]; - - require(codeNameIsWellKnown ? wellKnownFunctionality.submitable == submitable : true, "Wrong submitable flag for this submission"); - require(codeNameIsWellKnown ? wellKnownFunctionality.needsSender == needsSender : true, "Wrong needsSender flag for this submission"); - require(codeNameIsWellKnown ? wellKnownFunctionality.isInternal == isInternal : true, "Wrong isInternal flag for this submission"); - require(codeNameIsWellKnown ? compareStrings(wellKnownFunctionality.methodSignature, methodSignature) : true, "Wrong method signature for this submission"); - require(codeNameIsWellKnown ? compareStrings(wellKnownFunctionality.returnAbiParametersArray, returnAbiParametersArray) : true, "Wrong return abi parameters array for this submission"); - - require(codeNameIsWellKnown ? wellKnownFunctionality.active ? compareStrings(wellKnownFunctionality.codeName, replaces) : true : true, "Active well known functionality cannot be disabled"); - - require(compareStrings(replaces, _wellKnownFunctionalityModels[replaces].codeName) ? compareStrings(codeName, "") ? !_wellKnownFunctionalityModels[replaces].active : true : true, "Active well known functionality cannot be disabled"); + bool codeNameIsWellKnown = compareStrings( + codeName, + _wellKnownFunctionalityModels[string(codeName)].codeName + ); + + Functionality memory wellKnownFunctionality + = _wellKnownFunctionalityModels[string(codeName)]; + + require( + codeNameIsWellKnown + ? wellKnownFunctionality.submittable == submittable + : true, + "Wrong submittable flag for this submission" + ); + require( + codeNameIsWellKnown + ? wellKnownFunctionality.needsSender == needsSender + : true, + "Wrong needsSender flag for this submission" + ); + require( + codeNameIsWellKnown + ? wellKnownFunctionality.isInternal == isInternal + : true, + "Wrong isInternal flag for this submission" + ); + require( + codeNameIsWellKnown + ? compareStrings( + wellKnownFunctionality.methodSignature, + methodSignature + ) + : true, + "Wrong method signature for this submission" + ); + require( + codeNameIsWellKnown + ? compareStrings( + wellKnownFunctionality.returnAbiParametersArray, + returnAbiParametersArray + ) + : true, + "Wrong return abi parameters array for this submission" + ); + + require( + codeNameIsWellKnown + ? wellKnownFunctionality.active + ? compareStrings(wellKnownFunctionality.codeName, replaces) + : true + : true, + "Active well known functionality cannot be disabled" + ); + + require( + compareStrings( + replaces, + _wellKnownFunctionalityModels[replaces].codeName + ) + ? compareStrings(codeName, "") + ? !_wellKnownFunctionalityModels[replaces].active + : true + : true, + "Active well known functionality cannot be disabled" + ); } - function compareStrings(string memory a, string memory b) internal pure returns(bool) { + function compareStrings(string memory a, string memory b) + internal + pure + returns (bool) + { return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b)); } -} \ No newline at end of file +} diff --git a/contracts/MVDFunctionalityProposal.sol b/contracts/MVDFunctionalityProposal.sol index 28d83b9..8167544 100644 --- a/contracts/MVDFunctionalityProposal.sol +++ b/contracts/MVDFunctionalityProposal.sol @@ -4,8 +4,7 @@ import "./IMVDFunctionalityProposal.sol"; import "./IMVDProxy.sol"; import "./IERC20.sol"; -contract MVDFunctionalityProposal is IMVDFunctionalityProposal{ - +contract MVDFunctionalityProposal is IMVDFunctionalityProposal { bool private _collateralDataSet; address private _proxy; @@ -15,7 +14,7 @@ contract MVDFunctionalityProposal is IMVDFunctionalityProposal{ address private _sourceLocation; uint256 private _sourceLocationId; address private _location; - bool private _submitable; + bool private _submittable; string private _methodSignature; string private _returnAbiParametersArray; bool private _isInternal; @@ -36,13 +35,32 @@ contract MVDFunctionalityProposal is IMVDFunctionalityProposal{ uint256 private _votesHardCap; bool private _votesHardCapReached; - constructor(string memory codeName, address location, string memory methodSignature, string memory returnAbiParametersArray, - string memory replaces, address proxy) public { - init(codeName, location, methodSignature, returnAbiParametersArray, replaces, proxy); + constructor( + string memory codeName, + address location, + string memory methodSignature, + string memory returnAbiParametersArray, + string memory replaces, + address proxy + ) public { + init( + codeName, + location, + methodSignature, + returnAbiParametersArray, + replaces, + proxy + ); } - function init(string memory codeName, address location, string memory methodSignature, string memory returnAbiParametersArray, - string memory replaces, address proxy) public override { + function init( + string memory codeName, + address location, + string memory methodSignature, + string memory returnAbiParametersArray, + string memory replaces, + address proxy + ) public override { require(_proxy == address(0), "Already initialized!"); _token = IMVDProxy(_proxy = proxy).getToken(); _codeName = codeName; @@ -52,107 +70,139 @@ contract MVDFunctionalityProposal is IMVDFunctionalityProposal{ _replaces = replaces; } - function setCollateralData(bool emergency, address sourceLocation, uint256 sourceLocationId, bool submitable, bool isInternal, bool needsSender, address proposer, uint256 votesHardCap) public override { + function setCollateralData( + bool emergency, + address sourceLocation, + uint256 sourceLocationId, + bool submittable, + bool isInternal, + bool needsSender, + address proposer, + uint256 votesHardCap + ) public override { require(!_collateralDataSet, "setCollateralData already called!"); - require(_proxy == msg.sender, "Only Original Proxy can call this method!"); + require( + _proxy == msg.sender, + "Only Original Proxy can call this method!" + ); _sourceLocation = sourceLocation; _sourceLocationId = sourceLocationId; - _submitable = submitable; + _submittable = submittable; _isInternal = isInternal; _needsSender = needsSender; _proposer = proposer; - _surveyDuration = toUint256(IMVDProxy(_proxy).read((_emergency = emergency) ? "getMinimumBlockNumberForEmergencySurvey" : "getMinimumBlockNumberForSurvey", bytes(""))); + _surveyDuration = toUint256( + IMVDProxy(_proxy).read( + (_emergency = emergency) + ? "getMinimumBlockNumberForEmergencySurvey" + : "getMinimumBlockNumberForSurvey", + bytes("") + ) + ); _votesHardCap = votesHardCap; _collateralDataSet = true; } - function getProxy() public override view returns(address) { + function getProxy() public override view returns (address) { return _proxy; } - function getCodeName() public override view returns(string memory) { + function getCodeName() public override view returns (string memory) { return _codeName; } - function isEmergency() public override view returns(bool) { + function isEmergency() public override view returns (bool) { return _emergency; } - function getSourceLocation() public override view returns(address) { + function getSourceLocation() public override view returns (address) { return _sourceLocation; } - function getSourceLocationId() public override view returns(uint256) { + function getSourceLocationId() public override view returns (uint256) { return _sourceLocationId; } - function getLocation() public override view returns(address) { + function getLocation() public override view returns (address) { return _location; } - function isSubmitable() public override view returns(bool) { - return _submitable; + function issubmittable() public override view returns (bool) { + return _submittable; } - function getMethodSignature() public override view returns(string memory) { + function getMethodSignature() public override view returns (string memory) { return _methodSignature; } - function getReturnAbiParametersArray() public override view returns(string memory) { + function getReturnAbiParametersArray() + public + override + view + returns (string memory) + { return _returnAbiParametersArray; } - function isInternal() public override view returns(bool) { + function isInternal() public override view returns (bool) { return _isInternal; } - function needsSender() public override view returns(bool) { + function needsSender() public override view returns (bool) { return _needsSender; } - function getReplaces() public override view returns(string memory) { + function getReplaces() public override view returns (string memory) { return _replaces; } - function getProposer() public override view returns(address) { + function getProposer() public override view returns (address) { return _proposer; } - function getSurveyEndBlock() public override view returns(uint256) { + function getSurveyEndBlock() public override view returns (uint256) { return _surveyEndBlock; } - function getSurveyDuration() public override view returns(uint256) { + function getSurveyDuration() public override view returns (uint256) { return _surveyDuration; } - function getVote(address addr) public override view returns(uint256 accept, uint256 refuse) { + function getVote(address addr) + public + override + view + returns (uint256 accept, uint256 refuse) + { accept = _accept[addr]; refuse = _refuse[addr]; } - function getVotes() public override view returns(uint256, uint256) { + function getVotes() public override view returns (uint256, uint256) { return (_totalAccept, _totalRefuse); } - function isTerminated() public override view returns(bool) { + function isTerminated() public override view returns (bool) { return _terminated; } - function isDisabled() public override view returns(bool) { + function isDisabled() public override view returns (bool) { return _disabled; } - function isVotesHardCapReached() public override view returns(bool) { + function isVotesHardCapReached() public override view returns (bool) { return _votesHardCapReached; } - function getVotesHardCapToReach() public override view returns(uint256) { + function getVotesHardCapToReach() public override view returns (uint256) { return _votesHardCap; } function start() public override { - require(_collateralDataSet, "Still waiting for setCollateralData to be called!"); + require( + _collateralDataSet, + "Still waiting for setCollateralData to be called!" + ); require(msg.sender == _proxy, "Only Proxy can call this function!"); require(_surveyEndBlock == 0, "Already started!"); require(!_disabled, "Already disabled!"); @@ -160,58 +210,75 @@ contract MVDFunctionalityProposal is IMVDFunctionalityProposal{ } function disable() public override { - require(_collateralDataSet, "Still waiting for setCollateralData to be called!"); + require( + _collateralDataSet, + "Still waiting for setCollateralData to be called!" + ); require(msg.sender == _proxy, "Only Proxy can call this function!"); require(_surveyEndBlock == 0, "Already started!"); _disabled = true; _terminated = true; } - function toJSON() public override view returns(string memory) { - return string(abi.encodePacked( - '{', - getFirstJSONPart(_sourceLocation, _sourceLocationId, _location), - '","submitable":', - _submitable ? "true" : "false", - ',"emergency":', - _emergency ? "true" : "false", - ',"isInternal":', - _isInternal ? "true" : "false", - ',"needsSender":', - _needsSender ? "true" : "false", - ',', - getSecondJSONPart(), - ',"proposer":"', - toString(_proposer), - '","endBlock":', - toString(_surveyEndBlock), - ',"terminated":', - _terminated ? "true" : "false", - ',"accepted":', - toString(_totalAccept), - ',"refused":', - toString(_totalRefuse), - ',"disabled":', - _disabled ? 'true' : 'false', - '}') - ); - } - - function getSecondJSONPart() private view returns (string memory){ - return string(abi.encodePacked( - '"codeName":"', - _codeName, - '","methodSignature":"', - _methodSignature, - '","returnAbiParametersArray":', - formatReturnAbiParametersArray(_returnAbiParametersArray), - ',"replaces":"', - _replaces, - '"')); + function toJSON() public override view returns (string memory) { + return + string( + abi.encodePacked( + "{", + getFirstJSONPart( + _sourceLocation, + _sourceLocationId, + _location + ), + '","submittable":', + _submittable ? "true" : "false", + ',"emergency":', + _emergency ? "true" : "false", + ',"isInternal":', + _isInternal ? "true" : "false", + ',"needsSender":', + _needsSender ? "true" : "false", + ",", + getSecondJSONPart(), + ',"proposer":"', + toString(_proposer), + '","endBlock":', + toString(_surveyEndBlock), + ',"terminated":', + _terminated ? "true" : "false", + ',"accepted":', + toString(_totalAccept), + ',"refused":', + toString(_totalRefuse), + ',"disabled":', + _disabled ? "true" : "false", + "}" + ) + ); + } + + function getSecondJSONPart() private view returns (string memory) { + return + string( + abi.encodePacked( + '"codeName":"', + _codeName, + '","methodSignature":"', + _methodSignature, + '","returnAbiParametersArray":', + formatReturnAbiParametersArray(_returnAbiParametersArray), + ',"replaces":"', + _replaces, + '"' + ) + ); } modifier duringSurvey() { - require(_collateralDataSet, "Still waiting for setCollateralData to be called!"); + require( + _collateralDataSet, + "Still waiting for setCollateralData to be called!" + ); require(!_disabled, "Survey disabled!"); require(!_terminated, "Survey Terminated!"); require(!_votesHardCapReached, "Votes Hard Cap reached!"); @@ -221,17 +288,26 @@ contract MVDFunctionalityProposal is IMVDFunctionalityProposal{ } modifier onSurveyEnd() { - require(_collateralDataSet, "Still waiting for setCollateralData to be called!"); + require( + _collateralDataSet, + "Still waiting for setCollateralData to be called!" + ); require(!_disabled, "Survey disabled!"); require(_surveyEndBlock > 0, "Survey Not Started!"); - if(!_votesHardCapReached) { - require(block.number >= _surveyEndBlock, "Survey is still running!"); + if (!_votesHardCapReached) { + require( + block.number >= _surveyEndBlock, + "Survey is still running!" + ); } _; } function _checkVotesHardCap() private { - if(_votesHardCap == 0 || (_totalAccept < _votesHardCap && _totalRefuse < _votesHardCap)) { + if ( + _votesHardCap == 0 || + (_totalAccept < _votesHardCap && _totalRefuse < _votesHardCap) + ) { return; } _votesHardCapReached = true; @@ -321,7 +397,7 @@ contract MVDFunctionalityProposal is IMVDFunctionalityProposal{ } function withdraw() external override onSurveyEnd { - if(!_terminated && !_disabled) { + if (!_terminated && !_disabled) { terminate(); return; } @@ -335,10 +411,22 @@ contract MVDFunctionalityProposal is IMVDFunctionalityProposal{ } function _withdraw(bool launchError) private { - require(!launchError || _accept[msg.sender] + _refuse[msg.sender] > 0, "Nothing to Withdraw!"); - require(!launchError || !_withdrawed[msg.sender], "Already Withdrawed!"); - if(_accept[msg.sender] + _refuse[msg.sender] > 0 && !_withdrawed[msg.sender]) { - IERC20(_token).transfer(msg.sender, _accept[msg.sender] + _refuse[msg.sender]); + require( + !launchError || _accept[msg.sender] + _refuse[msg.sender] > 0, + "Nothing to Withdraw!" + ); + require( + !launchError || !_withdrawed[msg.sender], + "Already Withdrawed!" + ); + if ( + _accept[msg.sender] + _refuse[msg.sender] > 0 && + !_withdrawed[msg.sender] + ) { + IERC20(_token).transfer( + msg.sender, + _accept[msg.sender] + _refuse[msg.sender] + ); _withdrawed[msg.sender] = true; } } @@ -349,69 +437,78 @@ contract MVDFunctionalityProposal is IMVDFunctionalityProposal{ _terminated = true; } - function toUint256(bytes memory bs) public pure returns(uint256 x) { - if(bs.length >= 32) { + function toUint256(bytes memory bs) public pure returns (uint256 x) { + if (bs.length >= 32) { assembly { x := mload(add(bs, add(0x20, 0))) } } } - function toString(address _addr) public pure returns(string memory) { + function toString(address _addr) public pure returns (string memory) { bytes32 value = bytes32(uint256(_addr)); bytes memory alphabet = "0123456789abcdef"; bytes memory str = new bytes(42); - str[0] = '0'; - str[1] = 'x'; - for (uint i = 0; i < 20; i++) { - str[2+i*2] = alphabet[uint(uint8(value[i + 12] >> 4))]; - str[3+i*2] = alphabet[uint(uint8(value[i + 12] & 0x0f))]; + str[0] = "0"; + str[1] = "x"; + for (uint256 i = 0; i < 20; i++) { + str[2 + i * 2] = alphabet[uint256(uint8(value[i + 12] >> 4))]; + str[3 + i * 2] = alphabet[uint256(uint8(value[i + 12] & 0x0f))]; } return string(str); } - function toString(uint _i) public pure returns(string memory) { + function toString(uint256 _i) public pure returns (string memory) { if (_i == 0) { return "0"; } - uint j = _i; - uint len; + uint256 j = _i; + uint256 len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); - uint k = len - 1; + uint256 k = len - 1; while (_i != 0) { - bstr[k--] = byte(uint8(48 + _i % 10)); + bstr[k--] = bytes1(uint8(48 + (_i % 10))); _i /= 10; } return string(bstr); } - function getFirstJSONPart(address sourceLocation, uint256 sourceLocationId, address location) public pure returns(bytes memory) { - return abi.encodePacked( - '"sourceLocation":"', - toString(sourceLocation), - '","sourceLocationId":', - toString(sourceLocationId), - ',"location":"', - toString(location) - ); - } - - function formatReturnAbiParametersArray(string memory m) public pure returns(string memory) { + function getFirstJSONPart( + address sourceLocation, + uint256 sourceLocationId, + address location + ) public pure returns (bytes memory) { + return + abi.encodePacked( + '"sourceLocation":"', + toString(sourceLocation), + '","sourceLocationId":', + toString(sourceLocationId), + ',"location":"', + toString(location) + ); + } + + function formatReturnAbiParametersArray(string memory m) + public + pure + returns (string memory) + { bytes memory b = bytes(m); - if(b.length < 2) { + if (b.length < 2) { return "[]"; } - if(b[0] != bytes1("[")) { + if (b[0] != bytes1("[")) { return "[]"; } - if(b[b.length - 1] != bytes1("]")) { + if (b[b.length - 1] != bytes1("]")) { return "[]"; } return m; } -} \ No newline at end of file +} diff --git a/contracts/MVDProxy.sol b/contracts/MVDProxy.sol index 9ca8ef3..7c9e7b9 100644 --- a/contracts/MVDProxy.sol +++ b/contracts/MVDProxy.sol @@ -11,31 +11,55 @@ import "./IMVDWallet.sol"; import "./IERC721.sol"; contract MVDProxy is IMVDProxy { - address[] private _delegates; - constructor(address votingTokenAddress, address functionalityProposalManagerAddress, address stateHolderAddress, address functionalityModelsManagerAddress, address functionalitiesManagerAddress, address walletAddress, address doubleProxyAddress) public { - if(votingTokenAddress == address(0)) { + constructor( + address votingTokenAddress, + address functionalityProposalManagerAddress, + address stateHolderAddress, + address functionalityModelsManagerAddress, + address functionalitiesManagerAddress, + address walletAddress, + address doubleProxyAddress + ) public { + if (votingTokenAddress == address(0)) { return; } - init(votingTokenAddress, functionalityProposalManagerAddress, stateHolderAddress, functionalityModelsManagerAddress, functionalitiesManagerAddress, walletAddress, doubleProxyAddress); + init( + votingTokenAddress, + functionalityProposalManagerAddress, + stateHolderAddress, + functionalityModelsManagerAddress, + functionalitiesManagerAddress, + walletAddress, + doubleProxyAddress + ); } - function init(address votingTokenAddress, address functionalityProposalManagerAddress, address stateHolderAddress, address functionalityModelsManagerAddress, address functionalitiesManagerAddress, address walletAddress, address doubleProxyAddress) public override { - + function init( + address votingTokenAddress, + address functionalityProposalManagerAddress, + address stateHolderAddress, + address functionalityModelsManagerAddress, + address functionalitiesManagerAddress, + address walletAddress, + address doubleProxyAddress + ) public override { require(_delegates.length == 0, "Init already called!"); _delegates = new address[](7); IMVDProxyDelegate(_delegates[0] = votingTokenAddress).setProxy(); - IMVDProxyDelegate(_delegates[1] = functionalityProposalManagerAddress).setProxy(); + IMVDProxyDelegate(_delegates[1] = functionalityProposalManagerAddress) + .setProxy(); IMVDProxyDelegate(_delegates[2] = stateHolderAddress).setProxy(); _delegates[3] = functionalityModelsManagerAddress; - IMVDProxyDelegate(_delegates[4] = functionalitiesManagerAddress).setProxy(); + IMVDProxyDelegate(_delegates[4] = functionalitiesManagerAddress) + .setProxy(); IMVDProxyDelegate(_delegates[5] = walletAddress).setProxy(); @@ -46,104 +70,218 @@ contract MVDProxy is IMVDProxy { revert("No Eth Accepted"); } - function getDelegates() public override view returns(address[] memory) { + function getDelegates() public override view returns (address[] memory) { return _delegates; } - function getToken() public override view returns(address) { + function getToken() public override view returns (address) { return _delegates[0]; } - function getMVDFunctionalityProposalManagerAddress() public override view returns(address) { + function getMVDFunctionalityProposalManagerAddress() + public + override + view + returns (address) + { return _delegates[1]; } - function getStateHolderAddress() public override view returns(address) { + function getStateHolderAddress() public override view returns (address) { return _delegates[2]; } - function getMVDFunctionalityModelsManagerAddress() public override view returns(address) { + function getMVDFunctionalityModelsManagerAddress() + public + override + view + returns (address) + { return _delegates[3]; } - function getMVDFunctionalitiesManagerAddress() public override view returns(address) { + function getMVDFunctionalitiesManagerAddress() + public + override + view + returns (address) + { return _delegates[4]; } - function getMVDWalletAddress() public override view returns(address) { + function getMVDWalletAddress() public override view returns (address) { return _delegates[5]; } - function getDoubleProxyAddress() public override view returns(address) { + function getDoubleProxyAddress() public override view returns (address) { return _delegates[6]; } - function flushToWallet(address tokenAddress, bool is721, uint256 tokenId) public override { - require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), "Unauthorized action!"); - if(tokenAddress == address(0)) { + function flushToWallet( + address tokenAddress, + bool is721, + uint256 tokenId + ) public override { + require( + IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality( + msg.sender + ), + "Unauthorized action!" + ); + if (tokenAddress == address(0)) { payable(_delegates[5]).transfer(payable(address(this)).balance); return; } - if(is721) { - IERC721(tokenAddress).transferFrom(address(this), _delegates[5], tokenId); + if (is721) { + IERC721(tokenAddress).transferFrom( + address(this), + _delegates[5], + tokenId + ); return; } IERC20 token = IERC20(tokenAddress); token.transfer(_delegates[5], token.balanceOf(address(this))); } - function setDelegate(uint256 position, address newAddress) public override returns(address oldAddress) { - require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), "Unauthorized action!"); + function setDelegate(uint256 position, address newAddress) + public + override + returns (address oldAddress) + { + require( + IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality( + msg.sender + ), + "Unauthorized action!" + ); require(newAddress != address(0), "Cannot set void address!"); - if(position == 5) { - IMVDWallet(_delegates[5]).setNewWallet(payable(newAddress), _delegates[0]); + if (position == 5) { + IMVDWallet(_delegates[5]).setNewWallet( + payable(newAddress), + _delegates[0] + ); } oldAddress = _delegates[position]; _delegates[position] = newAddress; - if(position != 3) { + if (position != 3) { IMVDProxyDelegate(oldAddress).setProxy(); IMVDProxyDelegate(newAddress).setProxy(); } emit DelegateChanged(position, oldAddress, newAddress); } - function changeProxy(address newAddress, bytes memory initPayload) public override { - require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), "Unauthorized action!"); + function changeProxy(address newAddress, bytes memory initPayload) + public + override + { + require( + IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality( + msg.sender + ), + "Unauthorized action!" + ); require(newAddress != address(0), "Cannot set void address!"); - for(uint256 i = 0; i < _delegates.length; i++) { - if(i != 3) { + for (uint256 i = 0; i < _delegates.length; i++) { + if (i != 3) { IMVDProxyDelegate(_delegates[i]).setProxy(); } } _delegates = new address[](0); emit ProxyChanged(newAddress); - (bool response,) = newAddress.call(initPayload); + (bool response, ) = newAddress.call(initPayload); require(response, "New Proxy initPayload failed!"); } - function isValidProposal(address proposal) public override view returns (bool) { - return IMVDFunctionalityProposalManager(_delegates[1]).isValidProposal(proposal); + function isValidProposal(address proposal) + public + override + view + returns (bool) + { + return + IMVDFunctionalityProposalManager(_delegates[1]).isValidProposal( + proposal + ); } - function isAuthorizedFunctionality(address functionality) public override view returns(bool) { - return IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(functionality); + function isAuthorizedFunctionality(address functionality) + public + override + view + returns (bool) + { + return + IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality( + functionality + ); } - function newProposal(string memory codeName, bool emergency, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string memory methodSignature, string memory returnAbiParametersArray, bool isInternal, bool needsSender, string memory replaces) public override returns(address proposalAddress) { + function newProposal( + string memory codeName, + bool emergency, + address sourceLocation, + uint256 sourceLocationId, + address location, + bool submittable, + string memory methodSignature, + string memory returnAbiParametersArray, + bool isInternal, + bool needsSender, + string memory replaces + ) public override returns (address proposalAddress) { emergencyBehavior(emergency); - IMVDFunctionalityModelsManager(_delegates[3]).checkWellKnownFunctionalities(codeName, submitable, methodSignature, returnAbiParametersArray, isInternal, needsSender, replaces); - - IMVDFunctionalitiesManager functionalitiesManager = IMVDFunctionalitiesManager(_delegates[4]); - - IMVDFunctionalityProposal proposal = IMVDFunctionalityProposal(proposalAddress = IMVDFunctionalityProposalManager(_delegates[1]).newProposal(codeName, location, methodSignature, returnAbiParametersArray, replaces)); - proposal.setCollateralData(emergency, sourceLocation, sourceLocationId, submitable, isInternal, needsSender, msg.sender, functionalitiesManager.hasFunctionality("getVotesHardCap") ? toUint256(read("getVotesHardCap", "")) : 0); - - if(functionalitiesManager.hasFunctionality("onNewProposal")) { + IMVDFunctionalityModelsManager(_delegates[3]) + .checkWellKnownFunctionalities( + codeName, + submittable, + methodSignature, + returnAbiParametersArray, + isInternal, + needsSender, + replaces + ); + + + IMVDFunctionalitiesManager functionalitiesManager + = IMVDFunctionalitiesManager(_delegates[4]); + + IMVDFunctionalityProposal proposal = IMVDFunctionalityProposal( + proposalAddress = IMVDFunctionalityProposalManager(_delegates[1]) + .newProposal( + codeName, + location, + methodSignature, + returnAbiParametersArray, + replaces + ) + ); + proposal.setCollateralData( + emergency, + sourceLocation, + sourceLocationId, + submittable, + isInternal, + needsSender, + msg.sender, + functionalitiesManager.hasFunctionality("getVotesHardCap") + ? toUint256(read("getVotesHardCap", "")) + : 0 + ); + + if (functionalitiesManager.hasFunctionality("onNewProposal")) { submit("onNewProposal", abi.encode(proposalAddress)); } - if(!IMVDFunctionalitiesManager(_delegates[4]).hasFunctionality("startProposal") || !IMVDFunctionalitiesManager(_delegates[4]).hasFunctionality("disableProposal")) { + if ( + !IMVDFunctionalitiesManager(_delegates[4]).hasFunctionality( + "startProposal" + ) || + !IMVDFunctionalitiesManager(_delegates[4]).hasFunctionality( + "disableProposal" + ) + ) { proposal.start(); } @@ -151,107 +289,200 @@ contract MVDProxy is IMVDProxy { } function emergencyBehavior(bool emergency) private { - if(!emergency) { + if (!emergency) { return; } - (address loc, , string memory meth,,) = IMVDFunctionalitiesManager(_delegates[4]).getFunctionalityData("getEmergencySurveyStaking"); - (, bytes memory payload) = loc.staticcall(abi.encodeWithSignature(meth)); + (address loc, , string memory meth, , ) = IMVDFunctionalitiesManager( + _delegates[4] + ) + .getFunctionalityData("getEmergencySurveyStaking"); + (, bytes memory payload) = loc.staticcall( + abi.encodeWithSignature(meth) + ); uint256 staking = toUint256(payload); - if(staking > 0) { - IERC20(_delegates[0]).transferFrom(msg.sender, address(this), staking); + if (staking > 0) { + IERC20(_delegates[0]).transferFrom( + msg.sender, + address(this), + staking + ); } } function startProposal(address proposalAddress) public override { - require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), "Unauthorized action!"); - (address location,,,,) = IMVDFunctionalitiesManager(_delegates[4]).getFunctionalityData("startProposal"); - require(location == msg.sender, "Only startProposal Functionality can enable a delayed proposal"); - require(IMVDFunctionalityProposalManager(_delegates[1]).isValidProposal(proposalAddress), "Invalid Proposal Address!"); + require( + IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality( + msg.sender + ), + "Unauthorized action!" + ); + (address location, , , , ) = IMVDFunctionalitiesManager(_delegates[4]) + .getFunctionalityData("startProposal"); + require( + location == msg.sender, + "Only startProposal Functionality can enable a delayed proposal" + ); + require( + IMVDFunctionalityProposalManager(_delegates[1]).isValidProposal( + proposalAddress + ), + "Invalid Proposal Address!" + ); IMVDFunctionalityProposal(proposalAddress).start(); } function disableProposal(address proposalAddress) public override { - require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), "Unauthorized action!"); - (address location,,,,) = IMVDFunctionalitiesManager(_delegates[4]).getFunctionalityData("disableProposal"); - require(location == msg.sender, "Only disableProposal Functionality can disable a delayed proposal"); + require( + IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality( + msg.sender + ), + "Unauthorized action!" + ); + (address location, , , , ) = IMVDFunctionalitiesManager(_delegates[4]) + .getFunctionalityData("disableProposal"); + require( + location == msg.sender, + "Only disableProposal Functionality can disable a delayed proposal" + ); IMVDFunctionalityProposal(proposalAddress).disable(); } - function transfer(address receiver, uint256 value, address token) public override { - require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), "Only functionalities can transfer Proxy balances!"); + function transfer( + address receiver, + uint256 value, + address token + ) public override { + require( + IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality( + msg.sender + ), + "Only functionalities can transfer Proxy balances!" + ); IMVDWallet(_delegates[5]).transfer(receiver, value, token); } - function transfer721(address receiver, uint256 tokenId, bytes memory data, bool safe, address token) public override { - require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), "Only functionalities can transfer Proxy balances!"); - IMVDWallet(_delegates[5]).transfer(receiver, tokenId, data, safe, token); + function transfer721( + address receiver, + uint256 tokenId, + bytes memory data, + bool safe, + address token + ) public override { + require( + IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality( + msg.sender + ), + "Only functionalities can transfer Proxy balances!" + ); + IMVDWallet(_delegates[5]).transfer( + receiver, + tokenId, + data, + safe, + token + ); } function setProposal() public override { - - IMVDFunctionalityProposalManager(_delegates[1]).checkProposal(msg.sender); + IMVDFunctionalityProposalManager(_delegates[1]).checkProposal( + msg.sender + ); emit ProposalCheck(msg.sender); - IMVDFunctionalitiesManager functionalitiesManager = IMVDFunctionalitiesManager(_delegates[4]); - (address addressToCall,,string memory methodSignature,,) = functionalitiesManager.getFunctionalityData("checkSurveyResult"); + IMVDFunctionalitiesManager functionalitiesManager + = IMVDFunctionalitiesManager(_delegates[4]); - (bool surveyResult, bytes memory response) = addressToCall.staticcall(abi.encodeWithSignature(methodSignature, msg.sender)); + ( + address addressToCall, + , + string memory methodSignature, + , + + ) = functionalitiesManager.getFunctionalityData("checkSurveyResult"); + + (bool surveyResult, bytes memory response) = addressToCall.staticcall( + abi.encodeWithSignature(methodSignature, msg.sender) + ); surveyResult = toUint256(response) > 0; bool collateralCallResult = true; - (addressToCall,,methodSignature,,) = functionalitiesManager.getFunctionalityData("proposalEnd"); - if(addressToCall != address(0)) { + (addressToCall, , methodSignature, , ) = functionalitiesManager + .getFunctionalityData("proposalEnd"); + if (addressToCall != address(0)) { functionalitiesManager.setCallingContext(addressToCall); - (collateralCallResult,) = addressToCall.call(abi.encodeWithSignature(methodSignature, msg.sender, surveyResult)); + (collateralCallResult, ) = addressToCall.call( + abi.encodeWithSignature( + methodSignature, + msg.sender, + surveyResult + ) + ); functionalitiesManager.clearCallingContext(); } - IMVDFunctionalityProposal proposal = IMVDFunctionalityProposal(msg.sender); + IMVDFunctionalityProposal proposal = IMVDFunctionalityProposal( + msg.sender + ); uint256 staking = 0; address tokenAddress = _delegates[0]; address walletAddress = _delegates[5]; - if(proposal.isEmergency()) { - (addressToCall,,methodSignature,,) = functionalitiesManager.getFunctionalityData("getEmergencySurveyStaking"); - (, response) = addressToCall.staticcall(abi.encodeWithSignature(methodSignature)); + if (proposal.isEmergency()) { + (addressToCall, , methodSignature, , ) = functionalitiesManager + .getFunctionalityData("getEmergencySurveyStaking"); + (, response) = addressToCall.staticcall( + abi.encodeWithSignature(methodSignature) + ); staking = toUint256(response); } - if(!surveyResult) { - if(collateralCallResult) { + if (!surveyResult) { + if (collateralCallResult) { proposal.set(); emit ProposalSet(msg.sender, surveyResult); - if(staking > 0) { + if (staking > 0) { IERC20(tokenAddress).transfer(walletAddress, staking); } } return; } - if(collateralCallResult) { - try functionalitiesManager.setupFunctionality(msg.sender) returns(bool managerResult) { + if (collateralCallResult) { + try functionalitiesManager.setupFunctionality(msg.sender) returns ( + bool managerResult + ) { collateralCallResult = managerResult; } catch { collateralCallResult = false; } } - if(collateralCallResult) { + if (collateralCallResult) { proposal.set(); emit ProposalSet(msg.sender, surveyResult); - if(staking > 0) { - IERC20(tokenAddress).transfer(surveyResult ? proposal.getProposer() : walletAddress, staking); + if (staking > 0) { + IERC20(tokenAddress).transfer( + surveyResult ? proposal.getProposer() : walletAddress, + staking + ); } } } - function read(string memory codeName, bytes memory data) public override view returns(bytes memory returnData) { - - (address location, bytes memory payload) = IMVDFunctionalitiesManager(_delegates[4]).preConditionCheck(codeName, data, 0, msg.sender, 0); + function read(string memory codeName, bytes memory data) + public + override + view + returns (bytes memory returnData) + { + (address location, bytes memory payload) = IMVDFunctionalitiesManager( + _delegates[4] + ) + .preConditionCheck(codeName, data, 0, msg.sender, 0); bool ok; (ok, returnData) = location.staticcall(payload); @@ -259,47 +490,112 @@ contract MVDProxy is IMVDProxy { require(ok, "Failed to read from functionality"); } - function submit(string memory codeName, bytes memory data) public override payable returns(bytes memory returnData) { - - if(msg.value > 0) { + function submit(string memory codeName, bytes memory data) + public + override + payable + returns (bytes memory returnData) + { + if (msg.value > 0) { payable(_delegates[5]).transfer(msg.value); } - IMVDFunctionalitiesManager manager = IMVDFunctionalitiesManager(_delegates[4]); - (address location, bytes memory payload) = manager.preConditionCheck(codeName, data, 1, msg.sender, msg.value); + IMVDFunctionalitiesManager manager = IMVDFunctionalitiesManager( + _delegates[4] + ); + (address location, bytes memory payload) = manager.preConditionCheck( + codeName, + data, + 1, + msg.sender, + msg.value + ); bool changed = manager.setCallingContext(location); bool ok; (ok, returnData) = location.call(payload); - if(changed) { + if (changed) { manager.clearCallingContext(); } require(ok, "Failed to submit functionality"); } - function callFromManager(address location, bytes memory payload) public override returns(bool, bytes memory) { - require(msg.sender == _delegates[4], "Only Functionalities Manager can call this!"); + function callFromManager(address location, bytes memory payload) + public + override + returns (bool, bytes memory) + { + require( + msg.sender == _delegates[4], + "Only Functionalities Manager can call this!" + ); return location.call(payload); } - function emitFromManager(string memory codeName, address proposal, string memory replaced, address replacedSourceLocation, uint256 replacedSourceLocationId, address location, bool submitable, string memory methodSignature, bool isInternal, bool needsSender, address proposalAddress) public override { - require(msg.sender == _delegates[4], "Only Functionalities Manager can call this!"); - emit FunctionalitySet(codeName, proposal, replaced, replacedSourceLocation, replacedSourceLocationId, location, submitable, methodSignature, isInternal, needsSender, proposalAddress); + function emitFromManager( + string memory codeName, + address proposal, + string memory replaced, + address replacedSourceLocation, + uint256 replacedSourceLocationId, + address location, + bool submittable, + string memory methodSignature, + bool isInternal, + bool needsSender, + address proposalAddress + ) public override { + require( + msg.sender == _delegates[4], + "Only Functionalities Manager can call this!" + ); + emit FunctionalitySet( + codeName, + proposal, + replaced, + replacedSourceLocation, + replacedSourceLocationId, + location, + submittable, + methodSignature, + isInternal, + needsSender, + proposalAddress + ); } - function emitEvent(string memory eventSignature, bytes memory firstIndex, bytes memory secondIndex, bytes memory data) public override { - require(IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality(msg.sender), "Only authorized functionalities can emit events!"); - emit Event(eventSignature, keccak256(firstIndex), keccak256(secondIndex), data); + function emitEvent( + string memory eventSignature, + bytes memory firstIndex, + bytes memory secondIndex, + bytes memory data + ) public override { + require( + IMVDFunctionalitiesManager(_delegates[4]).isAuthorizedFunctionality( + msg.sender + ), + "Only authorized functionalities can emit events!" + ); + emit Event( + eventSignature, + keccak256(firstIndex), + keccak256(secondIndex), + data + ); } - function compareStrings(string memory a, string memory b) private pure returns(bool) { + function compareStrings(string memory a, string memory b) + private + pure + returns (bool) + { return keccak256(bytes(a)) == keccak256(bytes(b)); } - function toUint256(bytes memory bs) internal pure returns(uint256 x) { - if(bs.length >= 32) { + function toUint256(bytes memory bs) internal pure returns (uint256 x) { + if (bs.length >= 32) { assembly { x := mload(add(bs, add(0x20, 0))) } @@ -309,4 +605,4 @@ contract MVDProxy is IMVDProxy { interface IMVDProxyDelegate { function setProxy() external; -} \ No newline at end of file +} From 170eeed143d7e1506ab23f2fb36f8728f1b1cdc6 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Sat, 19 Sep 2020 14:55:00 +0200 Subject: [PATCH 03/12] Add docs output folder --- .gitmodules | 3 +++ docs/build | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 docs/build diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..555780d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "docs/build"] + path = docs/build + url = git@github.com:b-u-i-d-l/dfo-protocol-docs.git diff --git a/docs/build b/docs/build new file mode 160000 index 0000000..c8ac821 --- /dev/null +++ b/docs/build @@ -0,0 +1 @@ +Subproject commit c8ac8213183c58be0c0059bbc88f9a67979a5924 From e7d9fea380d4d7b835bafe4e0fc37ade67279d3d Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Sat, 19 Sep 2020 16:02:53 +0200 Subject: [PATCH 04/12] Add all the natspec --- contracts/CommonUtilities.sol | 2 +- contracts/DoubleProxy.sol | 2 +- contracts/Functionality.sol | 2 +- contracts/IDoubleProxy.sol | 8 +- contracts/IERC20.sol | 30 ++- contracts/IERC721.sol | 2 +- contracts/IERC721Receiver.sol | 2 +- contracts/IMVDFunctionalitiesManager.sol | 17 +- contracts/IMVDFunctionalityModelsManager.sol | 11 +- contracts/IMVDFunctionalityProposal.sol | 80 +++++-- .../IMVDFunctionalityProposalManager.sol | 30 ++- contracts/IMVDProxy.sol | 59 ++++- contracts/IMVDWallet.sol | 71 +++++- contracts/IStateHolder.sol | 78 +++++-- contracts/IVotingToken.sol | 64 +++++- contracts/MVDFunctionalitiesManager.sol | 2 +- contracts/MVDFunctionalityModelsManager.sol | 3 +- contracts/MVDFunctionalityProposal.sol | 13 +- contracts/MVDFunctionalityProposalManager.sol | 130 ++++++++--- contracts/MVDProxy.sol | 2 +- contracts/MVDWallet.sol | 76 +++++-- contracts/StateHolder.sol | 205 +++++++++++++----- contracts/VotingToken.sol | 159 +++++++++++--- 23 files changed, 822 insertions(+), 226 deletions(-) diff --git a/contracts/CommonUtilities.sol b/contracts/CommonUtilities.sol index 235bf38..1143ae9 100644 --- a/contracts/CommonUtilities.sol +++ b/contracts/CommonUtilities.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; import "./ICommonUtilities.sol"; diff --git a/contracts/DoubleProxy.sol b/contracts/DoubleProxy.sol index e9fb192..5ef576a 100644 --- a/contracts/DoubleProxy.sol +++ b/contracts/DoubleProxy.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; import "./IDoubleProxy.sol"; diff --git a/contracts/Functionality.sol b/contracts/Functionality.sol index 18add87..20e4746 100644 --- a/contracts/Functionality.sol +++ b/contracts/Functionality.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; // DOCUMENT struct Functionality { diff --git a/contracts/IDoubleProxy.sol b/contracts/IDoubleProxy.sol index b5e5fc4..cce018b 100644 --- a/contracts/IDoubleProxy.sol +++ b/contracts/IDoubleProxy.sol @@ -3,8 +3,6 @@ pragma solidity >=0.7.0; /** * @title Double Proxy Interface - * @dev - * */ interface IDoubleProxy { /** @@ -36,12 +34,16 @@ interface IDoubleProxy { /** * @dev Retrieve a portion of the proxies + * @param start Start Position + * @param offset End Position */ function proxies(uint256 start, uint256 offset) external view returns (address[] memory); - // DOCUMENT + /** + * @dev Retrieve all the proxies + */ function proxies() external view returns (address[] memory); } diff --git a/contracts/IERC20.sol b/contracts/IERC20.sol index 0ec4e7b..052555b 100644 --- a/contracts/IERC20.sol +++ b/contracts/IERC20.sol @@ -1,13 +1,31 @@ -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; interface IERC20 { function totalSupply() external view returns (uint256); + function balanceOf(address account) external view returns (uint256); - function transfer(address recipient, uint256 amount) external returns (bool); - function allowance(address owner, address spender) external view returns (uint256); + + function transfer(address recipient, uint256 amount) + external + returns (bool); + + function allowance(address owner, address spender) + external + view + returns (uint256); + function approve(address spender, uint256 amount) external returns (bool); - function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); + + function transferFrom( + address sender, + address recipient, + uint256 amount + ) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); - event Approval(address indexed owner, address indexed spender, uint256 value); -} \ No newline at end of file + event Approval( + address indexed owner, + address indexed spender, + uint256 value + ); +} diff --git a/contracts/IERC721.sol b/contracts/IERC721.sol index b28f9aa..a5395ab 100644 --- a/contracts/IERC721.sol +++ b/contracts/IERC721.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; interface IERC721 { function ownerOf(uint256 _tokenId) external view returns (address); diff --git a/contracts/IERC721Receiver.sol b/contracts/IERC721Receiver.sol index 8e44a4b..84fe3b5 100644 --- a/contracts/IERC721Receiver.sol +++ b/contracts/IERC721Receiver.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; interface IERC721Receiver { function onERC721Received( diff --git a/contracts/IMVDFunctionalitiesManager.sol b/contracts/IMVDFunctionalitiesManager.sol index f613d1a..3f4a9df 100644 --- a/contracts/IMVDFunctionalitiesManager.sol +++ b/contracts/IMVDFunctionalitiesManager.sol @@ -1,9 +1,8 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; /** * @title Interface for the Functionalities Manager - * @dev */ interface IMVDFunctionalitiesManager { /** @@ -44,12 +43,11 @@ interface IMVDFunctionalitiesManager { address checkVoteResultFunctionalityAddress ) external; - // DOCUMENT /** * @dev Add a functionality to the Functionalities Manager - * @param codeName - * @param sourceLocation - * @param sourceLocationId + * @param codeNameID of the Functionality + * @param sourceLocation ROBE location of the source code + * @param sourceLocationId ROBE id * @param location * @param submittable * @param methodSignature @@ -69,12 +67,11 @@ interface IMVDFunctionalitiesManager { bool needsSender ) external; - // DOCUMENT /** * @dev Replace a Functionality in the Functionalities Manager - * @param codeName - * @param sourceLocation - * @param sourceLocationId + * @param codeName ID of the Functionality + * @param sourceLocation ROBE location of the source code + * @param sourceLocationId ROBE id * @param location * @param submittable * @param methodSignature diff --git a/contracts/IMVDFunctionalityModelsManager.sol b/contracts/IMVDFunctionalityModelsManager.sol index f03bd91..c6e3070 100644 --- a/contracts/IMVDFunctionalityModelsManager.sol +++ b/contracts/IMVDFunctionalityModelsManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; /** * @title Functionalities Models Manager @@ -11,7 +11,14 @@ interface IMVDFunctionalityModelsManager { /** * @dev Check Well Known Functionalities. If the check fails it will raise its own errors. - * // DOCUMENT + * @param codeNameID of the Functionality + * @param location + * @param submittable + * @param methodSignature + * @param returnAbiParametersArray + * @param isInternal + * @param needsSender + * @replaces */ function checkWellKnownFunctionalities( string calldata codeName, diff --git a/contracts/IMVDFunctionalityProposal.sol b/contracts/IMVDFunctionalityProposal.sol index 316d836..6f8e3f0 100644 --- a/contracts/IMVDFunctionalityProposal.sol +++ b/contracts/IMVDFunctionalityProposal.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; /** * @title Interface for Proposal @@ -10,11 +10,11 @@ interface IMVDFunctionalityProposal { /** * @dev Functionality Initializer * @param codeName String ID of the Functionality - * @param location // DOCUMENTATION - * @param methodSignature - * @param returnAbiParameters - * @param replaces - * @param proxy + * @param location // DOCUMENTATION + * @param methodSignature // DOCUMENTATION + * @param returnAbiParametersArray // DOCUMENTATION + * @param replaces // DOCUMENTATION + * @param proxy // DOCUMENTATION */ function init( string calldata codeName, @@ -27,14 +27,14 @@ interface IMVDFunctionalityProposal { /** * @dev set the collateral attributes of the proposal - * @param emergency // DOCUMENTATION - * @param sourceLocation - * @param sourceLocationId - * @param submittable - * @param isInternal - * @param needsSender - * @param proposer - * @param votesHardCap + * @param emergency Bool flag controlling wether this is a standard or emergency proposal + * @param sourceLocation ROBE location of the source code + * @param sourceLocationId ROBE id + * @param submittable // DOCUMENTATION + * @param isInternal // DOCUMENTATION + * @param needsSender // DOCUMENTATION + * @param proposer Address of the proposer // DOCUMENTATION + * @param votesHardCap Hardcap value // DOCUMENTATION */ function setCollateralData( bool emergency, @@ -68,7 +68,7 @@ interface IMVDFunctionalityProposal { function getSourceLocation() external view returns (address); /** - * @dev // DOCUMENT + * @dev GET the ROBE id */ function getSourceLocationId() external view returns (uint256); @@ -94,22 +94,22 @@ interface IMVDFunctionalityProposal { function needsSender() external view returns (bool); /** - * @dev GET the ROBE source location + * @dev // DOCUMENTATION */ function getReplaces() external view returns (string memory); /** - * @dev GET the ROBE source location + * @dev GET the address of the proposer */ function getProposer() external view returns (address); /** - * @dev GET the ROBE source location + * @dev GET The proposal end block */ function getSurveyEndBlock() external view returns (uint256); /** - * @dev GET the ROBE source location + * @dev GET the duration of the Proposal in number of blocks */ function getSurveyDuration() external view returns (uint256); @@ -144,32 +144,74 @@ interface IMVDFunctionalityProposal { */ function getVotes() external view returns (uint256, uint256); + /** + * @dev // DOCUMENT + */ function start() external; + /** + * @dev // DOCUMENT + */ function disable() external; + /** + * @dev // DOCUMENT + */ function isDisabled() external view returns (bool); + /** + * @dev // DOCUMENT + */ function isTerminated() external view returns (bool); + /** + * @dev // DOCUMENT + */ function accept(uint256 amount) external; + /** + * @dev // DOCUMENT + */ function retireAccept(uint256 amount) external; + /** + * @dev // DOCUMENT + */ function moveToAccept(uint256 amount) external; + /** + * @dev // DOCUMENT + */ function refuse(uint256 amount) external; + /** + * @dev // DOCUMENT + */ function retireRefuse(uint256 amount) external; + /** + * @dev // DOCUMENT + */ function moveToRefuse(uint256 amount) external; + /** + * @dev // DOCUMENT + */ function retireAll() external; + /** + * @dev // DOCUMENT + */ function withdraw() external; + /** + * @dev // DOCUMENT + */ function terminate() external; + /** + * @dev // DOCUMENT + */ function set() external; event Accept(address indexed voter, uint256 amount); diff --git a/contracts/IMVDFunctionalityProposalManager.sol b/contracts/IMVDFunctionalityProposalManager.sol index 1645b73..fcc1506 100644 --- a/contracts/IMVDFunctionalityProposalManager.sol +++ b/contracts/IMVDFunctionalityProposalManager.sol @@ -1,20 +1,44 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; interface IMVDFunctionalityProposalManager { + /** + * @dev Add a new Proposal + * @param codeName ID of the proposal + * @param location // DOCUMENT + * @param methodSignature // DOCUMENT + * @param returnAbiParametersArray // DOCUMENT + * @param replaces // DOCUMENT + * @return proposal Address of the newly added proposal + */ function newProposal( string calldata codeName, address location, string calldata methodSignature, string calldata returnAbiParametersArray, string calldata replaces - ) external returns (address); + ) external returns (address proposal); + // DOCUMENT function checkProposal(address proposalAddress) external; + /** + * @dev GET the Proxy contract address + */ function getProxy() external view returns (address); + /** + * @dev SET the Proxy contract address + */ function setProxy() external; - function isValidProposal(address proposal) external view returns (bool); + /** + * @dev Check that a proposal is valid + * @param proposal Address of the proposal to check + * @return isValid Boolean indicating the validity of the function + */ + function isValidProposal(address proposal) + external + view + returns (bool isValid); } diff --git a/contracts/IMVDProxy.sol b/contracts/IMVDProxy.sol index 46f6bc0..3e4b6e5 100644 --- a/contracts/IMVDProxy.sol +++ b/contracts/IMVDProxy.sol @@ -1,7 +1,21 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; +/** + * // DOCUMENT Add detailed explanation of what a proxy is + * @title Proxy Interface + */ interface IMVDProxy { + /** + * @dev Initialization logic used during the constructor call + * @param votingTokenAddress Address of the Voting Token + * @param functionalityProposalManagerAddress Address of the Functionality Proposal Manager + * @param stateHolderAddress Address of the State Holder contract + * @param functionalityModelsManagerAddress Address of the Functionality Models Manager + * @param functionalitiesManagerAddress Address of the Functionalities Manager + * @param walletAddress Address of the wallet + * @param doubleProxyAddress Address of the double proxy + */ function init( address votingTokenAddress, address functionalityProposalManagerAddress, @@ -14,27 +28,48 @@ interface IMVDProxy { function getDelegates() external view returns (address[] memory); + /** + * @dev GET the voting token contract address + */ function getToken() external view returns (address); + /** + * @dev GET the Functionality Proposal Manager contract address + */ function getMVDFunctionalityProposalManagerAddress() external view returns (address); + /** + * @dev GET the State Holder contract address + */ function getStateHolderAddress() external view returns (address); + /** + * @dev GET the Functionality Models Manager contract address + */ function getMVDFunctionalityModelsManagerAddress() external view returns (address); + /** + * @dev GET the Functionalities Manager contract address + */ function getMVDFunctionalitiesManagerAddress() external view returns (address); + /** + * @dev GET the Wallet contract address + */ function getMVDWalletAddress() external view returns (address); + /** + * @dev GET the Double Proxy contract address + */ function getDoubleProxyAddress() external view returns (address); function setDelegate(uint256 position, address newAddress) @@ -51,6 +86,7 @@ interface IMVDProxy { view returns (bool); + // DOCUMENT function newProposal( string calldata codeName, bool emergency, @@ -69,12 +105,26 @@ interface IMVDProxy { function disableProposal(address proposalAddress) external; + /** + * @dev Transfer a token to an address + * @param receiver Address of the receiver + * @param value Amount of token to transfer + * @param token Address of the token to transfer + */ function transfer( address receiver, uint256 value, address token ) external; + /** + * @dev Transfer an ERC721 to an address + * @param receiver Address of the receiver + * @param tokenId ID of the ERC721 to transfer + * @param data // DOCUMENTATION + * @param safe Boolean flag for triggering the SafeTransfer + * @param token Address of the token to transfer + */ function transfer721( address receiver, uint256 tokenId, @@ -83,28 +133,34 @@ interface IMVDProxy { address token ) external; + // DOCUMENT function flushToWallet( address tokenAddress, bool is721, uint256 tokenId ) external; + // DOCUMENT function setProposal() external; + // DOCUMENT function read(string calldata codeName, bytes calldata data) external view returns (bytes memory returnData); + // DOCUMENT function submit(string calldata codeName, bytes calldata data) external payable returns (bytes memory returnData); + // DOCUMENT function callFromManager(address location, bytes calldata payload) external returns (bool, bytes memory); + // DOCUMENT function emitFromManager( string calldata codeName, address proposal, @@ -119,6 +175,7 @@ interface IMVDProxy { address proposalAddress ) external; + // DOCUMENT function emitEvent( string calldata eventSignature, bytes calldata firstIndex, diff --git a/contracts/IMVDWallet.sol b/contracts/IMVDWallet.sol index d0deefe..3dd7457 100644 --- a/contracts/IMVDWallet.sol +++ b/contracts/IMVDWallet.sol @@ -1,18 +1,73 @@ -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; +/** + * @title Wallet + * @dev // DOCUMENTATION + */ interface IMVDWallet { - + /** + * @dev GET the proxy address + */ function getProxy() external view returns (address); + /** + * @dev SET the proxy address + */ function setProxy() external; - function setNewWallet(address payable newWallet, address tokenAddress) external; + /** + * @dev SET new wallet + * @param newWallet New wallet address + * @param tokenAddress // DOCUMENT + */ + function setNewWallet(address payable newWallet, address tokenAddress) + external; + + /** + * @dev Transfer a token to an address + * @param receiver Address of the receiver + * @param value Amount of token to transfer + * @param tokenAddress Address of the token to transfer + */ + function transfer( + address receiver, + uint256 value, + address tokenAddress + ) external; - function transfer(address receiver, uint256 value, address tokenAddress) external; - - function transfer(address receiver, uint256 tokenId, bytes calldata data, bool safe, address token) external; + /** + * @dev Transfer an ERC721 to an address + * @param receiver Address of the receiver + * @param tokenId ID of the ERC721 to transfer + * @param data // DOCUMENTATION + * @param safe Boolean flag for triggering the SafeTransfer + * @param token Address of the token to transfer + */ + function transfer( + address receiver, + uint256 tokenId, + bytes calldata data, + bool safe, + address token + ) external; + /** + * @dev Send all of the specified tokens to the NewWallet + * @param token Address of the token to send + */ function flushToNewWallet(address token) external; - function flush721ToNewWallet(uint256 tokenId, bytes calldata data, bool safe, address tokenAddress) external; -} \ No newline at end of file + /** + * @dev Transfer an ERC721 to the NewWallet + * @param tokenId ID of the ERC721 to transfer + * @param data // DOCUMENTATION + * @param safe Boolean flag for triggering the SafeTransfer + * @param tokenAddress Address of the token to transfer + */ + function flush721ToNewWallet( + uint256 tokenId, + bytes calldata data, + bool safe, + address tokenAddress + ) external; +} diff --git a/contracts/IStateHolder.sol b/contracts/IStateHolder.sol index 1b4cd7c..34e0ccd 100644 --- a/contracts/IStateHolder.sol +++ b/contracts/IStateHolder.sol @@ -1,25 +1,69 @@ -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; interface IStateHolder { - function init() external; function getProxy() external view returns (address); + function setProxy() external; - function toJSON() external view returns(string memory); - function toJSON(uint256 start, uint256 l) external view returns(string memory); + + function toJSON() external view returns (string memory); + + function toJSON(uint256 start, uint256 l) + external + view + returns (string memory); + function getStateSize() external view returns (uint256); - function exists(string calldata varName) external view returns(bool); - function getDataType(string calldata varName) external view returns(string memory dataType); - function clear(string calldata varName) external returns(string memory oldDataType, bytes memory oldVal); - function setBytes(string calldata varName, bytes calldata val) external returns(bytes memory); - function getBytes(string calldata varName) external view returns(bytes memory); - function setString(string calldata varName, string calldata val) external returns(string memory); - function getString(string calldata varName) external view returns (string memory); - function setBool(string calldata varName, bool val) external returns(bool); + + function exists(string calldata varName) external view returns (bool); + + function getDataType(string calldata varName) + external + view + returns (string memory dataType); + + function clear(string calldata varName) + external + returns (string memory oldDataType, bytes memory oldVal); + + function setBytes(string calldata varName, bytes calldata val) + external + returns (bytes memory); + + function getBytes(string calldata varName) + external + view + returns (bytes memory); + + function setString(string calldata varName, string calldata val) + external + returns (string memory); + + function getString(string calldata varName) + external + view + returns (string memory); + + function setBool(string calldata varName, bool val) external returns (bool); + function getBool(string calldata varName) external view returns (bool); - function getUint256(string calldata varName) external view returns (uint256); - function setUint256(string calldata varName, uint256 val) external returns(uint256); - function getAddress(string calldata varName) external view returns (address); - function setAddress(string calldata varName, address val) external returns (address); -} \ No newline at end of file + + function getUint256(string calldata varName) + external + view + returns (uint256); + + function setUint256(string calldata varName, uint256 val) + external + returns (uint256); + + function getAddress(string calldata varName) + external + view + returns (address); + + function setAddress(string calldata varName, address val) + external + returns (address); +} diff --git a/contracts/IVotingToken.sol b/contracts/IVotingToken.sol index 1e20a09..6dc85b4 100644 --- a/contracts/IVotingToken.sol +++ b/contracts/IVotingToken.sol @@ -1,18 +1,66 @@ -pragma solidity ^0.6.0; +// SPDX-License-Identifier: MIT +pragma solidity >=0.7.0; +/** + * @title Voting Token interface + */ interface IVotingToken { - function init(string calldata name, string calldata symbol, uint256 decimals, uint256 totalSupply) external; + /** + * @dev Initialization logic using during the constructor Call + * @param name Name of the token used + * @param symbol Ticker symbol of the token used + * @param decimals Amount of decimals supported by the token + * @param totalSupply Total Supply of the token + */ + function init( + string calldata name, + string calldata symbol, + uint256 decimals, + uint256 totalSupply + ) external; + /** + * @dev GET the Proxy + */ function getProxy() external view returns (address); + + /** + * @dev SET the Proxy + */ function setProxy() external; - function name() external view returns(string memory); - function symbol() external view returns(string memory); - function decimals() external view returns(uint256); + /** + * @dev GET the token name + */ + function name() external view returns (string memory); + + /** + * @dev GET the token ticker symbol + */ + function symbol() external view returns (string memory); + + /** + * @dev GET amount of decimals supported by the token + */ + function decimals() external view returns (uint256); + /** + * @dev Mint functionality of the voting token + */ function mint(uint256 amount) external; + + /** + * @dev Burn functionality of the voting token + */ function burn(uint256 amount) external; - function increaseAllowance(address spender, uint256 addedValue) external returns (bool); - function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); -} \ No newline at end of file + // DOCUMENTATION + function increaseAllowance(address spender, uint256 addedValue) + external + returns (bool); + + // DOCUMENTATION + function decreaseAllowance(address spender, uint256 subtractedValue) + external + returns (bool); +} diff --git a/contracts/MVDFunctionalitiesManager.sol b/contracts/MVDFunctionalitiesManager.sol index fa4af7a..288757a 100644 --- a/contracts/MVDFunctionalitiesManager.sol +++ b/contracts/MVDFunctionalitiesManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; import "./IMVDFunctionalitiesManager.sol"; import "./CommonUtilities.sol"; diff --git a/contracts/MVDFunctionalityModelsManager.sol b/contracts/MVDFunctionalityModelsManager.sol index 2659a44..0ee9616 100644 --- a/contracts/MVDFunctionalityModelsManager.sol +++ b/contracts/MVDFunctionalityModelsManager.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; import "./IMVDFunctionalityModelsManager.sol"; import "./Functionality.sol"; @@ -174,6 +174,7 @@ contract MVDFunctionalityModelsManager is IMVDFunctionalityModelsManager { _wellKnownFunctionalityModels[string(codeName)].codeName ); + Functionality memory wellKnownFunctionality = _wellKnownFunctionalityModels[string(codeName)]; diff --git a/contracts/MVDFunctionalityProposal.sol b/contracts/MVDFunctionalityProposal.sol index 8167544..9099e21 100644 --- a/contracts/MVDFunctionalityProposal.sol +++ b/contracts/MVDFunctionalityProposal.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; import "./IMVDFunctionalityProposal.sol"; import "./IMVDProxy.sol"; @@ -30,7 +30,7 @@ contract MVDFunctionalityProposal is IMVDFunctionalityProposal { mapping(address => uint256) private _refuse; uint256 private _totalAccept; uint256 private _totalRefuse; - mapping(address => bool) private _withdrawed; + mapping(address => bool) private _withdrawn; uint256 private _votesHardCap; bool private _votesHardCapReached; @@ -415,19 +415,16 @@ contract MVDFunctionalityProposal is IMVDFunctionalityProposal { !launchError || _accept[msg.sender] + _refuse[msg.sender] > 0, "Nothing to Withdraw!" ); - require( - !launchError || !_withdrawed[msg.sender], - "Already Withdrawed!" - ); + require(!launchError || !_withdrawn[msg.sender], "Already Withdrawed!"); if ( _accept[msg.sender] + _refuse[msg.sender] > 0 && - !_withdrawed[msg.sender] + !_withdrawn[msg.sender] ) { IERC20(_token).transfer( msg.sender, _accept[msg.sender] + _refuse[msg.sender] ); - _withdrawed[msg.sender] = true; + _withdrawn[msg.sender] = true; } } diff --git a/contracts/MVDFunctionalityProposalManager.sol b/contracts/MVDFunctionalityProposalManager.sol index 4a6abc9..1500039 100644 --- a/contracts/MVDFunctionalityProposalManager.sol +++ b/contracts/MVDFunctionalityProposalManager.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; import "./IMVDFunctionalityProposalManager.sol"; import "./IMVDProxy.sol"; @@ -6,40 +6,100 @@ import "./MVDFunctionalityProposal.sol"; import "./IMVDFunctionalitiesManager.sol"; contract MVDFunctionalityProposalManager is IMVDFunctionalityProposalManager { - address private _proxy; mapping(address => bool) private _proposals; modifier onlyProxy() { - require(msg.sender == address(_proxy), "Only Proxy can call this functionality"); + require( + msg.sender == address(_proxy), + "Only Proxy can call this functionality" + ); _; } - function newProposal(string memory codeName, address location, string memory methodSignature, string memory returnAbiParametersArray, string memory replaces) public override onlyProxy returns(address) { - return setProposal(codeName, location, methodSignature, replaces, address(new MVDFunctionalityProposal(codeName, location, methodSignature, returnAbiParametersArray, replaces, _proxy))); + function newProposal( + string memory codeName, + address location, + string memory methodSignature, + string memory returnAbiParametersArray, + string memory replaces + ) public override onlyProxy returns (address) { + return + setProposal( + codeName, + location, + methodSignature, + replaces, + address( + new MVDFunctionalityProposal( + codeName, + location, + methodSignature, + returnAbiParametersArray, + replaces, + _proxy + ) + ) + ); } - function preconditionCheck(string memory codeName, address location, string memory methodSignature, string memory replaces) private view { - + function preconditionCheck( + string memory codeName, + address location, + string memory methodSignature, + string memory replaces + ) private view { bool hasCodeName = !compareStrings(codeName, ""); bool hasReplaces = !compareStrings(replaces, ""); - require((hasCodeName || !hasCodeName && !hasReplaces) ? location != address(0) : true, "Cannot have zero address for functionality to set or one time functionality to call"); - - require(location == address(0) || !compareStrings(methodSignature, ""), "Cannot have empty string for methodSignature"); - - require(hasCodeName || hasReplaces ? true : compareStrings(methodSignature, "callOneTime(address)"), "One Time Functionality method signature allowed is callOneTime(address)"); - - IMVDFunctionalitiesManager functionalitiesManager = IMVDFunctionalitiesManager(IMVDProxy(_proxy).getMVDFunctionalitiesManagerAddress()); - - require(hasCodeName && functionalitiesManager.hasFunctionality(codeName) ? compareStrings(codeName, replaces) : true, "codeName is already used by another functionality"); - - require(hasReplaces ? functionalitiesManager.hasFunctionality(replaces) : true, "Cannot replace unexisting or inactive functionality"); + require( + (hasCodeName || (!hasCodeName && !hasReplaces)) + ? location != address(0) + : true, + "Cannot have zero address for functionality to set or one time functionality to call" + ); + + require( + location == address(0) || !compareStrings(methodSignature, ""), + "Cannot have empty string for methodSignature" + ); + + require( + hasCodeName || hasReplaces + ? true + : compareStrings(methodSignature, "callOneTime(address)"), + "One Time Functionality method signature allowed is callOneTime(address)" + ); + + + IMVDFunctionalitiesManager functionalitiesManager + = IMVDFunctionalitiesManager( + IMVDProxy(_proxy).getMVDFunctionalitiesManagerAddress() + ); + + require( + hasCodeName && functionalitiesManager.hasFunctionality(codeName) + ? compareStrings(codeName, replaces) + : true, + "codeName is already used by another functionality" + ); + + require( + hasReplaces + ? functionalitiesManager.hasFunctionality(replaces) + : true, + "Cannot replace unexisting or inactive functionality" + ); } - function setProposal(string memory codeName, address location, string memory methodSignature, string memory replaces, address proposalAddress) private returns(address) { - + function setProposal( + string memory codeName, + address location, + string memory methodSignature, + string memory replaces, + address proposalAddress + ) private returns (address) { preconditionCheck(codeName, location, methodSignature, replaces); _proposals[proposalAddress] = true; @@ -50,7 +110,9 @@ contract MVDFunctionalityProposalManager is IMVDFunctionalityProposalManager { function checkProposal(address proposalAddress) public override onlyProxy { require(_proposals[proposalAddress], "Unauthorized Access!"); - IMVDFunctionalityProposal proposal = IMVDFunctionalityProposal(proposalAddress); + IMVDFunctionalityProposal proposal = IMVDFunctionalityProposal( + proposalAddress + ); uint256 surveyEndBlock = proposal.getSurveyEndBlock(); @@ -58,14 +120,19 @@ contract MVDFunctionalityProposalManager is IMVDFunctionalityProposalManager { require(!proposal.isDisabled(), "Proposal is disabled!"); - if(!proposal.isVotesHardCapReached()) { + if (!proposal.isVotesHardCapReached()) { require(block.number >= surveyEndBlock, "Survey is still running!"); } require(!proposal.isTerminated(), "Survey already terminated!"); } - function isValidProposal(address proposal) public override view returns (bool) { + function isValidProposal(address proposal) + public + override + view + returns (bool) + { return _proposals[proposal]; } @@ -74,11 +141,20 @@ contract MVDFunctionalityProposalManager is IMVDFunctionalityProposalManager { } function setProxy() public override { - require(_proxy == address(0) || _proxy == msg.sender, _proxy != address(0) ? "Proxy already set!" : "Only Proxy can toggle itself!"); - _proxy = _proxy == address(0) ? msg.sender : address(0); + require( + _proxy == address(0) || _proxy == msg.sender, + _proxy != address(0) + ? "Proxy already set!" + : "Only Proxy can toggle itself!" + ); + _proxy = _proxy == address(0) ? msg.sender : address(0); } - function compareStrings(string memory a, string memory b) private pure returns(bool) { + function compareStrings(string memory a, string memory b) + private + pure + returns (bool) + { return keccak256(bytes(a)) == keccak256(bytes(b)); } -} \ No newline at end of file +} diff --git a/contracts/MVDProxy.sol b/contracts/MVDProxy.sol index 7c9e7b9..574d159 100644 --- a/contracts/MVDProxy.sol +++ b/contracts/MVDProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; import "./IMVDProxy.sol"; import "./IMVDFunctionalityProposalManager.sol"; diff --git a/contracts/MVDWallet.sol b/contracts/MVDWallet.sol index b87a258..0490ea8 100644 --- a/contracts/MVDWallet.sol +++ b/contracts/MVDWallet.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; import "./IMVDWallet.sol"; import "./IMVDProxy.sol"; @@ -7,11 +7,13 @@ import "./IERC721.sol"; import "./IERC721Receiver.sol"; contract MVDWallet is IMVDWallet, IERC721Receiver { - address private _proxy; address payable private _newWallet; - function setNewWallet(address payable newWallet, address tokenAddress) public override { + function setNewWallet(address payable newWallet, address tokenAddress) + public + override + { require(msg.sender == _proxy, "Unauthorized Access!"); _newWallet = newWallet; _newWallet.transfer(address(this).balance); @@ -21,7 +23,7 @@ contract MVDWallet is IMVDWallet, IERC721Receiver { function flushToNewWallet(address tokenAddress) public override { require(_newWallet != address(0), "Unauthorized Access!"); - if(tokenAddress == address(0)) { + if (tokenAddress == address(0)) { payable(_newWallet).transfer(address(this).balance); return; } @@ -29,55 +31,91 @@ contract MVDWallet is IMVDWallet, IERC721Receiver { token.transfer(_newWallet, token.balanceOf(address(this))); } - function flush721ToNewWallet(uint256 tokenId, bytes memory data, bool safe, address tokenAddress) public override { + function flush721ToNewWallet( + uint256 tokenId, + bytes memory data, + bool safe, + address tokenAddress + ) public override { require(_newWallet != address(0), "Unauthorized Access!"); _transfer(_newWallet, tokenId, data, safe, tokenAddress); } - function transfer(address receiver, uint256 value, address token) public override { + function transfer( + address receiver, + uint256 value, + address token + ) public override { require(msg.sender == _proxy, "Unauthorized Access!"); - if(value == 0) { + if (value == 0) { return; } - if(token == address(0)) { + if (token == address(0)) { payable(receiver).transfer(value); return; } IERC20(token).transfer(receiver, value); } - function transfer(address receiver, uint256 tokenId, bytes memory data, bool safe, address token) public override { + function transfer( + address receiver, + uint256 tokenId, + bytes memory data, + bool safe, + address token + ) public override { require(msg.sender == _proxy, "Unauthorized Access!"); _transfer(receiver, tokenId, data, safe, token); } - function _transfer(address receiver, uint256 tokenId, bytes memory data, bool safe, address token) private { - if(safe) { - IERC721(token).safeTransferFrom(address(this), receiver, tokenId, data); + function _transfer( + address receiver, + uint256 tokenId, + bytes memory data, + bool safe, + address token + ) private { + if (safe) { + IERC721(token).safeTransferFrom( + address(this), + receiver, + tokenId, + data + ); } else { IERC721(token).transferFrom(address(this), receiver, tokenId); } } receive() external payable { - if(_newWallet != address(0)) { + if (_newWallet != address(0)) { _newWallet.transfer(address(this).balance); } } - function getProxy() public override view returns(address) { + function getProxy() public override view returns (address) { return _proxy; } function setProxy() public override { - require(_proxy == address(0) || _proxy == msg.sender, _proxy != address(0) ? "Proxy already set!" : "Only Proxy can toggle itself!"); - _proxy = _proxy == address(0) ? msg.sender : address(0); + require( + _proxy == address(0) || _proxy == msg.sender, + _proxy != address(0) + ? "Proxy already set!" + : "Only Proxy can toggle itself!" + ); + _proxy = _proxy == address(0) ? msg.sender : address(0); } - function onERC721Received(address, address, uint256 tokenId, bytes memory data) public override returns (bytes4) { - if(_newWallet != address(0)) { + function onERC721Received( + address, + address, + uint256 tokenId, + bytes memory data + ) public override returns (bytes4) { + if (_newWallet != address(0)) { _transfer(_newWallet, tokenId, data, true, msg.sender); } return 0x150b7a02; } -} \ No newline at end of file +} diff --git a/contracts/StateHolder.sol b/contracts/StateHolder.sol index 183a7f5..c5e4b50 100644 --- a/contracts/StateHolder.sol +++ b/contracts/StateHolder.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; import "./IMVDProxy.sol"; import "./CommonUtilities.sol"; @@ -6,14 +6,7 @@ import "./IStateHolder.sol"; import "./IMVDFunctionalitiesManager.sol"; contract StateHolder is IStateHolder, CommonUtilities { - - enum DataType { - ADDRESS, - BOOL, - BYTES, - STRING, - UINT256 - } + enum DataType {ADDRESS, BOOL, BYTES, STRING, UINT256} struct Var { string name; @@ -39,53 +32,85 @@ contract StateHolder is IStateHolder, CommonUtilities { modifier canSet { require(_state.length > 0, "Not Initialized!"); - if(_proxy != address(0)) { - require(IMVDFunctionalitiesManager(IMVDProxy(_proxy).getMVDFunctionalitiesManagerAddress()).isAuthorizedFunctionality(msg.sender), "UnauthorizedAccess"); + if (_proxy != address(0)) { + require( + IMVDFunctionalitiesManager( + IMVDProxy(_proxy).getMVDFunctionalitiesManagerAddress() + ) + .isAuthorizedFunctionality(msg.sender), + "UnauthorizedAccess" + ); } _; } - function toJSON() public override view returns(string memory) { + function toJSON() public override view returns (string memory) { return toJSON(0, _state.length - 1); } - function toJSON(uint256 start, uint256 l) public override view returns(string memory json) { + function toJSON(uint256 start, uint256 l) + public + override + view + returns (string memory json) + { uint256 length = start + 1 + l; json = "["; - for(uint256 i = start; i < length; i++) { - json = !_state[i].active ? json : string(abi.encodePacked(json, '{"name":"', _state[i].name, '","type":"', toString(_state[i].dataType), '"}', i == length - (_state[i].active ? 1 : 0) ? "" : ",")); + for (uint256 i = start; i < length; i++) { + json = !_state[i].active + ? json + : string( + abi.encodePacked( + json, + '{"name":"', + _state[i].name, + '","type":"', + toString(_state[i].dataType), + '"}', + i == length - (_state[i].active ? 1 : 0) ? "" : "," + ) + ); length += _state[i].active ? 0 : 1; length = length > _state.length ? _state.length : length; } - json = string(abi.encodePacked(json, ']')); + json = string(abi.encodePacked(json, "]")); } function getStateSize() public override view returns (uint256) { return _stateSize; } - function exists(string memory varName) public override view returns(bool) { + function exists(string memory varName) public override view returns (bool) { return _state[_index[varName]].active; } - function getDataType(string memory varName) public override view returns(string memory dataType) { + function getDataType(string memory varName) + public + override + view + returns (string memory dataType) + { Var memory v = _state[_index[varName]]; - if(v.active) { + if (v.active) { dataType = toString(v.dataType); } } - function setVal(string memory varName, DataType dataType, bytes memory val) private canSet returns(bytes memory oldVal) { - if(compareStrings(varName, "")) { + function setVal( + string memory varName, + DataType dataType, + bytes memory val + ) private canSet returns (bytes memory oldVal) { + if (compareStrings(varName, "")) { return ""; } Var memory v = _state[_index[varName]]; oldVal = v.value; v.name = varName; v.value = val; - if(v.position == 0) { - for(uint256 i = 1; i < _state.length; i++) { - if(!_state[i].active) { + if (v.position == 0) { + for (uint256 i = 1; i < _state.length; i++) { + if (!_state[i].active) { v.position = i; break; } @@ -94,11 +119,11 @@ contract StateHolder is IStateHolder, CommonUtilities { require(!v.active || v.dataType == dataType, "Invalid dataType"); } v.dataType = dataType; - if(!v.active) { + if (!v.active) { _stateSize++; } v.active = true; - if(v.position == 0) { + if (v.position == 0) { v.position = _state.length; _state.push(v); } else { @@ -107,9 +132,14 @@ contract StateHolder is IStateHolder, CommonUtilities { _index[varName] = v.position; } - function clear(string memory varName) public canSet override returns(string memory oldDataType, bytes memory oldVal) { + function clear(string memory varName) + public + override + canSet + returns (string memory oldDataType, bytes memory oldVal) + { Var storage v = _state[_index[varName]]; - if(v.position > 0 && v.active) { + if (v.position > 0 && v.active) { oldDataType = toString(v.dataType); oldVal = v.value; v.value = ""; @@ -120,44 +150,93 @@ contract StateHolder is IStateHolder, CommonUtilities { } } - function setBytes(string memory varName, bytes memory val) public override returns(bytes memory) { + function setBytes(string memory varName, bytes memory val) + public + override + returns (bytes memory) + { return setVal(varName, DataType.BYTES, val); } - function getBytes(string memory varName) public override view returns(bytes memory) { + function getBytes(string memory varName) + public + override + view + returns (bytes memory) + { return _state[_index[varName]].value; } - function setString(string memory varName, string memory val) public override returns(string memory) { + function setString(string memory varName, string memory val) + public + override + returns (string memory) + { return string(setVal(varName, DataType.STRING, bytes(val))); } - function getString(string memory varName) public override view returns (string memory) { + function getString(string memory varName) + public + override + view + returns (string memory) + { return string(_state[_index[varName]].value); } - function setBool(string memory varName, bool val) public override returns(bool) { - return toUint256(setVal(varName, DataType.BOOL, abi.encode(val ? 1 : 0))) == 1; + function setBool(string memory varName, bool val) + public + override + returns (bool) + { + return + toUint256( + setVal(varName, DataType.BOOL, abi.encode(val ? 1 : 0)) + ) == 1; } - function getBool(string memory varName) public override view returns (bool) { + function getBool(string memory varName) + public + override + view + returns (bool) + { return toUint256(_state[_index[varName]].value) == 1; } - function getUint256(string memory varName) public override view returns (uint256) { + function getUint256(string memory varName) + public + override + view + returns (uint256) + { return toUint256(_state[_index[varName]].value); } - function setUint256(string memory varName, uint256 val) public override returns(uint256) { + function setUint256(string memory varName, uint256 val) + public + override + returns (uint256) + { return toUint256(setVal(varName, DataType.UINT256, abi.encode(val))); } - function getAddress(string memory varName) public override view returns (address) { + function getAddress(string memory varName) + public + override + view + returns (address) + { return toAddress(_state[_index[varName]].value); } - function setAddress(string memory varName, address val) public override returns (address) { - return toAddress(setVal(varName, DataType.ADDRESS, abi.encodePacked(val))); + function setAddress(string memory varName, address val) + public + override + returns (address) + { + return + toAddress(setVal(varName, DataType.ADDRESS, abi.encodePacked(val))); } function getProxy() public override view returns (address) { @@ -166,26 +245,42 @@ contract StateHolder is IStateHolder, CommonUtilities { function setProxy() public override { require(_state.length != 0, "Init not called!"); - require(_proxy == address(0) || _proxy == msg.sender, _proxy != address(0) ? "Proxy already set!" : "Only Proxy can toggle itself!"); - _proxy = _proxy == address(0) ? msg.sender : address(0); + require( + _proxy == address(0) || _proxy == msg.sender, + _proxy != address(0) + ? "Proxy already set!" + : "Only Proxy can toggle itself!" + ); + _proxy = _proxy == address(0) ? msg.sender : address(0); } function toString(DataType dataType) private pure returns (string memory) { return - dataType == DataType.ADDRESS ? "address" : - dataType == DataType.BOOL ? "bool" : - dataType == DataType.BYTES ? "bytes" : - dataType == DataType.STRING ? "string" : - dataType == DataType.UINT256 ? "uint256" : - ""; + dataType == DataType.ADDRESS ? "address" : dataType == DataType.BOOL + ? "bool" + : dataType == DataType.BYTES + ? "bytes" + : dataType == DataType.STRING + ? "string" + : dataType == DataType.UINT256 + ? "uint256" + : ""; } - function toDataType(string memory dataType) private pure returns (DataType) { + function toDataType(string memory dataType) + private + pure + returns (DataType) + { return - compareStrings(dataType, "address") ? DataType.ADDRESS : - compareStrings(dataType, "bool") ? DataType.BOOL : - compareStrings(dataType, "string") ? DataType.STRING : - compareStrings(dataType, "uint256") ? DataType.UINT256 : - DataType.BYTES; + compareStrings(dataType, "address") + ? DataType.ADDRESS + : compareStrings(dataType, "bool") + ? DataType.BOOL + : compareStrings(dataType, "string") + ? DataType.STRING + : compareStrings(dataType, "uint256") + ? DataType.UINT256 + : DataType.BYTES; } -} \ No newline at end of file +} diff --git a/contracts/VotingToken.sol b/contracts/VotingToken.sol index 7da22d4..3c1a228 100644 --- a/contracts/VotingToken.sol +++ b/contracts/VotingToken.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.6.0; +pragma solidity >=0.7.0; import "./IMVDProxy.sol"; import "./IERC20.sol"; @@ -7,10 +7,9 @@ import "./IMVDFunctionalityProposalManager.sol"; import "./IMVDFunctionalitiesManager.sol"; contract VotingToken is IERC20, IVotingToken { + mapping(address => uint256) private _balances; - mapping (address => uint256) private _balances; - - mapping (address => mapping (address => uint256)) private _allowances; + mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; uint256 private _decimals; @@ -18,20 +17,30 @@ contract VotingToken is IERC20, IVotingToken { string private _name; string private _symbol; - constructor(string memory name, string memory symbol, uint256 decimals, uint256 totalSupply) public { - if(totalSupply == 0) { + constructor( + string memory name, + string memory symbol, + uint256 decimals, + uint256 totalSupply + ) public { + if (totalSupply == 0) { return; } init(name, symbol, decimals, totalSupply); } - function init(string memory name, string memory symbol, uint256 decimals, uint256 totalSupply) public override { + function init( + string memory name, + string memory symbol, + uint256 decimals, + uint256 totalSupply + ) public override { require(_totalSupply == 0, "Init already called!"); _name = name; _symbol = symbol; _decimals = decimals; - _totalSupply = totalSupply * (10 ** decimals); + _totalSupply = totalSupply * (10**decimals); _balances[msg.sender] = _totalSupply; emit Transfer(address(this), msg.sender, _totalSupply); } @@ -40,19 +49,19 @@ contract VotingToken is IERC20, IVotingToken { revert("ETH not accepted"); } - function getProxy() public override view returns(address) { + function getProxy() public override view returns (address) { return _proxy; } - function name() public override view returns(string memory) { + function name() public override view returns (string memory) { return _name; } - function symbol() public override view returns(string memory) { + function symbol() public override view returns (string memory) { return _symbol; } - function decimals() public override view returns(uint256) { + function decimals() public override view returns (uint256) { return _decimals; } @@ -64,49 +73,112 @@ contract VotingToken is IERC20, IVotingToken { return _balances[account]; } - function transfer(address recipient, uint256 amount) public override returns (bool) { + function transfer(address recipient, uint256 amount) + public + override + returns (bool) + { _transfer(msg.sender, recipient, amount); return true; } - function allowance(address owner, address spender) public override view returns (uint256) { + function allowance(address owner, address spender) + public + override + view + returns (uint256) + { return _allowances[owner][spender]; } - function approve(address spender, uint256 amount) public override returns (bool) { + function approve(address spender, uint256 amount) + public + override + returns (bool) + { _approve(msg.sender, spender, amount); return true; } - function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) { + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public override returns (bool) { _transfer(sender, recipient, amount); address txSender = msg.sender; - if(_proxy == address(0) || !(IMVDFunctionalityProposalManager(IMVDProxy(_proxy).getMVDFunctionalityProposalManagerAddress()).isValidProposal(txSender) && recipient == txSender)) { - _approve(sender, txSender, _allowances[sender][txSender] = sub(_allowances[sender][txSender], amount, "ERC20: transfer amount exceeds allowance")); + if ( + _proxy == address(0) || + !(IMVDFunctionalityProposalManager( + IMVDProxy(_proxy).getMVDFunctionalityProposalManagerAddress() + ) + .isValidProposal(txSender) && recipient == txSender) + ) { + _approve( + sender, + txSender, + _allowances[sender][txSender] = sub( + _allowances[sender][txSender], + amount, + "ERC20: transfer amount exceeds allowance" + ) + ); } return true; } - function increaseAllowance(address spender, uint256 addedValue) public override returns (bool) { - _approve(msg.sender, spender, add(_allowances[msg.sender][spender], addedValue)); + function increaseAllowance(address spender, uint256 addedValue) + public + override + returns (bool) + { + _approve( + msg.sender, + spender, + add(_allowances[msg.sender][spender], addedValue) + ); return true; } - function decreaseAllowance(address spender, uint256 subtractedValue) public override returns (bool) { - _approve(msg.sender, spender, sub(_allowances[msg.sender][spender], subtractedValue, "ERC20: decreased allowance below zero")); + function decreaseAllowance(address spender, uint256 subtractedValue) + public + override + returns (bool) + { + _approve( + msg.sender, + spender, + sub( + _allowances[msg.sender][spender], + subtractedValue, + "ERC20: decreased allowance below zero" + ) + ); return true; } - function _transfer(address sender, address recipient, uint256 amount) internal { + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); - _balances[sender] = sub(_balances[sender], amount, "ERC20: transfer amount exceeds balance"); + _balances[sender] = sub( + _balances[sender], + amount, + "ERC20: transfer amount exceeds balance" + ); _balances[recipient] = add(_balances[recipient], amount); emit Transfer(sender, recipient, amount); } - function _approve(address owner, address spender, uint256 amount) internal { + function _approve( + address owner, + address spender, + uint256 amount + ) internal { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); @@ -119,19 +191,34 @@ contract VotingToken is IERC20, IVotingToken { require(c >= a, "SafeMath: addition overflow"); } - function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256 c) { + function sub( + uint256 a, + uint256 b, + string memory errorMessage + ) internal pure returns (uint256 c) { require(b <= a, errorMessage); c = a - b; } function setProxy() public override { require(_totalSupply != 0, "Init not called!"); - require(_proxy == address(0) || _proxy == msg.sender, _proxy != address(0) ? "Proxy already set!" : "Only Proxy can toggle itself!"); - _proxy = _proxy == address(0) ? msg.sender : address(0); + require( + _proxy == address(0) || _proxy == msg.sender, + _proxy != address(0) + ? "Proxy already set!" + : "Only Proxy can toggle itself!" + ); + _proxy = _proxy == address(0) ? msg.sender : address(0); } function mint(uint256 amount) public override { - require(IMVDFunctionalitiesManager(IMVDProxy(_proxy).getMVDFunctionalitiesManagerAddress()).isAuthorizedFunctionality(msg.sender), "Unauthorized access!"); + require( + IMVDFunctionalitiesManager( + IMVDProxy(_proxy).getMVDFunctionalitiesManagerAddress() + ) + .isAuthorizedFunctionality(msg.sender), + "Unauthorized access!" + ); _totalSupply = add(_totalSupply, amount); _balances[_proxy] = add(_balances[_proxy], amount); @@ -139,8 +226,16 @@ contract VotingToken is IERC20, IVotingToken { } function burn(uint256 amount) public override { - _balances[msg.sender] = sub(_balances[msg.sender], amount, "VotingToken: burn amount exceeds balance"); - _totalSupply = sub(_totalSupply, amount, "VotingToken: burn amount exceeds total supply"); + _balances[msg.sender] = sub( + _balances[msg.sender], + amount, + "VotingToken: burn amount exceeds balance" + ); + _totalSupply = sub( + _totalSupply, + amount, + "VotingToken: burn amount exceeds total supply" + ); emit Transfer(msg.sender, address(0), amount); } -} \ No newline at end of file +} From d727c27f3aa34f8d12cba2474b810a5c48a7a086 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Sat, 19 Sep 2020 16:13:00 +0200 Subject: [PATCH 05/12] Prepare for docs generation --- .gitignore | 270 ++++++++++++++++++- .prettierrc | 15 ++ CONTRIBUTING.md | 67 +++++ contracts/IMVDFunctionalitiesManager.sol | 2 +- contracts/IMVDFunctionalityModelsManager.sol | 2 +- docs/mkdocs.yml | 26 ++ docs/requirements.in | 1 + docs/requirements.txt | 21 ++ package.json | 21 ++ 9 files changed, 422 insertions(+), 3 deletions(-) create mode 100644 .prettierrc create mode 100644 CONTRIBUTING.md create mode 100644 docs/mkdocs.yml create mode 100644 docs/requirements.in create mode 100644 docs/requirements.txt create mode 100644 package.json diff --git a/.gitignore b/.gitignore index c5e82d7..da336f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,269 @@ -bin \ No newline at end of file +/**/.vscode +/**/spa/**/style.css + +docs/md-build +docs/tmp + +# Created by https://www.toptal.com/developers/gitignore/api/python,solidity,visualstudiocode,react +# Edit at https://www.toptal.com/developers/gitignore?templates=python,solidity,visualstudiocode,react + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +pytestdebug.log + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ +doc/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +### react ### +.DS_* +logs +**/*.backup.* +**/*.back.* + +node_modules +bower_components + +*.sublime* + +psd +thumb +sketch + +### Solidity ### +# Logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env.test + +# parcel-bundler cache (https://parceljs.org/) + +# Next.js build output +.next + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +# End of https://www.toptal.com/developers/gitignore/api/python,solidity,visualstudiocode,react diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..2bf0ebc --- /dev/null +++ b/.prettierrc @@ -0,0 +1,15 @@ +{ + "overrides": [ + { + "files": "*.sol", + "options": { + "printWidth": 100, + "tabWidth": 4, + "useTabs": false, + "singleQuote": false, + "bracketSpacing": false, + "explicitTypes": "always" + } + } + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..d2292da --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,67 @@ +# Contributing guidelines + +## Table of Contents + +- [Table of Contents](#table-of-contents) +- [Coding Style](#coding-style) + - [Solidity](#solidity) + - [JavaScript](#javascript) + - [Python](#python) +- [Documentation](#documentation) + - [mkdocs](#mkdocs) + +## Coding Style + +### Solidity + +* Solidity portions of the codebase adhere follow the official [Solidity Styleguide] + +### JavaScript + +### Python + +* Python portions of the codebase follow standard PEP8 best practices. +* Python code must be formatted using the Black formatter using the provided settings. + +## Documentation + +New addition to the codebase must be fully documented. + +- JavaScript portions of the code should be annotated using JSDoc style docstrings. +- Solidity portions of the code should be fully annotated using [NatSpec]. + +Documentation is generated using [py-solidity-docgen] and rendered via [mkdocs]. +[py-solidity-docgen] parses NatSpec and outputs `.md` files inside `docs/md-build` according +to a pre-specified Jinja2 template. + +**NOTE:** Each `.sol` file should contain only one `Interface` or `Contract`. + +To build the documentation: + +```console +yarn docs:build +``` + +To serve the documentation + +```console +yarn docs:serve +``` + +### mkdocs + +To install [mkdocs] and [py-solidity-docgen] Python must be installed in the system. + +``` +pip install docs/requirements.in +``` + +**NOTE:** Working inside a virtual environment is highly recommended! + +--- + +[Solidity Styleguide]: https://solidity.readthedocs.io/en/v0.7.0/style-guide.html +[NatSpec]: https://solidity.readthedocs.io/en/v0.7.0/style-guide.html#natspec +[Write the Docs!]: docs/source/write_the_docs.rst +[py-solidity-docgen]: https://github.com/b-u-i-d-l/py-solidity-docgen +[mkdocs]: https://www.mkdocs.org/ diff --git a/contracts/IMVDFunctionalitiesManager.sol b/contracts/IMVDFunctionalitiesManager.sol index 3f4a9df..c18e8c3 100644 --- a/contracts/IMVDFunctionalitiesManager.sol +++ b/contracts/IMVDFunctionalitiesManager.sol @@ -45,7 +45,7 @@ interface IMVDFunctionalitiesManager { /** * @dev Add a functionality to the Functionalities Manager - * @param codeNameID of the Functionality + * @param codeName ID of the Functionality * @param sourceLocation ROBE location of the source code * @param sourceLocationId ROBE id * @param location diff --git a/contracts/IMVDFunctionalityModelsManager.sol b/contracts/IMVDFunctionalityModelsManager.sol index c6e3070..301d74a 100644 --- a/contracts/IMVDFunctionalityModelsManager.sol +++ b/contracts/IMVDFunctionalityModelsManager.sol @@ -11,7 +11,7 @@ interface IMVDFunctionalityModelsManager { /** * @dev Check Well Known Functionalities. If the check fails it will raise its own errors. - * @param codeNameID of the Functionality + * @param codeName ID of the Functionality * @param location * @param submittable * @param methodSignature diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml new file mode 100644 index 0000000..0c63ea9 --- /dev/null +++ b/docs/mkdocs.yml @@ -0,0 +1,26 @@ +site_name: DFO Protocol +docs_dir: md-build +site_dir: build +permalink: True +nav: + - Home: README.md + - Contributing: CONTRIBUTING.md + - API: + - Contracts: + - ICommonUtilities: contracts/ICommonUtilities.md + - IDounleProxy: contracts/IDoubleProxy.md + - IMVDFunctionalitiesManager: contracts/IMVDFunctionalitiesManager.md + - IMVDFunctionalityModelsManager: contracts/IMVDFunctionalityModelsManager.md + - IMVDFunctionalityProposal: contracts/IMVDFunctionalityProposal.md + - IMVDFunctionalityProposalManager: contracts/IMVDFunctionalityProposalManager.md + - IMVDProxy: contracts/IMVDProxy.md + - IMVDWallet: contracts/IMVDWallet.md + - IStateHolder: contracts/IStateHolder.md + - IVotingToken: contracts/IVotingToken.md +theme: + name: readthedocs + highlightjs: true + hljs_languages: + - yaml + - typescript + - javascript diff --git a/docs/requirements.in b/docs/requirements.in new file mode 100644 index 0000000..016bb16 --- /dev/null +++ b/docs/requirements.in @@ -0,0 +1 @@ +mkdocs diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..d9819f7 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,21 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile requirements.in +# +click==7.1.2 # via mkdocs, nltk +future==0.18.2 # via lunr +jinja2==2.11.2 # via mkdocs +joblib==0.16.0 # via nltk +livereload==2.6.3 # via mkdocs +lunr[languages]==0.5.8 # via mkdocs +markdown==3.2.2 # via mkdocs +markupsafe==1.1.1 # via jinja2 +mkdocs==1.1.2 # via -r requirements.in +nltk==3.5 # via lunr +pyyaml==5.3.1 # via mkdocs +regex==2020.7.14 # via nltk +six==1.15.0 # via livereload, lunr +tornado==6.0.4 # via livereload, mkdocs +tqdm==4.48.2 # via nltk diff --git a/package.json b/package.json new file mode 100644 index 0000000..54eb70d --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "dfo-hub-protocol", + "version": "0.5.0", + "main": "index.html", + "repository": "git@github.com:b-u-i-d-l/unifi.git", + "author": "BUIDL ", + "license": "MIT", + "devDependencies": { + "prettier": "^2.1.0", + "prettier-plugin-solidity": "^1.0.0-alpha.56" + }, + "scripts": { + "docs": "yarn docs:docgen && yarn docs:mkdocs:serve", + "docs:build": "yarn docs:docgen && yarn docs:mkdocs:build", + "docs:clean": "rm -r docs/{md-build,build}", + "docs:serve": "yarn docs:docgen && yarn docs:mkdocs:serve", + "docs:docgen": "py-solidity-docgen --input contracts --output docs/md-build && cp *.md docs/md-build", + "docs:mkdocs:build": "cd docs && mkdocs build", + "docs:mkdocs:serve": "yarn docs:docgen && cd docs && mkdocs serve" + } +} From 0a2e5627b5f9fe4a7c23ee79279fc2d711880f9d Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Sat, 19 Sep 2020 16:58:57 +0200 Subject: [PATCH 06/12] Update NatSpec --- contracts/IMVDFunctionalitiesManager.sol | 54 ++++++++---------- contracts/IMVDFunctionalityModelsManager.sol | 15 ++--- contracts/IMVDFunctionalityProposal.sol | 55 +++++++++++-------- .../IMVDFunctionalityProposalManager.sol | 11 ++-- contracts/IMVDProxy.sol | 48 ++++++++-------- contracts/IVotingToken.sol | 8 +-- 6 files changed, 92 insertions(+), 99 deletions(-) diff --git a/contracts/IMVDFunctionalitiesManager.sol b/contracts/IMVDFunctionalitiesManager.sol index c18e8c3..a856546 100644 --- a/contracts/IMVDFunctionalitiesManager.sol +++ b/contracts/IMVDFunctionalitiesManager.sol @@ -48,12 +48,14 @@ interface IMVDFunctionalitiesManager { * @param codeName ID of the Functionality * @param sourceLocation ROBE location of the source code * @param sourceLocationId ROBE id - * @param location - * @param submittable - * @param methodSignature - * @param returnAbiParametersArray - * @param isInternal - * @param needsSender + * @param location Address of the functionality/microservice to call + * @param submittable Boolean flag controlling wether the microservice writes data to the chain + * @param methodSignature Name of the method of the microservice you want to call + * @param returnAbiParametersArray Array of return values obtained from the called microservice's method + * @param isInternal Boolean flag controlling wether the microservice can be called from anyone (false) or + * can be called only by other microservices (true) + * @param needsSender All microservices calls are made py the Proxy, with this boolean flag you can + * forward the address that called the Proxy in the first place */ function addFunctionality( string calldata codeName, @@ -72,12 +74,14 @@ interface IMVDFunctionalitiesManager { * @param codeName ID of the Functionality * @param sourceLocation ROBE location of the source code * @param sourceLocationId ROBE id - * @param location - * @param submittable - * @param methodSignature - * @param returnAbiParametersArray - * @param isInternal - * @param needsSender + * @param location Address of the functionality/microservice to call + * @param submittable Boolean flag controlling wether the microservice writes data to the chain + * @param methodSignature Name of the method of the microservice you want to call + * @param returnAbiParametersArray Array of return values obtained from the called microservice's method + * @param isInternal Boolean flag controlling wether the microservice can be called from anyone (false) or + * can be called only by other microservices (true) + * @param needsSender All microservices calls are made py the Proxy, with this boolean flag you can + * forward the address that called the Proxy in the first place * @param position Position of the Functionality to replace */ function addFunctionality( @@ -108,20 +112,14 @@ interface IMVDFunctionalitiesManager { * @param functionality Functionality to be checked * @return valid Boolean flag indicating the validity of the Functionality */ - function isValidFunctionality(address functionality) - external - view - returns (bool valid); + function isValidFunctionality(address functionality) external view returns (bool valid); /** * @dev Check that the Functionality is an authorized one * @param functionality Functionality to be checked - * @return valid Boolean flag indicating the authorization status of the Functionality + * @return success Boolean flag indicating the authorization status of the Functionality */ - function isAuthorizedFunctionality(address functionality) - external - view - returns (bool success); + function isAuthorizedFunctionality(address functionality) external view returns (bool success); // DOCUMENT function setCallingContext(address location) external returns (bool); @@ -146,10 +144,7 @@ interface IMVDFunctionalitiesManager { * @param codeName ID of the Functionality to be checked * @return output Boolean flag indicating wether the Functionalities Manager has the given Functionality. */ - function hasFunctionality(string calldata codeName) - external - view - returns (bool output); + function hasFunctionality(string calldata codeName) external view returns (bool output); /** * @dev GET the amount of functionalities present in the Functionalities Manager @@ -181,10 +176,7 @@ interface IMVDFunctionalitiesManager { /** * @dev Given a Functionality ID return its JSON encoded version */ - function functionalityToJSON(string calldata codeName) - external - view - returns (string memory); + function functionalityToJSON(string calldata codeName) external view returns (string memory); // DOCUMENT function preConditionCheck( @@ -196,7 +188,5 @@ interface IMVDFunctionalitiesManager { ) external view returns (address location, bytes memory payload); // DOCUMENT - function setupFunctionality(address proposalAddress) - external - returns (bool); + function setupFunctionality(address proposalAddress) external returns (bool); } diff --git a/contracts/IMVDFunctionalityModelsManager.sol b/contracts/IMVDFunctionalityModelsManager.sol index 301d74a..617e324 100644 --- a/contracts/IMVDFunctionalityModelsManager.sol +++ b/contracts/IMVDFunctionalityModelsManager.sol @@ -12,13 +12,14 @@ interface IMVDFunctionalityModelsManager { /** * @dev Check Well Known Functionalities. If the check fails it will raise its own errors. * @param codeName ID of the Functionality - * @param location - * @param submittable - * @param methodSignature - * @param returnAbiParametersArray - * @param isInternal - * @param needsSender - * @replaces + * @param submittable Boolean flag controlling wether the microservice writes data to the chain + * @param methodSignature Name of the method of the microservice you want to call + * @param returnAbiParametersArray Array of return values obtained from the called microservice's method + * @param isInternal Boolean flag controlling wether the microservice can be called from anyone (false) or + * can be called only by other microservices (true) + * @param needsSender All microservices calls are made py the Proxy, with this boolean flag you can + * forward the address that called the Proxy in the first place + * @param replaces // DOCUMENT */ function checkWellKnownFunctionalities( string calldata codeName, diff --git a/contracts/IMVDFunctionalityProposal.sol b/contracts/IMVDFunctionalityProposal.sol index 6f8e3f0..87725a3 100644 --- a/contracts/IMVDFunctionalityProposal.sol +++ b/contracts/IMVDFunctionalityProposal.sol @@ -10,11 +10,11 @@ interface IMVDFunctionalityProposal { /** * @dev Functionality Initializer * @param codeName String ID of the Functionality - * @param location // DOCUMENTATION - * @param methodSignature // DOCUMENTATION - * @param returnAbiParametersArray // DOCUMENTATION + * @param location Address of the functionality/microservice to call + * @param methodSignature Name of the method of the microservice you want to call + * @param returnAbiParametersArray Array of return values obtained from the called microservice's method * @param replaces // DOCUMENTATION - * @param proxy // DOCUMENTATION + * @param proxy Address of the proxy */ function init( string calldata codeName, @@ -30,11 +30,13 @@ interface IMVDFunctionalityProposal { * @param emergency Bool flag controlling wether this is a standard or emergency proposal * @param sourceLocation ROBE location of the source code * @param sourceLocationId ROBE id - * @param submittable // DOCUMENTATION - * @param isInternal // DOCUMENTATION - * @param needsSender // DOCUMENTATION - * @param proposer Address of the proposer // DOCUMENTATION - * @param votesHardCap Hardcap value // DOCUMENTATION + * @param submittable Boolean flag controlling wether the microservice writes data to the chain + * @param isInternal Boolean flag controlling wether the microservice can be called from anyone (false) or + * can be called only by other microservices (true) + * @param needsSender All microservices calls are made py the Proxy, with this boolean flag you can + * forward the address that called the Proxy in the first place + * @param proposer Address of the proposer + * @param votesHardCap Hardcap value */ function setCollateralData( bool emergency, @@ -72,25 +74,35 @@ interface IMVDFunctionalityProposal { */ function getSourceLocationId() external view returns (uint256); - // DOCUMENTATION + /** + * @dev GET address of the microservice + */ function getLocation() external view returns (address); - // DOCUMENTATION + /** + * @dev GET the boolean flag controlling wether the microservice writes data to the chain + */ function issubmittable() external view returns (bool); - // DOCUMENTATION + /** + * @dev GET the name of the microservice method to invoke + */ function getMethodSignature() external view returns (string memory); - // DOCUMENTATION - function getReturnAbiParametersArray() - external - view - returns (string memory); + /** + * @dev GET the array of return values obtained from the called microservice's method + */ + function getReturnAbiParametersArray() external view returns (string memory); - // DOCUMENTATION + /** + * @dev GET the boolean flag controlling wether the microservice can be called from anyone (false) or + * can be called only by other microservices (true) + */ function isInternal() external view returns (bool); - // DOCUMENTATION + /** + * @dev GET the boolean flag controlling wether the original Proxy caller address should be forwarded or not + */ function needsSender() external view returns (bool); /** @@ -134,10 +146,7 @@ interface IMVDFunctionalityProposal { * @return accept Amount of YES votes * @return refuse Amount of NO votes */ - function getVote(address addr) - external - view - returns (uint256 accept, uint256 refuse); + function getVote(address addr) external view returns (uint256 accept, uint256 refuse); /** * @dev // DOCUMENT diff --git a/contracts/IMVDFunctionalityProposalManager.sol b/contracts/IMVDFunctionalityProposalManager.sol index fcc1506..61757d7 100644 --- a/contracts/IMVDFunctionalityProposalManager.sol +++ b/contracts/IMVDFunctionalityProposalManager.sol @@ -5,9 +5,9 @@ interface IMVDFunctionalityProposalManager { /** * @dev Add a new Proposal * @param codeName ID of the proposal - * @param location // DOCUMENT - * @param methodSignature // DOCUMENT - * @param returnAbiParametersArray // DOCUMENT + * @param location Address of the functionality/microservice to call + * @param methodSignature Name of the method of the microservice you want to call + * @param returnAbiParametersArray Array of return values obtained from the called microservice's method * @param replaces // DOCUMENT * @return proposal Address of the newly added proposal */ @@ -37,8 +37,5 @@ interface IMVDFunctionalityProposalManager { * @param proposal Address of the proposal to check * @return isValid Boolean indicating the validity of the function */ - function isValidProposal(address proposal) - external - view - returns (bool isValid); + function isValidProposal(address proposal) external view returns (bool isValid); } diff --git a/contracts/IMVDProxy.sol b/contracts/IMVDProxy.sol index 3e4b6e5..3ee78aa 100644 --- a/contracts/IMVDProxy.sol +++ b/contracts/IMVDProxy.sol @@ -36,10 +36,7 @@ interface IMVDProxy { /** * @dev GET the Functionality Proposal Manager contract address */ - function getMVDFunctionalityProposalManagerAddress() - external - view - returns (address); + function getMVDFunctionalityProposalManagerAddress() external view returns (address); /** * @dev GET the State Holder contract address @@ -49,18 +46,12 @@ interface IMVDProxy { /** * @dev GET the Functionality Models Manager contract address */ - function getMVDFunctionalityModelsManagerAddress() - external - view - returns (address); + function getMVDFunctionalityModelsManagerAddress() external view returns (address); /** * @dev GET the Functionalities Manager contract address */ - function getMVDFunctionalitiesManagerAddress() - external - view - returns (address); + function getMVDFunctionalitiesManagerAddress() external view returns (address); /** * @dev GET the Wallet contract address @@ -76,17 +67,28 @@ interface IMVDProxy { external returns (address oldAddress); - function changeProxy(address newAddress, bytes calldata initPayload) - external; + function changeProxy(address newAddress, bytes calldata initPayload) external; function isValidProposal(address proposal) external view returns (bool); - function isAuthorizedFunctionality(address functionality) - external - view - returns (bool); + function isAuthorizedFunctionality(address functionality) external view returns (bool); - // DOCUMENT + /** + * @dev Add a new proposal + * @param codeName ID of the Proposal + * @param emergency Boolean, true -> Emergency Proposal, false -> Standard Proposal + * @param sourceLocation ROBE location of the source code + * @param sourceLocationId ROBE id + * @param location Address of the functionality/microservice to call + * @param submittable Boolean flag controlling wether the microservice writes data to the chain + * @param methodSignature Name of the method of the microservice you want to call + * @param returnParametersJSONArray Array of json encoded return parameters of the proposal + * @param isInternal Boolean flag controlling wether the microservice can be called from anyone (false) or + * can be called only by other microservices (true) + * @param needsSender All microservices calls are made py the Proxy, with this boolean flag you can + * @param replaces // DOCUMENT + * @return proposalAddress Address of the newly created proposal + */ function newProposal( string calldata codeName, bool emergency, @@ -101,8 +103,10 @@ interface IMVDProxy { string calldata replaces ) external returns (address proposalAddress); + // DOCUMENTATION function startProposal(address proposalAddress) external; + // DOCUMENTATION function disableProposal(address proposalAddress) external; /** @@ -184,11 +188,7 @@ interface IMVDProxy { ) external; event ProxyChanged(address indexed newAddress); - event DelegateChanged( - uint256 position, - address indexed oldAddress, - address indexed newAddress - ); + event DelegateChanged(uint256 position, address indexed oldAddress, address indexed newAddress); event Proposal(address proposal); event ProposalCheck(address indexed proposal); diff --git a/contracts/IVotingToken.sol b/contracts/IVotingToken.sol index 6dc85b4..d6b225a 100644 --- a/contracts/IVotingToken.sol +++ b/contracts/IVotingToken.sol @@ -55,12 +55,8 @@ interface IVotingToken { function burn(uint256 amount) external; // DOCUMENTATION - function increaseAllowance(address spender, uint256 addedValue) - external - returns (bool); + function increaseAllowance(address spender, uint256 addedValue) external returns (bool); // DOCUMENTATION - function decreaseAllowance(address spender, uint256 subtractedValue) - external - returns (bool); + function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); } From ccc2887cb0d0de53a55f8a4c58bc87bb6244c65c Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Sat, 19 Sep 2020 17:13:42 +0200 Subject: [PATCH 07/12] Generated docs --- docs/build | 2 +- docs/mkdocs.yml | 1 - yarn.lock | 103 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 yarn.lock diff --git a/docs/build b/docs/build index c8ac821..93b20b6 160000 --- a/docs/build +++ b/docs/build @@ -1 +1 @@ -Subproject commit c8ac8213183c58be0c0059bbc88f9a67979a5924 +Subproject commit 93b20b6d6b54ab72b5433c6d2155bb4fd549883d diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 0c63ea9..e4797ea 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -15,7 +15,6 @@ nav: - IMVDFunctionalityProposalManager: contracts/IMVDFunctionalityProposalManager.md - IMVDProxy: contracts/IMVDProxy.md - IMVDWallet: contracts/IMVDWallet.md - - IStateHolder: contracts/IStateHolder.md - IVotingToken: contracts/IVotingToken.md theme: name: readthedocs diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..754350a --- /dev/null +++ b/yarn.lock @@ -0,0 +1,103 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@solidity-parser/parser@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.8.0.tgz#e56fe5f0e29753f928c8fb1ddf5f59e5d71363e9" + integrity sha512-4Eg1iWe6ZuJC9Ynfd8D2cnu06So0QL6V3i+fgQRqT8twPMr+N+kUvS5K7ILgWpuoAag/jb3r0wBDfmpib+yvaw== + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +dir-to-object@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dir-to-object/-/dir-to-object-2.0.0.tgz#29723e9bd1c3e58e4f307bd04ff634c0370c8f8a" + integrity sha512-sXs0JKIhymON7T1UZuO2Ud6VTNAx/VTBXIl4+3mjb2RgfOpt+hectX0x04YqPOPdkeOAKoJuKqwqnXXURNPNEA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.0.0.tgz#48a2309cc8a1d2e9d23bc6a67c39b63032e76ea4" + integrity sha512-6p1NII1Vm62wni/VR/cUMauVQoxmLVb9csqQlvLz+hO2gk8U2UYDfXHQSUYIBKmZwAKz867IDqG7B+u0mj+M6w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +esprima-extract-comments@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/esprima-extract-comments/-/esprima-extract-comments-1.1.0.tgz#0dacab567a5900240de6d344cf18c33617becbc9" + integrity sha512-sBQUnvJwpeE9QnPrxh7dpI/dp67erYG4WXEAreAMoelPRpMR7NWb4YtwRPn9b+H1uLQKl/qS8WYmyaljTpjIsw== + dependencies: + esprima "^4.0.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +extract-comments@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/extract-comments/-/extract-comments-1.1.0.tgz#b90bca033a056bd69b8ba1c6b6b120fc2ee95c18" + integrity sha512-dzbZV2AdSSVW/4E7Ti5hZdHWbA+Z80RJsJhr5uiL10oyjl/gy7/o+HI1HwK4/WSZhlq4SNKU3oUzXlM13Qx02Q== + dependencies: + esprima-extract-comments "^1.1.0" + parse-code-context "^1.0.0" + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +parse-code-context@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-code-context/-/parse-code-context-1.0.0.tgz#718c295c593d0d19a37f898473268cc75e98de1e" + integrity sha512-OZQaqKaQnR21iqhlnPfVisFjBWjhnMl5J9MgbP8xC+EwoVqbXrq78lp+9Zb3ahmLzrIX5Us/qbvBnaS3hkH6OA== + +prettier-plugin-solidity@^1.0.0-alpha.56: + version "1.0.0-alpha.57" + resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-alpha.57.tgz#972190efe96bce816f3af3f74948c8b86ad0abb1" + integrity sha512-GTcL3OzxPn54TMlopE+wcXOUfEnpw05jvJw3KJrXkWTHER1CbkuAFRP4xiFtbJYq35ssSRO5FN4yMshx2grTIw== + dependencies: + "@solidity-parser/parser" "^0.8.0" + dir-to-object "^2.0.0" + emoji-regex "^9.0.0" + escape-string-regexp "^4.0.0" + extract-comments "^1.1.0" + prettier "^2.0.5" + semver "^7.3.2" + string-width "^4.2.0" + +prettier@^2.0.5, prettier@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5" + integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg== + +semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + +string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" From 79469eb6d1e5192724f6fce4bb77b21382817571 Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Sat, 19 Sep 2020 17:42:05 +0200 Subject: [PATCH 08/12] Fix error with IMVDFunctionalityProposalManager --- contracts/IMVDFunctionalityProposalManager.sol | 4 ++++ docs/build | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/contracts/IMVDFunctionalityProposalManager.sol b/contracts/IMVDFunctionalityProposalManager.sol index 61757d7..7c9913f 100644 --- a/contracts/IMVDFunctionalityProposalManager.sol +++ b/contracts/IMVDFunctionalityProposalManager.sol @@ -1,6 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.7.0; +/** + * @title Functionality Proposal Manager + * @dev Microservice for adding new proposals + */ interface IMVDFunctionalityProposalManager { /** * @dev Add a new Proposal diff --git a/docs/build b/docs/build index 93b20b6..a5e6917 160000 --- a/docs/build +++ b/docs/build @@ -1 +1 @@ -Subproject commit 93b20b6d6b54ab72b5433c6d2155bb4fd549883d +Subproject commit a5e6917b66003ddcbda6e138d5151dfa2a452b3d From 55765d9a3a1e508eccdb87d6f37c521372e4b9b2 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Sun, 20 Sep 2020 16:56:34 +0200 Subject: [PATCH 09/12] Updates --- contracts/IDoubleProxy.sol | 14 +++- contracts/IMVDFunctionalitiesManager.sol | 76 ++++++++++++++----- contracts/IMVDFunctionalityModelsManager.sol | 6 +- contracts/IMVDFunctionalityProposal.sol | 50 ++++++------ .../IMVDFunctionalityProposalManager.sol | 14 +++- contracts/IMVDProxy.sol | 57 ++++++++++---- contracts/IMVDWallet.sol | 9 ++- contracts/IStateHolder.sol | 42 ++++++++++ contracts/IVotingToken.sol | 8 +- 9 files changed, 201 insertions(+), 75 deletions(-) diff --git a/contracts/IDoubleProxy.sol b/contracts/IDoubleProxy.sol index cce018b..408e6e3 100644 --- a/contracts/IDoubleProxy.sol +++ b/contracts/IDoubleProxy.sol @@ -3,27 +3,33 @@ pragma solidity >=0.7.0; /** * @title Double Proxy Interface + * @dev Double Proxy is the easiest way for side/external Contracts to locate and query the DFO. + * As the main Core Contract of a DFO is the Proxy, it also can be updated by Proposals. + * So, directly link the Proxy to external Contracts can be really a problem. + * To avoid this, it is better to link external contracts with the DoubleProxy. + * DoubleProxy is the Proxy of the Proxy, and is a Delegate that keeps track of the most recent Proxy address and all the other previous Proxies. + * Because it has a very lightweight and simple structure and logic, it does not need of changes, so it can be used as a secure anchor. */ interface IDoubleProxy { /** * @dev Initializer logic used during the constructor call * @param proxies Array of address of the old proxies, only used in legacy scenarios. Can be left empty. - * @param currentProxy Address of the current proxy + * @param currentProxy Address of the current Proxy */ function init(address[] calldata proxies, address currentProxy) external; /** - * @dev GET the proxy + * @dev GET the current Proxy */ function proxy() external view returns (address); /** - * @dev SET the proxy + * @dev Method callable by the current Proxy only. It is used when the Proxy or this delegate changes. */ function setProxy() external; /** - * @dev Check if the address is or has been a proxy + * @dev Check if the address is or has been a Proxy */ function isProxy(address) external view returns (bool); diff --git a/contracts/IMVDFunctionalitiesManager.sol b/contracts/IMVDFunctionalitiesManager.sol index a856546..ee227f5 100644 --- a/contracts/IMVDFunctionalitiesManager.sol +++ b/contracts/IMVDFunctionalitiesManager.sol @@ -3,31 +3,33 @@ pragma solidity >=0.7.0; /** * @title Interface for the Functionalities Manager + * @dev Functionalities Manager is the one that keeps track of all the Microservices of a DFO. + * It also contains all the logic to set/unset Microservices after a Proposal. */ interface IMVDFunctionalitiesManager { /** - * @dev GET the proxy + * @dev GET the Proxy */ function getProxy() external view returns (address); /** - * @dev SET the proxy + * @dev SET the Proxy */ function setProxy() external; /** * @dev Initializer logic used during the constructor call - * @param sourceLocation ROBE location of the source code - * @param getMinimumBlockNumberSourceLocationId ROBE id + * @param sourceLocation Location of the source code, saved in concatenated Base64 data chunks + * @param getMinimumBlockNumberSourceLocationId Base64 data chunk id of the corresponding Microservice * @param getMinimumBlockNumberFunctionalityAddress Address of the Functionality that controls * the block duration of regular proposals - * @param getEmergencyMinimumBlockNumberSourceLocationId ROBE id + * @param getEmergencyMinimumBlockNumberSourceLocationId Base64 data chunk id of the corresponding Microservice * @param getEmergencyMinimumBlockNumberFunctionalityAddress Address for the Functionality that controls * the block duration of emergency proposals - * @param getEmergencySurveyStakingSourceLocationId ROBE id + * @param getEmergencySurveyStakingSourceLocationId Base64 data chunk id of the corresponding Microservice * @param getEmergencySurveyStakingFunctionalityAddress Address for the Functionality that controls the * minimum amount of vote to be staked in order to start an Emergency Proposal - * @param checkVoteResultSourceLocationId ROBE id + * @param checkVoteResultSourceLocationId Base64 data chunk id of the corresponding Microservice * @param checkVoteResultFunctionalityAddress Address for the Functionality that controls the * check for determining if a Proposal was successful or it failed */ @@ -45,16 +47,16 @@ interface IMVDFunctionalitiesManager { /** * @dev Add a functionality to the Functionalities Manager - * @param codeName ID of the Functionality - * @param sourceLocation ROBE location of the source code - * @param sourceLocationId ROBE id + * @param codeName ID of the microservice, to be called by the user through Proxy. + * @param sourceLocation Location of the source code, saved in concatenated Base64 data chunks + * @param sourceLocationId Base64 data chunk id of the corresponding Microservice * @param location Address of the functionality/microservice to call * @param submittable Boolean flag controlling wether the microservice writes data to the chain * @param methodSignature Name of the method of the microservice you want to call * @param returnAbiParametersArray Array of return values obtained from the called microservice's method * @param isInternal Boolean flag controlling wether the microservice can be called from anyone (false) or * can be called only by other microservices (true) - * @param needsSender All microservices calls are made py the Proxy, with this boolean flag you can + * @param needsSender All microservices calls are made by the Proxy, with this boolean flag you can * forward the address that called the Proxy in the first place */ function addFunctionality( @@ -71,9 +73,9 @@ interface IMVDFunctionalitiesManager { /** * @dev Replace a Functionality in the Functionalities Manager - * @param codeName ID of the Functionality - * @param sourceLocation ROBE location of the source code - * @param sourceLocationId ROBE id + * @param codeName ID of the microservice, to be called by the user through Proxy. + * @param sourceLocation Location of the source code, saved in concatenated Base64 data chunks + * @param sourceLocationId Base64 data chunk id of the corresponding Microservice * @param location Address of the functionality/microservice to call * @param submittable Boolean flag controlling wether the microservice writes data to the chain * @param methodSignature Name of the method of the microservice you want to call @@ -121,13 +123,26 @@ interface IMVDFunctionalitiesManager { */ function isAuthorizedFunctionality(address functionality) external view returns (bool success); - // DOCUMENT + /** + * @dev This method can be called only by the Proxy. + * When a new submitable Microservice is called, this method is used to let other DFO Delegates (e.g. StateHolder) to be fully operative. + * If you call a Microservice directly, bypassing the Proxy, the context will be blank and Delegates cannot allow you to do any operation. + * @param location The address of the currently running Microservice + * @return true if the calling context is correctly set, false if the context was already set (this happens, for example, when someone calls a Microservice including a logic to call another Microservice through the Proxy). + */ function setCallingContext(address location) external returns (bool); - // DOCUMENT + /** + * @dev This method can be called only by the Proxy. + * Clears the context at the end of the Microservice execution + */ function clearCallingContext() external; - // DOCUMENT + /** + * @dev Utility method to retrieve all important stuff to call a Microservice + * @param codeName the codeName of the Microservice you need info + * @return the address of the contract including the logic of the Microservice, the method signature of the Microservice, the position in the Functionalities array, the location of the source code, saved in byte64 concatenated data chunks, the locationId of the source code. + */ function getFunctionalityData(string calldata codeName) external view @@ -151,10 +166,16 @@ interface IMVDFunctionalitiesManager { */ function getFunctionalitiesAmount() external view returns (uint256); - // DOCUMENT + /** + * @dev For frontend purposes. Gives back the info about functionalities using the JSON Array format + */ function functionalitiesToJSON() external view returns (string memory); - // DOCUMENT + /** + * @dev For frontend purposes. Gives back the info about functionalities using the JSON Array format + * @param start the start position of the array + * @param l the array offset + */ function functionalitiesToJSON(uint256 start, uint256 l) external view @@ -178,7 +199,16 @@ interface IMVDFunctionalitiesManager { */ function functionalityToJSON(string calldata codeName) external view returns (string memory); - // DOCUMENT + /** + * @dev Method called by the Proxy when someone calls a Microservice. + * It has a double function: checks if you are in the correct context (e.g. are you trying to call a non-submitable Microservice through the correct "read" function of the Proxy?) + * and gives back the address of the Microservice and the correct payload that the proxy will use to execute a .call() method. + * @param codeName the Microservice to be called + * @param data the payload to be used within the Microservice (ABI encoded) + * @param submittable 1 true, 0 false + * @param sender the original msg.sender of the Proxy read/submit call, to be used if the Microservice has the needsSender flag set to true + * @param value the original msg.value of the Proxy submit call, to be used if the Microservice is submitable and has the needsSender flag set to true + */ function preConditionCheck( string calldata codeName, bytes calldata data, @@ -187,6 +217,10 @@ interface IMVDFunctionalitiesManager { uint256 value ) external view returns (address location, bytes memory payload); - // DOCUMENT + /** + * @dev callable by the Proxy only. + * Sets up the new Microservice add/replace/remove action, grabbing the data from the MVDFunctionalityProposal at the given address + * @param proposalAddress the address of the Proposal to be set + */ function setupFunctionality(address proposalAddress) external returns (bool); } diff --git a/contracts/IMVDFunctionalityModelsManager.sol b/contracts/IMVDFunctionalityModelsManager.sol index 617e324..d6ee7da 100644 --- a/contracts/IMVDFunctionalityModelsManager.sol +++ b/contracts/IMVDFunctionalityModelsManager.sol @@ -3,7 +3,7 @@ pragma solidity >=0.7.0; /** * @title Functionalities Models Manager - * @dev Well Known Functionalities are "special" Fnctionalities must be implemented according to + * @dev Well Known Functionalities are "special" Functionalities/Microservices must be implemented according to * a specific pattern. Well Known Functionalities can be found in the implementation of this Interface. */ interface IMVDFunctionalityModelsManager { @@ -11,7 +11,7 @@ interface IMVDFunctionalityModelsManager { /** * @dev Check Well Known Functionalities. If the check fails it will raise its own errors. - * @param codeName ID of the Functionality + * @param codeName ID of the microservice, to be called by the user through Proxy. * @param submittable Boolean flag controlling wether the microservice writes data to the chain * @param methodSignature Name of the method of the microservice you want to call * @param returnAbiParametersArray Array of return values obtained from the called microservice's method @@ -19,7 +19,7 @@ interface IMVDFunctionalityModelsManager { * can be called only by other microservices (true) * @param needsSender All microservices calls are made py the Proxy, with this boolean flag you can * forward the address that called the Proxy in the first place - * @param replaces // DOCUMENT + * @param replaces codeName of the microservice that will be replaced by the Proposal to be created, can be blank. */ function checkWellKnownFunctionalities( string calldata codeName, diff --git a/contracts/IMVDFunctionalityProposal.sol b/contracts/IMVDFunctionalityProposal.sol index 87725a3..eecfd75 100644 --- a/contracts/IMVDFunctionalityProposal.sol +++ b/contracts/IMVDFunctionalityProposal.sol @@ -9,11 +9,11 @@ pragma solidity >=0.7.0; interface IMVDFunctionalityProposal { /** * @dev Functionality Initializer - * @param codeName String ID of the Functionality + * @param codeName ID of the microservice, to be called by the user through Proxy, can be blank. * @param location Address of the functionality/microservice to call * @param methodSignature Name of the method of the microservice you want to call * @param returnAbiParametersArray Array of return values obtained from the called microservice's method - * @param replaces // DOCUMENTATION + * @param replaces codeName of the microservice that will be replaced by this Proposal, can be blank. * @param proxy Address of the proxy */ function init( @@ -28,8 +28,8 @@ interface IMVDFunctionalityProposal { /** * @dev set the collateral attributes of the proposal * @param emergency Bool flag controlling wether this is a standard or emergency proposal - * @param sourceLocation ROBE location of the source code - * @param sourceLocationId ROBE id + * @param sourceLocation Location of the source code, saved in concatenated Base64 data chunks + * @param sourceLocationId Base64 data chunk id of the corresponding Microservice * @param submittable Boolean flag controlling wether the microservice writes data to the chain * @param isInternal Boolean flag controlling wether the microservice can be called from anyone (false) or * can be called only by other microservices (true) @@ -65,12 +65,12 @@ interface IMVDFunctionalityProposal { function isEmergency() external view returns (bool); /** - * @dev GET the ROBE source location + * @dev GET the Location of the source code, saved in concatenated Base64 data chunks */ function getSourceLocation() external view returns (address); /** - * @dev GET the ROBE id + * @dev GET the Base64 data chunk id of the corresponding Microservice */ function getSourceLocationId() external view returns (uint256); @@ -106,7 +106,7 @@ interface IMVDFunctionalityProposal { function needsSender() external view returns (bool); /** - * @dev // DOCUMENTATION + * @dev codeName of the microservice that will be replaced by this Proposal, can be blank. */ function getReplaces() external view returns (string memory); @@ -141,85 +141,87 @@ interface IMVDFunctionalityProposal { function toJSON() external view returns (string memory); /** - * @dev GET the current status of the voting - * @param addr // DOCUMENT + * @dev GET the current status of the voting of the given address + * @param addr The address of the voter you want to know status * @return accept Amount of YES votes * @return refuse Amount of NO votes */ function getVote(address addr) external view returns (uint256 accept, uint256 refuse); /** - * @dev // DOCUMENT + * @dev Get the current votes status + * @return accept Amount of YES votes + * @return refuse Amount of NO votes */ function getVotes() external view returns (uint256, uint256); /** - * @dev // DOCUMENT + * @dev Can be used by external Proposal Managers to delay the Survey Start */ function start() external; /** - * @dev // DOCUMENT + * @dev Can be used by external Proposal Managers to disable not-yet started Surveys */ function disable() external; /** - * @dev // DOCUMENT + * @dev Check if a Proposal was canceled before its start */ function isDisabled() external view returns (bool); /** - * @dev // DOCUMENT + * @dev Check if the Proposal reached the natural time termination or the reachement of the Hard Cap. */ function isTerminated() external view returns (bool); /** - * @dev // DOCUMENT + * @dev Vote to accept the Proposal, staking your voting tokens. Can be called only if the Proposal is still running. */ function accept(uint256 amount) external; /** - * @dev // DOCUMENT + * @dev Retire your votes. Can be called only if the Proposal is still running. */ function retireAccept(uint256 amount) external; /** - * @dev // DOCUMENT + * @dev Move some "refuse" votes to "accept". Can be called only if the Proposal is still running. */ function moveToAccept(uint256 amount) external; /** - * @dev // DOCUMENT + * @dev Vote to refuse the Proposal, staking your voting tokens. Can be called only if the Proposal is still running. */ function refuse(uint256 amount) external; /** - * @dev // DOCUMENT + * @dev Retire your votes. Can be called only if the Proposal is still running. */ function retireRefuse(uint256 amount) external; /** - * @dev // DOCUMENT + * @dev Move some "accept" votes to "refuse". Can be called only if the Proposal is still running. */ function moveToRefuse(uint256 amount) external; /** - * @dev // DOCUMENT + * @dev Retire all your votes, retreiving back your staked voting tokens. Can be called only if the Proposal is still running. */ function retireAll() external; /** - * @dev // DOCUMENT + * @dev Withdraw all the token you staked. Can be called only if the Proposal reaches the Hard Cap or the final Block. */ function withdraw() external; /** - * @dev // DOCUMENT + * @dev Force the Proposal to call the Proxy and execute the finalization operations. Can be called only if the Proposal reaches the Hard Cap or the final Block. */ function terminate() external; /** - * @dev // DOCUMENT + * @dev Callable by the Proxy only. Marks this Proposal as definitively terminate. User can still call the withdrawAll() function to withdraw the tokens, of course. */ function set() external; diff --git a/contracts/IMVDFunctionalityProposalManager.sol b/contracts/IMVDFunctionalityProposalManager.sol index 7c9913f..130987b 100644 --- a/contracts/IMVDFunctionalityProposalManager.sol +++ b/contracts/IMVDFunctionalityProposalManager.sol @@ -8,11 +8,16 @@ pragma solidity >=0.7.0; interface IMVDFunctionalityProposalManager { /** * @dev Add a new Proposal - * @param codeName ID of the proposal + * Work explanation: + * codeName is set and replaces is blank: the Proposal will add a new Microservice/Functionality + * codeName is blank and replaces is set: the Proposal will remove an existing Microservice/Functionality + * codeName and replaces are both set: the Proposal will replace an existing Functionality/Microservice with a new one + * codeName and replaces are both blank: the Proposal represents a One-Time Functionality, that will be executed just one time, if the Token Holders Pccepts this proposal. + * @param codeName ID of the microservice, to be called by the user through Proxy, can be blank. * @param location Address of the functionality/microservice to call * @param methodSignature Name of the method of the microservice you want to call * @param returnAbiParametersArray Array of return values obtained from the called microservice's method - * @param replaces // DOCUMENT + * @param replaces codeName of the microservice that will be replaced by this Proposal, can be blank. * @return proposal Address of the newly added proposal */ function newProposal( @@ -23,7 +28,10 @@ interface IMVDFunctionalityProposalManager { string calldata replaces ) external returns (address proposal); - // DOCUMENT + /** + * @dev Callable by the Proxy only. + * Contains the logic to check if a proposal is ready to be finalized (e.g. last block reached or hard cap reached). + */ function checkProposal(address proposalAddress) external; /** diff --git a/contracts/IMVDProxy.sol b/contracts/IMVDProxy.sol index 3ee78aa..639bdc5 100644 --- a/contracts/IMVDProxy.sol +++ b/contracts/IMVDProxy.sol @@ -75,10 +75,10 @@ interface IMVDProxy { /** * @dev Add a new proposal - * @param codeName ID of the Proposal + * @param codeName ID of the microservice, to be called by the user through Proxy, can be blank. * @param emergency Boolean, true -> Emergency Proposal, false -> Standard Proposal - * @param sourceLocation ROBE location of the source code - * @param sourceLocationId ROBE id + * @param sourceLocation Location of the source code, saved in concatenated Base64 data chunks + * @param sourceLocationId Base64 data chunk id of the corresponding Microservice * @param location Address of the functionality/microservice to call * @param submittable Boolean flag controlling wether the microservice writes data to the chain * @param methodSignature Name of the method of the microservice you want to call @@ -86,7 +86,7 @@ interface IMVDProxy { * @param isInternal Boolean flag controlling wether the microservice can be called from anyone (false) or * can be called only by other microservices (true) * @param needsSender All microservices calls are made py the Proxy, with this boolean flag you can - * @param replaces // DOCUMENT + * @param replaces codeName of the microservice that will be replaced by this Proposal, can be blank. * @return proposalAddress Address of the newly created proposal */ function newProposal( @@ -103,10 +103,14 @@ interface IMVDProxy { string calldata replaces ) external returns (address proposalAddress); - // DOCUMENTATION + /** + * @dev Can be used by external Proposal Managers to delay the Survey Start + */ function startProposal(address proposalAddress) external; - // DOCUMENTATION + /** + * @dev Can be used by external Proposal Managers to disable not-yet started Surveys + */ function disableProposal(address proposalAddress) external; /** @@ -125,7 +129,7 @@ interface IMVDProxy { * @dev Transfer an ERC721 to an address * @param receiver Address of the receiver * @param tokenId ID of the ERC721 to transfer - * @param data // DOCUMENTATION + * @param data The optional payload to pass in the safeTransferFrom function * @param safe Boolean flag for triggering the SafeTransfer * @param token Address of the token to transfer */ @@ -137,34 +141,56 @@ interface IMVDProxy { address token ) external; - // DOCUMENT + /** + * @dev Utility public method callable by everyone to send all ether/tokens/NFT accidentally sent to the Proxy. + * It flushes all in the DFO Wallet + * @param tokenAddress the ERC20/ERC721 token to transfer. address(0) means flush ether + * @param is721 tokenAddress is 721 or ERC20 + * @param tokenId the id of the eventual ERC721 Token to transfer + */ function flushToWallet( address tokenAddress, bool is721, uint256 tokenId ) external; - // DOCUMENT + /** + * @dev Callable by the Proposals only. Starts the Proposal finalization procedure + */ function setProposal() external; - // DOCUMENT + /** + * @dev Call a non-submitable (readonly function marked as pure or view) Microservice + * @param codeName the ID of the Microservice to be called + * @param data ABI encoded data payload to be passed to the Microservice + */ function read(string calldata codeName, bytes calldata data) external view returns (bytes memory returnData); - // DOCUMENT + /** + * @dev Call a submitable (which writes on the Blockchain State) Microservice + * @param codeName the ID of the Microservice to be called + * @param data ABI encoded data payload to be passed to the Microservice + */ function submit(string calldata codeName, bytes calldata data) external payable returns (bytes memory returnData); - // DOCUMENT + /** + * @dev callable by the MVDFunctionalitiesManager only. + * Calls a Microservice using the Proxy as msg.sender + */ function callFromManager(address location, bytes calldata payload) external returns (bool, bytes memory); - // DOCUMENT + /** + * @dev callable by the MVDFunctionalitiesManager only. + * Emits the FunctionalitySet event by the Proxy + */ function emitFromManager( string calldata codeName, address proposal, @@ -179,7 +205,10 @@ interface IMVDProxy { address proposalAddress ) external; - // DOCUMENT + /** + * @dev callable by Microservices only. + * Emits the general purpose "Event" event by the Proxy + */ function emitEvent( string calldata eventSignature, bytes calldata firstIndex, diff --git a/contracts/IMVDWallet.sol b/contracts/IMVDWallet.sol index 3dd7457..46d0165 100644 --- a/contracts/IMVDWallet.sol +++ b/contracts/IMVDWallet.sol @@ -2,7 +2,8 @@ pragma solidity >=0.7.0; /** * @title Wallet - * @dev // DOCUMENTATION + * @dev The wallet is used to store all the assets of a DFO (ethers, ERC20 Tokens, ERC721 NFTs). + * All the functions to transfer assets can be called by the Proxy only. */ interface IMVDWallet { /** @@ -18,7 +19,7 @@ interface IMVDWallet { /** * @dev SET new wallet * @param newWallet New wallet address - * @param tokenAddress // DOCUMENT + * @param tokenAddress The voting token, used to flush balance to new wallet */ function setNewWallet(address payable newWallet, address tokenAddress) external; @@ -39,7 +40,7 @@ interface IMVDWallet { * @dev Transfer an ERC721 to an address * @param receiver Address of the receiver * @param tokenId ID of the ERC721 to transfer - * @param data // DOCUMENTATION + * @param data The optional payload to pass in the safeTransferFrom function * @param safe Boolean flag for triggering the SafeTransfer * @param token Address of the token to transfer */ @@ -60,7 +61,7 @@ interface IMVDWallet { /** * @dev Transfer an ERC721 to the NewWallet * @param tokenId ID of the ERC721 to transfer - * @param data // DOCUMENTATION + * @param data The optional payload passed in the safeTransferFrom function * @param safe Boolean flag for triggering the SafeTransfer * @param tokenAddress Address of the token to transfer */ diff --git a/contracts/IStateHolder.sol b/contracts/IStateHolder.sol index 34e0ccd..9f10270 100644 --- a/contracts/IStateHolder.sol +++ b/contracts/IStateHolder.sol @@ -1,28 +1,70 @@ pragma solidity >=0.7.0; +/** + * @title State Holder + * StateHolder is the Database of a DFO. It stores all data the DFO needs to run its business logic. + * It works like a Key/Value storage and can save the main Solidity data types (address, bool, uint256, string, bytes). + * The read capabilities are of course public. While se write capabilities (set/clear) can be called by DFO Microservices only. + * The set methods also return the previous value of the set variable + */ interface IStateHolder { + + /** + * @dev Initialization logic using during the constructor Call + */ function init() external; + /** + * @dev GET the Proxy + */ function getProxy() external view returns (address); + /** + * @dev SET the Proxy + */ function setProxy() external; + /** + * @dev For frontend purposes. Returns the StateHolder's keys and values in JSON Format + */ function toJSON() external view returns (string memory); + /** + * @dev For frontend purposes. Returns the StateHolder's keys and values in JSON Format + * @param start the values array start + * @param l the values array offset + */ function toJSON(uint256 start, uint256 l) external view returns (string memory); + /** + * @dev returns the number of values set in the StateHolder + */ function getStateSize() external view returns (uint256); + /** + * @param varName the name of the variable to check + * @return true if varName is set, false otherwhise + */ function exists(string calldata varName) external view returns (bool); + /** + * @param varName the name of the variable to check + * @return dataType the data type of this var, if any. + */ function getDataType(string calldata varName) external view returns (string memory dataType); + /** + * @dev delete the variable from the StateHolder + * @param varName the name of the variable to delete + * @return oldDataType the data type of the deleted variable + * @return oldVal the old value of the deleted variable + */ function clear(string calldata varName) external returns (string memory oldDataType, bytes memory oldVal); diff --git a/contracts/IVotingToken.sol b/contracts/IVotingToken.sol index d6b225a..d3c0544 100644 --- a/contracts/IVotingToken.sol +++ b/contracts/IVotingToken.sol @@ -54,9 +54,13 @@ interface IVotingToken { */ function burn(uint256 amount) external; - // DOCUMENTATION + /** + * @dev see the OpenZeppelin's documentation + */ function increaseAllowance(address spender, uint256 addedValue) external returns (bool); - // DOCUMENTATION + /** + * @dev see the OpenZeppelin's documentation + */ function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); } From 19a3b28fda2bc7a00d58c9b7ae7d593ecc8b5bdd Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Sun, 20 Sep 2020 17:13:41 +0200 Subject: [PATCH 10/12] Update docs --- contracts/IMVDFunctionalitiesManager.sol | 4 ++-- docs/build | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/IMVDFunctionalitiesManager.sol b/contracts/IMVDFunctionalitiesManager.sol index ee227f5..4ffe997 100644 --- a/contracts/IMVDFunctionalitiesManager.sol +++ b/contracts/IMVDFunctionalitiesManager.sol @@ -128,9 +128,9 @@ interface IMVDFunctionalitiesManager { * When a new submitable Microservice is called, this method is used to let other DFO Delegates (e.g. StateHolder) to be fully operative. * If you call a Microservice directly, bypassing the Proxy, the context will be blank and Delegates cannot allow you to do any operation. * @param location The address of the currently running Microservice - * @return true if the calling context is correctly set, false if the context was already set (this happens, for example, when someone calls a Microservice including a logic to call another Microservice through the Proxy). + * @return changed True if the calling context is correctly set, false if the context was already set (this happens, for example, when someone calls a Microservice including a logic to call another Microservice through the Proxy). */ - function setCallingContext(address location) external returns (bool); + function setCallingContext(address location) external returns (bool changed); /** * @dev This method can be called only by the Proxy. diff --git a/docs/build b/docs/build index a5e6917..79c9d2f 160000 --- a/docs/build +++ b/docs/build @@ -1 +1 @@ -Subproject commit a5e6917b66003ddcbda6e138d5151dfa2a452b3d +Subproject commit 79c9d2fdae00f96fcf83fb32386c68014d5c9121 From f08b37e2ded63f0a245fc10802e1f4274ae5468e Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Mon, 21 Sep 2020 14:02:21 +0200 Subject: [PATCH 11/12] Typos Fixes --- README.md | 2 +- docs/mkdocs.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 628ca16..73c6384 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Decentralized Flexible Organization - DFO -## Microservices on Ethereum 👽 for Independent Dapps ugradable by voting 😱 +## Microservices on Ethereum 👽 for Independent Dapps upgradable by voting 😱 ##### Authors: Marco Vasapollo ([@vasapower](https://twitter.com/vasapower_9)) and Alessandro Mario Laganà Toschi ([@alessandromlt](https://twitter.com/alessandromlt)) | diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index e4797ea..d2a0de2 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -8,7 +8,7 @@ nav: - API: - Contracts: - ICommonUtilities: contracts/ICommonUtilities.md - - IDounleProxy: contracts/IDoubleProxy.md + - IDoubleProxy: contracts/IDoubleProxy.md - IMVDFunctionalitiesManager: contracts/IMVDFunctionalitiesManager.md - IMVDFunctionalityModelsManager: contracts/IMVDFunctionalityModelsManager.md - IMVDFunctionalityProposal: contracts/IMVDFunctionalityProposal.md From d48f7b225bb05f365f135932e57867942a862afd Mon Sep 17 00:00:00 2001 From: "Michele \"Ubik\" De Simoni" Date: Tue, 22 Sep 2020 23:01:39 +0200 Subject: [PATCH 12/12] Update docs with StateHolder --- contracts/IStateHolder.sol | 45 +++++++++----------------------------- contracts/IVotingToken.sol | 5 ++++- docs/build | 2 +- 3 files changed, 15 insertions(+), 37 deletions(-) diff --git a/contracts/IStateHolder.sol b/contracts/IStateHolder.sol index 9f10270..8b8b77a 100644 --- a/contracts/IStateHolder.sol +++ b/contracts/IStateHolder.sol @@ -8,7 +8,6 @@ pragma solidity >=0.7.0; * The set methods also return the previous value of the set variable */ interface IStateHolder { - /** * @dev Initialization logic using during the constructor Call */ @@ -34,10 +33,7 @@ interface IStateHolder { * @param start the values array start * @param l the values array offset */ - function toJSON(uint256 start, uint256 l) - external - view - returns (string memory); + function toJSON(uint256 start, uint256 l) external view returns (string memory); /** * @dev returns the number of values set in the StateHolder @@ -46,7 +42,7 @@ interface IStateHolder { /** * @param varName the name of the variable to check - * @return true if varName is set, false otherwhise + * @return true if varName is set, false otherwise */ function exists(string calldata varName) external view returns (bool); @@ -54,10 +50,7 @@ interface IStateHolder { * @param varName the name of the variable to check * @return dataType the data type of this var, if any. */ - function getDataType(string calldata varName) - external - view - returns (string memory dataType); + function getDataType(string calldata varName) external view returns (string memory dataType); /** * @dev delete the variable from the StateHolder @@ -69,43 +62,25 @@ interface IStateHolder { external returns (string memory oldDataType, bytes memory oldVal); - function setBytes(string calldata varName, bytes calldata val) - external - returns (bytes memory); + function setBytes(string calldata varName, bytes calldata val) external returns (bytes memory); - function getBytes(string calldata varName) - external - view - returns (bytes memory); + function getBytes(string calldata varName) external view returns (bytes memory); function setString(string calldata varName, string calldata val) external returns (string memory); - function getString(string calldata varName) - external - view - returns (string memory); + function getString(string calldata varName) external view returns (string memory); function setBool(string calldata varName, bool val) external returns (bool); function getBool(string calldata varName) external view returns (bool); - function getUint256(string calldata varName) - external - view - returns (uint256); + function getUint256(string calldata varName) external view returns (uint256); - function setUint256(string calldata varName, uint256 val) - external - returns (uint256); + function setUint256(string calldata varName, uint256 val) external returns (uint256); - function getAddress(string calldata varName) - external - view - returns (address); + function getAddress(string calldata varName) external view returns (address); - function setAddress(string calldata varName, address val) - external - returns (address); + function setAddress(string calldata varName, address val) external returns (address); } diff --git a/contracts/IVotingToken.sol b/contracts/IVotingToken.sol index d3c0544..00c241d 100644 --- a/contracts/IVotingToken.sol +++ b/contracts/IVotingToken.sol @@ -2,7 +2,10 @@ pragma solidity >=0.7.0; /** - * @title Voting Token interface + * @title Voting Token interface. + * @dev A voting token is an ERC20 used inside a DFO to vote proposals. + * Since proposals are code and voting tokens control which proposal get accepted, they are the + * programmable equities of the DFO. */ interface IVotingToken { /** diff --git a/docs/build b/docs/build index 79c9d2f..5fd4d62 160000 --- a/docs/build +++ b/docs/build @@ -1 +1 @@ -Subproject commit 79c9d2fdae00f96fcf83fb32386c68014d5c9121 +Subproject commit 5fd4d623af6c03c5d98c5a7a774462f19285bc6d