Skip to content

Commit

Permalink
feat: Access Control #1 (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
Whytecrowe authored May 19, 2023
2 parents 5e164d9 + b2c6c15 commit 57af0f6
Show file tree
Hide file tree
Showing 30 changed files with 980 additions and 377 deletions.
2 changes: 0 additions & 2 deletions .solcover.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,3 @@ module.exports = {
'contracts/token/mocks/ZeroTokenMock.sol'
]
};
// TODO: in package.json set check-coverage script from --branches
// to equal 87 when Access Control is added!
4 changes: 3 additions & 1 deletion .solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
}
],
"constructor-syntax": "warn",
"named-parameters-mapping": "error"
"named-parameters-mapping": "error",
"comprehensive-interface": "error",
"max-line-length": ["error", 120]
}
}
35 changes: 35 additions & 0 deletions contracts/access/AccessControlled.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import { ZNSRoles } from "./ZNSRoles.sol";
import { IZNSAccessController } from "./IZNSAccessController.sol";


abstract contract AccessControlled is ZNSRoles {
event AccessControllerSet(address accessController);

IZNSAccessController internal accessController;

modifier onlyRole(bytes32 role) {
accessController.checkRole(role, msg.sender);
_;
}

/**
* @dev This is here to make sure the external function is always implemented in children,
* otherwise we will not be able to reset the module (not ideal since it might
* not get to the final interface of a child).
* TODO AC: how do we make sure this gets to the final interface?
*/
function setAccessController(address _accessController) external virtual;

function getAccessController() external view returns (address) {
return address(accessController);
}

function _setAccessController(address _accessController) internal {
require(_accessController != address(0), "AC: _accessController is 0x0 address");
accessController = IZNSAccessController(_accessController);
emit AccessControllerSet(_accessController);
}
}
16 changes: 16 additions & 0 deletions contracts/access/IZNSAccessController.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import { IAccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol";


interface IZNSAccessController is IAccessControlUpgradeable {
function initialize(
address[] calldata governorAddresses,
address[] calldata operatorAddresses
) external;

function checkRole(bytes32 role, address account) external view;

function setRoleAdmin(bytes32 role, bytes32 adminRole) external;
}
45 changes: 45 additions & 0 deletions contracts/access/ZNSAccessController.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import { IZNSAccessController } from "./IZNSAccessController.sol";
import { ZNSRoles } from "./ZNSRoles.sol";


contract ZNSAccessController is AccessControlUpgradeable, ZNSRoles, IZNSAccessController {
// solhint-disable-next-line func-name-mixedcase
function initialize(
address[] calldata governorAddresses,
address[] calldata adminAddresses
) external override initializer {
// give roles to all addresses
_grantRoleToMany(GOVERNOR_ROLE, governorAddresses);
_grantRoleToMany(ADMIN_ROLE, adminAddresses);

// all of the governors control admins TODO AC: ???
_setRoleAdmin(ADMIN_ROLE, GOVERNOR_ROLE);
// all of the governors control governors TODO AC: ???
_setRoleAdmin(GOVERNOR_ROLE, GOVERNOR_ROLE);
// all of the admins control registrar TODO AC: ???
_setRoleAdmin(REGISTRAR_ROLE, ADMIN_ROLE);
}

// TODO AC: should we keep this function here so that we can get standardized message?
// test this function for gas usage with a standardized message vs a custom message
// when using the recommended method of `hasRole`
function checkRole(bytes32 role, address account) external view override {
_checkRole(role, account);
}

// TODO AC: is this function necessary? how often will it be used?
function _grantRoleToMany(bytes32 role, address[] calldata addresses) internal {
for (uint256 i = 0; i < addresses.length; i++) {
_grantRole(role, addresses[i]);
}
}

// TODO AC: how safe is this?
function setRoleAdmin(bytes32 role, bytes32 adminRole) external override onlyRole(GOVERNOR_ROLE) {
_setRoleAdmin(role, adminRole);
}
}
19 changes: 19 additions & 0 deletions contracts/access/ZNSRoles.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;


abstract contract ZNSRoles {
// TODO AC: test getting this from AC contract vs inheriting these roles in every other contract
// the highest rank, only assigns Admins
bytes32 public constant GOVERNOR_ROLE = keccak256("GOVERNOR_ROLE");
// the main maintainer role, that gets access to all system functions
// TODO AC: should we split responsibilities in a better way?
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
// operator can be here to future proof, if we need a new role
// so we don't have to upgrade all contracts
// TODO AC: change name of this role
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
// this role is here specifically for the ZNSEthRegistrar contract
bytes32 public constant REGISTRAR_ROLE = keccak256("REGISTRAR_ROLE");
// TODO AC: what other roles do we need here?
}
20 changes: 20 additions & 0 deletions contracts/distribution/IZNSEthRegistrar.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;


interface IZNSEthRegistrar {
event DomainRegistered(
bytes32 indexed domainHash,
Expand All @@ -17,6 +18,15 @@ interface IZNSEthRegistrar {
address indexed registrant
);

// TODO AC: remove ZNS from names here and in state vars
event ZnsRegistrySet(address znsRegistry);

event ZnsTreasurySet(address znsTreasury);

event ZnsDomainTokenSet(address znsDomainToken);

event ZnsAddressResolverSet(address znsAddressResolver);

function registerDomain(
string calldata name,
address domainContent
Expand All @@ -25,4 +35,14 @@ interface IZNSEthRegistrar {
function revokeDomain(bytes32 domainHash) external;

function reclaimDomain(bytes32 domainHash) external;

function setZnsRegistry(address znsRegistry_) external;

function setZnsTreasury(address znsTreasury_) external;

function setZnsDomainToken(address znsDomainToken_) external;

function setZnsAddressResolver(address znsAddressResolver_) external;

function setAccessController(address accessController_) external;
}
19 changes: 6 additions & 13 deletions contracts/distribution/IZNSPriceOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ interface IZNSPriceOracle {
event PriceMultiplierSet(uint256 multiplier);
event BaseLengthSet(uint256 length, bool isRootDomain);
event BaseLengthsSet(uint256 rootDomainLength, uint256 subdomainLength);
event ZNSRegistrarSet(address registrar);
event FeePercentageSet(uint256 feePercentage);

/**
Expand Down Expand Up @@ -61,6 +60,12 @@ interface IZNSPriceOracle {
uint256 priceMultiplier;
}

function initialize(
address accessController_,
PriceParams calldata priceConfig_,
uint256 regFeePercentage_
) external;

/**
* @notice Get the price of a given domain name length
* @param name The name of the domain to check
Expand Down Expand Up @@ -115,16 +120,4 @@ interface IZNSPriceOracle {
* @param subdomainLength The length for subdomains
*/
function setBaseLengths(uint256 rootLength, uint256 subdomainLength) external;

/**
* @notice Set the ZNSRegistrar for this contract
* @param registrar The registrar to set
*/
function setZNSRegistrar(address registrar) external;

/**
* @notice Return true if a user is authorized, otherwise false
* @param user The user to check
*/
function isAuthorized(address user) external view returns (bool);
}
14 changes: 6 additions & 8 deletions contracts/distribution/IZNSTreasury.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,9 @@ interface IZNSTreasury {
uint256 indexed amount
);

/**
* @notice Emitted when the admin user is set
* @param user The admin user to set
*/
event AdminSet(address user, bool status);
event ZnsPriceOracleSet(address znsPriceOracle);

event ZnsStakingTokenSet(address znsStakingToken);

event ZeroVaultAddressSet(address zeroVault);

Expand All @@ -51,9 +49,9 @@ interface IZNSTreasury {

function unstakeForDomain(bytes32 domainHash, address owner) external;

function setZNSRegistrar(address znsRegistrar_) external;

function setZeroVaultAddress(address zeroVaultAddress) external;

function setAdmin(address user, bool status) external;
function setPriceOracle(address znsPriceOracle_) external;

function setStakingToken(address stakingToken_) external;
}
Loading

0 comments on commit 57af0f6

Please sign in to comment.