From b7220a0d250d7f392ad08a95813927726c96a987 Mon Sep 17 00:00:00 2001 From: mesowea Date: Mon, 13 Mar 2023 00:09:19 +0200 Subject: [PATCH 1/6] Add comments to IRegistry.sol and IUserInfoRegistry.sol expalining what do the updateUserStatsForPRT and transferOwnershipAndInject functions do --- contracts/interfaces/IRegistry.sol | 6 ++++++ contracts/interfaces/IUserInfoRegistry.sol | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/contracts/interfaces/IRegistry.sol b/contracts/interfaces/IRegistry.sol index 7de61da..2771bd2 100644 --- a/contracts/interfaces/IRegistry.sol +++ b/contracts/interfaces/IRegistry.sol @@ -6,6 +6,12 @@ pragma solidity 0.8.17; * With this contract you can add new contracts, update the implementation of proxy contracts */ interface IRegistry { + /// @notice Function for transfeerring the ownership and injecting the dependecies to the contracts + /// @dev zero address passed in the newOwner_ argument will trigger the revertion of the function call + /// @param newOwner_ new system owner + /// @param names_ an array of the contract names to inject dependencies in + function transferOwnershipAndInject(address newOwner_, string[] calldata names_) external; + /// @notice Function to get the address of the system owner /// @return a system owner address function getSystemOwner() external view returns (address); diff --git a/contracts/interfaces/IUserInfoRegistry.sol b/contracts/interfaces/IUserInfoRegistry.sol index 7af8c0c..ea108d5 100644 --- a/contracts/interfaces/IUserInfoRegistry.sol +++ b/contracts/interfaces/IUserInfoRegistry.sol @@ -180,6 +180,12 @@ interface IUserInfoRegistry { uint256 amount_ ) external; + /// @notice A system function that is needed to update users' PRT stats + /// @dev Only DefiCore contract can call this function + /// @param userAddr_ the user we want to update stats for + /// @param repaysCount_ the number of the borrow repays the user did + /// @param liquidationsCount_ the number of times user got liquidated + /// @param isSupply_ whether we update stats for user supply or borrow function updateUserStatsForPRT( address userAddr_, uint256 repaysCount_, From 38079c0027351358136aba14ffde73485958a50b Mon Sep 17 00:00:00 2001 From: mesowea Date: Mon, 13 Mar 2023 14:18:23 +0200 Subject: [PATCH 2/6] Add RoleManager contract, add roles constants, public function to check roles and implementation exapmple --- contracts/RoleManager.sol | 73 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 contracts/RoleManager.sol diff --git a/contracts/RoleManager.sol b/contracts/RoleManager.sol new file mode 100644 index 0000000..7d2082d --- /dev/null +++ b/contracts/RoleManager.sol @@ -0,0 +1,73 @@ +pragma solidity 0.8.17; + +import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; + +contract RoleManager is AccessControlUpgradeable { + bytes32 public constant ROLE_MANAGER_ADMIN = keccak256("ROLE_MANAGER_ADMIN"); + + bytes32 public constant ASSET_PARAMETERS_PARAM_SETTER = + keccak256("ASSET_PARAMETERS_PARAM_SETTER"); + bytes32 public constant ASSET_PARAMETERS_FREEZER = keccak256("ASSET_PARAMETERS_FREEZER"); + bytes32 public constant ASSET_PARAMETERS_COLLATERAL_ENABLER = + keccak256("ASSET_PARAMETERS_COLLATERAL_ENABLER"); + + bytes32 public constant DEFI_CORE_PAUZER = keccak256("DEFI_CORE_PAUZER"); + + bytes32 public constant PRT_PARAM_UPDATER = keccak256("PRT_PARAM_UPDATER"); + + bytes32 public constant REGISTRY_OWNER_UPDATER_AND_INJECTOR = + keccak256("REGISTRY_OWNER_UPDATER_AND_INJECTOR"); + + bytes32 public constant REWARDS_DISTRIBUTION_REWARDS_SETTER = + keccak256("REWARDS_DISTRIBUTION_REWARDS_SETTER"); + + bytes32 public constant SYSTEM_PARAMETERS_REWARDS_TOKEN_SETTER = + keccak256("SYSTEM_PARAMETERS_REWARDS_TOKEN_SETTER"); + bytes32 public constant SYSTEM_PARAMETERS_LIQUIDATION_BOUNDARY_SETTER = + keccak256("SYSTEM_PARAMETERS_LIQUIDATION_BOUNDARY_SETTER"); + bytes32 public constant SYSTEM_PARAMETERS_STABLE_POOLS_AVAILABILITY_SETTER = + keccak256("SYSTEM_PARAMETERS_STABLE_POOLS_AVAILABILITY_SETTER"); + bytes32 public constant SYSTEM_PARAMETERS_MIN_CURRENCY_AMOUNT_SETTER = + keccak256("SYSTEM_PARAMETERS_MIN_CURRENCY_AMOUNT_SETTER"); + + bytes32 public constant SYSTEM_POOLS_REGISTRY_POOLS_MANAGER = + keccak256("SYSTEM_POOLS_REGISTRY_POOLS_MANAGER"); + //Should create an injector for every contract which has dependencies? + bytes32 public constant SYSTEM_POOLS_REGISTRY_INJECTOR = + keccak256("SYSTEM_POOLS_REGISTRY_INJECTOR"); + bytes32 public constant SYSTEM_POOLS_RESERVE_FUNDS_MANAGER = + keccak256("SYSTEM_POOLS_RESERVE_FUNDS_MANAGER"); + + function roleManagerInitialize() external initializer { + _setupRole(ROLE_MANAGER_ADMIN, msg.sender); + _setRoleAdmin(ROLE_MANAGER_ADMIN, ROLE_MANAGER_ADMIN); + } + + function checkRole(bytes32 role, address account) public view virtual { + _checkRole(role, account); + } +} + +/*example: + +pragma solidity 0.8.17; + +import "./interfaces/IRoleManager.sol"; + +contract PRT is IPRT, ERC721Upgradeable, AbstractDependant, ReentrancyGuardUpgradeable { + + .... + + IRoleManager internal _roleManager; + + modifier onlyRole(bytes32 role) { + _roleManager.checkRole(role, msg.sender); + _; + } + + function updatePRTParams(PRTParams calldata prtParams_) external override onlyRole(keccak256("PRT_PARAM_UPDATER")) { + _prtParams = prtParams_; + } + +} +*/ From 5bbeb1deaad65956a5e01aa45c6c26b7df95319e Mon Sep 17 00:00:00 2001 From: mesowea Date: Tue, 14 Mar 2023 09:45:56 +0200 Subject: [PATCH 3/6] Implement role division on several contracts --- contracts/AssetParameters.sol | 59 +++++- contracts/DefiCore.sol | 12 +- contracts/PRT.sol | 12 +- contracts/Registry.sol | 6 + contracts/RewardsDistribution.sol | 10 +- contracts/RoleManager.sol | 69 +++---- contracts/SystemParameters.sol | 26 ++- contracts/SystemPoolsRegistry.sol | 34 +++- contracts/UserInfoRegistry.sol | 2 + contracts/common/Globals.sol | 18 ++ contracts/interfaces/IRegistry.sol | 5 + contracts/interfaces/IRoleManager.sol | 9 + ds | 273 ++++++++++++++++++++++++++ 13 files changed, 473 insertions(+), 62 deletions(-) create mode 100644 contracts/interfaces/IRoleManager.sol create mode 100644 ds diff --git a/contracts/AssetParameters.sol b/contracts/AssetParameters.sol index 070a5d7..74b91d9 100644 --- a/contracts/AssetParameters.sol +++ b/contracts/AssetParameters.sol @@ -12,6 +12,7 @@ import "./interfaces/IAssetParameters.sol"; import "./interfaces/ISystemPoolsRegistry.sol"; import "./interfaces/IBasicPool.sol"; import "./interfaces/IPriceManager.sol"; +import "./interfaces/IRoleManager.sol"; import "./libraries/PureParameters.sol"; @@ -50,6 +51,7 @@ contract AssetParameters is IAssetParameters, AbstractDependant { address internal _systemOwnerAddr; ISystemParameters internal _systemParameters; ISystemPoolsRegistry internal _systemPoolsRegistry; + IRoleManager internal _roleManager; mapping(bytes32 => mapping(bytes32 => PureParameters.Param)) internal _parameters; @@ -69,12 +71,18 @@ contract AssetParameters is IAssetParameters, AbstractDependant { _; } + modifier onlyHasRoleOrRoleManagerAdmin(bytes32 _role) { + _roleManager.hasRoleOrAdmin(_role, msg.sender); + _; + } + function setDependencies(address contractsRegistry_) external override dependant { IRegistry registry_ = IRegistry(contractsRegistry_); _systemOwnerAddr = registry_.getSystemOwner(); _systemParameters = ISystemParameters(registry_.getSystemParametersContract()); _systemPoolsRegistry = ISystemPoolsRegistry(registry_.getSystemPoolsRegistryContract()); + _roleManager = IRoleManager(registry_.getRoleManagerContract()); } function setPoolInitParams( @@ -103,7 +111,12 @@ contract AssetParameters is IAssetParameters, AbstractDependant { function setupAnnualBorrowRate( bytes32 assetKey_, uint256 newAnnualBorrowRate_ - ) external override onlySystemOwner onlyExists(assetKey_) { + ) + external + override + onlyHasRoleOrRoleManagerAdmin(ASSET_PARAMETERS_MANAGER) + onlyExists(assetKey_) + { require( _systemParameters.getStablePoolsAvailability(), "AssetParameters: Stable pools unavailable." @@ -135,34 +148,61 @@ contract AssetParameters is IAssetParameters, AbstractDependant { function setupMainParameters( bytes32 assetKey_, MainPoolParams calldata mainParams_ - ) external override onlySystemOwner onlyExists(assetKey_) { + ) + external + override + onlyHasRoleOrRoleManagerAdmin(ASSET_PARAMETERS_MANAGER) + onlyExists(assetKey_) + { _setupMainParameters(assetKey_, mainParams_); } function setupInterestRateModel( bytes32 assetKey_, InterestRateParams calldata interestParams_ - ) external override onlySystemOwner onlyExists(assetKey_) { + ) + external + override + onlyHasRoleOrRoleManagerAdmin(ASSET_PARAMETERS_MANAGER) + onlyExists(assetKey_) + { _setupInterestRateParams(assetKey_, interestParams_); } function setupDistributionsMinimums( bytes32 assetKey_, DistributionMinimums calldata distrMinimums_ - ) external override onlySystemOwner onlyExists(assetKey_) { + ) + external + override + onlyHasRoleOrRoleManagerAdmin(ASSET_PARAMETERS_MANAGER) + onlyExists(assetKey_) + { _setupDistributionsMinimums(assetKey_, distrMinimums_); } function setupAllParameters( bytes32 assetKey_, AllPoolParams calldata poolParams_ - ) external override onlySystemOwner onlyExists(assetKey_) { + ) + external + override + onlyHasRoleOrRoleManagerAdmin(ASSET_PARAMETERS_MANAGER) + onlyExists(assetKey_) + { _setupInterestRateParams(assetKey_, poolParams_.interestRateParams); _setupMainParameters(assetKey_, poolParams_.mainParams); _setupDistributionsMinimums(assetKey_, poolParams_.distrMinimums); } - function freeze(bytes32 assetKey_) external override onlySystemOwner onlyExists(assetKey_) { + function freeze( + bytes32 assetKey_ + ) + external + override + onlyHasRoleOrRoleManagerAdmin(ASSET_PARAMETERS_MANAGER) + onlyExists(assetKey_) + { _parameters[assetKey_][FREEZE_KEY] = PureParameters.makeBoolParam(true); emit FreezeParamUpdated(assetKey_, true); @@ -171,7 +211,12 @@ contract AssetParameters is IAssetParameters, AbstractDependant { function enableCollateral( bytes32 assetKey_, bool forPRT_ - ) external override onlySystemOwner onlyExists(assetKey_) { + ) + external + override + onlyHasRoleOrRoleManagerAdmin(ASSET_PARAMETERS_MANAGER) + onlyExists(assetKey_) + { forPRT_ ? _parameters[assetKey_][ENABLE_COLLATERAL_WITH_PRT_KEY] = PureParameters .makeBoolParam(true) diff --git a/contracts/DefiCore.sol b/contracts/DefiCore.sol index 31a34b1..b80eb6b 100644 --- a/contracts/DefiCore.sol +++ b/contracts/DefiCore.sol @@ -19,6 +19,7 @@ import "./interfaces/ISystemPoolsRegistry.sol"; import "./interfaces/IRewardsDistribution.sol"; import "./interfaces/IBasicPool.sol"; import "./interfaces/IPRT.sol"; +import "./interfaces/IRoleManager.sol"; import "./libraries/AssetsHelperLibrary.sol"; import "./libraries/MathHelper.sol"; @@ -43,6 +44,7 @@ contract DefiCore is ISystemPoolsRegistry internal _systemPoolsRegistry; IRewardsDistribution internal _rewardsDistribution; IPRT internal _prt; + IRoleManager internal _roleManager; mapping(address => mapping(bytes32 => bool)) public override disabledCollateralAssets; @@ -54,6 +56,11 @@ contract DefiCore is _; } + modifier onlyHasRoleOrRoleManagerAdmin(bytes32 _role) { + _roleManager.hasRoleOrAdmin(_role, msg.sender); + _; + } + function defiCoreInitialize() external initializer { __Pausable_init(); __ReentrancyGuard_init(); @@ -69,13 +76,14 @@ contract DefiCore is _rewardsDistribution = IRewardsDistribution(registry_.getRewardsDistributionContract()); _systemPoolsRegistry = ISystemPoolsRegistry(registry_.getSystemPoolsRegistryContract()); _prt = IPRT(registry_.getPRTContract()); + _roleManager = IRoleManager(registry_.getRoleManagerContract()); } - function pause() external override onlySystemOwner { + function pause() external override onlyHasRoleOrRoleManagerAdmin(DEFI_CORE_PAUSER) { _pause(); } - function unpause() external override onlySystemOwner { + function unpause() external override onlyHasRoleOrRoleManagerAdmin(DEFI_CORE_PAUSER) { _unpause(); } diff --git a/contracts/PRT.sol b/contracts/PRT.sol index ec3096e..dc9ce6f 100644 --- a/contracts/PRT.sol +++ b/contracts/PRT.sol @@ -10,6 +10,7 @@ import "./interfaces/IPRT.sol"; import "./interfaces/IRegistry.sol"; import "./interfaces/IDefiCore.sol"; import "./interfaces/IUserInfoRegistry.sol"; +import "./interfaces/IRoleManager.sol"; import "./common/Globals.sol"; @@ -18,6 +19,7 @@ contract PRT is IPRT, ERC721Upgradeable, AbstractDependant, ReentrancyGuardUpgra address internal _systemOwnerAddr; IDefiCore internal _defiCore; IUserInfoRegistry internal _userInfoRegistry; + IRoleManager internal _roleManager; PRTParams internal _prtParams; @@ -26,6 +28,11 @@ contract PRT is IPRT, ERC721Upgradeable, AbstractDependant, ReentrancyGuardUpgra _; } + modifier onlyHasRoleOrRoleManagerAdmin(bytes32 _role) { + _roleManager.hasRoleOrAdmin(_role, msg.sender); + _; + } + function prtInitialize( string calldata name_, string calldata symbol_, @@ -42,9 +49,12 @@ contract PRT is IPRT, ERC721Upgradeable, AbstractDependant, ReentrancyGuardUpgra _systemOwnerAddr = registry_.getSystemOwner(); _defiCore = IDefiCore(registry_.getDefiCoreContract()); _userInfoRegistry = IUserInfoRegistry(registry_.getUserInfoRegistryContract()); + _roleManager = IRoleManager(registry_.getRoleManagerContract()); } - function updatePRTParams(PRTParams calldata prtParams_) external override onlySystemOwner { + function updatePRTParams( + PRTParams calldata prtParams_ + ) external override onlyHasRoleOrRoleManagerAdmin(PRT_PARAM_UPDATER) { _prtParams = prtParams_; } diff --git a/contracts/Registry.sol b/contracts/Registry.sol index cf0d9fb..0c4a67f 100644 --- a/contracts/Registry.sol +++ b/contracts/Registry.sol @@ -23,6 +23,8 @@ contract Registry is IRegistry, OwnableContractsRegistry { string public constant PRT_NAME = "PLATFORM_REPUTATION_TOKEN"; + string public constant ROLE_MANAGER_NAME = "ROLE_MANAGER_NAME"; + function transferOwnershipAndInject( address newOwner_, string[] calldata names_ @@ -83,4 +85,8 @@ contract Registry is IRegistry, OwnableContractsRegistry { function getPRTContract() external view override returns (address) { return getContract(PRT_NAME); } + + function getRoleManagerContract() external view override returns (address) { + return getContract(ROLE_MANAGER_NAME); + } } diff --git a/contracts/RewardsDistribution.sol b/contracts/RewardsDistribution.sol index d10bdbf..80ea846 100644 --- a/contracts/RewardsDistribution.sol +++ b/contracts/RewardsDistribution.sol @@ -10,6 +10,7 @@ import "./interfaces/IAssetParameters.sol"; import "./interfaces/IRewardsDistribution.sol"; import "./interfaces/ISystemPoolsRegistry.sol"; import "./interfaces/IBasicPool.sol"; +import "./interfaces/IRoleManager.sol"; import "./libraries/MathHelper.sol"; @@ -22,6 +23,7 @@ contract RewardsDistribution is IRewardsDistribution, AbstractDependant { address internal _defiCoreAddr; IAssetParameters internal _assetParameters; ISystemPoolsRegistry internal _systemPoolsRegistry; + IRoleManager internal _roleManager; mapping(bytes32 => LiquidityPoolInfo) public liquidityPoolsInfo; mapping(bytes32 => mapping(address => UserDistributionInfo)) public usersDistributionInfo; @@ -42,6 +44,11 @@ contract RewardsDistribution is IRewardsDistribution, AbstractDependant { _; } + modifier onlyHasRoleOrRoleManagerAdmin(bytes32 _role) { + _roleManager.hasRoleOrAdmin(_role, msg.sender); + _; + } + function setDependencies(address contractsRegistry_) external override dependant { IRegistry registry_ = IRegistry(contractsRegistry_); @@ -49,6 +56,7 @@ contract RewardsDistribution is IRewardsDistribution, AbstractDependant { _defiCoreAddr = registry_.getDefiCoreContract(); _assetParameters = IAssetParameters(registry_.getAssetParametersContract()); _systemPoolsRegistry = ISystemPoolsRegistry(registry_.getSystemPoolsRegistryContract()); + _roleManager = IRoleManager(registry_.getRoleManagerContract()); } function updateCumulativeSums( @@ -85,7 +93,7 @@ contract RewardsDistribution is IRewardsDistribution, AbstractDependant { function setupRewardsPerBlockBatch( bytes32[] calldata assetKeys_, uint256[] calldata rewardsPerBlock_ - ) external override onlySystemOwner { + ) external override onlyHasRoleOrRoleManagerAdmin(REWARDS_DISTRIBUTION_MANAGER) { require( _onlyExistingRewardsAssetKey(), "RewardsDistributionL Unable to setup rewards per block." diff --git a/contracts/RoleManager.sol b/contracts/RoleManager.sol index 7d2082d..cda74c2 100644 --- a/contracts/RoleManager.sol +++ b/contracts/RoleManager.sol @@ -2,53 +2,47 @@ pragma solidity 0.8.17; import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; -contract RoleManager is AccessControlUpgradeable { - bytes32 public constant ROLE_MANAGER_ADMIN = keccak256("ROLE_MANAGER_ADMIN"); - - bytes32 public constant ASSET_PARAMETERS_PARAM_SETTER = - keccak256("ASSET_PARAMETERS_PARAM_SETTER"); - bytes32 public constant ASSET_PARAMETERS_FREEZER = keccak256("ASSET_PARAMETERS_FREEZER"); - bytes32 public constant ASSET_PARAMETERS_COLLATERAL_ENABLER = - keccak256("ASSET_PARAMETERS_COLLATERAL_ENABLER"); - - bytes32 public constant DEFI_CORE_PAUZER = keccak256("DEFI_CORE_PAUZER"); - - bytes32 public constant PRT_PARAM_UPDATER = keccak256("PRT_PARAM_UPDATER"); +import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; - bytes32 public constant REGISTRY_OWNER_UPDATER_AND_INJECTOR = - keccak256("REGISTRY_OWNER_UPDATER_AND_INJECTOR"); +import "./common/Globals.sol"; - bytes32 public constant REWARDS_DISTRIBUTION_REWARDS_SETTER = - keccak256("REWARDS_DISTRIBUTION_REWARDS_SETTER"); +contract RoleManager is AccessControlUpgradeable { + function roleManagerInitialize() external initializer { + _setupRole(ROLE_MANAGER_ADMIN, msg.sender); + } - bytes32 public constant SYSTEM_PARAMETERS_REWARDS_TOKEN_SETTER = - keccak256("SYSTEM_PARAMETERS_REWARDS_TOKEN_SETTER"); - bytes32 public constant SYSTEM_PARAMETERS_LIQUIDATION_BOUNDARY_SETTER = - keccak256("SYSTEM_PARAMETERS_LIQUIDATION_BOUNDARY_SETTER"); - bytes32 public constant SYSTEM_PARAMETERS_STABLE_POOLS_AVAILABILITY_SETTER = - keccak256("SYSTEM_PARAMETERS_STABLE_POOLS_AVAILABILITY_SETTER"); - bytes32 public constant SYSTEM_PARAMETERS_MIN_CURRENCY_AMOUNT_SETTER = - keccak256("SYSTEM_PARAMETERS_MIN_CURRENCY_AMOUNT_SETTER"); + function hasRoleOrAdmin(bytes32 role_, address account_) public view virtual { + require( + hasRole(role_, account_) || hasRole(ROLE_MANAGER_ADMIN, account_), + string( + abi.encodePacked( + "RoleManager: account is missing role ", + StringsUpgradeable.toHexString(uint256(role_), 32) + ) + ) + ); + } - bytes32 public constant SYSTEM_POOLS_REGISTRY_POOLS_MANAGER = - keccak256("SYSTEM_POOLS_REGISTRY_POOLS_MANAGER"); - //Should create an injector for every contract which has dependencies? - bytes32 public constant SYSTEM_POOLS_REGISTRY_INJECTOR = - keccak256("SYSTEM_POOLS_REGISTRY_INJECTOR"); - bytes32 public constant SYSTEM_POOLS_RESERVE_FUNDS_MANAGER = - keccak256("SYSTEM_POOLS_RESERVE_FUNDS_MANAGER"); + function grantRole(bytes32 role_, address account_) public override { + require( + hasRole(ROLE_MANAGER_ADMIN, msg.sender), + "RoleManager: only ROLE_MANAGER_ADMIN can grant roles" + ); - function roleManagerInitialize() external initializer { - _setupRole(ROLE_MANAGER_ADMIN, msg.sender); - _setRoleAdmin(ROLE_MANAGER_ADMIN, ROLE_MANAGER_ADMIN); + _grantRole(role_, account_); } - function checkRole(bytes32 role, address account) public view virtual { - _checkRole(role, account); + function revokeRole(bytes32 role_, address account_) public override { + require( + hasRole(ROLE_MANAGER_ADMIN, msg.sender), + "RoleManager: only ROLE_MANAGER_ADMIN can revoke roles" + ); + + _revokeRole(role_, account_); } } -/*example: +/*example: pragma solidity 0.8.17; @@ -66,6 +60,7 @@ contract PRT is IPRT, ERC721Upgradeable, AbstractDependant, ReentrancyGuardUpgra } function updatePRTParams(PRTParams calldata prtParams_) external override onlyRole(keccak256("PRT_PARAM_UPDATER")) { + _prtParams = prtParams_; } diff --git a/contracts/SystemParameters.sol b/contracts/SystemParameters.sol index f56e3a6..c29c0f2 100644 --- a/contracts/SystemParameters.sol +++ b/contracts/SystemParameters.sol @@ -5,6 +5,7 @@ import "@dlsl/dev-modules/contracts-registry/AbstractDependant.sol"; import "./interfaces/IRegistry.sol"; import "./interfaces/ISystemParameters.sol"; +import "./interfaces/IRoleManager.sol"; import "./libraries/PureParameters.sol"; @@ -19,6 +20,7 @@ contract SystemParameters is ISystemParameters, AbstractDependant { bytes32 public constant MIN_CURRENCY_AMOUNT_KEY = keccak256("MIN_CURRENCY_AMOUNT"); address internal _systemOwnerAddr; + IRoleManager internal _roleManager; mapping(bytes32 => PureParameters.Param) internal _parameters; @@ -30,11 +32,21 @@ contract SystemParameters is ISystemParameters, AbstractDependant { _; } + modifier onlyHasRoleOrRoleManagerAdmin(bytes32 _role) { + _roleManager.hasRoleOrAdmin(_role, msg.sender); + _; + } + function setDependencies(address contractsRegistry_) external override dependant { - _systemOwnerAddr = IRegistry(contractsRegistry_).getSystemOwner(); + IRegistry registry_ = IRegistry(contractsRegistry_); + + _systemOwnerAddr = registry_.getSystemOwner(); + _roleManager = IRoleManager(registry_.getRoleManagerContract()); } - function setRewardsTokenAddress(address rewardsToken_) external override onlySystemOwner { + function setRewardsTokenAddress( + address rewardsToken_ + ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_PARAMETERS_MANAGER) { PureParameters.Param memory currentParam_ = _parameters[REWARDS_TOKEN_KEY]; if (PureParameters.paramExists(currentParam_)) { @@ -49,7 +61,9 @@ contract SystemParameters is ISystemParameters, AbstractDependant { emit RewardsTokenUpdated(rewardsToken_); } - function setupLiquidationBoundary(uint256 newValue_) external override onlySystemOwner { + function setupLiquidationBoundary( + uint256 newValue_ + ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_PARAMETERS_MANAGER) { require( newValue_ >= PRECISION * 50 && newValue_ <= PRECISION * 80, "SystemParameters: The new value of the liquidation boundary is invalid." @@ -60,7 +74,9 @@ contract SystemParameters is ISystemParameters, AbstractDependant { emit LiquidationBoundaryUpdated(newValue_); } - function setupStablePoolsAvailability(bool newValue_) external override onlySystemOwner { + function setupStablePoolsAvailability( + bool newValue_ + ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_PARAMETERS_MANAGER) { _parameters[STABLE_POOLS_AVAILABILITY_KEY] = PureParameters.makeBoolParam(newValue_); emit StablePoolsAvailabilityUpdated(newValue_); @@ -68,7 +84,7 @@ contract SystemParameters is ISystemParameters, AbstractDependant { function setupMinCurrencyAmount( uint256 newMinCurrencyAmount_ - ) external override onlySystemOwner { + ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_PARAMETERS_MANAGER) { _parameters[MIN_CURRENCY_AMOUNT_KEY] = PureParameters.makeUintParam(newMinCurrencyAmount_); emit MinCurrencyAmountUpdated(newMinCurrencyAmount_); diff --git a/contracts/SystemPoolsRegistry.sol b/contracts/SystemPoolsRegistry.sol index 6a2593e..3b458f6 100644 --- a/contracts/SystemPoolsRegistry.sol +++ b/contracts/SystemPoolsRegistry.sol @@ -18,6 +18,9 @@ import "./interfaces/ISystemPoolsRegistry.sol"; import "./interfaces/IBasicPool.sol"; import "./interfaces/IPriceManager.sol"; import "./interfaces/ISystemPoolsFactory.sol"; +import "./interfaces/IRoleManager.sol"; + +import "./common/Globals.sol"; contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDependant { using Paginator for EnumerableSet.Bytes32Set; @@ -35,6 +38,7 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep IRewardsDistribution internal _rewardsDistribution; ISystemPoolsFactory internal _systemPoolsFactory; IPriceManager internal _priceManager; + IRoleManager internal _roleManager; EnumerableSet.Bytes32Set internal _allSupportedAssetKeys; mapping(bytes32 => PoolInfo) public override poolsInfo; @@ -49,6 +53,11 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep _; } + modifier onlyHasRoleOrRoleManagerAdmin(bytes32 _role) { + _roleManager.hasRoleOrAdmin(_role, msg.sender); + _; + } + function systemPoolsRegistryInitialize( address liquidityPoolImpl_, bytes32 nativeAssetKey_, @@ -73,9 +82,12 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep _priceManager = IPriceManager(registry_.getPriceManagerContract()); _rewardsDistribution = IRewardsDistribution(registry_.getRewardsDistributionContract()); _systemPoolsFactory = ISystemPoolsFactory(registry_.getSystemPoolsFactoryContract()); + _roleManager = IRoleManager(registry_.getRoleManagerContract()); } - function updateRewardsAssetKey(bytes32 newRewardsAssetKey_) external onlySystemOwner { + function updateRewardsAssetKey( + bytes32 newRewardsAssetKey_ + ) external onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_MANAGER) { require( IBasicPool(poolsInfo[newRewardsAssetKey_].poolAddr).assetAddr() == _systemParameters.getRewardsTokenAddress(), @@ -88,7 +100,7 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep function addPoolsBeacon( PoolType poolType_, address poolImpl_ - ) external override onlySystemOwner { + ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_MANAGER) { PoolTypeInfo storage _poolTypeInfo = _poolTypesInfo[poolType_]; require( @@ -106,7 +118,7 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep string calldata tokenSymbol_, bool isCollateral_, bool isCollateralWithPRT_ - ) external override onlySystemOwner { + ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_MANAGER) { _addPool( assetAddr_, assetKey_, @@ -122,7 +134,7 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep address assetAddr_, bytes32 assetKey_, address chainlinkOracle_ - ) external override onlySystemOwner { + ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_MANAGER) { require( _systemParameters.getStablePoolsAvailability(), "SystemPoolsRegistry: Stable pools are unavailable." @@ -136,7 +148,7 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep bytes32 assetKey_, uint256 amountToWithdraw_, bool isAllFunds_ - ) external override onlySystemOwner { + ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_RESERVE_FUNDS_MANAGER) { require(onlyExistingPool(assetKey_), "SystemPoolsRegistry: Pool doesn't exist."); if (!isAllFunds_) { @@ -157,7 +169,7 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep address recipientAddr_, uint256 offset_, uint256 limit_ - ) external override onlySystemOwner { + ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_RESERVE_FUNDS_MANAGER) { bytes32[] memory _assetsKeys = getSupportedAssetKeys(offset_, limit_); for (uint256 i = 0; i < _assetsKeys.length; i++) { @@ -172,7 +184,7 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep function upgradePoolsImpl( PoolType poolType_, address newPoolsImpl_ - ) external override onlySystemOwner { + ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_MANAGER) { address poolBeacon_ = _poolTypesInfo[poolType_].poolBeaconAddr; require(poolBeacon_ != address(0), "SystemPoolsRegistry: Unsupported pool type."); @@ -180,7 +192,11 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep UpgradeableBeacon(poolBeacon_).upgradeTo(newPoolsImpl_); } - function injectDependenciesToExistingPools() external override onlySystemOwner { + function injectDependenciesToExistingPools() + external + override + onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_MANAGER) + { IRegistry registry_ = _registry; address[] memory allPools_ = getAllPools(); @@ -193,7 +209,7 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep function injectDependencies( uint256 offset_, uint256 limit_ - ) external override onlySystemOwner { + ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_MANAGER) { IRegistry registry_ = _registry; address[] memory _pools = getPools(offset_, limit_); diff --git a/contracts/UserInfoRegistry.sol b/contracts/UserInfoRegistry.sol index 85d3ad5..31ece18 100644 --- a/contracts/UserInfoRegistry.sol +++ b/contracts/UserInfoRegistry.sol @@ -22,6 +22,8 @@ import "./interfaces/IPRT.sol"; import "./libraries/AssetsHelperLibrary.sol"; import "./libraries/MathHelper.sol"; +import "./common/Globals.sol"; + contract UserInfoRegistry is IUserInfoRegistry, AbstractDependant { using EnumerableSet for EnumerableSet.Bytes32Set; using AssetsHelperLibrary for bytes32; diff --git a/contracts/common/Globals.sol b/contracts/common/Globals.sol index 07e9885..0f9523f 100644 --- a/contracts/common/Globals.sol +++ b/contracts/common/Globals.sol @@ -7,3 +7,21 @@ uint256 constant BLOCKS_PER_DAY = 4900; uint256 constant BLOCKS_PER_YEAR = BLOCKS_PER_DAY * 365; uint8 constant PRICE_DECIMALS = 8; + +bytes32 constant ROLE_MANAGER_ADMIN = keccak256("ROLE_MANAGER_ADMIN"); + +bytes32 constant ASSET_PARAMETERS_MANAGER = keccak256("ASSET_PARAMETERS_MANAGER"); + +bytes32 constant DEFI_CORE_PAUSER = keccak256("DEFI_CORE_PAUSER"); + +bytes32 constant PRT_PARAM_UPDATER = keccak256("PRT_PARAM_UPDATER"); + +bytes32 constant REWARDS_DISTRIBUTION_MANAGER = keccak256("REWARDS_DISTRIBUTION_MANAGER"); + +bytes32 constant SYSTEM_PARAMETERS_MANAGER = keccak256("SYSTEM_PARAMETERS_MANAGER"); + +bytes32 constant SYSTEM_POOLS_MANAGER = keccak256("SYSTEM_POOLS_MANAGER"); + +bytes32 constant SYSTEM_POOLS_RESERVE_FUNDS_MANAGER = keccak256( + "SYSTEM_POOLS_RESERVE_FUNDS_MANAGER" +); diff --git a/contracts/interfaces/IRegistry.sol b/contracts/interfaces/IRegistry.sol index 2771bd2..f34852e 100644 --- a/contracts/interfaces/IRegistry.sol +++ b/contracts/interfaces/IRegistry.sol @@ -65,4 +65,9 @@ interface IRegistry { /// @dev Used in dependency injection mechanism in the system /// @return PRT contract address function getPRTContract() external view returns (address); + + /// @notice Function to get the address of the RoleManager contract + /// @dev Used in dependency injection mechanism in the system + /// @return RoleManager contract address + function getRoleManagerContract() external view returns (address); } diff --git a/contracts/interfaces/IRoleManager.sol b/contracts/interfaces/IRoleManager.sol new file mode 100644 index 0000000..306e182 --- /dev/null +++ b/contracts/interfaces/IRoleManager.sol @@ -0,0 +1,9 @@ +pragma solidity 0.8.17; + +interface IRoleManager { + function hasRoleOrAdmin(bytes32 role_, address account_) external view; + + function grantRole(bytes32 role_, address account_) external; + + function revokeRole(bytes32 role, address account) external; +} diff --git a/ds b/ds new file mode 100644 index 0000000..7d7d381 --- /dev/null +++ b/ds @@ -0,0 +1,273 @@ +commit 6ce88979061904e462689ac342e6c6fae0c76847 (HEAD -> feature/roles) +Merge: 38079c0 4aec8b1 +Author: mesowea +Date: Mon Mar 13 15:22:54 2023 +0200 + + Merge branch 'main' into feature/roles + +commit 38079c0027351358136aba14ffde73485958a50b (origin/feature/roles) +Author: mesowea +Date: Mon Mar 13 14:18:23 2023 +0200 + + Add RoleManager contract, add roles constants, public function to check roles and implementation exapmple + +commit b7220a0d250d7f392ad08a95813927726c96a987 (origin/feature/PRT, feature/PRT) +Author: mesowea +Date: Mon Mar 13 00:09:19 2023 +0200 + + Add comments to IRegistry.sol and IUserInfoRegistry.sol expalining what do the updateUserStatsForPRT and transferOwnershipAndInject functions do + +commit 4aec8b1043d134b2a2ad37367e60327a52bef347 (origin/main, origin/HEAD, main) +Merge: 5998c98 088883f +Author: Oleg Komendant <44612825+Hrom131@users.noreply.github.com> +Date: Thu Mar 2 15:50:55 2023 +0200 + + Merge pull request #4 from defaino/feature/PRT + + Coverage Increase + +commit 088883fe54b1bc7a1853d74fdb51f3a71a01a901 +Author: mesowea +Date: Thu Mar 2 15:47:59 2023 +0200 + + package.json fix + +commit 64fc97516f253641c539f5067466348d3fe3713f +Author: mesowea +Date: Thu Mar 2 14:48:13 2023 +0200 + + Add 'modifierWhitelist' to solcover.js with 'nonReentrant' and 'dependant' modifiers + +commit ad323629142c5ccbf5c3986cd97b8ac2c2784e7b +Author: mesowea +Date: Tue Feb 28 04:30:50 2023 +0200 + + Increase AbstractPool, WETH, UserInfoRegistry, RewardsDistribution coverage + +commit 68231d84dfa4df784006a2ecb22d8f1ec34b8d27 +Author: mesowea +Date: Sun Feb 26 00:56:54 2023 +0200 + + Increase coverage to almost 100%, skip nonReentrant and some unreachable paths + +commit 5998c98dfad7129f14376176c12acbd62f55ade5 +Merge: 0f8542b fd0daf1 +Author: Oleg Komendant <44612825+Hrom131@users.noreply.github.com> +Date: Mon Feb 20 16:50:35 2023 +0200 + + Merge pull request #3 from defaino/feature/PRT + + PRT feature + +commit fd0daf16cfce87917c084f9203fb88763a8b9655 +Author: mesowea +Date: Fri Feb 17 16:16:07 2023 +0200 + + Fix style, 'getUsersLiquidiationInfo' test + +commit f1bb9c9870658f0fdb15ced0200b41a3bf01f3fb +Author: mesowea +Date: Wed Feb 15 02:21:00 2023 +0200 + + Increase PRT coverage to 100%, add comments in PRT and UserInfoRegistry interfaces + +commit e1ecdbe3353282b597751504febea8d7c1e816f0 +Author: mesowea +Date: Tue Feb 14 01:12:40 2023 +0200 + + Add PRT tests, edit deploy migration taking into account prt contract and params that differ for users with prt + +commit 84720a466f77cd746549d686aedb86517a65b716 +Author: mesowea +Date: Sat Feb 11 15:32:56 2023 +0200 + + Add PRT contract, PRT stats calculations and special pool parameters for the users with PRT + +commit 0f8542bf653d21b013d4d03b83b59e0f8fc971c7 +Author: Yaroslav Panasenko +Date: Thu Feb 9 19:53:40 2023 +0200 + + Add license + +commit 192f416804a6d5387758f454c502f56cd6859804 +Merge: 8c82564 520a488 +Author: Oleh Komendant +Date: Mon Jan 30 11:37:19 2023 +0000 + + Merge branch 'feature/ownership' into 'main' + + Add transferOwnershipAndInject, tests and needed mocks + + See merge request dl-defi-core/contracts!4 + +commit 520a4881be4942b92214eb67ac26fea969058fbe +Author: mesowea +Date: Fri Jan 13 18:11:49 2023 +0200 + + Fix test for renounceOwnership() + +commit 51ddbea17e6e3f1e46962e03f27b2fddd1258934 +Author: mesowea +Date: Fri Jan 13 18:08:28 2023 +0200 + + Add a reverting renounceOwnership(), add a check for the address(0) in transferwnershipndnject, fix the tests + +commit c2b9ca77abf0833d528f6271c4599dfb60e5fa5d +Author: mesowea +Date: Thu Jan 12 16:53:20 2023 +0200 + + fix missing mocks and test + +commit c91e84765cd7d73c352d96c95405980beedafba7 +Author: mesowea +Date: Thu Jan 12 16:48:10 2023 +0200 + + Add transferOwnershipAndInject, tests and needed mocks + +commit 8c825640e0ebe169e58dba7087fbbc0abebbf0cc +Merge: 7c1d933 a76c26f +Author: Oleh Komendant +Date: Fri Jan 6 12:50:24 2023 +0000 + + Merge branch 'feature/global_update' into 'main' + + Feature/global update + + See merge request dl-defi-core/contracts!2 + +commit a76c26ffe848296d8854f08e0175b63d3f8438c4 +Author: oleg.komendant +Date: Fri Jan 6 14:49:14 2023 +0200 + + Fix coverage + +commit f73ab0a367e69d6ae3add3b33247f0a5d03ddf0e +Author: oleg.komendant +Date: Mon Jan 2 19:47:40 2023 +0200 + + Update code style + +commit 22a84eb939ade225fe5a801546baf381302768c6 +Author: oleg.komendant +Date: Tue Dec 27 14:51:51 2022 +0200 + + Update deploy scripts + +commit cd8b9adce052908e82c9ea694748bf7e818176f1 +Author: oleg.komendant +Date: Mon Dec 26 16:47:29 2022 +0200 + + Update contracts to new version + +commit 7c1d933aa47e6b43874182bae347e8f641a9fd5b +Merge: e4313d5 73457d9 +Author: Oleh Komendant +Date: Sat Mar 19 15:13:30 2022 +0000 + + Merge branch 'fix/contracts_refactoring' into 'main' + + Fix/contracts refactoring + + See merge request dl-defi-core/contracts!1 + +commit 73457d9ce31d4a166a8058fbefa2eb9f389a13e9 +Author: oleg.komendant +Date: Sat Mar 19 17:09:06 2022 +0200 + + Fix bug with liquidation logic + +commit 640bf003708b53ee7314c18dbfb0e78a3795b82f +Author: oleg.komendant +Date: Sat Mar 19 14:55:14 2022 +0200 + + Add SafeERC20 library + +commit 2d59a353f52db00d1233d4731ab48a29dcbd1c3f +Author: oleg.komendant +Date: Thu Mar 17 23:06:22 2022 +0200 + + Refactor and optimize contracts + +commit 09b7da98e8b712a3e6e0ebd432a226cccb3aed42 +Author: oleg.komendant +Date: Thu Mar 17 20:49:02 2022 +0200 + + Add new unit tests + +commit 7537d6b791129803854d2be3bea44d3de07182cb +Author: oleg.komendant +Date: Thu Mar 17 00:10:29 2022 +0200 + + Fix InterestRate library and unit tests + +commit 38e6255067f7f75fed769419b21b36ad819bd0d2 +Author: oleg.komendant +Date: Wed Mar 16 22:58:25 2022 +0200 + + Add documentation comments; fix functions order; fix some bugs + +commit d775df2589b13dd6dc1f06185216981dba54b732 +Author: oleg.komendant +Date: Mon Mar 14 20:33:04 2022 +0200 + + Rewrite migrations and upgrade hardhat files + +commit 0d6d4aefbb6bb2119b459953cc6bc404c58605be +Author: oleg.komendant +Date: Fri Mar 11 20:29:18 2022 +0200 + + Update tests and remove unused files + +commit 233d4ca70a4d0c25ea02657d4c7c13008f766a37 +Author: oleg.komendant +Date: Wed Mar 9 14:15:51 2022 +0200 + + Rename N tokens to LP tokens; remove useless test files + +commit 30a14b6c645a35f461a8fca89fc6fad528683421 +Author: oleg.komendant +Date: Tue Mar 8 20:53:30 2022 +0200 + + Rewrite contracts for frontend + +commit 63c5141657b718b62e33feb5676d447a34fe83c4 +Author: oleg.komendant +Date: Tue Mar 1 17:00:58 2022 +0200 + + Move to Beacon proxy implementation + +commit e2295acca72af5cdef55010f7e6d67397454608d +Author: oleg.komendant +Date: Tue Mar 1 16:16:29 2022 +0200 + + Move AbstractDependant contract to abstract folder + +commit 75237bb6957825e252e56ea2ee92541f12ecd921 +Author: oleg.komendant +Date: Tue Mar 1 16:11:18 2022 +0200 + + Remove integration part + +commit 662bb39a30c40c0fe23dfcb9f8cc9ffd1b084939 +Author: oleg.komendant +Date: Mon Feb 28 15:57:30 2022 +0200 + + Update to latest version + +commit 773ba8a2e10dd8a5ecd9fa121f9764a64646c446 +Author: oleg.komendant +Date: Mon Feb 28 14:26:45 2022 +0200 + + Setup hardhat env + +commit e4313d5c0b3559d7bfeadc58e84cdece6064ddba +Author: oleg.komendant +Date: Mon Feb 28 12:53:59 2022 +0200 + + Initial commit + +commit c1c345073a0a6d7c43eed63e3f3834ef7b3498ee +Author: Oleh Komendant +Date: Mon Feb 28 10:38:04 2022 +0000 + + Initial commit From 1125f46d117910ad44520a0f725c02a98467384a Mon Sep 17 00:00:00 2001 From: mesowea Date: Thu, 16 Mar 2023 00:14:51 +0200 Subject: [PATCH 4/6] Chnage roles mechanism: add view functions to RoleManager to check the roles, add calls to such functions in dependant contract --- contracts/AssetParameters.sol | 82 +++++++------------- contracts/DefiCore.sol | 25 +++---- contracts/PRT.sol | 18 +---- contracts/RewardsDistribution.sol | 17 +---- contracts/RoleManager.sol | 103 ++++++++++++++++---------- contracts/SystemParameters.sol | 41 ++++------ contracts/SystemPoolsRegistry.sol | 74 +++++++++--------- contracts/UserInfoRegistry.sol | 2 - contracts/common/Globals.sol | 18 ----- contracts/interfaces/IRoleManager.sol | 16 +++- 10 files changed, 168 insertions(+), 228 deletions(-) diff --git a/contracts/AssetParameters.sol b/contracts/AssetParameters.sol index 74b91d9..69677f8 100644 --- a/contracts/AssetParameters.sol +++ b/contracts/AssetParameters.sol @@ -63,19 +63,6 @@ contract AssetParameters is IAssetParameters, AbstractDependant { _; } - modifier onlySystemOwner() { - require( - msg.sender == _systemOwnerAddr, - "AssetParameters: Only system owner can call this function." - ); - _; - } - - modifier onlyHasRoleOrRoleManagerAdmin(bytes32 _role) { - _roleManager.hasRoleOrAdmin(_role, msg.sender); - _; - } - function setDependencies(address contractsRegistry_) external override dependant { IRegistry registry_ = IRegistry(contractsRegistry_); @@ -111,12 +98,9 @@ contract AssetParameters is IAssetParameters, AbstractDependant { function setupAnnualBorrowRate( bytes32 assetKey_, uint256 newAnnualBorrowRate_ - ) - external - override - onlyHasRoleOrRoleManagerAdmin(ASSET_PARAMETERS_MANAGER) - onlyExists(assetKey_) - { + ) external override onlyExists(assetKey_) { + _onlyAssetParametersManager(); + require( _systemParameters.getStablePoolsAvailability(), "AssetParameters: Stable pools unavailable." @@ -148,61 +132,44 @@ contract AssetParameters is IAssetParameters, AbstractDependant { function setupMainParameters( bytes32 assetKey_, MainPoolParams calldata mainParams_ - ) - external - override - onlyHasRoleOrRoleManagerAdmin(ASSET_PARAMETERS_MANAGER) - onlyExists(assetKey_) - { + ) external override onlyExists(assetKey_) { + _onlyAssetParametersManager(); + _setupMainParameters(assetKey_, mainParams_); } function setupInterestRateModel( bytes32 assetKey_, InterestRateParams calldata interestParams_ - ) - external - override - onlyHasRoleOrRoleManagerAdmin(ASSET_PARAMETERS_MANAGER) - onlyExists(assetKey_) - { + ) external override onlyExists(assetKey_) { + _onlyAssetParametersManager(); + _setupInterestRateParams(assetKey_, interestParams_); } function setupDistributionsMinimums( bytes32 assetKey_, DistributionMinimums calldata distrMinimums_ - ) - external - override - onlyHasRoleOrRoleManagerAdmin(ASSET_PARAMETERS_MANAGER) - onlyExists(assetKey_) - { + ) external override onlyExists(assetKey_) { + _onlyAssetParametersManager(); + _setupDistributionsMinimums(assetKey_, distrMinimums_); } function setupAllParameters( bytes32 assetKey_, AllPoolParams calldata poolParams_ - ) - external - override - onlyHasRoleOrRoleManagerAdmin(ASSET_PARAMETERS_MANAGER) - onlyExists(assetKey_) - { + ) external override onlyExists(assetKey_) { + _onlyAssetParametersManager(); + _setupInterestRateParams(assetKey_, poolParams_.interestRateParams); _setupMainParameters(assetKey_, poolParams_.mainParams); _setupDistributionsMinimums(assetKey_, poolParams_.distrMinimums); } - function freeze( - bytes32 assetKey_ - ) - external - override - onlyHasRoleOrRoleManagerAdmin(ASSET_PARAMETERS_MANAGER) - onlyExists(assetKey_) - { + function freeze(bytes32 assetKey_) external override onlyExists(assetKey_) { + _onlyAssetParametersManager(); + _parameters[assetKey_][FREEZE_KEY] = PureParameters.makeBoolParam(true); emit FreezeParamUpdated(assetKey_, true); @@ -211,12 +178,9 @@ contract AssetParameters is IAssetParameters, AbstractDependant { function enableCollateral( bytes32 assetKey_, bool forPRT_ - ) - external - override - onlyHasRoleOrRoleManagerAdmin(ASSET_PARAMETERS_MANAGER) - onlyExists(assetKey_) - { + ) external override onlyExists(assetKey_) { + _onlyAssetParametersManager(); + forPRT_ ? _parameters[assetKey_][ENABLE_COLLATERAL_WITH_PRT_KEY] = PureParameters .makeBoolParam(true) @@ -300,6 +264,10 @@ contract AssetParameters is IAssetParameters, AbstractDependant { return _getParam(assetKey_, MAX_UTILIZATION_RATIO_KEY).getUintFromParam(); } + function _onlyAssetParametersManager() internal { + _roleManager.isAssetParametersManager(msg.sender); + } + function _setupInterestRateParams( bytes32 assetKey_, InterestRateParams calldata interestParams_ diff --git a/contracts/DefiCore.sol b/contracts/DefiCore.sol index b80eb6b..9bb7afe 100644 --- a/contracts/DefiCore.sol +++ b/contracts/DefiCore.sol @@ -48,19 +48,6 @@ contract DefiCore is mapping(address => mapping(bytes32 => bool)) public override disabledCollateralAssets; - modifier onlySystemOwner() { - require( - msg.sender == _systemOwnerAddr, - "DefiCore: Only system owner can call this function." - ); - _; - } - - modifier onlyHasRoleOrRoleManagerAdmin(bytes32 _role) { - _roleManager.hasRoleOrAdmin(_role, msg.sender); - _; - } - function defiCoreInitialize() external initializer { __Pausable_init(); __ReentrancyGuard_init(); @@ -79,11 +66,15 @@ contract DefiCore is _roleManager = IRoleManager(registry_.getRoleManagerContract()); } - function pause() external override onlyHasRoleOrRoleManagerAdmin(DEFI_CORE_PAUSER) { + function pause() external override { + _onlyDefiCorePauser(); + _pause(); } - function unpause() external override onlyHasRoleOrRoleManagerAdmin(DEFI_CORE_PAUSER) { + function unpause() external override { + _onlyDefiCorePauser(); + _unpause(); } @@ -653,6 +644,10 @@ contract DefiCore is } } + function _onlyDefiCorePauser() internal { + _roleManager.isDefiCorePauser(msg.sender); + } + function _borrowInternal( bytes32 assetKey_, uint256 borrowAmount_, diff --git a/contracts/PRT.sol b/contracts/PRT.sol index dc9ce6f..5e5256e 100644 --- a/contracts/PRT.sol +++ b/contracts/PRT.sol @@ -12,8 +12,6 @@ import "./interfaces/IDefiCore.sol"; import "./interfaces/IUserInfoRegistry.sol"; import "./interfaces/IRoleManager.sol"; -import "./common/Globals.sol"; - contract PRT is IPRT, ERC721Upgradeable, AbstractDependant, ReentrancyGuardUpgradeable { uint256 internal _tokenIdCounter; address internal _systemOwnerAddr; @@ -23,16 +21,6 @@ contract PRT is IPRT, ERC721Upgradeable, AbstractDependant, ReentrancyGuardUpgra PRTParams internal _prtParams; - modifier onlySystemOwner() { - require(msg.sender == _systemOwnerAddr, "PRT: Only system owner can call this function"); - _; - } - - modifier onlyHasRoleOrRoleManagerAdmin(bytes32 _role) { - _roleManager.hasRoleOrAdmin(_role, msg.sender); - _; - } - function prtInitialize( string calldata name_, string calldata symbol_, @@ -52,9 +40,9 @@ contract PRT is IPRT, ERC721Upgradeable, AbstractDependant, ReentrancyGuardUpgra _roleManager = IRoleManager(registry_.getRoleManagerContract()); } - function updatePRTParams( - PRTParams calldata prtParams_ - ) external override onlyHasRoleOrRoleManagerAdmin(PRT_PARAM_UPDATER) { + function updatePRTParams(PRTParams calldata prtParams_) external override { + _roleManager.isPRTParamUpdater(msg.sender); + _prtParams = prtParams_; } diff --git a/contracts/RewardsDistribution.sol b/contracts/RewardsDistribution.sol index 80ea846..5eecc41 100644 --- a/contracts/RewardsDistribution.sol +++ b/contracts/RewardsDistribution.sol @@ -36,19 +36,6 @@ contract RewardsDistribution is IRewardsDistribution, AbstractDependant { _; } - modifier onlySystemOwner() { - require( - msg.sender == _systemOwnerAddr, - "RewardsDistribution: Only system owner can call this function." - ); - _; - } - - modifier onlyHasRoleOrRoleManagerAdmin(bytes32 _role) { - _roleManager.hasRoleOrAdmin(_role, msg.sender); - _; - } - function setDependencies(address contractsRegistry_) external override dependant { IRegistry registry_ = IRegistry(contractsRegistry_); @@ -93,7 +80,9 @@ contract RewardsDistribution is IRewardsDistribution, AbstractDependant { function setupRewardsPerBlockBatch( bytes32[] calldata assetKeys_, uint256[] calldata rewardsPerBlock_ - ) external override onlyHasRoleOrRoleManagerAdmin(REWARDS_DISTRIBUTION_MANAGER) { + ) external override { + _roleManager.isRewardsDistributionManager(msg.sender); + require( _onlyExistingRewardsAssetKey(), "RewardsDistributionL Unable to setup rewards per block." diff --git a/contracts/RoleManager.sol b/contracts/RoleManager.sol index cda74c2..2b652a4 100644 --- a/contracts/RoleManager.sol +++ b/contracts/RoleManager.sol @@ -4,65 +4,86 @@ import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol" import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; -import "./common/Globals.sol"; - contract RoleManager is AccessControlUpgradeable { - function roleManagerInitialize() external initializer { - _setupRole(ROLE_MANAGER_ADMIN, msg.sender); - } + bytes32 constant ROLE_MANAGER_ADMIN = keccak256("ROLE_MANAGER_ADMIN"); - function hasRoleOrAdmin(bytes32 role_, address account_) public view virtual { - require( - hasRole(role_, account_) || hasRole(ROLE_MANAGER_ADMIN, account_), - string( - abi.encodePacked( - "RoleManager: account is missing role ", - StringsUpgradeable.toHexString(uint256(role_), 32) - ) - ) - ); - } + bytes32 constant ROLE_MANAGER_ROLE_GOVERNOR = keccak256("ROLE_MANAGER_ROLE_GOVERNOR"); - function grantRole(bytes32 role_, address account_) public override { - require( - hasRole(ROLE_MANAGER_ADMIN, msg.sender), - "RoleManager: only ROLE_MANAGER_ADMIN can grant roles" - ); + bytes32 constant ASSET_PARAMETERS_MANAGER = keccak256("ASSET_PARAMETERS_MANAGER"); - _grantRole(role_, account_); + bytes32 constant DEFI_CORE_PAUSER = keccak256("DEFI_CORE_PAUSER"); + + bytes32 constant PRT_PARAM_UPDATER = keccak256("PRT_PARAM_UPDATER"); + + bytes32 constant REWARDS_DISTRIBUTION_MANAGER = keccak256("REWARDS_DISTRIBUTION_MANAGER"); + + bytes32 constant SYSTEM_PARAMETERS_MANAGER = keccak256("SYSTEM_PARAMETERS_MANAGER"); + + bytes32 constant SYSTEM_POOLS_MANAGER = keccak256("SYSTEM_POOLS_MANAGER"); + + bytes32 constant SYSTEM_POOLS_RESERVE_FUNDS_MANAGER = + keccak256("SYSTEM_POOLS_RESERVE_FUNDS_MANAGER"); + + function roleManagerInitialize( + bytes32[] calldata roles_, + address[] calldata accounts_ + ) external initializer { + require(roles_.length == accounts_.length, "RoleManager: arrays are of different sizes"); + for (uint256 i = 0; i < roles_.length; ++i) { + _setupRole(roles_[i], accounts_[i]); + } + _setupRole(ROLE_MANAGER_ADMIN, msg.sender); } - function revokeRole(bytes32 role_, address account_) public override { - require( - hasRole(ROLE_MANAGER_ADMIN, msg.sender), - "RoleManager: only ROLE_MANAGER_ADMIN can revoke roles" - ); + function isAssetParametersManager(address account_) external view { + _hasRoleOrAdmin(ASSET_PARAMETERS_MANAGER, account_); + } - _revokeRole(role_, account_); + function isDefiCorePauser(address account_) external view { + _hasRoleOrAdmin(DEFI_CORE_PAUSER, account_); } -} -/*example: + function isPRTParamUpdater(address account_) external view { + _hasRoleOrAdmin(PRT_PARAM_UPDATER, account_); + } -pragma solidity 0.8.17; + function isRewardsDistributionManager(address account_) external view { + _hasRoleOrAdmin(REWARDS_DISTRIBUTION_MANAGER, account_); + } -import "./interfaces/IRoleManager.sol"; + function isSystemParametersManager(address account_) external view { + _hasRoleOrAdmin(SYSTEM_PARAMETERS_MANAGER, account_); + } -contract PRT is IPRT, ERC721Upgradeable, AbstractDependant, ReentrancyGuardUpgradeable { + function isSystemPoolsManager(address account_) external view { + _hasRoleOrAdmin(SYSTEM_POOLS_MANAGER, account_); + } - .... + function isSystemPoolsReserveFundsManager(address account_) external view { + _hasRoleOrAdmin(SYSTEM_POOLS_RESERVE_FUNDS_MANAGER, account_); + } - IRoleManager internal _roleManager; + function grantRole(bytes32 role_, address account_) public override { + _hasRoleOrAdmin(ROLE_MANAGER_ROLE_GOVERNOR, msg.sender); - modifier onlyRole(bytes32 role) { - _roleManager.checkRole(role, msg.sender); - _; + _grantRole(role_, account_); } - function updatePRTParams(PRTParams calldata prtParams_) external override onlyRole(keccak256("PRT_PARAM_UPDATER")) { + function revokeRole(bytes32 role_, address account_) public override { + _hasRoleOrAdmin(ROLE_MANAGER_ROLE_GOVERNOR, msg.sender); - _prtParams = prtParams_; + _revokeRole(role_, account_); } + function _hasRoleOrAdmin(bytes32 role_, address account_) internal view virtual { + require( + hasRole(role_, account_) || hasRole(ROLE_MANAGER_ADMIN, account_), + string( + abi.encodePacked( + "RoleManager: account is missing role ", + StringsUpgradeable.toHexString(uint256(role_), 32) + ) + ) + ); + } } -*/ diff --git a/contracts/SystemParameters.sol b/contracts/SystemParameters.sol index c29c0f2..d3baf04 100644 --- a/contracts/SystemParameters.sol +++ b/contracts/SystemParameters.sol @@ -24,19 +24,6 @@ contract SystemParameters is ISystemParameters, AbstractDependant { mapping(bytes32 => PureParameters.Param) internal _parameters; - modifier onlySystemOwner() { - require( - msg.sender == _systemOwnerAddr, - "SystemParameters: Only system owner can call this function." - ); - _; - } - - modifier onlyHasRoleOrRoleManagerAdmin(bytes32 _role) { - _roleManager.hasRoleOrAdmin(_role, msg.sender); - _; - } - function setDependencies(address contractsRegistry_) external override dependant { IRegistry registry_ = IRegistry(contractsRegistry_); @@ -44,9 +31,9 @@ contract SystemParameters is ISystemParameters, AbstractDependant { _roleManager = IRoleManager(registry_.getRoleManagerContract()); } - function setRewardsTokenAddress( - address rewardsToken_ - ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_PARAMETERS_MANAGER) { + function setRewardsTokenAddress(address rewardsToken_) external override { + _onlySystemParametersManager(); + PureParameters.Param memory currentParam_ = _parameters[REWARDS_TOKEN_KEY]; if (PureParameters.paramExists(currentParam_)) { @@ -61,9 +48,9 @@ contract SystemParameters is ISystemParameters, AbstractDependant { emit RewardsTokenUpdated(rewardsToken_); } - function setupLiquidationBoundary( - uint256 newValue_ - ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_PARAMETERS_MANAGER) { + function setupLiquidationBoundary(uint256 newValue_) external override { + _onlySystemParametersManager(); + require( newValue_ >= PRECISION * 50 && newValue_ <= PRECISION * 80, "SystemParameters: The new value of the liquidation boundary is invalid." @@ -74,17 +61,17 @@ contract SystemParameters is ISystemParameters, AbstractDependant { emit LiquidationBoundaryUpdated(newValue_); } - function setupStablePoolsAvailability( - bool newValue_ - ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_PARAMETERS_MANAGER) { + function setupStablePoolsAvailability(bool newValue_) external override { + _onlySystemParametersManager(); + _parameters[STABLE_POOLS_AVAILABILITY_KEY] = PureParameters.makeBoolParam(newValue_); emit StablePoolsAvailabilityUpdated(newValue_); } - function setupMinCurrencyAmount( - uint256 newMinCurrencyAmount_ - ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_PARAMETERS_MANAGER) { + function setupMinCurrencyAmount(uint256 newMinCurrencyAmount_) external override { + _onlySystemParametersManager(); + _parameters[MIN_CURRENCY_AMOUNT_KEY] = PureParameters.makeUintParam(newMinCurrencyAmount_); emit MinCurrencyAmountUpdated(newMinCurrencyAmount_); @@ -106,6 +93,10 @@ contract SystemParameters is ISystemParameters, AbstractDependant { return _getParam(MIN_CURRENCY_AMOUNT_KEY).getUintFromParam(); } + function _onlySystemParametersManager() internal { + _roleManager.isSystemParametersManager(msg.sender); + } + function _getParam(bytes32 paramKey_) internal view returns (PureParameters.Param memory) { require( PureParameters.paramExists(_parameters[paramKey_]), diff --git a/contracts/SystemPoolsRegistry.sol b/contracts/SystemPoolsRegistry.sol index 3b458f6..b9bb449 100644 --- a/contracts/SystemPoolsRegistry.sol +++ b/contracts/SystemPoolsRegistry.sol @@ -20,8 +20,6 @@ import "./interfaces/IPriceManager.sol"; import "./interfaces/ISystemPoolsFactory.sol"; import "./interfaces/IRoleManager.sol"; -import "./common/Globals.sol"; - contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDependant { using Paginator for EnumerableSet.Bytes32Set; using EnumerableSet for EnumerableSet.Bytes32Set; @@ -45,19 +43,6 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep mapping(address => bool) public override existingLiquidityPools; mapping(PoolType => PoolTypeInfo) internal _poolTypesInfo; - modifier onlySystemOwner() { - require( - msg.sender == _systemOwnerAddr, - "SystemPoolsRegistry: Only system owner can call this function." - ); - _; - } - - modifier onlyHasRoleOrRoleManagerAdmin(bytes32 _role) { - _roleManager.hasRoleOrAdmin(_role, msg.sender); - _; - } - function systemPoolsRegistryInitialize( address liquidityPoolImpl_, bytes32 nativeAssetKey_, @@ -85,9 +70,9 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep _roleManager = IRoleManager(registry_.getRoleManagerContract()); } - function updateRewardsAssetKey( - bytes32 newRewardsAssetKey_ - ) external onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_MANAGER) { + function updateRewardsAssetKey(bytes32 newRewardsAssetKey_) external { + _onlySystemPoolsManager(); + require( IBasicPool(poolsInfo[newRewardsAssetKey_].poolAddr).assetAddr() == _systemParameters.getRewardsTokenAddress(), @@ -97,10 +82,9 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep rewardsAssetKey = newRewardsAssetKey_; } - function addPoolsBeacon( - PoolType poolType_, - address poolImpl_ - ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_MANAGER) { + function addPoolsBeacon(PoolType poolType_, address poolImpl_) external override { + _onlySystemPoolsManager(); + PoolTypeInfo storage _poolTypeInfo = _poolTypesInfo[poolType_]; require( @@ -118,7 +102,9 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep string calldata tokenSymbol_, bool isCollateral_, bool isCollateralWithPRT_ - ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_MANAGER) { + ) external override { + _onlySystemPoolsManager(); + _addPool( assetAddr_, assetKey_, @@ -134,7 +120,9 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep address assetAddr_, bytes32 assetKey_, address chainlinkOracle_ - ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_MANAGER) { + ) external override { + _onlySystemPoolsManager(); + require( _systemParameters.getStablePoolsAvailability(), "SystemPoolsRegistry: Stable pools are unavailable." @@ -148,7 +136,9 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep bytes32 assetKey_, uint256 amountToWithdraw_, bool isAllFunds_ - ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_RESERVE_FUNDS_MANAGER) { + ) external override { + _onlySystemPoolsReserveFundsManager(); + require(onlyExistingPool(assetKey_), "SystemPoolsRegistry: Pool doesn't exist."); if (!isAllFunds_) { @@ -169,7 +159,9 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep address recipientAddr_, uint256 offset_, uint256 limit_ - ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_RESERVE_FUNDS_MANAGER) { + ) external override { + _onlySystemPoolsReserveFundsManager(); + bytes32[] memory _assetsKeys = getSupportedAssetKeys(offset_, limit_); for (uint256 i = 0; i < _assetsKeys.length; i++) { @@ -181,10 +173,9 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep } } - function upgradePoolsImpl( - PoolType poolType_, - address newPoolsImpl_ - ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_MANAGER) { + function upgradePoolsImpl(PoolType poolType_, address newPoolsImpl_) external override { + _onlySystemPoolsManager(); + address poolBeacon_ = _poolTypesInfo[poolType_].poolBeaconAddr; require(poolBeacon_ != address(0), "SystemPoolsRegistry: Unsupported pool type."); @@ -192,11 +183,9 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep UpgradeableBeacon(poolBeacon_).upgradeTo(newPoolsImpl_); } - function injectDependenciesToExistingPools() - external - override - onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_MANAGER) - { + function injectDependenciesToExistingPools() external override { + _onlySystemPoolsManager(); + IRegistry registry_ = _registry; address[] memory allPools_ = getAllPools(); @@ -206,10 +195,9 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep } } - function injectDependencies( - uint256 offset_, - uint256 limit_ - ) external override onlyHasRoleOrRoleManagerAdmin(SYSTEM_POOLS_MANAGER) { + function injectDependencies(uint256 offset_, uint256 limit_) external override { + _onlySystemPoolsManager(); + IRegistry registry_ = _registry; address[] memory _pools = getPools(offset_, limit_); @@ -356,6 +344,14 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep return _getPoolsAddresses(getSupportedAssetKeysByType(poolType_, offset_, limit_)); } + function _onlySystemPoolsManager() internal { + _roleManager.isSystemPoolsManager(msg.sender); + } + + function _onlySystemPoolsReserveFundsManager() internal { + _roleManager.isSystemPoolsReserveFundsManager(msg.sender); + } + function _addPool( address assetAddr_, bytes32 assetKey_, diff --git a/contracts/UserInfoRegistry.sol b/contracts/UserInfoRegistry.sol index 31ece18..85d3ad5 100644 --- a/contracts/UserInfoRegistry.sol +++ b/contracts/UserInfoRegistry.sol @@ -22,8 +22,6 @@ import "./interfaces/IPRT.sol"; import "./libraries/AssetsHelperLibrary.sol"; import "./libraries/MathHelper.sol"; -import "./common/Globals.sol"; - contract UserInfoRegistry is IUserInfoRegistry, AbstractDependant { using EnumerableSet for EnumerableSet.Bytes32Set; using AssetsHelperLibrary for bytes32; diff --git a/contracts/common/Globals.sol b/contracts/common/Globals.sol index 0f9523f..07e9885 100644 --- a/contracts/common/Globals.sol +++ b/contracts/common/Globals.sol @@ -7,21 +7,3 @@ uint256 constant BLOCKS_PER_DAY = 4900; uint256 constant BLOCKS_PER_YEAR = BLOCKS_PER_DAY * 365; uint8 constant PRICE_DECIMALS = 8; - -bytes32 constant ROLE_MANAGER_ADMIN = keccak256("ROLE_MANAGER_ADMIN"); - -bytes32 constant ASSET_PARAMETERS_MANAGER = keccak256("ASSET_PARAMETERS_MANAGER"); - -bytes32 constant DEFI_CORE_PAUSER = keccak256("DEFI_CORE_PAUSER"); - -bytes32 constant PRT_PARAM_UPDATER = keccak256("PRT_PARAM_UPDATER"); - -bytes32 constant REWARDS_DISTRIBUTION_MANAGER = keccak256("REWARDS_DISTRIBUTION_MANAGER"); - -bytes32 constant SYSTEM_PARAMETERS_MANAGER = keccak256("SYSTEM_PARAMETERS_MANAGER"); - -bytes32 constant SYSTEM_POOLS_MANAGER = keccak256("SYSTEM_POOLS_MANAGER"); - -bytes32 constant SYSTEM_POOLS_RESERVE_FUNDS_MANAGER = keccak256( - "SYSTEM_POOLS_RESERVE_FUNDS_MANAGER" -); diff --git a/contracts/interfaces/IRoleManager.sol b/contracts/interfaces/IRoleManager.sol index 306e182..eef2259 100644 --- a/contracts/interfaces/IRoleManager.sol +++ b/contracts/interfaces/IRoleManager.sol @@ -1,9 +1,21 @@ pragma solidity 0.8.17; interface IRoleManager { - function hasRoleOrAdmin(bytes32 role_, address account_) external view; - function grantRole(bytes32 role_, address account_) external; function revokeRole(bytes32 role, address account) external; + + function isAssetParametersManager(address account_) external view; + + function isDefiCorePauser(address account_) external view; + + function isPRTParamUpdater(address account_) external view; + + function isRewardsDistributionManager(address account_) external view; + + function isSystemParametersManager(address account_) external view; + + function isSystemPoolsManager(address account_) external view; + + function isSystemPoolsReserveFundsManager(address account_) external view; } From 66fa579c2088115df8adc23fc5d4c0f74694f9b0 Mon Sep 17 00:00:00 2001 From: mesowea Date: Fri, 17 Mar 2023 03:21:34 +0200 Subject: [PATCH 5/6] Change existing tests and deploy scripts in accordance with RoleManager contract addition, add RoleManager tests --- contracts/RoleManager.sol | 5 +- deploy/1_contracts_deploy.js | 9 + deploy/2_init_all.js | 6 +- ds | 273 -------------------------- test/assetParameters.test.js | 38 ++-- test/defiCore.test.js | 13 +- test/liquidityPool.test.js | 16 +- test/priceManager.test.js | 2 + test/prt.test.js | 13 +- test/registry.test.js | 6 + test/rewardsDistribution.test.js | 12 +- test/roleManager.test.js | 319 +++++++++++++++++++++++++++++++ test/stablePool.test.js | 8 + test/systemParameters.test.js | 23 ++- test/systemPoolsRegistry.test.js | 42 ++-- test/userInfoRegistry.test.js | 8 + 16 files changed, 473 insertions(+), 320 deletions(-) delete mode 100644 ds create mode 100644 test/roleManager.test.js diff --git a/contracts/RoleManager.sol b/contracts/RoleManager.sol index 2b652a4..29f11b3 100644 --- a/contracts/RoleManager.sol +++ b/contracts/RoleManager.sol @@ -28,7 +28,10 @@ contract RoleManager is AccessControlUpgradeable { bytes32[] calldata roles_, address[] calldata accounts_ ) external initializer { - require(roles_.length == accounts_.length, "RoleManager: arrays are of different sizes"); + require( + roles_.length == accounts_.length, + "RoleManager: passed arrays are of different sizes" + ); for (uint256 i = 0; i < roles_.length; ++i) { _setupRole(roles_[i], accounts_[i]); } diff --git a/deploy/1_contracts_deploy.js b/deploy/1_contracts_deploy.js index 059575c..01f1a25 100644 --- a/deploy/1_contracts_deploy.js +++ b/deploy/1_contracts_deploy.js @@ -11,6 +11,7 @@ const RewardsDistribution = artifacts.require("RewardsDistribution"); const UserInfoRegistry = artifacts.require("UserInfoRegistry"); const PriceManager = artifacts.require("PriceManager"); const Prt = artifacts.require("PRT"); +const RoleManager = artifacts.require("RoleManager"); const { artifacts } = require("hardhat"); const { isStablePoolsAvailable } = require("./helpers/deployHelper.js"); @@ -55,6 +56,9 @@ module.exports = async (deployer, logger) => { await deployer.deploy(Prt); const prt = await Prt.deployed(); + await deployer.deploy(RoleManager); + const roleManager = await RoleManager.deployed(); + await deployer.deploy(LiquidityPool); if (isStablePoolsAvailable()) { @@ -112,6 +116,11 @@ module.exports = async (deployer, logger) => { "Add Prt contract proxy to the registry" ); + logger.logTransaction( + await registry.addProxyContract(await registry.ROLE_MANAGER_NAME(), roleManager.address), + "Add RoleManager contract proxy to the registry" + ); + console.log(); logger.logTransaction( diff --git a/deploy/2_init_all.js b/deploy/2_init_all.js index 535b58c..9ff01e2 100644 --- a/deploy/2_init_all.js +++ b/deploy/2_init_all.js @@ -5,6 +5,7 @@ const SystemPoolsRegistry = artifacts.require("SystemPoolsRegistry"); const LiquidityPool = artifacts.require("LiquidityPool"); const InterestRateLibrary = artifacts.require("InterestRateLibrary"); const Prt = artifacts.require("PRT"); +const RoleManager = artifacts.require("RoleManager"); const { artifacts } = require("hardhat"); @@ -24,6 +25,7 @@ module.exports = async (deployer, logger) => { const systemPoolsRegistry = await SystemPoolsRegistry.at(await registry.getSystemPoolsRegistryContract()); const interestRateLibrary = await InterestRateLibrary.at(await registry.getInterestRateLibraryContract()); const prt = await Prt.at(await registry.getPRTContract()); + const roleManager = await RoleManager.at(await registry.getRoleManagerContract()); const rewardsAssetKey = getAssetKey(rewardsAssetSymbol()); const nativeTokenKey = getAssetKey(nativeAssetSymbol()); @@ -34,6 +36,7 @@ module.exports = async (deployer, logger) => { logger.logTransaction(await defiCore.defiCoreInitialize(), "Init DefiCore"); logger.logTransaction(await prt.prtInitialize(prtArr.name, prtArr.symbol, prtArr.prtParams), "Init PRT"); + logger.logTransaction(await roleManager.roleManagerInitialize([], []), "Init RoleManager"); logger.logTransaction( await systemPoolsRegistry.systemPoolsRegistryInitialize( ( @@ -110,7 +113,8 @@ module.exports = async (deployer, logger) => { ["PriceManager", await registry.getPriceManagerContract()], ["InterestRateLibrary", interestRateLibrary.address], ["RewardsToken", rewardsAssetAddress], - ["PRT", prt.address] + ["PRT", prt.address], + ["RoleManager", roleManager.address] ); console.log("+--------------------------------------------------------------------------------+"); diff --git a/ds b/ds deleted file mode 100644 index 7d7d381..0000000 --- a/ds +++ /dev/null @@ -1,273 +0,0 @@ -commit 6ce88979061904e462689ac342e6c6fae0c76847 (HEAD -> feature/roles) -Merge: 38079c0 4aec8b1 -Author: mesowea -Date: Mon Mar 13 15:22:54 2023 +0200 - - Merge branch 'main' into feature/roles - -commit 38079c0027351358136aba14ffde73485958a50b (origin/feature/roles) -Author: mesowea -Date: Mon Mar 13 14:18:23 2023 +0200 - - Add RoleManager contract, add roles constants, public function to check roles and implementation exapmple - -commit b7220a0d250d7f392ad08a95813927726c96a987 (origin/feature/PRT, feature/PRT) -Author: mesowea -Date: Mon Mar 13 00:09:19 2023 +0200 - - Add comments to IRegistry.sol and IUserInfoRegistry.sol expalining what do the updateUserStatsForPRT and transferOwnershipAndInject functions do - -commit 4aec8b1043d134b2a2ad37367e60327a52bef347 (origin/main, origin/HEAD, main) -Merge: 5998c98 088883f -Author: Oleg Komendant <44612825+Hrom131@users.noreply.github.com> -Date: Thu Mar 2 15:50:55 2023 +0200 - - Merge pull request #4 from defaino/feature/PRT - - Coverage Increase - -commit 088883fe54b1bc7a1853d74fdb51f3a71a01a901 -Author: mesowea -Date: Thu Mar 2 15:47:59 2023 +0200 - - package.json fix - -commit 64fc97516f253641c539f5067466348d3fe3713f -Author: mesowea -Date: Thu Mar 2 14:48:13 2023 +0200 - - Add 'modifierWhitelist' to solcover.js with 'nonReentrant' and 'dependant' modifiers - -commit ad323629142c5ccbf5c3986cd97b8ac2c2784e7b -Author: mesowea -Date: Tue Feb 28 04:30:50 2023 +0200 - - Increase AbstractPool, WETH, UserInfoRegistry, RewardsDistribution coverage - -commit 68231d84dfa4df784006a2ecb22d8f1ec34b8d27 -Author: mesowea -Date: Sun Feb 26 00:56:54 2023 +0200 - - Increase coverage to almost 100%, skip nonReentrant and some unreachable paths - -commit 5998c98dfad7129f14376176c12acbd62f55ade5 -Merge: 0f8542b fd0daf1 -Author: Oleg Komendant <44612825+Hrom131@users.noreply.github.com> -Date: Mon Feb 20 16:50:35 2023 +0200 - - Merge pull request #3 from defaino/feature/PRT - - PRT feature - -commit fd0daf16cfce87917c084f9203fb88763a8b9655 -Author: mesowea -Date: Fri Feb 17 16:16:07 2023 +0200 - - Fix style, 'getUsersLiquidiationInfo' test - -commit f1bb9c9870658f0fdb15ced0200b41a3bf01f3fb -Author: mesowea -Date: Wed Feb 15 02:21:00 2023 +0200 - - Increase PRT coverage to 100%, add comments in PRT and UserInfoRegistry interfaces - -commit e1ecdbe3353282b597751504febea8d7c1e816f0 -Author: mesowea -Date: Tue Feb 14 01:12:40 2023 +0200 - - Add PRT tests, edit deploy migration taking into account prt contract and params that differ for users with prt - -commit 84720a466f77cd746549d686aedb86517a65b716 -Author: mesowea -Date: Sat Feb 11 15:32:56 2023 +0200 - - Add PRT contract, PRT stats calculations and special pool parameters for the users with PRT - -commit 0f8542bf653d21b013d4d03b83b59e0f8fc971c7 -Author: Yaroslav Panasenko -Date: Thu Feb 9 19:53:40 2023 +0200 - - Add license - -commit 192f416804a6d5387758f454c502f56cd6859804 -Merge: 8c82564 520a488 -Author: Oleh Komendant -Date: Mon Jan 30 11:37:19 2023 +0000 - - Merge branch 'feature/ownership' into 'main' - - Add transferOwnershipAndInject, tests and needed mocks - - See merge request dl-defi-core/contracts!4 - -commit 520a4881be4942b92214eb67ac26fea969058fbe -Author: mesowea -Date: Fri Jan 13 18:11:49 2023 +0200 - - Fix test for renounceOwnership() - -commit 51ddbea17e6e3f1e46962e03f27b2fddd1258934 -Author: mesowea -Date: Fri Jan 13 18:08:28 2023 +0200 - - Add a reverting renounceOwnership(), add a check for the address(0) in transferwnershipndnject, fix the tests - -commit c2b9ca77abf0833d528f6271c4599dfb60e5fa5d -Author: mesowea -Date: Thu Jan 12 16:53:20 2023 +0200 - - fix missing mocks and test - -commit c91e84765cd7d73c352d96c95405980beedafba7 -Author: mesowea -Date: Thu Jan 12 16:48:10 2023 +0200 - - Add transferOwnershipAndInject, tests and needed mocks - -commit 8c825640e0ebe169e58dba7087fbbc0abebbf0cc -Merge: 7c1d933 a76c26f -Author: Oleh Komendant -Date: Fri Jan 6 12:50:24 2023 +0000 - - Merge branch 'feature/global_update' into 'main' - - Feature/global update - - See merge request dl-defi-core/contracts!2 - -commit a76c26ffe848296d8854f08e0175b63d3f8438c4 -Author: oleg.komendant -Date: Fri Jan 6 14:49:14 2023 +0200 - - Fix coverage - -commit f73ab0a367e69d6ae3add3b33247f0a5d03ddf0e -Author: oleg.komendant -Date: Mon Jan 2 19:47:40 2023 +0200 - - Update code style - -commit 22a84eb939ade225fe5a801546baf381302768c6 -Author: oleg.komendant -Date: Tue Dec 27 14:51:51 2022 +0200 - - Update deploy scripts - -commit cd8b9adce052908e82c9ea694748bf7e818176f1 -Author: oleg.komendant -Date: Mon Dec 26 16:47:29 2022 +0200 - - Update contracts to new version - -commit 7c1d933aa47e6b43874182bae347e8f641a9fd5b -Merge: e4313d5 73457d9 -Author: Oleh Komendant -Date: Sat Mar 19 15:13:30 2022 +0000 - - Merge branch 'fix/contracts_refactoring' into 'main' - - Fix/contracts refactoring - - See merge request dl-defi-core/contracts!1 - -commit 73457d9ce31d4a166a8058fbefa2eb9f389a13e9 -Author: oleg.komendant -Date: Sat Mar 19 17:09:06 2022 +0200 - - Fix bug with liquidation logic - -commit 640bf003708b53ee7314c18dbfb0e78a3795b82f -Author: oleg.komendant -Date: Sat Mar 19 14:55:14 2022 +0200 - - Add SafeERC20 library - -commit 2d59a353f52db00d1233d4731ab48a29dcbd1c3f -Author: oleg.komendant -Date: Thu Mar 17 23:06:22 2022 +0200 - - Refactor and optimize contracts - -commit 09b7da98e8b712a3e6e0ebd432a226cccb3aed42 -Author: oleg.komendant -Date: Thu Mar 17 20:49:02 2022 +0200 - - Add new unit tests - -commit 7537d6b791129803854d2be3bea44d3de07182cb -Author: oleg.komendant -Date: Thu Mar 17 00:10:29 2022 +0200 - - Fix InterestRate library and unit tests - -commit 38e6255067f7f75fed769419b21b36ad819bd0d2 -Author: oleg.komendant -Date: Wed Mar 16 22:58:25 2022 +0200 - - Add documentation comments; fix functions order; fix some bugs - -commit d775df2589b13dd6dc1f06185216981dba54b732 -Author: oleg.komendant -Date: Mon Mar 14 20:33:04 2022 +0200 - - Rewrite migrations and upgrade hardhat files - -commit 0d6d4aefbb6bb2119b459953cc6bc404c58605be -Author: oleg.komendant -Date: Fri Mar 11 20:29:18 2022 +0200 - - Update tests and remove unused files - -commit 233d4ca70a4d0c25ea02657d4c7c13008f766a37 -Author: oleg.komendant -Date: Wed Mar 9 14:15:51 2022 +0200 - - Rename N tokens to LP tokens; remove useless test files - -commit 30a14b6c645a35f461a8fca89fc6fad528683421 -Author: oleg.komendant -Date: Tue Mar 8 20:53:30 2022 +0200 - - Rewrite contracts for frontend - -commit 63c5141657b718b62e33feb5676d447a34fe83c4 -Author: oleg.komendant -Date: Tue Mar 1 17:00:58 2022 +0200 - - Move to Beacon proxy implementation - -commit e2295acca72af5cdef55010f7e6d67397454608d -Author: oleg.komendant -Date: Tue Mar 1 16:16:29 2022 +0200 - - Move AbstractDependant contract to abstract folder - -commit 75237bb6957825e252e56ea2ee92541f12ecd921 -Author: oleg.komendant -Date: Tue Mar 1 16:11:18 2022 +0200 - - Remove integration part - -commit 662bb39a30c40c0fe23dfcb9f8cc9ffd1b084939 -Author: oleg.komendant -Date: Mon Feb 28 15:57:30 2022 +0200 - - Update to latest version - -commit 773ba8a2e10dd8a5ecd9fa121f9764a64646c446 -Author: oleg.komendant -Date: Mon Feb 28 14:26:45 2022 +0200 - - Setup hardhat env - -commit e4313d5c0b3559d7bfeadc58e84cdece6064ddba -Author: oleg.komendant -Date: Mon Feb 28 12:53:59 2022 +0200 - - Initial commit - -commit c1c345073a0a6d7c43eed63e3f3834ef7b3498ee -Author: Oleh Komendant -Date: Mon Feb 28 10:38:04 2022 +0000 - - Initial commit diff --git a/test/assetParameters.test.js b/test/assetParameters.test.js index 57e567c..def1d6a 100644 --- a/test/assetParameters.test.js +++ b/test/assetParameters.test.js @@ -21,6 +21,7 @@ const PriceManager = artifacts.require("PriceManager"); const ChainlinkOracleMock = artifacts.require("ChainlinkOracleMock"); const SystemPoolsRegistry = artifacts.require("SystemPoolsRegistry"); const Prt = artifacts.require("PRT"); +const RoleManager = artifacts.require("RoleManager"); DefiCore.numberFormat = "BigNumber"; AssetParameters.numberFormat = "BigNumber"; @@ -68,6 +69,7 @@ describe("AssetParameters", () => { let systemPoolsRegistry; let rewardsToken; let prt; + let roleManager; async function createLiquidityPool(assetKey, symbol, isCollateral) { const token = await MockERC20.new("Mock" + symbol, symbol); @@ -144,6 +146,7 @@ describe("AssetParameters", () => { const _stablePoolImpl = await StablePool.new(); const _systemPoolsRegistry = await SystemPoolsRegistry.new(); const _prt = await Prt.new(); + const _roleManager = await RoleManager.new(); await registry.__OwnableContractsRegistry_init(); @@ -156,6 +159,7 @@ describe("AssetParameters", () => { await registry.addProxyContract(await registry.PRICE_MANAGER_NAME(), _priceManager.address); await registry.addProxyContract(await registry.SYSTEM_POOLS_REGISTRY_NAME(), _systemPoolsRegistry.address); await registry.addProxyContract(await registry.PRT_NAME(), _prt.address); + await registry.addProxyContract(await registry.ROLE_MANAGER_NAME(), _roleManager.address); await registry.addContract(await registry.INTEREST_RATE_LIBRARY_NAME(), interestRateLibrary.address); @@ -163,6 +167,7 @@ describe("AssetParameters", () => { assetParameters = await AssetParameters.at(await registry.getAssetParametersContract()); rewardsDistribution = await RewardsDistribution.at(await registry.getRewardsDistributionContract()); systemPoolsRegistry = await SystemPoolsRegistry.at(await registry.getSystemPoolsRegistryContract()); + roleManager = await RoleManager.at(await registry.getRoleManagerContract()); const defiCore = await DefiCore.at(await registry.getDefiCoreContract()); @@ -177,6 +182,7 @@ describe("AssetParameters", () => { await registry.injectDependencies(await registry.PRT_NAME()); await defiCore.defiCoreInitialize(); + await roleManager.roleManagerInitialize([], []); await systemPoolsRegistry.systemPoolsRegistryInitialize(_liquidityPoolImpl.address, rewardsTokenKey, zeroKey); await systemPoolsRegistry.addPoolsBeacon(1, _stablePoolImpl.address); @@ -274,12 +280,13 @@ describe("AssetParameters", () => { }); describe("setupAllParameters", () => { - it("should get exception if called not by systemOwner", async () => { - const reason = "AssetParameters: Only system owner can call this function."; + it("should get exception if called not by an asset manager/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0x06c492a7eb572cfeccd28edc322064a12cedb3c4e3bddbb1357cd02f3a9f15fc"; await truffleAssert.reverts( assetParameters.setupAllParameters( - stableKey, + rewardsTokenKey, [ [colRatio, colRatio, reserveFactor, liquidationDiscount, maxUR], [0, firstSlope, secondSlope, utilizationBreakingPoint], @@ -385,8 +392,9 @@ describe("AssetParameters", () => { assert.equal(result.receipt.logs[0].args.isCollateral, true); }); - it("should get exception if called not by systemOwner", async () => { - const reason = "AssetParameters: Only system owner can call this function."; + it("should get exception if called not by an asset manager/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0x06c492a7eb572cfeccd28edc322064a12cedb3c4e3bddbb1357cd02f3a9f15fc"; await truffleAssert.reverts(assetParameters.enableCollateral(daiKey, false, { from: USER2 }), reason); }); @@ -489,8 +497,9 @@ describe("AssetParameters", () => { ); }); - it("should get exception if called not by systemOwner", async () => { - const reason = "AssetParameters: Only system owner can call this function."; + it("should get exception if called not by an asset manager/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0x06c492a7eb572cfeccd28edc322064a12cedb3c4e3bddbb1357cd02f3a9f15fc"; await truffleAssert.reverts( assetParameters.setupInterestRateModel(daiKey, [0, firstSlope, secondSlope, utilizationBreakingPoint], { @@ -603,8 +612,9 @@ describe("AssetParameters", () => { ); }); - it("should get exception if called not by systemOwner", async () => { - const reason = "AssetParameters: Only system owner can call this function."; + it("should get exception if called not by an asset manager/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0x06c492a7eb572cfeccd28edc322064a12cedb3c4e3bddbb1357cd02f3a9f15fc"; await truffleAssert.reverts( assetParameters.setupMainParameters(daiKey, [colRatio, colRatio, reserveFactor, liquidationDiscount, maxUR], { from: USER2, @@ -671,8 +681,9 @@ describe("AssetParameters", () => { ); }); - it("should get exception if called not by systemOwner", async () => { - const reason = "AssetParameters: Only system owner can call this function."; + it("should get exception if called not by an asset manager/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0x06c492a7eb572cfeccd28edc322064a12cedb3c4e3bddbb1357cd02f3a9f15fc"; await truffleAssert.reverts( assetParameters.setupDistributionsMinimums(daiKey, [minSupplyDistributionPart, minBorrowDistributionPart], { @@ -740,8 +751,9 @@ describe("AssetParameters", () => { await truffleAssert.reverts(assetParameters.setupAnnualBorrowRate(stableKey, newRate), reason); }); - it("should get exception if called not by systemOwner", async () => { - const reason = "AssetParameters: Only system owner can call this function."; + it("should get exception if called not by an asset manager/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0x06c492a7eb572cfeccd28edc322064a12cedb3c4e3bddbb1357cd02f3a9f15fc"; await truffleAssert.reverts( assetParameters.setupAnnualBorrowRate(stableKey, annualBorrowRate, { from: USER2 }), diff --git a/test/defiCore.test.js b/test/defiCore.test.js index 19c7cdd..c174783 100644 --- a/test/defiCore.test.js +++ b/test/defiCore.test.js @@ -6,7 +6,7 @@ const { ZERO_ADDR } = require("../scripts/utils/constants"); const Reverter = require("./helpers/reverter"); const truffleAssert = require("truffle-assertions"); -const { web3 } = require("hardhat"); +const { web3, artifacts } = require("hardhat"); const { assert } = require("chai"); const Registry = artifacts.require("Registry"); @@ -24,6 +24,7 @@ const InterestRateLibrary = artifacts.require("InterestRateLibrary"); const WETH = artifacts.require("WETH"); const StablePermitToken = artifacts.require("StablePermitTokenMock"); const Prt = artifacts.require("PRT"); +const RoleManager = artifacts.require("RoleManager"); const MockERC20 = artifacts.require("MockERC20"); const ChainlinkOracleMock = artifacts.require("ChainlinkOracleMock"); @@ -48,6 +49,7 @@ describe("DefiCore", async () => { let userInfoRegistry; let systemPoolsRegistry; let prt; + let roleManager; let nativePool; let daiPool; @@ -195,6 +197,7 @@ describe("DefiCore", async () => { const _stablePoolImpl = await StablePool.new(); const _priceManager = await PriceManager.new(); const _prt = await Prt.new(); + const _roleManager = await RoleManager.new(); await registry.__OwnableContractsRegistry_init(); @@ -209,6 +212,7 @@ describe("DefiCore", async () => { await registry.addProxyContract(await registry.SYSTEM_POOLS_FACTORY_NAME(), _liquidityPoolFactory.address); await registry.addProxyContract(await registry.PRICE_MANAGER_NAME(), _priceManager.address); await registry.addProxyContract(await registry.PRT_NAME(), _prt.address); + await registry.addProxyContract(await registry.ROLE_MANAGER_NAME(), _roleManager.address); await registry.addContract(await registry.INTEREST_RATE_LIBRARY_NAME(), interestRateLibrary.address); @@ -218,6 +222,7 @@ describe("DefiCore", async () => { systemPoolsRegistry = await SystemPoolsRegistry.at(await registry.getSystemPoolsRegistryContract()); rewardsDistribution = await RewardsDistribution.at(await registry.getRewardsDistributionContract()); systemParameters = await SystemParameters.at(await registry.getSystemParametersContract()); + roleManager = await RoleManager.at(await registry.getRoleManagerContract()); await registry.injectDependencies(await registry.DEFI_CORE_NAME()); await registry.injectDependencies(await registry.SYSTEM_PARAMETERS_NAME()); @@ -234,6 +239,7 @@ describe("DefiCore", async () => { tokens.push(nativeToken); await defiCore.defiCoreInitialize(); + await roleManager.roleManagerInitialize([], []); await systemPoolsRegistry.systemPoolsRegistryInitialize(_liquidityPoolImpl.address, nativeTokenKey, zeroKey); await systemPoolsRegistry.addPoolsBeacon(1, _stablePoolImpl.address); @@ -2350,8 +2356,9 @@ describe("DefiCore", async () => { await defiCore.borrowFor(daiKey, borrowAmount, USER1, { from: USER1 }); }); - it("should get exception if called by not a system owner", async () => { - const reason = "DefiCore: Only system owner can call this function."; + it("should get exception if called not by an DEFI_CORE_PAUSER/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0x8218bbe530296352d0683ccaec4d2919edba0ac7752d8e2243cb95823bb15fd5"; await truffleAssert.reverts(defiCore.pause({ from: USER1 }), reason); await truffleAssert.reverts(defiCore.unpause({ from: USER1 }), reason); diff --git a/test/liquidityPool.test.js b/test/liquidityPool.test.js index 7a2fae1..d82b2bf 100644 --- a/test/liquidityPool.test.js +++ b/test/liquidityPool.test.js @@ -24,6 +24,7 @@ const PriceManager = artifacts.require("PriceManager"); const InterestRateLibrary = artifacts.require("InterestRateLibrary"); const WETH = artifacts.require("WETH"); const Prt = artifacts.require("PRT"); +const RoleManager = artifacts.require("RoleManager"); const MockERC20 = artifacts.require("MockERC20"); const ChainlinkOracleMock = artifacts.require("ChainlinkOracleMock"); @@ -48,6 +49,7 @@ describe("LiquidityPool", () => { let userInfoRegistry; let systemPoolsRegistry; let prt; + let roleManager; let nativePool; let liquidityPool; @@ -217,6 +219,7 @@ describe("LiquidityPool", () => { const _liquidityPoolImpl = await LiquidityPool.new(); const _priceManager = await PriceManager.new(); const _prt = await Prt.new(); + const _roleManager = await RoleManager.new(); await registry.__OwnableContractsRegistry_init(); @@ -229,6 +232,7 @@ describe("LiquidityPool", () => { await registry.addProxyContract(await registry.SYSTEM_POOLS_FACTORY_NAME(), _liquidityPoolFactory.address); await registry.addProxyContract(await registry.PRICE_MANAGER_NAME(), _priceManager.address); await registry.addProxyContract(await registry.PRT_NAME(), _prt.address); + await registry.addProxyContract(await registry.ROLE_MANAGER_NAME(), _roleManager.address); await registry.addContract(await registry.INTEREST_RATE_LIBRARY_NAME(), interestRateLibrary.address); @@ -238,6 +242,7 @@ describe("LiquidityPool", () => { systemPoolsRegistry = await SystemPoolsRegistry.at(await registry.getSystemPoolsRegistryContract()); rewardsDistribution = await RewardsDistribution.at(await registry.getRewardsDistributionContract()); systemParameters = await SystemParameters.at(await registry.getSystemParametersContract()); + roleManager = await RoleManager.at(await registry.getRoleManagerContract()); await registry.injectDependencies(await registry.DEFI_CORE_NAME()); await registry.injectDependencies(await registry.SYSTEM_PARAMETERS_NAME()); @@ -254,6 +259,7 @@ describe("LiquidityPool", () => { tokens.push(nativeToken); await defiCore.defiCoreInitialize(); + await roleManager.roleManagerInitialize([], []); await systemPoolsRegistry.systemPoolsRegistryInitialize(_liquidityPoolImpl.address, nativeTokenKey, zeroKey); await deployRewardsPool(rewardsToken.address, await rewardsToken.symbol()); @@ -1894,8 +1900,9 @@ describe("LiquidityPool", () => { ); }); - it("should get exception if called by not a system owner", async () => { - const reason = "SystemPoolsRegistry: Only system owner can call this function."; + it("should get exception if called not by an SYSTEM_POOLS_RESERVE_FUNDS_MANAGER/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0xd0b4cd1a8528008585d67ae3c0cc016d46e0ae3dfe660512aad856820ce86b94"; await truffleAssert.reverts( systemPoolsRegistry.withdrawReservedFunds(RECIPIENT, tokenKey, 0, true, { from: USER1 }), @@ -1959,8 +1966,9 @@ describe("LiquidityPool", () => { assert.equal(toBN(await liquidityPool.totalReserves()).toString(), 0); }); - it("should get an exception if called not by systemowner", async () => { - const reason = "SystemPoolsRegistry: Only system owner can call this function."; + it("should get exception if called not by an SYSTEM_POOLS_RESERVE_FUNDS_MANAGER/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0xd0b4cd1a8528008585d67ae3c0cc016d46e0ae3dfe660512aad856820ce86b94"; await truffleAssert.reverts( systemPoolsRegistry.withdrawAllReservedFunds(RECIPIENT, 0, 2, { from: USER2 }), diff --git a/test/priceManager.test.js b/test/priceManager.test.js index 472eae0..6748872 100644 --- a/test/priceManager.test.js +++ b/test/priceManager.test.js @@ -4,6 +4,7 @@ const { ZERO_ADDR } = require("../scripts/utils/constants"); const truffleAssert = require("truffle-assertions"); const Reverter = require("./helpers/reverter"); +const { artifacts } = require("hardhat"); const Registry = artifacts.require("Registry"); const PriceManager = artifacts.require("PriceManager"); @@ -41,6 +42,7 @@ describe("PriceManager", async () => { await registry.addContract(await registry.DEFI_CORE_NAME(), NOTHING); await registry.addContract(await registry.REWARDS_DISTRIBUTION_NAME(), NOTHING); await registry.addContract(await registry.SYSTEM_POOLS_FACTORY_NAME(), NOTHING); + await registry.addContract(await registry.ROLE_MANAGER_NAME(), NOTHING); priceManager = await PriceManager.at(await registry.getPriceManagerContract()); diff --git a/test/prt.test.js b/test/prt.test.js index 9e57f60..b8c5b64 100644 --- a/test/prt.test.js +++ b/test/prt.test.js @@ -24,6 +24,7 @@ const InterestRateLibrary = artifacts.require("InterestRateLibrary"); const Prt = artifacts.require("PRT"); const WETH = artifacts.require("WETH"); const StablePermitToken = artifacts.require("StablePermitTokenMock"); +const RoleManager = artifacts.require("RoleManager"); const MockERC20 = artifacts.require("MockERC20"); const ChainlinkOracleMock = artifacts.require("ChainlinkOracleMock"); @@ -51,6 +52,7 @@ describe("PRT", () => { let systemPoolsRegistry; let rewardsDistribution; let prt; + let roleManager; let nativePool; let daiPool; @@ -183,6 +185,7 @@ describe("PRT", () => { const _stablePoolImpl = await StablePool.new(); const _priceManager = await PriceManager.new(); const _prt = await Prt.new(); + const _roleManager = await RoleManager.new(); await registry.__OwnableContractsRegistry_init(); @@ -196,6 +199,7 @@ describe("PRT", () => { await registry.addProxyContract(await registry.SYSTEM_POOLS_FACTORY_NAME(), _liquidityPoolFactory.address); await registry.addProxyContract(await registry.PRICE_MANAGER_NAME(), _priceManager.address); await registry.addProxyContract(await registry.PRT_NAME(), _prt.address); + await registry.addProxyContract(await registry.ROLE_MANAGER_NAME(), _roleManager.address); await registry.addContract(await registry.INTEREST_RATE_LIBRARY_NAME(), interestRateLibrary.address); @@ -206,6 +210,7 @@ describe("PRT", () => { rewardsDistribution = await RewardsDistribution.at(await registry.getRewardsDistributionContract()); systemParameters = await SystemParameters.at(await registry.getSystemParametersContract()); prt = await Prt.at(await registry.getPRTContract()); + roleManager = await RoleManager.at(await registry.getRoleManagerContract()); const _prtReentrancy = await PRTReentrancy.new( await registry.getPRTContract(), @@ -232,6 +237,7 @@ describe("PRT", () => { tokens.push(nativeToken); await defiCore.defiCoreInitialize(); + await roleManager.roleManagerInitialize([], []); await systemPoolsRegistry.systemPoolsRegistryInitialize(_liquidityPoolImpl.address, nativeTokenKey, zeroKey); await prt.prtInitialize("Platform Reputation Token", "PRT", [ [1000000000000, 100], @@ -568,8 +574,9 @@ describe("PRT", () => { }); describe("updatePRTRarams()", () => { - it("should revert if not the system owner tries to update the PRT params", async () => { - let reason = "PRT: Only system owner can call this function"; + it("should get exception if called not by an PRT_PARAM_UPDATER/role manager admin", async () => { + let reason = + "RoleManager: account is missing role 0x2a497a2a3812d7536bf2ddd564e1e7644c23860987ec1d72aa63fa3250b93e25"; await truffleAssert.reverts( prt.updatePRTParams( [ @@ -581,7 +588,7 @@ describe("PRT", () => { reason ); }); - it("should pass if the system owner tries to update the PRT params", async () => { + it("should pass if the PRT_PARAM_UPDATER tries to update the PRT params", async () => { await truffleAssert.passes( prt.updatePRTParams([ [3000000000000, 100], diff --git a/test/registry.test.js b/test/registry.test.js index 0a5c676..668f518 100644 --- a/test/registry.test.js +++ b/test/registry.test.js @@ -5,6 +5,7 @@ const { getInterestRateLibraryAddr } = require("./helpers/coverage-helper"); const truffleAssert = require("truffle-assertions"); const Reverter = require("./helpers/reverter"); const { Assertion } = require("chai"); +const { artifacts } = require("hardhat"); const Registry = artifacts.require("Registry"); const AssetParameters = artifacts.require("AssetParametersMock"); @@ -16,6 +17,7 @@ const PriceManager = artifacts.require("PriceManager"); const UserInfoRegistry = artifacts.require("UserInfoRegistry"); const SystemPoolsFactory = artifacts.require("SystemPoolsFactory"); const Prt = artifacts.require("PRT"); +const RoleManager = artifacts.require("RoleManager"); describe("Registry", async () => { const reverter = new Reverter(); @@ -29,6 +31,7 @@ describe("Registry", async () => { let systemParameters; let systemPoolsRegistry; let prt; + let roleManager; before("setup", async () => { LIQUIDITY_POOL_REGISTRY = await accounts(9); @@ -45,6 +48,7 @@ describe("Registry", async () => { const _userInfoRegistry = await UserInfoRegistry.new(); const _systemPoolsFactory = await SystemPoolsFactory.new(); const _prt = await Prt.new(); + const _roleManager = await RoleManager.new(); await registry.__OwnableContractsRegistry_init(); @@ -58,12 +62,14 @@ describe("Registry", async () => { await registry.addProxyContract(await registry.REWARDS_DISTRIBUTION_NAME(), _rewardsDistribution.address); await registry.addProxyContract(await registry.SYSTEM_POOLS_REGISTRY_NAME(), _systemPoolsRegistry.address); await registry.addProxyContract(await registry.PRT_NAME(), _prt.address); + await registry.addProxyContract(await registry.ROLE_MANAGER_NAME(), _roleManager.address); defiCore = await DefiCore.at(await registry.getDefiCoreContract()); assetParameters = await AssetParameters.at(await registry.getAssetParametersContract()); systemPoolsRegistry = await SystemPoolsRegistry.at(await registry.getSystemPoolsRegistryContract()); rewardsDistribution = await RewardsDistribution.at(await registry.getRewardsDistributionContract()); systemParameters = await SystemParameters.at(await registry.getSystemParametersContract()); + roleManager = await RoleManager.at(await registry.getRoleManagerContract()); await reverter.snapshot(); }); diff --git a/test/rewardsDistribution.test.js b/test/rewardsDistribution.test.js index 94efb1a..7902bb9 100644 --- a/test/rewardsDistribution.test.js +++ b/test/rewardsDistribution.test.js @@ -6,6 +6,7 @@ const { ZERO_ADDR } = require("../scripts/utils/constants"); const Reverter = require("./helpers/reverter"); const truffleAssert = require("truffle-assertions"); +const { artifacts } = require("hardhat"); const Registry = artifacts.require("Registry"); const DefiCore = artifacts.require("DefiCore"); @@ -22,6 +23,7 @@ const Prt = artifacts.require("PRT"); const InterestRateLibrary = artifacts.require("InterestRateLibrary"); const WETH = artifacts.require("WETH"); const StablePermitToken = artifacts.require("StablePermitTokenMock"); +const RoleManager = artifacts.require("RoleManager"); const MockERC20 = artifacts.require("MockERC20"); const ChainlinkOracleMock = artifacts.require("ChainlinkOracleMock"); @@ -43,6 +45,7 @@ describe("RewardsDistribution", () => { let rewardsDistribution; let systemPoolsRegistry; let prt; + let roleManager; let daiPool; @@ -223,6 +226,7 @@ describe("RewardsDistribution", () => { const _stablePoolImpl = await StablePool.new(); const _priceManager = await PriceManager.new(); const _prt = await Prt.new(); + const _roleManager = await RoleManager.new(); await registry.__OwnableContractsRegistry_init(); @@ -237,6 +241,7 @@ describe("RewardsDistribution", () => { await registry.addProxyContract(await registry.SYSTEM_POOLS_FACTORY_NAME(), _liquidityPoolFactory.address); await registry.addProxyContract(await registry.PRICE_MANAGER_NAME(), _priceManager.address); await registry.addProxyContract(await registry.PRT_NAME(), _prt.address); + await registry.addProxyContract(await registry.ROLE_MANAGER_NAME(), _roleManager.address); await registry.addContract(await registry.INTEREST_RATE_LIBRARY_NAME(), interestRateLibrary.address); @@ -245,6 +250,7 @@ describe("RewardsDistribution", () => { systemPoolsRegistry = await SystemPoolsRegistry.at(await registry.getSystemPoolsRegistryContract()); rewardsDistribution = await RewardsDistribution.at(await registry.getRewardsDistributionContract()); systemParameters = await SystemParameters.at(await registry.getSystemParametersContract()); + roleManager = await RoleManager.at(await registry.getRoleManagerContract()); await registry.injectDependencies(await registry.DEFI_CORE_NAME()); await registry.injectDependencies(await registry.SYSTEM_PARAMETERS_NAME()); @@ -261,6 +267,7 @@ describe("RewardsDistribution", () => { tokens.push(nativeToken); await defiCore.defiCoreInitialize(); + await roleManager.roleManagerInitialize([], []); await systemPoolsRegistry.systemPoolsRegistryInitialize(_liquidityPoolImpl.address, nativeTokenKey, zeroKey); await systemPoolsRegistry.addPoolsBeacon(1, _stablePoolImpl.address); @@ -838,11 +845,12 @@ describe("RewardsDistribution", () => { await truffleAssert.reverts(rewardsDistribution.setupRewardsPerBlockBatch(keys, rewardsPerBlock), reason); }); - it("should get exception if not system onwer try to call this function", async () => { + it("should get exception if called not by an REWARDS_DISTRIBUTION_MANAGER/role manager admin", async () => { await systemParameters.setRewardsTokenAddress(rewardsToken.address); await systemPoolsRegistry.updateRewardsAssetKey(rewardsTokenKey); - const reason = "RewardsDistribution: Only system owner can call this function."; + const reason = + "RoleManager: account is missing role 0x850ebe1af891c28af526a1ab7de2aec67dea6bf3e98038a47ffc67205e96ea7e"; await truffleAssert.reverts( rewardsDistribution.setupRewardsPerBlockBatch([daiKey], [oneToken], { from: USER1 }), diff --git a/test/roleManager.test.js b/test/roleManager.test.js new file mode 100644 index 0000000..2928a3e --- /dev/null +++ b/test/roleManager.test.js @@ -0,0 +1,319 @@ +const truffleAssert = require("truffle-assertions"); +const Reverter = require("./helpers/reverter"); + +const { artifacts } = require("hardhat"); +const { utils } = require("ethers"); +const { accounts } = require("../scripts/utils/utils"); +const { assert } = require("chai"); + +const RoleManager = artifacts.require("RoleManager"); + +if (!String.prototype.format) { + String.prototype.format = function (...args) { + return this.replace(/(\{\d+\})/g, function (a) { + return args[+a.substr(1, a.length - 2) || 0]; + }); + }; +} + +describe("RoleManager", () => { + const reverter = new Reverter(); + + let ROLE_MANAGER_ADMIN; + let ANOTHER_ACCOUNT; + let ANOTHER_ACCOUNT1; + let ANOTHER_ACCOUNT2; + + let roleManager; + + before("setup", async () => { + ROLE_MANAGER_ADMIN = await accounts(0); + ANOTHER_ACCOUNT = await accounts(1); + ANOTHER_ACCOUNT1 = await accounts(2); + ANOTHER_ACCOUNT2 = await accounts(3); + + const _roleManager = await RoleManager.new(); + + roleManager = await RoleManager.at(_roleManager.address); + + await reverter.snapshot(); + }); + + afterEach("revert", reverter.revert); + + describe("roleManagerInitialize()", () => { + it("should correctly grant the ROLE_MANAGER_ADMIN role to msg.sender", async () => { + await roleManager.roleManagerInitialize([], []); + const ROLE_MANAGER_ADMIN_ROLE = utils.keccak256(utils.toUtf8Bytes("ROLE_MANAGER_ADMIN")); + assert.equal(await roleManager.hasRole(ROLE_MANAGER_ADMIN_ROLE, ROLE_MANAGER_ADMIN), true); + }); + + it("should grant the roles passed to the corresponding accounts", async () => { + const ROLE_MANAGER_ADMIN_ROLE = utils.keccak256(utils.toUtf8Bytes("ROLE_MANAGER_ADMIN")); + const PRT_PARAM_UPDATER_ROLE = utils.keccak256(utils.toUtf8Bytes("PRT_PARAM_UPDATER")); + const DEFI_CORE_PAUSER_ROLE = utils.keccak256(utils.toUtf8Bytes("DEFI_CORE_PAUSER")); + const SYSTEM_POOLS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_POOLS_MANAGER")); + + await roleManager.roleManagerInitialize( + [PRT_PARAM_UPDATER_ROLE, DEFI_CORE_PAUSER_ROLE, SYSTEM_POOLS_MANAGER_ROLE], + [ANOTHER_ACCOUNT, ANOTHER_ACCOUNT1, ANOTHER_ACCOUNT2] + ); + + assert.equal(await roleManager.hasRole(ROLE_MANAGER_ADMIN_ROLE, ROLE_MANAGER_ADMIN), true); + assert.equal(await roleManager.hasRole(PRT_PARAM_UPDATER_ROLE, ANOTHER_ACCOUNT), true); + assert.equal(await roleManager.hasRole(DEFI_CORE_PAUSER_ROLE, ANOTHER_ACCOUNT1), true); + assert.equal(await roleManager.hasRole(SYSTEM_POOLS_MANAGER_ROLE, ANOTHER_ACCOUNT2), true); + + assert.equal(await roleManager.hasRole(ROLE_MANAGER_ADMIN_ROLE, ANOTHER_ACCOUNT), false); + assert.equal(await roleManager.hasRole(PRT_PARAM_UPDATER_ROLE, ANOTHER_ACCOUNT2), false); + assert.equal(await roleManager.hasRole(DEFI_CORE_PAUSER_ROLE, ROLE_MANAGER_ADMIN), false); + assert.equal(await roleManager.hasRole(SYSTEM_POOLS_MANAGER_ROLE, ANOTHER_ACCOUNT1), false); + }); + + it("should grant the same roles to multiple accounts if needed", async () => { + const PRT_PARAM_UPDATER_ROLE = utils.keccak256(utils.toUtf8Bytes("PRT_PARAM_UPDATER")); + + await roleManager.roleManagerInitialize( + [PRT_PARAM_UPDATER_ROLE, PRT_PARAM_UPDATER_ROLE, PRT_PARAM_UPDATER_ROLE], + [ANOTHER_ACCOUNT, ANOTHER_ACCOUNT1, ANOTHER_ACCOUNT2] + ); + + assert.equal(await roleManager.hasRole(PRT_PARAM_UPDATER_ROLE, ANOTHER_ACCOUNT), true); + assert.equal(await roleManager.hasRole(PRT_PARAM_UPDATER_ROLE, ANOTHER_ACCOUNT1), true); + assert.equal(await roleManager.hasRole(PRT_PARAM_UPDATER_ROLE, ANOTHER_ACCOUNT2), true); + }); + + it("should revert if called after the initilizing", async () => { + const reason = "Initializable: contract is already initialized"; + await roleManager.roleManagerInitialize([], []); + await truffleAssert.reverts(roleManager.roleManagerInitialize([], []), reason); + }); + + it("should revert if roles and accounts arrays are of different size", async () => { + const reason = "RoleManager: passed arrays are of different sizes"; + + const PRT_PARAM_UPDATER_ROLE = utils.keccak256(utils.toUtf8Bytes("PRT_PARAM_UPDATER")); + const DEFI_CORE_PAUSER_ROLE = utils.keccak256(utils.toUtf8Bytes("DEFI_CORE_PAUSER")); + const SYSTEM_POOLS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_POOLS_MANAGER")); + + await truffleAssert.reverts( + roleManager.roleManagerInitialize( + [PRT_PARAM_UPDATER_ROLE, DEFI_CORE_PAUSER_ROLE, SYSTEM_POOLS_MANAGER_ROLE], + [ANOTHER_ACCOUNT, ANOTHER_ACCOUNT1] + ), + reason + ); + + await truffleAssert.reverts( + roleManager.roleManagerInitialize( + [PRT_PARAM_UPDATER_ROLE, DEFI_CORE_PAUSER_ROLE], + [ANOTHER_ACCOUNT, ANOTHER_ACCOUNT1, ANOTHER_ACCOUNT2] + ), + reason + ); + }); + }); + + describe("isAssetParametersManager()", () => { + it("should successfuly pass if the account has the ROLE_MANAGER_ADMIN or ASSET_PARAMETERS_MANAGER role", async () => { + const ASSET_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); + + await roleManager.roleManagerInitialize([ASSET_PARAMETERS_MANAGER_ROLE], [ANOTHER_ACCOUNT]); + + await truffleAssert.passes(roleManager.isAssetParametersManager(ANOTHER_ACCOUNT)); + await truffleAssert.passes(roleManager.isAssetParametersManager(ROLE_MANAGER_ADMIN)); + }); + + it("should revert if the account has neither ROLE_MANAGER_ADMIN nor ASSET_PARAMETERS_MANAGER role", async () => { + const ASSET_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); + let reason = "RoleManager: account is missing role {0}".format(ASSET_PARAMETERS_MANAGER_ROLE); + await truffleAssert.reverts(roleManager.isAssetParametersManager(ANOTHER_ACCOUNT), reason); + }); + }); + + describe("isDefiCorePauser()", () => { + it("should successfuly pass if the account has the ROLE_MANAGER_ADMIN or DEFI_CORE_PAUSER role", async () => { + const DEFI_CORE_PAUSER_ROLE = utils.keccak256(utils.toUtf8Bytes("DEFI_CORE_PAUSER")); + + await roleManager.roleManagerInitialize([DEFI_CORE_PAUSER_ROLE], [ANOTHER_ACCOUNT]); + + await truffleAssert.passes(roleManager.isDefiCorePauser(ANOTHER_ACCOUNT)); + await truffleAssert.passes(roleManager.isDefiCorePauser(ROLE_MANAGER_ADMIN)); + }); + + it("should revert if the account has neither ROLE_MANAGER_ADMIN nor DEFI_CORE_PAUSER role", async () => { + const DEFI_CORE_PAUSER_ROLE = utils.keccak256(utils.toUtf8Bytes("DEFI_CORE_PAUSER")); + let reason = "RoleManager: account is missing role {0}".format(DEFI_CORE_PAUSER_ROLE); + await truffleAssert.reverts(roleManager.isDefiCorePauser(ANOTHER_ACCOUNT), reason); + }); + }); + + describe("isPRTParamUpdater()", () => { + it("should successfuly pass if the account has the ROLE_MANAGER_ADMIN or PRT_PARAM_UPDATER role", async () => { + const PRT_PARAM_UPDATER_ROLE = utils.keccak256(utils.toUtf8Bytes("PRT_PARAM_UPDATER")); + + await roleManager.roleManagerInitialize([PRT_PARAM_UPDATER_ROLE], [ANOTHER_ACCOUNT]); + + await truffleAssert.passes(roleManager.isPRTParamUpdater(ANOTHER_ACCOUNT)); + await truffleAssert.passes(roleManager.isPRTParamUpdater(ROLE_MANAGER_ADMIN)); + }); + + it("should revert if the account has neither ROLE_MANAGER_ADMIN nor PRT_PARAM_UPDATER role", async () => { + const PRT_PARAM_UPDATER_ROLE = utils.keccak256(utils.toUtf8Bytes("PRT_PARAM_UPDATER")); + let reason = "RoleManager: account is missing role {0}".format(PRT_PARAM_UPDATER_ROLE); + await truffleAssert.reverts(roleManager.isPRTParamUpdater(ANOTHER_ACCOUNT), reason); + }); + }); + + describe("isRewardsDistributionManager()", () => { + it("should successfuly pass if the account has the ROLE_MANAGER_ADMIN or REWARDS_DISTRIBUTION_MANAGER role", async () => { + const REWARDS_DISTRIBUTION_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("REWARDS_DISTRIBUTION_MANAGER")); + + await roleManager.roleManagerInitialize([REWARDS_DISTRIBUTION_MANAGER_ROLE], [ANOTHER_ACCOUNT]); + + await truffleAssert.passes(roleManager.isRewardsDistributionManager(ANOTHER_ACCOUNT)); + await truffleAssert.passes(roleManager.isRewardsDistributionManager(ROLE_MANAGER_ADMIN)); + }); + + it("should revert if the account has neither ROLE_MANAGER_ADMIN nor REWARDS_DISTRIBUTION_MANAGER role", async () => { + const REWARDS_DISTRIBUTION_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("REWARDS_DISTRIBUTION_MANAGER")); + let reason = "RoleManager: account is missing role {0}".format(REWARDS_DISTRIBUTION_MANAGER_ROLE); + await truffleAssert.reverts(roleManager.isRewardsDistributionManager(ANOTHER_ACCOUNT), reason); + }); + }); + + describe("isSystemParametersManager()", () => { + it("should successfuly pass if the account has the ROLE_MANAGER_ADMIN or SYSTEM_PARAMETERS_MANAGER role", async () => { + const SYSTEM_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_PARAMETERS_MANAGER")); + + await roleManager.roleManagerInitialize([SYSTEM_PARAMETERS_MANAGER_ROLE], [ANOTHER_ACCOUNT]); + + await truffleAssert.passes(roleManager.isSystemParametersManager(ANOTHER_ACCOUNT)); + await truffleAssert.passes(roleManager.isSystemParametersManager(ROLE_MANAGER_ADMIN)); + }); + + it("should revert if the account has neither ROLE_MANAGER_ADMIN nor SYSTEM_PARAMETERS_MANAGER role", async () => { + const SYSTEM_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_PARAMETERS_MANAGER")); + let reason = "RoleManager: account is missing role {0}".format(SYSTEM_PARAMETERS_MANAGER_ROLE); + await truffleAssert.reverts(roleManager.isSystemParametersManager(ANOTHER_ACCOUNT), reason); + }); + }); + + describe("isSystemPoolsManager()", () => { + it("should successfuly pass if the account has the ROLE_MANAGER_ADMIN or SYSTEM_POOLS_MANAGER role", async () => { + const SYSTEM_POOLS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_POOLS_MANAGER")); + + await roleManager.roleManagerInitialize([SYSTEM_POOLS_MANAGER_ROLE], [ANOTHER_ACCOUNT]); + + await truffleAssert.passes(roleManager.isSystemPoolsManager(ANOTHER_ACCOUNT)); + await truffleAssert.passes(roleManager.isSystemPoolsManager(ROLE_MANAGER_ADMIN)); + }); + + it("should revert if the account has neither ROLE_MANAGER_ADMIN nor SYSTEM_POOLS_MANAGER role", async () => { + const SYSTEM_POOLS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_POOLS_MANAGER")); + let reason = "RoleManager: account is missing role {0}".format(SYSTEM_POOLS_MANAGER_ROLE); + await truffleAssert.reverts(roleManager.isSystemPoolsManager(ANOTHER_ACCOUNT), reason); + }); + }); + + describe("isSystemPoolsReserveFundsManager()", () => { + it("should successfuly pass if the account has the ROLE_MANAGER_ADMIN or SYSTEM_POOLS_RESERVE_FUNDS_MANAGER role", async () => { + const SYSTEM_POOLS_RESERVE_FUNDS_MANAGER_ROLE = utils.keccak256( + utils.toUtf8Bytes("SYSTEM_POOLS_RESERVE_FUNDS_MANAGER") + ); + + await roleManager.roleManagerInitialize([SYSTEM_POOLS_RESERVE_FUNDS_MANAGER_ROLE], [ANOTHER_ACCOUNT]); + + await truffleAssert.passes(roleManager.isSystemPoolsReserveFundsManager(ANOTHER_ACCOUNT)); + await truffleAssert.passes(roleManager.isSystemPoolsReserveFundsManager(ROLE_MANAGER_ADMIN)); + }); + + it("should revert if the account has neither ROLE_MANAGER_ADMIN nor SYSTEM_POOLS_RESERVE_FUNDS_MANAGER role", async () => { + const SYSTEM_POOLS_RESERVE_FUNDS_MANAGER_ROLE = utils.keccak256( + utils.toUtf8Bytes("SYSTEM_POOLS_RESERVE_FUNDS_MANAGER") + ); + let reason = "RoleManager: account is missing role {0}".format(SYSTEM_POOLS_RESERVE_FUNDS_MANAGER_ROLE); + await truffleAssert.reverts(roleManager.isSystemPoolsReserveFundsManager(ANOTHER_ACCOUNT), reason); + }); + }); + + describe("grantRole()", () => { + it("should successfuly pass if the calling account has the ROLE_MANAGER_ADMIN or ROLE_MANAGER_ROLE_GOVERNOR role", async () => { + const ROLE_MANAGER_ROLE_GOVERNOR_ROLE = utils.keccak256(utils.toUtf8Bytes("ROLE_MANAGER_ROLE_GOVERNOR")); + + const ROLE_TO_GRANT = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); + + await roleManager.roleManagerInitialize([ROLE_MANAGER_ROLE_GOVERNOR_ROLE], [ANOTHER_ACCOUNT]); + + await truffleAssert.passes(roleManager.grantRole(ROLE_TO_GRANT, ANOTHER_ACCOUNT1, { from: ANOTHER_ACCOUNT })); + await truffleAssert.passes(roleManager.grantRole(ROLE_TO_GRANT, ANOTHER_ACCOUNT1, { from: ROLE_MANAGER_ADMIN })); + }); + + it("should revert if the account has neither ROLE_MANAGER_ADMIN nor ROLE_MANAGER_ROLE_GOVERNOR role", async () => { + const ROLE_MANAGER_ROLE_GOVERNOR_ROLE = utils.keccak256(utils.toUtf8Bytes("ROLE_MANAGER_ROLE_GOVERNOR")); + let reason = "RoleManager: account is missing role {0}".format(ROLE_MANAGER_ROLE_GOVERNOR_ROLE); + + const ROLE_TO_GRANT = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); + + await truffleAssert.reverts( + roleManager.grantRole(ROLE_TO_GRANT, ANOTHER_ACCOUNT1, { from: ANOTHER_ACCOUNT }), + reason + ); + }); + }); + + describe("revokeRole()", () => { + it("should successfuly pass if the calling account has the ROLE_MANAGER_ADMIN or ROLE_MANAGER_ROLE_GOVERNOR role", async () => { + const ROLE_MANAGER_ROLE_GOVERNOR_ROLE = utils.keccak256(utils.toUtf8Bytes("ROLE_MANAGER_ROLE_GOVERNOR")); + const ROLE_TO_GRANT = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); + const ROLE_TO_REVOKE = ROLE_TO_GRANT; + + await roleManager.roleManagerInitialize([ROLE_MANAGER_ROLE_GOVERNOR_ROLE], [ANOTHER_ACCOUNT]); + + await roleManager.grantRole(ROLE_TO_GRANT, ANOTHER_ACCOUNT1); + await roleManager.revokeRole(ROLE_TO_REVOKE, ANOTHER_ACCOUNT1, { from: ANOTHER_ACCOUNT }); + + await roleManager.grantRole(ROLE_TO_GRANT, ANOTHER_ACCOUNT1); + await roleManager.revokeRole(ROLE_TO_REVOKE, ANOTHER_ACCOUNT1); + }); + + it("should successfuly pass if try to revoke the role the account doesn't have", async () => { + const ROLE_MANAGER_ROLE_GOVERNOR_ROLE = utils.keccak256(utils.toUtf8Bytes("ROLE_MANAGER_ROLE_GOVERNOR")); + const ROLE_TO_GRANT = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); + const ROLE_TO_REVOKE = ROLE_TO_GRANT; + const ANOTHER_ROLE_TO_REVOKE = utils.keccak256(utils.toUtf8Bytes("ANOTHER ROLE")); + + await roleManager.roleManagerInitialize([ROLE_MANAGER_ROLE_GOVERNOR_ROLE], [ANOTHER_ACCOUNT]); + + await roleManager.grantRole(ROLE_TO_GRANT, ANOTHER_ACCOUNT1); + await roleManager.revokeRole(ROLE_TO_REVOKE, ANOTHER_ACCOUNT1, { from: ANOTHER_ACCOUNT }); + await roleManager.revokeRole(ROLE_TO_REVOKE, ANOTHER_ACCOUNT1, { from: ANOTHER_ACCOUNT }); + + await roleManager.revokeRole(ANOTHER_ROLE_TO_REVOKE, ANOTHER_ACCOUNT1, { from: ANOTHER_ACCOUNT }); + + await roleManager.grantRole(ROLE_TO_GRANT, ANOTHER_ACCOUNT1); + await roleManager.revokeRole(ROLE_TO_REVOKE, ANOTHER_ACCOUNT1); + await roleManager.revokeRole(ROLE_TO_REVOKE, ANOTHER_ACCOUNT1); + + await roleManager.revokeRole(ANOTHER_ROLE_TO_REVOKE, ANOTHER_ACCOUNT1); + }); + + it("should revert if the account has neither ROLE_MANAGER_ADMIN nor ROLE_MANAGER_ROLE_GOVERNOR role", async () => { + const ROLE_MANAGER_ROLE_GOVERNOR_ROLE = utils.keccak256(utils.toUtf8Bytes("ROLE_MANAGER_ROLE_GOVERNOR")); + let reason = "RoleManager: account is missing role {0}".format(ROLE_MANAGER_ROLE_GOVERNOR_ROLE); + + await roleManager.roleManagerInitialize([], []); + + const ROLE_TO_GRANT = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); + + await roleManager.grantRole(ROLE_TO_GRANT, ANOTHER_ACCOUNT1); + + const ROLE_TO_REVOKE = ROLE_TO_GRANT; + + await truffleAssert.reverts( + roleManager.revokeRole(ROLE_TO_REVOKE, ANOTHER_ACCOUNT1, { from: ANOTHER_ACCOUNT2 }), + reason + ); + }); + }); +}); diff --git a/test/stablePool.test.js b/test/stablePool.test.js index 58de125..f35642f 100644 --- a/test/stablePool.test.js +++ b/test/stablePool.test.js @@ -6,6 +6,7 @@ const { ZERO_ADDR } = require("../scripts/utils/constants"); const truffleAssert = require("truffle-assertions"); const Reverter = require("./helpers/reverter"); +const { artifacts } = require("hardhat"); const Registry = artifacts.require("Registry"); const DefiCore = artifacts.require("DefiCore"); @@ -19,6 +20,8 @@ const LiquidityPool = artifacts.require("LiquidityPool"); const StablePool = artifacts.require("StablePool"); const PriceManager = artifacts.require("PriceManager"); const Prt = artifacts.require("PRT"); +const RoleManager = artifacts.require("RoleManager"); + const InterestRateLibrary = artifacts.require("InterestRateLibrary"); const WETH = artifacts.require("WETH"); const StablePermitToken = artifacts.require("StablePermitTokenMock"); @@ -42,6 +45,7 @@ describe("StablePool", async () => { let systemPoolsRegistry; let stableToken; let prt; + let roleManager; let stablePool; @@ -161,6 +165,7 @@ describe("StablePool", async () => { const _stablePoolImpl = await StablePool.new(); const _priceManager = await PriceManager.new(); const _prt = await Prt.new(); + const _roleManager = await RoleManager.new(); await registry.__OwnableContractsRegistry_init(); @@ -175,12 +180,14 @@ describe("StablePool", async () => { await registry.addProxyContract(await registry.SYSTEM_POOLS_FACTORY_NAME(), _liquidityPoolFactory.address); await registry.addProxyContract(await registry.PRICE_MANAGER_NAME(), _priceManager.address); await registry.addProxyContract(await registry.PRT_NAME(), _prt.address); + await registry.addProxyContract(await registry.ROLE_MANAGER_NAME(), _roleManager.address); await registry.addContract(await registry.INTEREST_RATE_LIBRARY_NAME(), interestRateLibrary.address); defiCore = await DefiCore.at(await registry.getDefiCoreContract()); assetParameters = await AssetParameters.at(await registry.getAssetParametersContract()); systemPoolsRegistry = await SystemPoolsRegistry.at(await registry.getSystemPoolsRegistryContract()); + roleManager = await RoleManager.at(await registry.getRoleManagerContract()); const systemParameters = await SystemParameters.at(await registry.getSystemParametersContract()); const rewardsDistribution = await RewardsDistribution.at(await registry.getRewardsDistributionContract()); @@ -199,6 +206,7 @@ describe("StablePool", async () => { tokens.push(nativeToken); await defiCore.defiCoreInitialize(); + await roleManager.roleManagerInitialize([], []); await systemPoolsRegistry.systemPoolsRegistryInitialize( _liquidityPoolImpl.address, nativeTokenKey, diff --git a/test/systemParameters.test.js b/test/systemParameters.test.js index df80990..d3278d3 100644 --- a/test/systemParameters.test.js +++ b/test/systemParameters.test.js @@ -3,9 +3,11 @@ const { ZERO_ADDR } = require("../scripts/utils/constants"); const truffleAssert = require("truffle-assertions"); const Reverter = require("./helpers/reverter"); +const { artifacts } = require("hardhat"); const SystemParameters = artifacts.require("SystemParameters"); const Registry = artifacts.require("Registry"); +const RoleManager = artifacts.require("RoleManager"); SystemParameters.numberFormat = "BigNumber"; Registry.numberFormat = "BigNumber"; @@ -19,6 +21,7 @@ describe("SystemParameters", () => { let systemParameters; let registry; + let roleManager; const minCurrencyAmount = wei(0.1); before("setup", async () => { @@ -28,12 +31,17 @@ describe("SystemParameters", () => { registry = await Registry.new(); const _systemParameters = await SystemParameters.new(); + const _roleManager = await RoleManager.new(); await registry.__OwnableContractsRegistry_init(); await registry.addProxyContract(await registry.SYSTEM_PARAMETERS_NAME(), _systemParameters.address); + await registry.addProxyContract(await registry.ROLE_MANAGER_NAME(), _roleManager.address); systemParameters = await SystemParameters.at(await registry.getSystemParametersContract()); + roleManager = await RoleManager.at(await registry.getRoleManagerContract()); + + roleManager.roleManagerInitialize([], []); await registry.injectDependencies(await registry.SYSTEM_PARAMETERS_NAME()); @@ -50,8 +58,9 @@ describe("SystemParameters", () => { }); describe("setupMinCurrencyAmount", () => { - it("should get exception if called by not a system owner", async () => { - const reason = "SystemParameters: Only system owner can call this function."; + it("should get exception if called not by an SYSTEM_PARAMETERS_MANAGER/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0x5150d4e12a451b0e6f6df3626ccce38a6036b7e6ef17dc4a5038ccfa0cab851a"; await truffleAssert.reverts( systemParameters.setupMinCurrencyAmount(minCurrencyAmount, { from: SOMEBODY }), @@ -85,8 +94,9 @@ describe("SystemParameters", () => { await truffleAssert.reverts(systemParameters.setRewardsTokenAddress(ZERO_ADDR), reason); }); - it("should get exception if called by not a system owner", async () => { - const reason = "SystemParameters: Only system owner can call this function."; + it("should get exception if called not by an SYSTEM_PARAMETERS_MANAGER/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0x5150d4e12a451b0e6f6df3626ccce38a6036b7e6ef17dc4a5038ccfa0cab851a"; await truffleAssert.reverts(systemParameters.setRewardsTokenAddress(ZERO_ADDR, { from: SOMEBODY }), reason); await truffleAssert.reverts(systemParameters.setRewardsTokenAddress(ZERO_ADDR, { from: SOMEBODY }), reason); @@ -126,9 +136,10 @@ describe("SystemParameters", () => { }); describe("onlySystemOwner modifier", () => { - it("should get exception if not system owner try to call functions", async () => { + it("should get exception if called not by an SYSTEM_PARAMETERS_MANAGER/role manager admin", async () => { const newValue = getPrecision().times(50); - const reason = "SystemParameters: Only system owner can call this function."; + const reason = + "RoleManager: account is missing role 0x5150d4e12a451b0e6f6df3626ccce38a6036b7e6ef17dc4a5038ccfa0cab851a"; await truffleAssert.reverts(systemParameters.setupLiquidationBoundary(newValue, { from: SOMEBODY }), reason); await truffleAssert.reverts(systemParameters.setupStablePoolsAvailability(true, { from: SOMEBODY }), reason); diff --git a/test/systemPoolsRegistry.test.js b/test/systemPoolsRegistry.test.js index e629a00..ee5fe5a 100644 --- a/test/systemPoolsRegistry.test.js +++ b/test/systemPoolsRegistry.test.js @@ -24,6 +24,8 @@ const LiquidityPoolMock = artifacts.require("LiquidityPoolMock"); const AbstractPool = artifacts.require("AbstractPool"); const PriceManager = artifacts.require("PriceManager"); const Prt = artifacts.require("PRT"); +const RoleManager = artifacts.require("RoleManager"); + const InterestRateLibrary = artifacts.require("InterestRateLibrary"); const WETH = artifacts.require("WETH"); const StablePermitToken = artifacts.require("StablePermitTokenMock"); @@ -71,6 +73,7 @@ describe("SystemPoolsRegistry", () => { let systemPoolsRegistry; let liquidityPoolFactory; let prt; + let roleManager; let rewardsToken; @@ -169,6 +172,7 @@ describe("SystemPoolsRegistry", () => { const _liquidityPoolImpl = await LiquidityPool.new(); const _priceManager = await PriceManager.new(); const _prt = await Prt.new(); + const _roleManager = await RoleManager.new(); await registry.__OwnableContractsRegistry_init(); @@ -181,6 +185,7 @@ describe("SystemPoolsRegistry", () => { await registry.addProxyContract(await registry.SYSTEM_POOLS_FACTORY_NAME(), _liquidityPoolFactory.address); await registry.addProxyContract(await registry.PRICE_MANAGER_NAME(), _priceManager.address); await registry.addProxyContract(await registry.PRT_NAME(), _prt.address); + await registry.addProxyContract(await registry.ROLE_MANAGER_NAME(), _roleManager.address); await registry.addContract(await registry.INTEREST_RATE_LIBRARY_NAME(), interestRateLibrary.address); @@ -190,6 +195,7 @@ describe("SystemPoolsRegistry", () => { rewardsDistribution = await RewardsDistribution.at(await registry.getRewardsDistributionContract()); systemParameters = await SystemParameters.at(await registry.getSystemParametersContract()); liquidityPoolFactory = await SystemPoolsFactory.at(await registry.getSystemPoolsFactoryContract()); + roleManager = await RoleManager.at(await registry.getRoleManagerContract()); await registry.injectDependencies(await registry.DEFI_CORE_NAME()); await registry.injectDependencies(await registry.SYSTEM_PARAMETERS_NAME()); @@ -202,6 +208,7 @@ describe("SystemPoolsRegistry", () => { await registry.injectDependencies(await registry.PRT_NAME()); await defiCore.defiCoreInitialize(); + await roleManager.roleManagerInitialize([], []); await systemPoolsRegistry.systemPoolsRegistryInitialize(_liquidityPoolImpl.address, nativeTokenKey, zeroKey); await systemParameters.setupStablePoolsAvailability(true); @@ -283,8 +290,9 @@ describe("SystemPoolsRegistry", () => { await truffleAssert.reverts(systemPoolsRegistry.updateRewardsAssetKey(someKey), reason); }); - it("should get exception if called by not a system owner", async () => { - const reason = "SystemPoolsRegistry: Only system owner can call this function."; + it("should get exception if called not by an SYSTEM_POOLS_MANAGER/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0xa6422b3c9a6d3dc00d8db23ad51c1008c5e46eaa60434b734a90225deb0e7cb9"; assert.isTrue(compareKeys(await systemPoolsRegistry.rewardsAssetKey(), zeroKey)); assert.equal(await getLiquidityPoolAddr(zeroKey), await systemPoolsRegistry.getRewardsLiquidityPool()); @@ -318,8 +326,9 @@ describe("SystemPoolsRegistry", () => { await truffleAssert.reverts(systemPoolsRegistry.addPoolsBeacon(0, NOTHING), reason); }); - it("should get exception if not system owner try to call this function", async () => { - const reason = "SystemPoolsRegistry: Only system owner can call this function."; + it("should get exception if called not by an SYSTEM_POOLS_MANAGER/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0xa6422b3c9a6d3dc00d8db23ad51c1008c5e46eaa60434b734a90225deb0e7cb9"; await truffleAssert.reverts(systemPoolsRegistry.addPoolsBeacon(1, NOTHING, { from: USER1 }), reason); }); @@ -385,8 +394,9 @@ describe("SystemPoolsRegistry", () => { await truffleAssert.reverts(liquidityPoolFactory.newLiquidityPool(TEST_ASSET, daiKey, "DAI"), reason); }); - it("should get exception if called by not a system owner", async () => { - const reason = "SystemPoolsRegistry: Only system owner can call this function."; + it("should get exception if called not by an SYSTEM_POOLS_MANAGER/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0xa6422b3c9a6d3dc00d8db23ad51c1008c5e46eaa60434b734a90225deb0e7cb9"; await truffleAssert.reverts( systemPoolsRegistry.addLiquidityPool(TEST_ASSET, daiKey, chainlinkOracle.address, "DAI", true, true, { @@ -431,8 +441,9 @@ describe("SystemPoolsRegistry", () => { await truffleAssert.reverts(systemPoolsRegistry.addStablePool(NOTHING, someKey, NOTHING), reason); }); - it("should get exception if called by not a system owner", async () => { - const reason = "SystemPoolsRegistry: Only system owner can call this function."; + it("should get exception if called not by an SYSTEM_POOLS_MANAGER/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0xa6422b3c9a6d3dc00d8db23ad51c1008c5e46eaa60434b734a90225deb0e7cb9"; await truffleAssert.reverts( systemPoolsRegistry.addStablePool(someToken.address, someKey, NOTHING, { from: USER1 }), @@ -468,8 +479,9 @@ describe("SystemPoolsRegistry", () => { await truffleAssert.reverts(systemPoolsRegistry.upgradePoolsImpl(1, NOTHING), reason); }); - it("should get exception if called by not a system owner", async () => { - const reason = "SystemPoolsRegistry: Only system owner can call this function."; + it("should get exception if called not by an SYSTEM_POOLS_MANAGER/role manager admin", async () => { + const reason = + "RoleManager: account is missing role 0xa6422b3c9a6d3dc00d8db23ad51c1008c5e46eaa60434b734a90225deb0e7cb9"; await createLiquidityPool(daiKey, "DAI", true); const daiPool = await LiquidityPool.at(await getLiquidityPoolAddr(daiKey)); @@ -560,8 +572,9 @@ describe("SystemPoolsRegistry", () => { await truffleAssert.reverts(abstractPools[0].setDependencies(registry.address, { from: USER2 }), reason); }); - it("injectDependenciesToExistingPools() should get exception if called by not a system owner", async () => { - const reason = "SystemPoolsRegistry: Only system owner can call this function."; + it("injectDependenciesToExistingPools() should get exception if called by not a SYSTEM_POOLS_MANAGER", async () => { + const reason = + "RoleManager: account is missing role 0xa6422b3c9a6d3dc00d8db23ad51c1008c5e46eaa60434b734a90225deb0e7cb9"; const currentPriceManager = await registry.getPriceManagerContract(); const newPriceManager = await PriceManager.new(); @@ -574,8 +587,9 @@ describe("SystemPoolsRegistry", () => { await truffleAssert.reverts(systemPoolsRegistry.injectDependenciesToExistingPools({ from: USER1 }), reason); }); - it("injectDependencies() should get exception if called by not a system owner", async () => { - const reason = "SystemPoolsRegistry: Only system owner can call this function."; + it("injectDependencies() should get exception if called by not a SYSTEM_POOLS_MANAGER", async () => { + const reason = + "RoleManager: account is missing role 0xa6422b3c9a6d3dc00d8db23ad51c1008c5e46eaa60434b734a90225deb0e7cb9"; const currentPriceManager = await registry.getPriceManagerContract(); const newPriceManager = await PriceManager.new(); diff --git a/test/userInfoRegistry.test.js b/test/userInfoRegistry.test.js index b3d7190..44218db 100644 --- a/test/userInfoRegistry.test.js +++ b/test/userInfoRegistry.test.js @@ -6,6 +6,7 @@ const { ZERO_ADDR } = require("../scripts/utils/constants"); const truffleAssert = require("truffle-assertions"); const Reverter = require("./helpers/reverter"); +const { artifacts } = require("hardhat"); const Registry = artifacts.require("Registry"); const DefiCore = artifacts.require("DefiCore"); @@ -20,6 +21,8 @@ const StablePool = artifacts.require("StablePool"); const PriceManager = artifacts.require("PriceManager"); const InterestRateLibrary = artifacts.require("InterestRateLibrary"); const Prt = artifacts.require("PRT"); +const RoleManager = artifacts.require("RoleManager"); + const WETH = artifacts.require("WETH"); const StablePermitToken = artifacts.require("StablePermitTokenMock"); @@ -49,6 +52,7 @@ describe("UserInfoRegistry", () => { let systemPoolsRegistry; let rewardsDistribution; let prt; + let roleManager; let nativePool; let daiPool; @@ -186,6 +190,7 @@ describe("UserInfoRegistry", () => { const _stablePoolImpl = await StablePool.new(); const _priceManager = await PriceManager.new(); const _prt = await Prt.new(); + const _roleManager = await RoleManager.new(); await registry.__OwnableContractsRegistry_init(); @@ -200,6 +205,7 @@ describe("UserInfoRegistry", () => { await registry.addProxyContract(await registry.SYSTEM_POOLS_FACTORY_NAME(), _liquidityPoolFactory.address); await registry.addProxyContract(await registry.PRICE_MANAGER_NAME(), _priceManager.address); await registry.addProxyContract(await registry.PRT_NAME(), _prt.address); + await registry.addProxyContract(await registry.ROLE_MANAGER_NAME(), _roleManager.address); await registry.addContract(await registry.INTEREST_RATE_LIBRARY_NAME(), interestRateLibrary.address); @@ -210,6 +216,7 @@ describe("UserInfoRegistry", () => { rewardsDistribution = await RewardsDistribution.at(await registry.getRewardsDistributionContract()); systemParameters = await SystemParameters.at(await registry.getSystemParametersContract()); prt = await Prt.at(await registry.getPRTContract()); + roleManager = await RoleManager.at(await registry.getRoleManagerContract()); await registry.injectDependencies(await registry.DEFI_CORE_NAME()); await registry.injectDependencies(await registry.SYSTEM_PARAMETERS_NAME()); @@ -226,6 +233,7 @@ describe("UserInfoRegistry", () => { tokens.push(nativeToken); await defiCore.defiCoreInitialize(); + await roleManager.roleManagerInitialize([], []); await systemPoolsRegistry.systemPoolsRegistryInitialize(_liquidityPoolImpl.address, nativeTokenKey, zeroKey); await prt.prtInitialize("Platform Reputation Token", "PRT", [ [1000000000000, 100], From 748e7e56da8f97129c6b4f11f7389fd5f8856a29 Mon Sep 17 00:00:00 2001 From: mesowea Date: Tue, 21 Mar 2023 00:32:13 +0200 Subject: [PATCH 6/6] Add modifiers which check whether a user has a particular role using the internal function in the contracts with a role mechanism, add comments to IRoleManager, replace 'only system owner can call...' comments with the corresponding role names, change string formating in tests --- contracts/AssetParameters.sol | 35 +++++------- contracts/DefiCore.sol | 13 +++-- contracts/PRT.sol | 13 ++++- contracts/RewardsDistribution.sol | 13 ++++- contracts/SystemParameters.sol | 29 ++++++---- contracts/SystemPoolsRegistry.sol | 55 ++++++++++--------- contracts/interfaces/IAssetParameters.sol | 14 ++--- contracts/interfaces/IDefiCore.sol | 4 +- contracts/interfaces/IPRT.sol | 2 +- contracts/interfaces/IRewardsDistribution.sol | 2 +- contracts/interfaces/IRoleManager.sol | 30 +++++++++- contracts/interfaces/ISystemParameters.sol | 8 +-- contracts/interfaces/ISystemPoolsRegistry.sol | 21 ++++--- deploy/1_contracts_deploy.js | 1 - deploy/2_init_all.js | 2 - test/assetParameters.test.js | 45 ++++++++------- test/defiCore.test.js | 7 ++- test/liquidityPool.test.js | 17 ++++-- test/priceManager.test.js | 1 - test/prt.test.js | 8 ++- test/registry.test.js | 1 - test/rewardsDistribution.test.js | 8 +-- test/roleManager.test.js | 34 ++++++------ test/stablePool.test.js | 1 - test/systemParameters.test.js | 41 ++++++++++---- test/systemPoolsRegistry.test.js | 46 ++++++++-------- test/userInfoRegistry.test.js | 1 - 27 files changed, 262 insertions(+), 190 deletions(-) diff --git a/contracts/AssetParameters.sol b/contracts/AssetParameters.sol index 69677f8..b1723c9 100644 --- a/contracts/AssetParameters.sol +++ b/contracts/AssetParameters.sol @@ -63,6 +63,11 @@ contract AssetParameters is IAssetParameters, AbstractDependant { _; } + modifier onlyAssetParametersManager() { + _onlyAssetParametersManager(); + _; + } + function setDependencies(address contractsRegistry_) external override dependant { IRegistry registry_ = IRegistry(contractsRegistry_); @@ -98,9 +103,7 @@ contract AssetParameters is IAssetParameters, AbstractDependant { function setupAnnualBorrowRate( bytes32 assetKey_, uint256 newAnnualBorrowRate_ - ) external override onlyExists(assetKey_) { - _onlyAssetParametersManager(); - + ) external override onlyAssetParametersManager onlyExists(assetKey_) { require( _systemParameters.getStablePoolsAvailability(), "AssetParameters: Stable pools unavailable." @@ -132,44 +135,36 @@ contract AssetParameters is IAssetParameters, AbstractDependant { function setupMainParameters( bytes32 assetKey_, MainPoolParams calldata mainParams_ - ) external override onlyExists(assetKey_) { - _onlyAssetParametersManager(); - + ) external override onlyAssetParametersManager onlyExists(assetKey_) { _setupMainParameters(assetKey_, mainParams_); } function setupInterestRateModel( bytes32 assetKey_, InterestRateParams calldata interestParams_ - ) external override onlyExists(assetKey_) { - _onlyAssetParametersManager(); - + ) external override onlyAssetParametersManager onlyExists(assetKey_) { _setupInterestRateParams(assetKey_, interestParams_); } function setupDistributionsMinimums( bytes32 assetKey_, DistributionMinimums calldata distrMinimums_ - ) external override onlyExists(assetKey_) { - _onlyAssetParametersManager(); - + ) external override onlyAssetParametersManager onlyExists(assetKey_) { _setupDistributionsMinimums(assetKey_, distrMinimums_); } function setupAllParameters( bytes32 assetKey_, AllPoolParams calldata poolParams_ - ) external override onlyExists(assetKey_) { - _onlyAssetParametersManager(); - + ) external override onlyAssetParametersManager onlyExists(assetKey_) { _setupInterestRateParams(assetKey_, poolParams_.interestRateParams); _setupMainParameters(assetKey_, poolParams_.mainParams); _setupDistributionsMinimums(assetKey_, poolParams_.distrMinimums); } - function freeze(bytes32 assetKey_) external override onlyExists(assetKey_) { - _onlyAssetParametersManager(); - + function freeze( + bytes32 assetKey_ + ) external override onlyAssetParametersManager onlyExists(assetKey_) { _parameters[assetKey_][FREEZE_KEY] = PureParameters.makeBoolParam(true); emit FreezeParamUpdated(assetKey_, true); @@ -178,9 +173,7 @@ contract AssetParameters is IAssetParameters, AbstractDependant { function enableCollateral( bytes32 assetKey_, bool forPRT_ - ) external override onlyExists(assetKey_) { - _onlyAssetParametersManager(); - + ) external override onlyAssetParametersManager onlyExists(assetKey_) { forPRT_ ? _parameters[assetKey_][ENABLE_COLLATERAL_WITH_PRT_KEY] = PureParameters .makeBoolParam(true) diff --git a/contracts/DefiCore.sol b/contracts/DefiCore.sol index 9bb7afe..e98c6a4 100644 --- a/contracts/DefiCore.sol +++ b/contracts/DefiCore.sol @@ -48,6 +48,11 @@ contract DefiCore is mapping(address => mapping(bytes32 => bool)) public override disabledCollateralAssets; + modifier onlyDefiCorePauser() { + _onlyDefiCorePauser(); + _; + } + function defiCoreInitialize() external initializer { __Pausable_init(); __ReentrancyGuard_init(); @@ -66,15 +71,11 @@ contract DefiCore is _roleManager = IRoleManager(registry_.getRoleManagerContract()); } - function pause() external override { - _onlyDefiCorePauser(); - + function pause() external override onlyDefiCorePauser { _pause(); } - function unpause() external override { - _onlyDefiCorePauser(); - + function unpause() external override onlyDefiCorePauser { _unpause(); } diff --git a/contracts/PRT.sol b/contracts/PRT.sol index 5e5256e..310c978 100644 --- a/contracts/PRT.sol +++ b/contracts/PRT.sol @@ -21,6 +21,11 @@ contract PRT is IPRT, ERC721Upgradeable, AbstractDependant, ReentrancyGuardUpgra PRTParams internal _prtParams; + modifier onlyPRTParamUpdater() { + _onlyPRTParamUpdater(); + _; + } + function prtInitialize( string calldata name_, string calldata symbol_, @@ -40,9 +45,7 @@ contract PRT is IPRT, ERC721Upgradeable, AbstractDependant, ReentrancyGuardUpgra _roleManager = IRoleManager(registry_.getRoleManagerContract()); } - function updatePRTParams(PRTParams calldata prtParams_) external override { - _roleManager.isPRTParamUpdater(msg.sender); - + function updatePRTParams(PRTParams calldata prtParams_) external override onlyPRTParamUpdater { _prtParams = prtParams_; } @@ -98,6 +101,10 @@ contract PRT is IPRT, ERC721Upgradeable, AbstractDependant, ReentrancyGuardUpgra _burn(tokenId_); } + function _onlyPRTParamUpdater() internal { + _roleManager.isPRTParamUpdater(msg.sender); + } + function _checkUserPRTStats( address userAddr_, IUserInfoRegistry.LastSavedUserPosition memory userPosition_, diff --git a/contracts/RewardsDistribution.sol b/contracts/RewardsDistribution.sol index 5eecc41..afb6d28 100644 --- a/contracts/RewardsDistribution.sol +++ b/contracts/RewardsDistribution.sol @@ -36,6 +36,11 @@ contract RewardsDistribution is IRewardsDistribution, AbstractDependant { _; } + modifier onlyRewardsDistributionManager() { + _onlyRewardsDistributionManager(); + _; + } + function setDependencies(address contractsRegistry_) external override dependant { IRegistry registry_ = IRegistry(contractsRegistry_); @@ -80,9 +85,7 @@ contract RewardsDistribution is IRewardsDistribution, AbstractDependant { function setupRewardsPerBlockBatch( bytes32[] calldata assetKeys_, uint256[] calldata rewardsPerBlock_ - ) external override { - _roleManager.isRewardsDistributionManager(msg.sender); - + ) external override onlyRewardsDistributionManager { require( _onlyExistingRewardsAssetKey(), "RewardsDistributionL Unable to setup rewards per block." @@ -180,6 +183,10 @@ contract RewardsDistribution is IRewardsDistribution, AbstractDependant { } } + function _onlyRewardsDistributionManager() internal { + _roleManager.isRewardsDistributionManager(msg.sender); + } + function _updateSumsWithUserReward( address userAddr_, bytes32 assetKey_, diff --git a/contracts/SystemParameters.sol b/contracts/SystemParameters.sol index d3baf04..4865e46 100644 --- a/contracts/SystemParameters.sol +++ b/contracts/SystemParameters.sol @@ -24,6 +24,11 @@ contract SystemParameters is ISystemParameters, AbstractDependant { mapping(bytes32 => PureParameters.Param) internal _parameters; + modifier onlySystemParametersManager() { + _onlySystemParametersManager(); + _; + } + function setDependencies(address contractsRegistry_) external override dependant { IRegistry registry_ = IRegistry(contractsRegistry_); @@ -31,9 +36,9 @@ contract SystemParameters is ISystemParameters, AbstractDependant { _roleManager = IRoleManager(registry_.getRoleManagerContract()); } - function setRewardsTokenAddress(address rewardsToken_) external override { - _onlySystemParametersManager(); - + function setRewardsTokenAddress( + address rewardsToken_ + ) external override onlySystemParametersManager { PureParameters.Param memory currentParam_ = _parameters[REWARDS_TOKEN_KEY]; if (PureParameters.paramExists(currentParam_)) { @@ -48,9 +53,9 @@ contract SystemParameters is ISystemParameters, AbstractDependant { emit RewardsTokenUpdated(rewardsToken_); } - function setupLiquidationBoundary(uint256 newValue_) external override { - _onlySystemParametersManager(); - + function setupLiquidationBoundary( + uint256 newValue_ + ) external override onlySystemParametersManager { require( newValue_ >= PRECISION * 50 && newValue_ <= PRECISION * 80, "SystemParameters: The new value of the liquidation boundary is invalid." @@ -61,17 +66,17 @@ contract SystemParameters is ISystemParameters, AbstractDependant { emit LiquidationBoundaryUpdated(newValue_); } - function setupStablePoolsAvailability(bool newValue_) external override { - _onlySystemParametersManager(); - + function setupStablePoolsAvailability( + bool newValue_ + ) external override onlySystemParametersManager { _parameters[STABLE_POOLS_AVAILABILITY_KEY] = PureParameters.makeBoolParam(newValue_); emit StablePoolsAvailabilityUpdated(newValue_); } - function setupMinCurrencyAmount(uint256 newMinCurrencyAmount_) external override { - _onlySystemParametersManager(); - + function setupMinCurrencyAmount( + uint256 newMinCurrencyAmount_ + ) external override onlySystemParametersManager { _parameters[MIN_CURRENCY_AMOUNT_KEY] = PureParameters.makeUintParam(newMinCurrencyAmount_); emit MinCurrencyAmountUpdated(newMinCurrencyAmount_); diff --git a/contracts/SystemPoolsRegistry.sol b/contracts/SystemPoolsRegistry.sol index b9bb449..3fd5bf3 100644 --- a/contracts/SystemPoolsRegistry.sol +++ b/contracts/SystemPoolsRegistry.sol @@ -43,6 +43,16 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep mapping(address => bool) public override existingLiquidityPools; mapping(PoolType => PoolTypeInfo) internal _poolTypesInfo; + modifier onlySystemPoolsManager() { + _onlySystemPoolsManager(); + _; + } + + modifier onlySystemPoolsReserveFundsManager() { + _onlySystemPoolsReserveFundsManager(); + _; + } + function systemPoolsRegistryInitialize( address liquidityPoolImpl_, bytes32 nativeAssetKey_, @@ -70,9 +80,7 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep _roleManager = IRoleManager(registry_.getRoleManagerContract()); } - function updateRewardsAssetKey(bytes32 newRewardsAssetKey_) external { - _onlySystemPoolsManager(); - + function updateRewardsAssetKey(bytes32 newRewardsAssetKey_) external onlySystemPoolsManager { require( IBasicPool(poolsInfo[newRewardsAssetKey_].poolAddr).assetAddr() == _systemParameters.getRewardsTokenAddress(), @@ -82,9 +90,10 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep rewardsAssetKey = newRewardsAssetKey_; } - function addPoolsBeacon(PoolType poolType_, address poolImpl_) external override { - _onlySystemPoolsManager(); - + function addPoolsBeacon( + PoolType poolType_, + address poolImpl_ + ) external override onlySystemPoolsManager { PoolTypeInfo storage _poolTypeInfo = _poolTypesInfo[poolType_]; require( @@ -102,9 +111,7 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep string calldata tokenSymbol_, bool isCollateral_, bool isCollateralWithPRT_ - ) external override { - _onlySystemPoolsManager(); - + ) external override onlySystemPoolsManager { _addPool( assetAddr_, assetKey_, @@ -120,9 +127,7 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep address assetAddr_, bytes32 assetKey_, address chainlinkOracle_ - ) external override { - _onlySystemPoolsManager(); - + ) external override onlySystemPoolsManager { require( _systemParameters.getStablePoolsAvailability(), "SystemPoolsRegistry: Stable pools are unavailable." @@ -136,9 +141,7 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep bytes32 assetKey_, uint256 amountToWithdraw_, bool isAllFunds_ - ) external override { - _onlySystemPoolsReserveFundsManager(); - + ) external override onlySystemPoolsReserveFundsManager { require(onlyExistingPool(assetKey_), "SystemPoolsRegistry: Pool doesn't exist."); if (!isAllFunds_) { @@ -159,9 +162,7 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep address recipientAddr_, uint256 offset_, uint256 limit_ - ) external override { - _onlySystemPoolsReserveFundsManager(); - + ) external override onlySystemPoolsReserveFundsManager { bytes32[] memory _assetsKeys = getSupportedAssetKeys(offset_, limit_); for (uint256 i = 0; i < _assetsKeys.length; i++) { @@ -173,9 +174,10 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep } } - function upgradePoolsImpl(PoolType poolType_, address newPoolsImpl_) external override { - _onlySystemPoolsManager(); - + function upgradePoolsImpl( + PoolType poolType_, + address newPoolsImpl_ + ) external override onlySystemPoolsManager { address poolBeacon_ = _poolTypesInfo[poolType_].poolBeaconAddr; require(poolBeacon_ != address(0), "SystemPoolsRegistry: Unsupported pool type."); @@ -183,9 +185,7 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep UpgradeableBeacon(poolBeacon_).upgradeTo(newPoolsImpl_); } - function injectDependenciesToExistingPools() external override { - _onlySystemPoolsManager(); - + function injectDependenciesToExistingPools() external override onlySystemPoolsManager { IRegistry registry_ = _registry; address[] memory allPools_ = getAllPools(); @@ -195,9 +195,10 @@ contract SystemPoolsRegistry is ISystemPoolsRegistry, Initializable, AbstractDep } } - function injectDependencies(uint256 offset_, uint256 limit_) external override { - _onlySystemPoolsManager(); - + function injectDependencies( + uint256 offset_, + uint256 limit_ + ) external override onlySystemPoolsManager { IRegistry registry_ = _registry; address[] memory _pools = getPools(offset_, limit_); diff --git a/contracts/interfaces/IAssetParameters.sol b/contracts/interfaces/IAssetParameters.sol index 1982173..598561c 100644 --- a/contracts/interfaces/IAssetParameters.sol +++ b/contracts/interfaces/IAssetParameters.sol @@ -111,19 +111,19 @@ interface IAssetParameters { ) external; /// @notice Function for setting the annual borrow rate of the stable pool - /// @dev Only contract owner can call this function. Only for stable pools + /// @dev Only ASSET_PARAMETERS_MANAGER can call this function. Only for stable pools /// @param assetKey_ pool key for which parameters will be set /// @param newAnnualBorrowRate_ new annual borrow rate parameter function setupAnnualBorrowRate(bytes32 assetKey_, uint256 newAnnualBorrowRate_) external; /// @notice Function for setting the main parameters of the pool - /// @dev Only contract owner can call this function + /// @dev Only ASSET_PARAMETERS_MANAGER can call this function /// @param assetKey_ pool key for which parameters will be set /// @param mainParams_ structure with the main parameters of the pool function setupMainParameters(bytes32 assetKey_, MainPoolParams calldata mainParams_) external; /// @notice Function for setting the interest rate parameters of the pool - /// @dev Only contract owner can call this function + /// @dev Only ASSET_PARAMETERS_MANAGER can call this function /// @param assetKey_ pool key for which parameters will be set /// @param interestParams_ structure with the interest rate parameters of the pool function setupInterestRateModel( @@ -132,7 +132,7 @@ interface IAssetParameters { ) external; /// @notice Function for setting the distribution minimums of the pool - /// @dev Only contract owner can call this function + /// @dev Only ASSET_PARAMETERS_MANAGER can call this function /// @param assetKey_ pool key for which parameters will be set /// @param distrMinimums_ structure with the distribution minimums of the pool function setupDistributionsMinimums( @@ -141,18 +141,18 @@ interface IAssetParameters { ) external; /// @notice Function for setting all pool parameters - /// @dev Only contract owner can call this function + /// @dev Only ASSET_PARAMETERS_MANAGER can call this function /// @param assetKey_ pool key for which parameters will be set /// @param poolParams_ structure with all pool parameters function setupAllParameters(bytes32 assetKey_, AllPoolParams calldata poolParams_) external; /// @notice Function for freezing the pool - /// @dev Only contract owner can call this function + /// @dev Only ASSET_PARAMETERS_MANAGER can call this function /// @param assetKey_ pool key to be frozen function freeze(bytes32 assetKey_) external; /// @notice Function to enable the pool as a collateral - /// @dev Only contract owner can call this function + /// @dev Only ASSET_PARAMETERS_MANAGER can call this function /// @param assetKey_ the pool key to be enabled as a collateral /// @param forPRT_ whether to enable the asset as a collateral for the users with PRT function enableCollateral(bytes32 assetKey_, bool forPRT_) external; diff --git a/contracts/interfaces/IDefiCore.sol b/contracts/interfaces/IDefiCore.sol index 4a3c39e..68ebee7 100644 --- a/contracts/interfaces/IDefiCore.sol +++ b/contracts/interfaces/IDefiCore.sol @@ -75,11 +75,11 @@ interface IDefiCore { event DistributionRewardWithdrawn(address indexed userAddr, uint256 rewardAmount); /// @notice Function for pausing all user interactions with the system - /// @dev Only contract owner can call this function + /// @dev Only DEFI_CORE_PAUSER can call this function function pause() external; /// @notice Function for unpausing all user interactions with the system - /// @dev Only contract owner can call this function + /// @dev Only DEFI_CORE_PAUSER can call this function function unpause() external; /// @notice With this function you can change the value of the disabled of the asset as a collateral diff --git a/contracts/interfaces/IPRT.sol b/contracts/interfaces/IPRT.sol index b2f503c..2a0b719 100644 --- a/contracts/interfaces/IPRT.sol +++ b/contracts/interfaces/IPRT.sol @@ -25,7 +25,7 @@ interface IPRT { } /// @notice A system function that is needed to update the requirements for PRT - /// @dev Only the system owner can call this function + /// @dev Only the PRT_PARAM_UPDATER can call this function /// @param prtParams_ element type PRTParams structure with the new requirements function updatePRTParams(PRTParams calldata prtParams_) external; diff --git a/contracts/interfaces/IRewardsDistribution.sol b/contracts/interfaces/IRewardsDistribution.sol index 8ff99cc..521934c 100644 --- a/contracts/interfaces/IRewardsDistribution.sol +++ b/contracts/interfaces/IRewardsDistribution.sol @@ -60,7 +60,7 @@ interface IRewardsDistribution { ) external returns (uint256 userReward_); /// @notice Function to update block rewards for desired pools - /// @dev Can call only by contract owner. The passed arrays must be of the same length + /// @dev Can call only by REWARDS_DISTRIBUTION_MANAGER. The passed arrays must be of the same length /// @param assetKeys_ array of pool identifiers /// @param rewardsPerBlock_ array of new rewards per block function setupRewardsPerBlockBatch( diff --git a/contracts/interfaces/IRoleManager.sol b/contracts/interfaces/IRoleManager.sol index eef2259..02365dc 100644 --- a/contracts/interfaces/IRoleManager.sol +++ b/contracts/interfaces/IRoleManager.sol @@ -1,21 +1,49 @@ +// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.17; +/** + * This contract stores different roles across the protocol and their corresponding accounts. + * It also can be used for checking whether a particular user has a specific role, creating, granting and revoking the roles. + * The contract also stores a set of constants with the role names which are used across the protocol. + */ interface IRoleManager { + /// @notice Function for granting the role to the specified account + /// @dev Only user with the ROLE_MANAGER_ROLE_GOVERNOR or ROLE_MANAGER_ADMIN role can call this function + /// @param role_ role to grant to the account + /// @param account_ account to grant the role to function grantRole(bytes32 role_, address account_) external; - function revokeRole(bytes32 role, address account) external; + /// @notice Function for revoking the role from the specified account + /// @dev Only user with the ROLE_MANAGER_ROLE_GOVERNOR or ROLE_MANAGER_ADMIN role can call this function + /// @param role_ role to revoke from the account + /// @param account_ account to revoke the role from + function revokeRole(bytes32 role_, address account_) external; + /// @notice Function to check whether the address has the ASSET_PARAMETERS_MANAGER or ROLE_MANAGER_ADMIN role + /// @dev Used in AssetParameters contract to check the caller's roles in some function. Reverts if the account has neither of the roles mentioned above. function isAssetParametersManager(address account_) external view; + /// @notice Function to check whether the address has the DEFI_CORE_PAUSER or ROLE_MANAGER_ADMIN role + /// @dev Used in DefiCore contract to check the caller's roles in some function. Reverts if the account has neither of the roles mentioned above. function isDefiCorePauser(address account_) external view; + /// @notice Function to check whether the address has the PRT_PARAM_UPDATER or ROLE_MANAGER_ADMIN role + /// @dev Used in PRT contract to check the caller's roles in some function. Reverts if the account has neither of the roles mentioned above. function isPRTParamUpdater(address account_) external view; + /// @notice Function to check whether the address has the REWARDS_DISTRIBUTION_MANAGER or ROLE_MANAGER_ADMIN role + /// @dev Used in RewardsDistribution contract to check the caller's roles in some function. Reverts if the account has neither of the roles mentioned above. function isRewardsDistributionManager(address account_) external view; + /// @notice Function to check whether the address has the SYSTEM_PARAMETERS_MANAGER or ROLE_MANAGER_ADMIN role + /// @dev Used in SystemParameters contract to check the caller's roles in some function. Reverts if the account has neither of the roles mentioned above. function isSystemParametersManager(address account_) external view; + /// @notice Function to check whether the address has the SYSTEM_POOLS_MANAGER or ROLE_MANAGER_ADMIN role + /// @dev Used in SystemPoolManager contract to check the caller's roles in some function. Reverts if the account has neither of the roles mentioned above. function isSystemPoolsManager(address account_) external view; + /// @notice Function to check whether the address has the SYSTEM_POOLS_RESERVE_FUNDS_MANAGER or ROLE_MANAGER_ADMIN role + /// @dev Used in SystemPoolManager contract to check the caller's roles in some function. Reverts if the account has neither of the roles mentioned above. function isSystemPoolsReserveFundsManager(address account_) external view; } diff --git a/contracts/interfaces/ISystemParameters.sol b/contracts/interfaces/ISystemParameters.sol index 990a281..81a7893 100644 --- a/contracts/interfaces/ISystemParameters.sol +++ b/contracts/interfaces/ISystemParameters.sol @@ -22,22 +22,22 @@ interface ISystemParameters { event MinCurrencyAmountUpdated(uint256 newValue); /// @notice The function that updates the rewards token address. Can update only if current rewards token address is zero address - /// @dev Only owner of this contract can call this function + /// @dev Only SYSTEM_PARAMETERS_MANAGER can call this function /// @param rewardsToken_ new value of the rewards token parameter function setRewardsTokenAddress(address rewardsToken_) external; /// @notice The function that updates the parameter of the same name to a new value - /// @dev Only owner of this contract can call this function + /// @dev Only SYSTEM_PARAMETERS_MANAGER can call this function /// @param newValue_ new value of the liquidation boundary parameter function setupLiquidationBoundary(uint256 newValue_) external; /// @notice The function that updates the parameter of the same name to a new value - /// @dev Only owner of this contract can call this function + /// @dev Only SYSTEM_PARAMETERS_MANAGER can call this function /// @param newValue_ new value of the stable pools availability parameter function setupStablePoolsAvailability(bool newValue_) external; /// @notice The function that updates the parameter of the same name - /// @dev Only owner of this contract can call this function + /// @dev Only SYSTEM_PARAMETERS_MANAGER can call this function /// @param newMinCurrencyAmount_ new value of the min currency amount parameter function setupMinCurrencyAmount(uint256 newMinCurrencyAmount_) external; diff --git a/contracts/interfaces/ISystemPoolsRegistry.sol b/contracts/interfaces/ISystemPoolsRegistry.sol index 8d68a60..fa1b156 100644 --- a/contracts/interfaces/ISystemPoolsRegistry.sol +++ b/contracts/interfaces/ISystemPoolsRegistry.sol @@ -101,13 +101,13 @@ interface ISystemPoolsRegistry { event PoolAdded(bytes32 assetKey, address assetAddr, address poolAddr, PoolType poolType); /// @notice Function to add a beacon contract for the desired type of pools - /// @dev Only contract owner can call this function + /// @dev Only SYSTEM_POOLS_MANAGER can call this function /// @param poolType_ the type of pool for which the beacon contract will be added /// @param poolImpl_ the implementation address for the desired pool type function addPoolsBeacon(PoolType poolType_, address poolImpl_) external; /// @notice The function is needed to add new liquidity pools - /// @dev Only contract owner can call this function + /// @dev Only SYSTEM_POOLS_MANAGER call this function /// @param assetAddr_ address of the underlying liquidity pool asset /// @param assetKey_ pool key of the added liquidity pool /// @param chainlinkOracle_ the address of the chainlink oracle for the passed asset @@ -124,7 +124,7 @@ interface ISystemPoolsRegistry { ) external; /// @notice The function is needed to add new stable pools - /// @dev Only contract owner can call this function + /// @dev Only SYSTEM_POOLS_MANAGER can call this function /// @param assetAddr_ address of the underlying stable pool asset /// @param assetKey_ pool key of the added stable pool /// @param chainlinkOracle_ the address of the chainlink oracle for the passed asset @@ -135,7 +135,7 @@ interface ISystemPoolsRegistry { ) external; /// @notice Withdraws a certain amount of reserve funds from a certain pool to a certain recipient - /// @dev Only contract owner can call this function + /// @dev Only SYSTEM_POOLS_RESERVE_FUNDS_MANAGER can call this function /// @param recipientAddr_ the address of the user to whom the withdrawal will be sent /// @param assetKey_ key of the required pool /// @param amountToWithdraw_ amount for withdrawal of reserve funds @@ -148,7 +148,7 @@ interface ISystemPoolsRegistry { ) external; /// @notice Withdrawal of all reserve funds from pools with pagination - /// @dev Only contract owner can call this function + /// @dev Only SYSTEM_POOLS_RESERVE_FUNDS_MANAGER can call this function /// @param recipientAddr_ the address of the user to whom the withdrawal will be sent /// @param offset_ offset for pagination /// @param limit_ maximum number of elements for pagination @@ -158,18 +158,23 @@ interface ISystemPoolsRegistry { uint256 limit_ ) external; + /// @notice The function is needed to update the reward asset + /// @dev Only SYSTEM_POOLS_MANAGER can call this function + /// @param newRewardsAssetKey_ key of the new rewards asset + function updateRewardsAssetKey(bytes32 newRewardsAssetKey_) external; + /// @notice The function is needed to update the implementation of the pools - /// @dev Only contract owner can call this function + /// @dev Only SYSTEM_POOLS_MANAGER can call this function /// @param poolType_ needed pool type from PoolType enum /// @param newPoolsImpl_ address of the new pools implementation function upgradePoolsImpl(PoolType poolType_, address newPoolsImpl_) external; /// @notice The function inject dependencies to existing liquidity pools - /// @dev Only contract owner can call this function + /// @dev Only SYSTEM_POOLS_MANAGER can call this function function injectDependenciesToExistingPools() external; /// @notice The function inject dependencies with pagination - /// @dev Only contract owner can call this function + /// @dev Only SYSTEM_POOLS_MANAGER can call this function function injectDependencies(uint256 offset_, uint256 limit_) external; /// @notice The function returns the native asset key diff --git a/deploy/1_contracts_deploy.js b/deploy/1_contracts_deploy.js index 01f1a25..3d30f1c 100644 --- a/deploy/1_contracts_deploy.js +++ b/deploy/1_contracts_deploy.js @@ -13,7 +13,6 @@ const PriceManager = artifacts.require("PriceManager"); const Prt = artifacts.require("PRT"); const RoleManager = artifacts.require("RoleManager"); -const { artifacts } = require("hardhat"); const { isStablePoolsAvailable } = require("./helpers/deployHelper.js"); require("dotenv").config(); diff --git a/deploy/2_init_all.js b/deploy/2_init_all.js index 9ff01e2..f715f2d 100644 --- a/deploy/2_init_all.js +++ b/deploy/2_init_all.js @@ -7,8 +7,6 @@ const InterestRateLibrary = artifacts.require("InterestRateLibrary"); const Prt = artifacts.require("PRT"); const RoleManager = artifacts.require("RoleManager"); -const { artifacts } = require("hardhat"); - const { parsePrtData, getAssetKey, diff --git a/test/assetParameters.test.js b/test/assetParameters.test.js index def1d6a..f49db4d 100644 --- a/test/assetParameters.test.js +++ b/test/assetParameters.test.js @@ -2,6 +2,7 @@ const { toBytes, fromBytes, compareKeys } = require("./helpers/bytesCompareLibra const { getInterestRateLibraryAddr } = require("./helpers/coverage-helper"); const { toBN, accounts, wei, getPrecision, getPercentage100 } = require("../scripts/utils/utils"); const { ZERO_ADDR } = require("../scripts/utils/constants"); +const { utils } = require("ethers"); const truffleAssert = require("truffle-assertions"); const Reverter = require("./helpers/reverter"); @@ -280,9 +281,9 @@ describe("AssetParameters", () => { }); describe("setupAllParameters", () => { - it("should get exception if called not by an asset manager/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0x06c492a7eb572cfeccd28edc322064a12cedb3c4e3bddbb1357cd02f3a9f15fc"; + it("should get exception if called not by an ASSET_PARAMETERS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const ASSET_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); + const reason = `RoleManager: account is missing role ${ASSET_PARAMETERS_MANAGER_ROLE}`; await truffleAssert.reverts( assetParameters.setupAllParameters( @@ -360,8 +361,11 @@ describe("AssetParameters", () => { assert.equal(result.logs[0].args.newValue, true); }); - it("should not access to freeze the pool by not core", async () => { - await truffleAssert.reverts(assetParameters.freeze(daiKey, { from: SOMEBODY })); + it("should not access to freeze the pool by not an ASSET_PARAMETERS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const ASSET_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); + const reason = `RoleManager: account is missing role ${ASSET_PARAMETERS_MANAGER_ROLE}`; + + await truffleAssert.reverts(assetParameters.freeze(daiKey, { from: SOMEBODY }), reason); }); it("should not access to freeze pool of the not exists token", async () => { @@ -392,9 +396,9 @@ describe("AssetParameters", () => { assert.equal(result.receipt.logs[0].args.isCollateral, true); }); - it("should get exception if called not by an asset manager/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0x06c492a7eb572cfeccd28edc322064a12cedb3c4e3bddbb1357cd02f3a9f15fc"; + it("should get exception if called not by an ASSET_PARAMETERS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const ASSET_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); + const reason = `RoleManager: account is missing role ${ASSET_PARAMETERS_MANAGER_ROLE}`; await truffleAssert.reverts(assetParameters.enableCollateral(daiKey, false, { from: USER2 }), reason); }); @@ -497,9 +501,9 @@ describe("AssetParameters", () => { ); }); - it("should get exception if called not by an asset manager/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0x06c492a7eb572cfeccd28edc322064a12cedb3c4e3bddbb1357cd02f3a9f15fc"; + it("should get exception if called not by an ASSET_PARAMETERS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const ASSET_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); + const reason = `RoleManager: account is missing role ${ASSET_PARAMETERS_MANAGER_ROLE}`; await truffleAssert.reverts( assetParameters.setupInterestRateModel(daiKey, [0, firstSlope, secondSlope, utilizationBreakingPoint], { @@ -612,9 +616,10 @@ describe("AssetParameters", () => { ); }); - it("should get exception if called not by an asset manager/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0x06c492a7eb572cfeccd28edc322064a12cedb3c4e3bddbb1357cd02f3a9f15fc"; + it("should get exception if called not by an ASSET_PARAMETERS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const ASSET_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); + const reason = `RoleManager: account is missing role ${ASSET_PARAMETERS_MANAGER_ROLE}`; + await truffleAssert.reverts( assetParameters.setupMainParameters(daiKey, [colRatio, colRatio, reserveFactor, liquidationDiscount, maxUR], { from: USER2, @@ -681,9 +686,9 @@ describe("AssetParameters", () => { ); }); - it("should get exception if called not by an asset manager/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0x06c492a7eb572cfeccd28edc322064a12cedb3c4e3bddbb1357cd02f3a9f15fc"; + it("should get exception if called not by an ASSET_PARAMETERS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const ASSET_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); + const reason = `RoleManager: account is missing role ${ASSET_PARAMETERS_MANAGER_ROLE}`; await truffleAssert.reverts( assetParameters.setupDistributionsMinimums(daiKey, [minSupplyDistributionPart, minBorrowDistributionPart], { @@ -751,9 +756,9 @@ describe("AssetParameters", () => { await truffleAssert.reverts(assetParameters.setupAnnualBorrowRate(stableKey, newRate), reason); }); - it("should get exception if called not by an asset manager/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0x06c492a7eb572cfeccd28edc322064a12cedb3c4e3bddbb1357cd02f3a9f15fc"; + it("should get exception if called not by an ASSET_PARAMETERS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const ASSET_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); + const reason = `RoleManager: account is missing role ${ASSET_PARAMETERS_MANAGER_ROLE}`; await truffleAssert.reverts( assetParameters.setupAnnualBorrowRate(stableKey, annualBorrowRate, { from: USER2 }), diff --git a/test/defiCore.test.js b/test/defiCore.test.js index c174783..8084e93 100644 --- a/test/defiCore.test.js +++ b/test/defiCore.test.js @@ -3,6 +3,7 @@ const { toBytes, compareKeys, deepCompareKeys } = require("./helpers/bytesCompar const { getInterestRateLibraryAddr } = require("./helpers/coverage-helper"); const { toBN, accounts, getPrecision, getPercentage100, wei } = require("../scripts/utils/utils"); const { ZERO_ADDR } = require("../scripts/utils/constants"); +const { utils } = require("ethers"); const Reverter = require("./helpers/reverter"); const truffleAssert = require("truffle-assertions"); @@ -2356,9 +2357,9 @@ describe("DefiCore", async () => { await defiCore.borrowFor(daiKey, borrowAmount, USER1, { from: USER1 }); }); - it("should get exception if called not by an DEFI_CORE_PAUSER/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0x8218bbe530296352d0683ccaec4d2919edba0ac7752d8e2243cb95823bb15fd5"; + it("should get exception if called not by an DEFI_CORE_PAUSER or ROLE_MANAGER_ADMIN", async () => { + const DEFI_CORE_PAUSER_ROLE = utils.keccak256(utils.toUtf8Bytes("DEFI_CORE_PAUSER")); + const reason = `RoleManager: account is missing role ${DEFI_CORE_PAUSER_ROLE}`; await truffleAssert.reverts(defiCore.pause({ from: USER1 }), reason); await truffleAssert.reverts(defiCore.unpause({ from: USER1 }), reason); diff --git a/test/liquidityPool.test.js b/test/liquidityPool.test.js index d82b2bf..6f7c92d 100644 --- a/test/liquidityPool.test.js +++ b/test/liquidityPool.test.js @@ -2,6 +2,7 @@ const { setNextBlockTime, mine, getCurrentBlockNumber } = require("./helpers/blo const { toBytes, deepCompareKeys } = require("./helpers/bytesCompareLibrary"); const { getInterestRateLibraryAddr } = require("./helpers/coverage-helper"); const { toBN, accounts, getPrecision, getPercentage100, wei } = require("../scripts/utils/utils"); +const { utils } = require("ethers"); const { ZERO_ADDR } = require("../scripts/utils/constants"); const truffleAssert = require("truffle-assertions"); @@ -1900,9 +1901,11 @@ describe("LiquidityPool", () => { ); }); - it("should get exception if called not by an SYSTEM_POOLS_RESERVE_FUNDS_MANAGER/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0xd0b4cd1a8528008585d67ae3c0cc016d46e0ae3dfe660512aad856820ce86b94"; + it("should get exception if called not by an SYSTEM_POOLS_RESERVE_FUNDS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const SYSTEM_POOLS_RESERVE_FUNDS_MANAGER_ROLE = utils.keccak256( + utils.toUtf8Bytes("SYSTEM_POOLS_RESERVE_FUNDS_MANAGER") + ); + const reason = `RoleManager: account is missing role ${SYSTEM_POOLS_RESERVE_FUNDS_MANAGER_ROLE}`; await truffleAssert.reverts( systemPoolsRegistry.withdrawReservedFunds(RECIPIENT, tokenKey, 0, true, { from: USER1 }), @@ -1966,9 +1969,11 @@ describe("LiquidityPool", () => { assert.equal(toBN(await liquidityPool.totalReserves()).toString(), 0); }); - it("should get exception if called not by an SYSTEM_POOLS_RESERVE_FUNDS_MANAGER/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0xd0b4cd1a8528008585d67ae3c0cc016d46e0ae3dfe660512aad856820ce86b94"; + it("should get exception if called not by an SYSTEM_POOLS_RESERVE_FUNDS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const SYSTEM_POOLS_RESERVE_FUNDS_MANAGER_ROLE = utils.keccak256( + utils.toUtf8Bytes("SYSTEM_POOLS_RESERVE_FUNDS_MANAGER") + ); + const reason = `RoleManager: account is missing role ${SYSTEM_POOLS_RESERVE_FUNDS_MANAGER_ROLE}`; await truffleAssert.reverts( systemPoolsRegistry.withdrawAllReservedFunds(RECIPIENT, 0, 2, { from: USER2 }), diff --git a/test/priceManager.test.js b/test/priceManager.test.js index 6748872..667c1f1 100644 --- a/test/priceManager.test.js +++ b/test/priceManager.test.js @@ -4,7 +4,6 @@ const { ZERO_ADDR } = require("../scripts/utils/constants"); const truffleAssert = require("truffle-assertions"); const Reverter = require("./helpers/reverter"); -const { artifacts } = require("hardhat"); const Registry = artifacts.require("Registry"); const PriceManager = artifacts.require("PriceManager"); diff --git a/test/prt.test.js b/test/prt.test.js index b8c5b64..c05d200 100644 --- a/test/prt.test.js +++ b/test/prt.test.js @@ -1,6 +1,7 @@ const { toBytes, compareKeys, deepCompareKeys } = require("./helpers/bytesCompareLibrary"); const { getInterestRateLibraryAddr } = require("./helpers/coverage-helper"); const { toBN, accounts, getPrecision, getPercentage100, wei } = require("../scripts/utils/utils"); +const { utils } = require("ethers"); const { ZERO_ADDR } = require("../scripts/utils/constants"); const { setNextBlockTime, setTime, mine, getCurrentBlockTime } = require("./helpers/block-helper"); @@ -574,9 +575,10 @@ describe("PRT", () => { }); describe("updatePRTRarams()", () => { - it("should get exception if called not by an PRT_PARAM_UPDATER/role manager admin", async () => { - let reason = - "RoleManager: account is missing role 0x2a497a2a3812d7536bf2ddd564e1e7644c23860987ec1d72aa63fa3250b93e25"; + it("should get exception if called not by an PRT_PARAM_UPDATER or ROLE_MANAGER_ADMIN", async () => { + const PRT_PARAM_UPDATER_ROLE = utils.keccak256(utils.toUtf8Bytes("PRT_PARAM_UPDATER")); + const reason = `RoleManager: account is missing role ${PRT_PARAM_UPDATER_ROLE}`; + await truffleAssert.reverts( prt.updatePRTParams( [ diff --git a/test/registry.test.js b/test/registry.test.js index 668f518..1380109 100644 --- a/test/registry.test.js +++ b/test/registry.test.js @@ -5,7 +5,6 @@ const { getInterestRateLibraryAddr } = require("./helpers/coverage-helper"); const truffleAssert = require("truffle-assertions"); const Reverter = require("./helpers/reverter"); const { Assertion } = require("chai"); -const { artifacts } = require("hardhat"); const Registry = artifacts.require("Registry"); const AssetParameters = artifacts.require("AssetParametersMock"); diff --git a/test/rewardsDistribution.test.js b/test/rewardsDistribution.test.js index 7902bb9..8fe8dbe 100644 --- a/test/rewardsDistribution.test.js +++ b/test/rewardsDistribution.test.js @@ -3,10 +3,10 @@ const { toBytes } = require("./helpers/bytesCompareLibrary"); const { getInterestRateLibraryAddr } = require("./helpers/coverage-helper"); const { toBN, accounts, getPrecision, getPercentage100, wei } = require("../scripts/utils/utils"); const { ZERO_ADDR } = require("../scripts/utils/constants"); +const { utils } = require("ethers"); const Reverter = require("./helpers/reverter"); const truffleAssert = require("truffle-assertions"); -const { artifacts } = require("hardhat"); const Registry = artifacts.require("Registry"); const DefiCore = artifacts.require("DefiCore"); @@ -845,12 +845,12 @@ describe("RewardsDistribution", () => { await truffleAssert.reverts(rewardsDistribution.setupRewardsPerBlockBatch(keys, rewardsPerBlock), reason); }); - it("should get exception if called not by an REWARDS_DISTRIBUTION_MANAGER/role manager admin", async () => { + it("should get exception if called not by an REWARDS_DISTRIBUTION_MANAGER or ROLE_MANAGER_ADMIN", async () => { await systemParameters.setRewardsTokenAddress(rewardsToken.address); await systemPoolsRegistry.updateRewardsAssetKey(rewardsTokenKey); - const reason = - "RoleManager: account is missing role 0x850ebe1af891c28af526a1ab7de2aec67dea6bf3e98038a47ffc67205e96ea7e"; + const REWARDS_DISTRIBUTION_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("REWARDS_DISTRIBUTION_MANAGER")); + const reason = `RoleManager: account is missing role ${REWARDS_DISTRIBUTION_MANAGER_ROLE}`; await truffleAssert.reverts( rewardsDistribution.setupRewardsPerBlockBatch([daiKey], [oneToken], { from: USER1 }), diff --git a/test/roleManager.test.js b/test/roleManager.test.js index 2928a3e..f21e9e6 100644 --- a/test/roleManager.test.js +++ b/test/roleManager.test.js @@ -1,21 +1,12 @@ const truffleAssert = require("truffle-assertions"); const Reverter = require("./helpers/reverter"); -const { artifacts } = require("hardhat"); const { utils } = require("ethers"); const { accounts } = require("../scripts/utils/utils"); const { assert } = require("chai"); const RoleManager = artifacts.require("RoleManager"); -if (!String.prototype.format) { - String.prototype.format = function (...args) { - return this.replace(/(\{\d+\})/g, function (a) { - return args[+a.substr(1, a.length - 2) || 0]; - }); - }; -} - describe("RoleManager", () => { const reverter = new Reverter(); @@ -126,7 +117,8 @@ describe("RoleManager", () => { it("should revert if the account has neither ROLE_MANAGER_ADMIN nor ASSET_PARAMETERS_MANAGER role", async () => { const ASSET_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); - let reason = "RoleManager: account is missing role {0}".format(ASSET_PARAMETERS_MANAGER_ROLE); + const reason = `RoleManager: account is missing role ${ASSET_PARAMETERS_MANAGER_ROLE}`; + await truffleAssert.reverts(roleManager.isAssetParametersManager(ANOTHER_ACCOUNT), reason); }); }); @@ -143,7 +135,8 @@ describe("RoleManager", () => { it("should revert if the account has neither ROLE_MANAGER_ADMIN nor DEFI_CORE_PAUSER role", async () => { const DEFI_CORE_PAUSER_ROLE = utils.keccak256(utils.toUtf8Bytes("DEFI_CORE_PAUSER")); - let reason = "RoleManager: account is missing role {0}".format(DEFI_CORE_PAUSER_ROLE); + const reason = `RoleManager: account is missing role ${DEFI_CORE_PAUSER_ROLE}`; + await truffleAssert.reverts(roleManager.isDefiCorePauser(ANOTHER_ACCOUNT), reason); }); }); @@ -160,7 +153,8 @@ describe("RoleManager", () => { it("should revert if the account has neither ROLE_MANAGER_ADMIN nor PRT_PARAM_UPDATER role", async () => { const PRT_PARAM_UPDATER_ROLE = utils.keccak256(utils.toUtf8Bytes("PRT_PARAM_UPDATER")); - let reason = "RoleManager: account is missing role {0}".format(PRT_PARAM_UPDATER_ROLE); + const reason = `RoleManager: account is missing role ${PRT_PARAM_UPDATER_ROLE}`; + await truffleAssert.reverts(roleManager.isPRTParamUpdater(ANOTHER_ACCOUNT), reason); }); }); @@ -177,7 +171,8 @@ describe("RoleManager", () => { it("should revert if the account has neither ROLE_MANAGER_ADMIN nor REWARDS_DISTRIBUTION_MANAGER role", async () => { const REWARDS_DISTRIBUTION_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("REWARDS_DISTRIBUTION_MANAGER")); - let reason = "RoleManager: account is missing role {0}".format(REWARDS_DISTRIBUTION_MANAGER_ROLE); + const reason = `RoleManager: account is missing role ${REWARDS_DISTRIBUTION_MANAGER_ROLE}`; + await truffleAssert.reverts(roleManager.isRewardsDistributionManager(ANOTHER_ACCOUNT), reason); }); }); @@ -194,7 +189,8 @@ describe("RoleManager", () => { it("should revert if the account has neither ROLE_MANAGER_ADMIN nor SYSTEM_PARAMETERS_MANAGER role", async () => { const SYSTEM_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_PARAMETERS_MANAGER")); - let reason = "RoleManager: account is missing role {0}".format(SYSTEM_PARAMETERS_MANAGER_ROLE); + const reason = `RoleManager: account is missing role ${SYSTEM_PARAMETERS_MANAGER_ROLE}`; + await truffleAssert.reverts(roleManager.isSystemParametersManager(ANOTHER_ACCOUNT), reason); }); }); @@ -211,7 +207,8 @@ describe("RoleManager", () => { it("should revert if the account has neither ROLE_MANAGER_ADMIN nor SYSTEM_POOLS_MANAGER role", async () => { const SYSTEM_POOLS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_POOLS_MANAGER")); - let reason = "RoleManager: account is missing role {0}".format(SYSTEM_POOLS_MANAGER_ROLE); + const reason = `RoleManager: account is missing role ${SYSTEM_POOLS_MANAGER_ROLE}`; + await truffleAssert.reverts(roleManager.isSystemPoolsManager(ANOTHER_ACCOUNT), reason); }); }); @@ -232,7 +229,8 @@ describe("RoleManager", () => { const SYSTEM_POOLS_RESERVE_FUNDS_MANAGER_ROLE = utils.keccak256( utils.toUtf8Bytes("SYSTEM_POOLS_RESERVE_FUNDS_MANAGER") ); - let reason = "RoleManager: account is missing role {0}".format(SYSTEM_POOLS_RESERVE_FUNDS_MANAGER_ROLE); + const reason = `RoleManager: account is missing role ${SYSTEM_POOLS_RESERVE_FUNDS_MANAGER_ROLE}`; + await truffleAssert.reverts(roleManager.isSystemPoolsReserveFundsManager(ANOTHER_ACCOUNT), reason); }); }); @@ -251,7 +249,7 @@ describe("RoleManager", () => { it("should revert if the account has neither ROLE_MANAGER_ADMIN nor ROLE_MANAGER_ROLE_GOVERNOR role", async () => { const ROLE_MANAGER_ROLE_GOVERNOR_ROLE = utils.keccak256(utils.toUtf8Bytes("ROLE_MANAGER_ROLE_GOVERNOR")); - let reason = "RoleManager: account is missing role {0}".format(ROLE_MANAGER_ROLE_GOVERNOR_ROLE); + const reason = `RoleManager: account is missing role ${ROLE_MANAGER_ROLE_GOVERNOR_ROLE}`; const ROLE_TO_GRANT = utils.keccak256(utils.toUtf8Bytes("ASSET_PARAMETERS_MANAGER")); @@ -300,7 +298,7 @@ describe("RoleManager", () => { it("should revert if the account has neither ROLE_MANAGER_ADMIN nor ROLE_MANAGER_ROLE_GOVERNOR role", async () => { const ROLE_MANAGER_ROLE_GOVERNOR_ROLE = utils.keccak256(utils.toUtf8Bytes("ROLE_MANAGER_ROLE_GOVERNOR")); - let reason = "RoleManager: account is missing role {0}".format(ROLE_MANAGER_ROLE_GOVERNOR_ROLE); + const reason = `RoleManager: account is missing role ${ROLE_MANAGER_ROLE_GOVERNOR_ROLE}`; await roleManager.roleManagerInitialize([], []); diff --git a/test/stablePool.test.js b/test/stablePool.test.js index f35642f..919ed49 100644 --- a/test/stablePool.test.js +++ b/test/stablePool.test.js @@ -6,7 +6,6 @@ const { ZERO_ADDR } = require("../scripts/utils/constants"); const truffleAssert = require("truffle-assertions"); const Reverter = require("./helpers/reverter"); -const { artifacts } = require("hardhat"); const Registry = artifacts.require("Registry"); const DefiCore = artifacts.require("DefiCore"); diff --git a/test/systemParameters.test.js b/test/systemParameters.test.js index d3278d3..f9a88ea 100644 --- a/test/systemParameters.test.js +++ b/test/systemParameters.test.js @@ -1,9 +1,9 @@ const { accounts, getPrecision, wei } = require("../scripts/utils/utils"); const { ZERO_ADDR } = require("../scripts/utils/constants"); +const { utils } = require("ethers"); const truffleAssert = require("truffle-assertions"); const Reverter = require("./helpers/reverter"); -const { artifacts } = require("hardhat"); const SystemParameters = artifacts.require("SystemParameters"); const Registry = artifacts.require("Registry"); @@ -58,9 +58,9 @@ describe("SystemParameters", () => { }); describe("setupMinCurrencyAmount", () => { - it("should get exception if called not by an SYSTEM_PARAMETERS_MANAGER/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0x5150d4e12a451b0e6f6df3626ccce38a6036b7e6ef17dc4a5038ccfa0cab851a"; + it("should get exception if called not by an SYSTEM_PARAMETERS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const SYSTEM_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_PARAMETERS_MANAGER")); + const reason = `RoleManager: account is missing role ${SYSTEM_PARAMETERS_MANAGER_ROLE}`; await truffleAssert.reverts( systemParameters.setupMinCurrencyAmount(minCurrencyAmount, { from: SOMEBODY }), @@ -94,9 +94,9 @@ describe("SystemParameters", () => { await truffleAssert.reverts(systemParameters.setRewardsTokenAddress(ZERO_ADDR), reason); }); - it("should get exception if called not by an SYSTEM_PARAMETERS_MANAGER/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0x5150d4e12a451b0e6f6df3626ccce38a6036b7e6ef17dc4a5038ccfa0cab851a"; + it("should get exception if called not by an SYSTEM_PARAMETERS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const SYSTEM_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_PARAMETERS_MANAGER")); + const reason = `RoleManager: account is missing role ${SYSTEM_PARAMETERS_MANAGER_ROLE}`; await truffleAssert.reverts(systemParameters.setRewardsTokenAddress(ZERO_ADDR, { from: SOMEBODY }), reason); await truffleAssert.reverts(systemParameters.setRewardsTokenAddress(ZERO_ADDR, { from: SOMEBODY }), reason); @@ -123,6 +123,16 @@ describe("SystemParameters", () => { await truffleAssert.reverts(systemParameters.setupLiquidationBoundary(newValue), reason); }); + + it("should get exception if called not by an SYSTEM_PARAMETERS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const SYSTEM_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_PARAMETERS_MANAGER")); + const reason = `RoleManager: account is missing role ${SYSTEM_PARAMETERS_MANAGER_ROLE}`; + + const newValue = getPrecision().times(50); + + await truffleAssert.reverts(systemParameters.setupLiquidationBoundary(newValue, { from: SOMEBODY }), reason); + await truffleAssert.reverts(systemParameters.setupLiquidationBoundary(newValue, { from: SOMEBODY }), reason); + }); }); describe("setupStablePoolsAvailability", () => { @@ -133,13 +143,22 @@ describe("SystemParameters", () => { assert.equal(txReceipt.receipt.logs[0].event, "StablePoolsAvailabilityUpdated"); assert.equal(txReceipt.receipt.logs[0].args.newValue, true); }); + + it("should get exception if called not by an SYSTEM_PARAMETERS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const SYSTEM_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_PARAMETERS_MANAGER")); + const reason = `RoleManager: account is missing role ${SYSTEM_PARAMETERS_MANAGER_ROLE}`; + + await truffleAssert.reverts(systemParameters.setupStablePoolsAvailability(true, { from: SOMEBODY }), reason); + await truffleAssert.reverts(systemParameters.setupStablePoolsAvailability(true, { from: SOMEBODY }), reason); + }); }); - describe("onlySystemOwner modifier", () => { - it("should get exception if called not by an SYSTEM_PARAMETERS_MANAGER/role manager admin", async () => { + describe("onlySystemParametersManager modifier", () => { + it("should get exception if called not by an SYSTEM_PARAMETERS_MANAGER or ROLE_MANAGER_ADMIN", async () => { const newValue = getPrecision().times(50); - const reason = - "RoleManager: account is missing role 0x5150d4e12a451b0e6f6df3626ccce38a6036b7e6ef17dc4a5038ccfa0cab851a"; + + const SYSTEM_PARAMETERS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_PARAMETERS_MANAGER")); + const reason = `RoleManager: account is missing role ${SYSTEM_PARAMETERS_MANAGER_ROLE}`; await truffleAssert.reverts(systemParameters.setupLiquidationBoundary(newValue, { from: SOMEBODY }), reason); await truffleAssert.reverts(systemParameters.setupStablePoolsAvailability(true, { from: SOMEBODY }), reason); diff --git a/test/systemPoolsRegistry.test.js b/test/systemPoolsRegistry.test.js index ee5fe5a..1d01b26 100644 --- a/test/systemPoolsRegistry.test.js +++ b/test/systemPoolsRegistry.test.js @@ -2,12 +2,12 @@ const { setNextBlockTime, getCurrentBlockTime } = require("./helpers/block-helpe const { toBytes, fromBytes, deepCompareKeys, compareKeys } = require("./helpers/bytesCompareLibrary"); const { getInterestRateLibraryAddr } = require("./helpers/coverage-helper"); const { toBN, accounts, getPrecision, getPercentage100, wei } = require("../scripts/utils/utils"); +const { utils } = require("ethers"); const { ZERO_ADDR } = require("../scripts/utils/constants"); const truffleAssert = require("truffle-assertions"); const Reverter = require("./helpers/reverter"); const { assert } = require("chai"); -const { artifacts } = require("hardhat"); const Registry = artifacts.require("Registry"); const DefiCore = artifacts.require("DefiCore"); @@ -290,9 +290,9 @@ describe("SystemPoolsRegistry", () => { await truffleAssert.reverts(systemPoolsRegistry.updateRewardsAssetKey(someKey), reason); }); - it("should get exception if called not by an SYSTEM_POOLS_MANAGER/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0xa6422b3c9a6d3dc00d8db23ad51c1008c5e46eaa60434b734a90225deb0e7cb9"; + it("should get exception if called not by an SYSTEM_POOLS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const SYSTEM_POOLS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_POOLS_MANAGER")); + const reason = `RoleManager: account is missing role ${SYSTEM_POOLS_MANAGER_ROLE}`; assert.isTrue(compareKeys(await systemPoolsRegistry.rewardsAssetKey(), zeroKey)); assert.equal(await getLiquidityPoolAddr(zeroKey), await systemPoolsRegistry.getRewardsLiquidityPool()); @@ -326,9 +326,9 @@ describe("SystemPoolsRegistry", () => { await truffleAssert.reverts(systemPoolsRegistry.addPoolsBeacon(0, NOTHING), reason); }); - it("should get exception if called not by an SYSTEM_POOLS_MANAGER/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0xa6422b3c9a6d3dc00d8db23ad51c1008c5e46eaa60434b734a90225deb0e7cb9"; + it("should get exception if called not by an SYSTEM_POOLS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const SYSTEM_POOLS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_POOLS_MANAGER")); + const reason = `RoleManager: account is missing role ${SYSTEM_POOLS_MANAGER_ROLE}`; await truffleAssert.reverts(systemPoolsRegistry.addPoolsBeacon(1, NOTHING, { from: USER1 }), reason); }); @@ -394,9 +394,9 @@ describe("SystemPoolsRegistry", () => { await truffleAssert.reverts(liquidityPoolFactory.newLiquidityPool(TEST_ASSET, daiKey, "DAI"), reason); }); - it("should get exception if called not by an SYSTEM_POOLS_MANAGER/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0xa6422b3c9a6d3dc00d8db23ad51c1008c5e46eaa60434b734a90225deb0e7cb9"; + it("should get exception if called not by an SYSTEM_POOLS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const SYSTEM_POOLS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_POOLS_MANAGER")); + const reason = `RoleManager: account is missing role ${SYSTEM_POOLS_MANAGER_ROLE}`; await truffleAssert.reverts( systemPoolsRegistry.addLiquidityPool(TEST_ASSET, daiKey, chainlinkOracle.address, "DAI", true, true, { @@ -441,9 +441,9 @@ describe("SystemPoolsRegistry", () => { await truffleAssert.reverts(systemPoolsRegistry.addStablePool(NOTHING, someKey, NOTHING), reason); }); - it("should get exception if called not by an SYSTEM_POOLS_MANAGER/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0xa6422b3c9a6d3dc00d8db23ad51c1008c5e46eaa60434b734a90225deb0e7cb9"; + it("should get exception if called not by an SYSTEM_POOLS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const SYSTEM_POOLS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_POOLS_MANAGER")); + const reason = `RoleManager: account is missing role ${SYSTEM_POOLS_MANAGER_ROLE}`; await truffleAssert.reverts( systemPoolsRegistry.addStablePool(someToken.address, someKey, NOTHING, { from: USER1 }), @@ -479,9 +479,10 @@ describe("SystemPoolsRegistry", () => { await truffleAssert.reverts(systemPoolsRegistry.upgradePoolsImpl(1, NOTHING), reason); }); - it("should get exception if called not by an SYSTEM_POOLS_MANAGER/role manager admin", async () => { - const reason = - "RoleManager: account is missing role 0xa6422b3c9a6d3dc00d8db23ad51c1008c5e46eaa60434b734a90225deb0e7cb9"; + it("should get exception if called not by an SYSTEM_POOLS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const SYSTEM_POOLS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_POOLS_MANAGER")); + const reason = `RoleManager: account is missing role ${SYSTEM_POOLS_MANAGER_ROLE}`; + await createLiquidityPool(daiKey, "DAI", true); const daiPool = await LiquidityPool.at(await getLiquidityPoolAddr(daiKey)); @@ -572,9 +573,9 @@ describe("SystemPoolsRegistry", () => { await truffleAssert.reverts(abstractPools[0].setDependencies(registry.address, { from: USER2 }), reason); }); - it("injectDependenciesToExistingPools() should get exception if called by not a SYSTEM_POOLS_MANAGER", async () => { - const reason = - "RoleManager: account is missing role 0xa6422b3c9a6d3dc00d8db23ad51c1008c5e46eaa60434b734a90225deb0e7cb9"; + it("injectDependenciesToExistingPools() should get exception if called by not a SYSTEM_POOLS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const SYSTEM_POOLS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_POOLS_MANAGER")); + const reason = `RoleManager: account is missing role ${SYSTEM_POOLS_MANAGER_ROLE}`; const currentPriceManager = await registry.getPriceManagerContract(); const newPriceManager = await PriceManager.new(); @@ -587,9 +588,10 @@ describe("SystemPoolsRegistry", () => { await truffleAssert.reverts(systemPoolsRegistry.injectDependenciesToExistingPools({ from: USER1 }), reason); }); - it("injectDependencies() should get exception if called by not a SYSTEM_POOLS_MANAGER", async () => { - const reason = - "RoleManager: account is missing role 0xa6422b3c9a6d3dc00d8db23ad51c1008c5e46eaa60434b734a90225deb0e7cb9"; + it("injectDependencies() should get exception if called by not a SYSTEM_POOLS_MANAGER or ROLE_MANAGER_ADMIN", async () => { + const SYSTEM_POOLS_MANAGER_ROLE = utils.keccak256(utils.toUtf8Bytes("SYSTEM_POOLS_MANAGER")); + const reason = `RoleManager: account is missing role ${SYSTEM_POOLS_MANAGER_ROLE}`; + const currentPriceManager = await registry.getPriceManagerContract(); const newPriceManager = await PriceManager.new(); diff --git a/test/userInfoRegistry.test.js b/test/userInfoRegistry.test.js index 44218db..d075af6 100644 --- a/test/userInfoRegistry.test.js +++ b/test/userInfoRegistry.test.js @@ -6,7 +6,6 @@ const { ZERO_ADDR } = require("../scripts/utils/constants"); const truffleAssert = require("truffle-assertions"); const Reverter = require("./helpers/reverter"); -const { artifacts } = require("hardhat"); const Registry = artifacts.require("Registry"); const DefiCore = artifacts.require("DefiCore");