// SPDX-License-Identifier: UNLICENSED pragma solidity =0.8.18; import "../../SomaAccessControl/utils/AccessibleUpgradeable.sol"; import "../ISomaGuard.sol"; import "./GuardHelper.sol"; import "./IMultiGuardable.sol"; /** * @notice Implementation of the {IGuardable} interface. */ abstract contract MultiGuardableUpgradeable is IMultiGuardable, AccessibleUpgradeable { /** * @notice Initializer for extended contracts. */ function __Guardable__init() internal { __Context_init_unchained(); __ERC165_init_unchained(); __Guardable__init_unchained(); __SomaContract_init_unchained(); __Accessible_init_unchained(); __Multicall_init_unchained(); __Pausable_init_unchained(); } /** * @notice Unchained initializer for extended contracts. */ function __Guardable__init_unchained() internal onlyInitializing { LOCAL_UPDATE_PRIVILEGES_ROLE = keccak256(abi.encodePacked(address(this), GLOBAL_UPDATE_PRIVILEGES_ROLE)); _updateRequiredPrivileges(DEFAULT_ID, bytes32(type(uint256).max)); } bytes32 public immutable DEFAULT_PRIVILEGES = GuardHelper.DEFAULT_PRIVILEGES; bytes32 public immutable DEFAULT_ID = 0x00; bytes32 public constant GLOBAL_UPDATE_PRIVILEGES_ROLE = keccak256("Guardable.GLOBAL_UPDATE_PRIVILEGES_ROLE"); bytes32 public LOCAL_UPDATE_PRIVILEGES_ROLE; mapping(bytes32 => bytes32) private _requiredPrivileges; /** * @notice Modifier restricting a function call to accounts that have the required privileges. */ modifier onlyApprovedPrivileges(address sender) { require(hasPrivileges(sender), "required privileges not met"); _; } /** * @inheritdoc IMultiGuardable */ function hasPrivileges(address account) public view virtual override returns (bool) { return hasPrivileges(DEFAULT_ID, account); } /** * @inheritdoc IMultiGuardable */ function hasPrivileges(bytes32 id, address account) public view virtual override returns (bool) { return ISomaGuard(SOMA.guard()).check(account, requiredPrivileges(id)); } /** * @inheritdoc IMultiGuardable */ function requiredPrivileges() public view virtual override returns (bytes32) { return requiredPrivileges(DEFAULT_ID); } /** * @inheritdoc IMultiGuardable */ function requiredPrivileges(bytes32 id) public view virtual override returns (bytes32) { return _requiredPrivileges[id]; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IMultiGuardable).interfaceId || super.supportsInterface(interfaceId); } /** * @inheritdoc IMultiGuardable */ function updateRequiredPrivileges(bytes32 newRequiredPrivileges) public virtual override returns (bool) { return updateRequiredPrivileges(DEFAULT_ID, newRequiredPrivileges); } /** * @inheritdoc IMultiGuardable */ function updateRequiredPrivileges(bytes32 id, bytes32 newRequiredPrivileges) public virtual override returns (bool) { require( hasRole(LOCAL_UPDATE_PRIVILEGES_ROLE, _msgSender()) || hasRole(GLOBAL_UPDATE_PRIVILEGES_ROLE, _msgSender()), "Guardable: you do not have the required roles to do this" ); _updateRequiredPrivileges(id, newRequiredPrivileges); return true; } function _updateRequiredPrivileges(bytes32 id, bytes32 newRequiredPrivileges) internal { emit RequiredPrivilegesUpdated(id, _requiredPrivileges[id], newRequiredPrivileges, _msgSender()); _requiredPrivileges[id] = newRequiredPrivileges; } uint256[50] private __gap; }