Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor component lock #620

Merged
merged 9 commits into from
Aug 26, 2024
387 changes: 201 additions & 186 deletions contracts/authorization/AccessAdmin.sol

Large diffs are not rendered by default.

183 changes: 183 additions & 0 deletions contracts/authorization/AccessAdminLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;

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

import {IAccess} from "./IAccess.sol";
import {IAccessAdmin} from "./IAccessAdmin.sol";
import {IAuthorization} from "./IAuthorization.sol";
import {IRegistry} from "../registry/IRegistry.sol";

import {ContractLib} from "../shared/ContractLib.sol";
import {ObjectType} from "../type/ObjectType.sol";
import {RoleId} from "../type/RoleId.sol";
import {SelectorLib} from "../type/Selector.sol";
import {Str, StrLib} from "../type/String.sol";
import {TimestampLib} from "../type/Timestamp.sol";
import {VersionPart} from "../type/Version.sol";


library AccessAdminLib { // ACCESS_ADMIN_LIB

function checkRoleCreation(
IAccessAdmin accessAdmin,
RoleId roleId,
IAccess.RoleInfo memory info
)
public
view
{
// check role does not yet exist // ACCESS_ADMIN_LIB role creation checks
if(accessAdmin.roleExists(roleId)) {
revert IAccessAdmin.ErrorAccessAdminRoleAlreadyCreated(
roleId,
accessAdmin.getRoleInfo(roleId).name.toString());
}

// check admin role exists
if(!accessAdmin.roleExists(info.adminRoleId)) {
revert IAccessAdmin.ErrorAccessAdminRoleAdminNotExisting(info.adminRoleId);
}

// check role name is not empty
if(info.name.length() == 0) {
revert IAccessAdmin.ErrorAccessAdminRoleNameEmpty(roleId);
}

// check role name is not used for another role
RoleId roleIdForName = accessAdmin.getRoleForName(StrLib.toString(info.name));
if(roleIdForName.gtz()) {
revert IAccessAdmin.ErrorAccessAdminRoleNameAlreadyExists(
roleId,
info.name.toString(),
roleIdForName);
}
}

function checkTargetCreation(
IAccessAdmin accessAdmin,
address target,
string memory targetName,
bool checkAuthority
)
public
view
{
// check target does not yet exist
if(accessAdmin.targetExists(target)) {
revert IAccessAdmin.ErrorAccessAdminTargetAlreadyCreated(
target,
accessAdmin.getTargetInfo(target).name.toString());
}

// check target name is not empty
Str name = StrLib.toStr(targetName);
if(name.length() == 0) {
revert IAccessAdmin.ErrorAccessAdminTargetNameEmpty(target);
}

// check target name is not used for another target
address targetForName = accessAdmin.getTargetForName(name);
if(targetForName != address(0)) {
revert IAccessAdmin.ErrorAccessAdminTargetNameAlreadyExists(
target,
targetName,
targetForName);
}

// check target is an access managed contract
if (!ContractLib.isAccessManaged(target)) {
revert IAccessAdmin.ErrorAccessAdminTargetNotAccessManaged(target);
}

// check target shares authority with this contract
if (checkAuthority) {
address targetAuthority = AccessManagedUpgradeable(target).authority();
if (targetAuthority != accessAdmin.authority()) {
revert IAccessAdmin.ErrorAccessAdminTargetAuthorityMismatch(accessAdmin.authority(), targetAuthority);
}
}

}


function checkAuthorization(
address authorizationOld,
address authorization,
ObjectType expectedDomain,
VersionPart expectedRelease,
bool checkAlreadyInitialized
)
public
view
{
// checks
// check not yet initialized
if (checkAlreadyInitialized && authorizationOld != address(0)) {
revert IAccessAdmin.ErrorAccessAdminAlreadyInitialized(authorizationOld);
}

// check contract type matches
if (!ContractLib.supportsInterface(authorization, type(IAuthorization).interfaceId)) {
revert IAccessAdmin.ErrorAccessAdminNotAuthorization(authorization);
}

// check domain matches
ObjectType domain = IAuthorization(authorization).getDomain();
if (domain != expectedDomain) {
revert IAccessAdmin.ErrorAccessAdminDomainMismatch(authorization, expectedDomain, domain);
}

// check release matches
VersionPart authorizationRelease = IAuthorization(authorization).getRelease();
if (authorizationRelease != expectedRelease) {
revert IAccessAdmin.ErrorAccessAdminReleaseMismatch(authorization, expectedRelease, authorizationRelease);
}
}


function checkIsRegistered(
address registry,
address target,
ObjectType expectedType
)
public
view
{
ObjectType tagetType = IRegistry(registry).getObjectInfo(target).objectType;
if (tagetType.eqz()) {
revert IAccessAdmin.ErrorAccessAdminNotRegistered(target);
}

if (tagetType != expectedType) {
revert IAccessAdmin.ErrorAccessAdminTargetTypeMismatch(target, expectedType, tagetType);
}
}

function toRole(RoleId adminRoleId, IAccessAdmin.RoleType roleType, uint32 maxMemberCount, string memory name)
public
view
returns (IAccess.RoleInfo memory)
{
return IAccess.RoleInfo({
name: StrLib.toStr(name),
adminRoleId: adminRoleId,
roleType: roleType,
maxMemberCount: maxMemberCount,
createdAt: TimestampLib.blockTimestamp(),
pausedAt: TimestampLib.max()
});
}

function toFunction(bytes4 selector, string memory name)
public
view
returns (IAccess.FunctionInfo memory)
{
return IAccess.FunctionInfo({
name: StrLib.toStr(name),
selector: SelectorLib.toSelector(selector),
createdAt: TimestampLib.blockTimestamp()});
}

}
71 changes: 40 additions & 31 deletions contracts/authorization/AccessManagerCloneable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
pragma solidity ^0.8.20;

import {AccessManagerUpgradeable} from "@openzeppelin/contracts-upgradeable/access/manager/AccessManagerUpgradeable.sol";
import {IAccessManaged} from "@openzeppelin/contracts/access/manager/IAccessManaged.sol";
import {IAccessManager} from "@openzeppelin/contracts/access/manager/IAccessManager.sol";

import {InitializableERC165} from "../shared/InitializableERC165.sol";
import {RegistryLinked} from "../shared/RegistryLinked.sol";
import {VersionPart, VersionLib} from "../type/Version.sol";
import {VersionPart} from "../type/Version.sol";


/// @dev An AccessManager based on OpenZeppelin that is cloneable and has a central lock property.
Expand All @@ -28,6 +27,7 @@ contract AccessManagerCloneable is
VersionPart private _release;
bool private _isLocked;


modifier onlyAdminRole() {
(bool isMember, ) = hasRole(ADMIN_ROLE, msg.sender);
if(!isMember) {
Expand All @@ -36,12 +36,14 @@ contract AccessManagerCloneable is
_;
}


function initialize(address admin)
external
public
initializer()
{
__ERC165_init();
__AccessManager_init(admin);
_initializeERC165();

_registerInterface(type(IAccessManager).interfaceId);
}

Expand All @@ -56,22 +58,27 @@ contract AccessManagerCloneable is
onlyAdminRole
reinitializer(uint64(release.toInt()))
{
_completeSetup(registry, release, true);
_checkAndSetRegistry(registry);
_checkAndSetRelease(release);
}

/// @dev Completes the setup of the access manager.
/// Links the access manager to the registry and sets the release version.
function completeSetup(
address registry,
VersionPart release,
bool verifyRelease
)
public
onlyAdminRole
reinitializer(uint64(release.toInt()))
{
_completeSetup(registry, release, verifyRelease);
}
// /// @dev Completes the setup of the access manager.
// /// Links the access manager to the registry and sets the release version.
// function completeSetup(
// address registry,
// VersionPart release,
// bool verifyRelease
// )
// public
// onlyAdminRole
// reinitializer(uint64(release.toInt()))
// {
// _checkAndSetRegistry(registry);

// if (verifyRelease) {
// _checkAndSetRelease(release);
// }
// }

/// @dev Returns true if the caller is authorized to call the target with the given selector and the manager lock is not set to locked.
/// Feturn values as in OpenZeppelin AccessManager.
Expand All @@ -89,12 +96,12 @@ contract AccessManagerCloneable is
uint32 delay
)
{
(immediate, delay) = super.canCall(caller, target, selector);

// locking of all contracts under control of this access manager
if (isLocked()) {
if (_isLocked) {
revert ErrorAccessManagerTargetAdminLocked(target);
}

(immediate, delay) = super.canCall(caller, target, selector);
}


Expand Down Expand Up @@ -126,24 +133,26 @@ contract AccessManagerCloneable is
}


function _completeSetup(
address registry,
VersionPart release,
bool verifyRelease
)
function _checkAndSetRelease(VersionPart release)
internal
{
if (!release.isValidRelease()) {
revert ErrorAccessManagerInvalidRelease(release);
}

_release = release;
}


function _checkAndSetRegistry(address registry)
internal
{
// checks
if(address(getRegistry()) != address(0)) {
revert ErrorAccessManagerRegistryAlreadySet(address(getRegistry()) );
}

if (verifyRelease && !release.isValidRelease()) {
revert ErrorAccessManagerInvalidRelease(release);
}

// effects
__RegistryLinked_init(registry);
_release = release;
}
}
Loading
Loading