// SPDX-License-Identifier: GPL-3.0 // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= // :=*%@@@#=. :#@@% *@@@%= // .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- // :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. // -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ // =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- // -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: // :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. // %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. // #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ // *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- // -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: // .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- // -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- // -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# // *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- // +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: // =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: // .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. // +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. // -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. // ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. // @@@@@@+. +@@*. .+@@@@@%=. // -@@@@@= =@@%: -#@@@@%+. // +@@@@@. =@@@= .+@@@@@*: // #@@@@#:%@@#. :*@@@@#- // @@@@@%@@@= :#@@@@+. // :@@@@@@@#.:#@@@%- // +@@@@@@-.*@@@*: // #@@@@#.=@@@+. // @@@@+-%@%= // :@@@#%@%= // +@@@@%- // :#%%= // /** * NOTICE * * The T-REX software is licensed under a proprietary license or the GPL v.3. * If you choose to receive it under the GPL v.3 license, the following applies: * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * * Copyright (C) 2023, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ pragma solidity 0.8.17; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "./IModule.sol"; abstract contract AbstractModuleUpgradeable is IModule, Initializable, OwnableUpgradeable, UUPSUpgradeable { struct AbstractModuleStorage { /// compliance contract binding status mapping(address => bool) complianceBound; } // keccak256(abi.encode(uint256(keccak256("ERC3643.storage.AbstractModule")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant _ABSTRACT_MODULE_STORAGE_LOCATION = 0xf6cc97de1266c180cd39f3b311632644143ce7873d2927755382ad4b39e8ae00; /** * @dev Throws if `_compliance` is not a bound compliance contract address. */ modifier onlyBoundCompliance(address _compliance) { AbstractModuleStorage storage s = _getAbstractModuleStorage(); require(s.complianceBound[_compliance], "compliance not bound"); _; } /** * @dev Throws if called from an address that is not a bound compliance contract. */ modifier onlyComplianceCall() { AbstractModuleStorage storage s = _getAbstractModuleStorage(); require(s.complianceBound[msg.sender], "only bound compliance can call"); _; } /** * @dev See {IModule-bindCompliance}. */ function bindCompliance(address _compliance) external override { AbstractModuleStorage storage s = _getAbstractModuleStorage(); require(_compliance != address(0), "invalid argument - zero address"); require(!s.complianceBound[_compliance], "compliance already bound"); require(msg.sender == _compliance, "only compliance contract can call"); s.complianceBound[_compliance] = true; emit ComplianceBound(_compliance); } /** * @dev See {IModule-unbindCompliance}. */ function unbindCompliance(address _compliance) external onlyComplianceCall override { AbstractModuleStorage storage s = _getAbstractModuleStorage(); require(_compliance != address(0), "invalid argument - zero address"); require(msg.sender == _compliance, "only compliance contract can call"); s.complianceBound[_compliance] = false; emit ComplianceUnbound(_compliance); } /** * @dev See {IModule-isComplianceBound}. */ function isComplianceBound(address _compliance) external view override returns (bool) { AbstractModuleStorage storage s = _getAbstractModuleStorage(); return s.complianceBound[_compliance]; } // solhint-disable-next-line func-name-mixedcase function __AbstractModule_init() internal onlyInitializing { __Ownable_init(); __AbstractModule_init_unchained(); } // solhint-disable-next-line no-empty-blocks, func-name-mixedcase function __AbstractModule_init_unchained() internal onlyInitializing { } // solhint-disable-next-line no-empty-blocks function _authorizeUpgrade(address /*newImplementation*/) internal override virtual onlyOwner { } function _getAbstractModuleStorage() private pure returns (AbstractModuleStorage storage s) { // solhint-disable-next-line no-inline-assembly assembly { s.slot := _ABSTRACT_MODULE_STORAGE_LOCATION } } }