```
+- For `RuleConditionalTransferLight` fuzz/integration tests, note that mint and burn paths (`from == address(0)` or `to == address(0)`) are intentionally exempt from approval consumption.
+- Ownable2Step variants also include dedicated tests for ownership transfer and manager-only functions (IdentityRegistry, MaxTotalSupply, SanctionsList).
+- Coverage-focused tests also target deployment wrappers and operation-rule overloads (`created`, `destroyed`, spender-aware `transferred`) to improve line/function coverage in `src/rules/operation` and `src/rules/validation/deployment`.
+
Generate gas report
```bash
diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html
similarity index 50%
rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html
rename to doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html
index 6808037..65bc64a 100644
--- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html
+++ b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSet.sol - functions
-
+ LCOV - lcov.info - abstract/RuleAddressSet/RuleAddressSet.sol - functions
+
LCOV - code coverage report
-
+
-
+
@@ -31,92 +31,100 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
+
+
-
+
-
+
diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.func.html
similarity index 50%
rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html
rename to doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.func.html
index 3ebf795..5984b78 100644
--- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html
+++ b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.func.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSet.sol - functions
-
+ LCOV - lcov.info - abstract/RuleAddressSet/RuleAddressSet.sol - functions
+
LCOV - code coverage report
-
+
-
+
@@ -31,92 +31,100 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
+
+
-
+
-
+
diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html
similarity index 75%
rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html
rename to doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html
index cded5ef..cef3ac8 100644
--- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html
+++ b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSet.sol
-
+ LCOV - lcov.info - abstract/RuleAddressSet/RuleAddressSet.sol
+
LCOV - code coverage report
-
+
-
+
@@ -31,34 +31,34 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
+
+
-
+
-
+
@@ -72,168 +72,170 @@
1 : : // SPDX-License-Identifier: MPL-2.0
2 : : pragma solidity ^0.8.20;
3 : :
- 4 : : import {AccessControlModuleStandalone} from "../../../../modules/AccessControlModuleStandalone.sol";
- 5 : : import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../../../modules/MetaTxModuleStandalone.sol";
- 6 : : import {RuleAddressSetInternal} from "./RuleAddressSetInternal.sol";
- 7 : : import {RuleAddressSetInvariantStorage} from "./invariantStorage/RuleAddressSetInvariantStorage.sol";
- 8 : : /* ==== Interfaces === */
- 9 : : import {IIdentityRegistryContains} from "../../../interfaces/IIdentityRegistry.sol";
- 10 : : import {IAddressList} from "../../../interfaces/IAddressList.sol";
- 11 : : /**
- 12 : : * @title Rule Address Set
- 13 : : * @notice Manages a permissioned set of addresses related to rule logic.
- 14 : : * @dev
- 15 : : * - Provides controlled functions for adding and removing addresses.
- 16 : : * - Integrates `AccessControl` for role-based access.
- 17 : : * - Supports gasless transactions via ERC-2771 meta-transactions.
- 18 : : * - Extends internal logic defined in {RuleAddressSetInternal}.
- 19 : : */
- 20 : :
- 21 : : abstract contract RuleAddressSet is
- 22 : : AccessControlModuleStandalone,
- 23 : : MetaTxModuleStandalone,
- 24 : : RuleAddressSetInternal,
- 25 : : RuleAddressSetInvariantStorage,
- 26 : : IAddressList
- 27 : : {
- 28 : : /*//////////////////////////////////////////////////////////////
- 29 : : STATE
- 30 : : //////////////////////////////////////////////////////////////*/
- 31 : :
- 32 : : /// @notice Cached number of currently listed addresses.
- 33 : : uint256 private _listedAddressCountCache;
- 34 : :
- 35 : : /*//////////////////////////////////////////////////////////////
- 36 : : CONSTRUCTOR
- 37 : : //////////////////////////////////////////////////////////////*/
- 38 : :
- 39 : : /**
- 40 : : * @notice Initializes the RuleAddressSet contract.
- 41 : : * @param admin The address granted the default admin role.
- 42 : : * @param forwarderIrrevocable Address of the ERC2771 forwarder (for meta-transactions).
- 43 : : * @dev Reverts if the admin address is the zero address.
- 44 : : */
- 45 : : constructor(address admin, address forwarderIrrevocable)
- 46 : : MetaTxModuleStandalone(forwarderIrrevocable)
- 47 : : AccessControlModuleStandalone(admin)
- 48 : : {
- 49 : : // nothing to do
- 50 : : }
- 51 : :
- 52 : : /*//////////////////////////////////////////////////////////////
- 53 : : CORE LOGIC
- 54 : : //////////////////////////////////////////////////////////////*/
+ 4 : : import {MetaTxModuleStandalone, ERC2771Context} from "../../../../modules/MetaTxModuleStandalone.sol";
+ 5 : : import {RuleAddressSetInternal} from "./RuleAddressSetInternal.sol";
+ 6 : : import {RuleAddressSetInvariantStorage} from "./invariantStorage/RuleAddressSetInvariantStorage.sol";
+ 7 : : /* ==== Interfaces === */
+ 8 : : import {IIdentityRegistryContains} from "../../../interfaces/IIdentityRegistry.sol";
+ 9 : : import {IAddressList} from "../../../interfaces/IAddressList.sol";
+ 10 : : /**
+ 11 : : * @title Rule Address Set
+ 12 : : * @notice Manages a permissioned set of addresses related to rule logic.
+ 13 : : * @dev
+ 14 : : * - Provides controlled functions for adding and removing addresses.
+ 15 : : * - Integrates `AccessControl` for role-based access.
+ 16 : : * - Supports gasless transactions via ERC-2771 meta-transactions.
+ 17 : : * - Extends internal logic defined in {RuleAddressSetInternal}.
+ 18 : : */
+ 19 : :
+ 20 : : abstract contract RuleAddressSet is
+ 21 : : MetaTxModuleStandalone,
+ 22 : : RuleAddressSetInternal,
+ 23 : : RuleAddressSetInvariantStorage,
+ 24 : : IAddressList
+ 25 : : {
+ 26 : : /*//////////////////////////////////////////////////////////////
+ 27 : : STATE
+ 28 : : //////////////////////////////////////////////////////////////*/
+ 29 : :
+ 30 : : /*//////////////////////////////////////////////////////////////
+ 31 : : CONSTRUCTOR
+ 32 : : //////////////////////////////////////////////////////////////*/
+ 33 : :
+ 34 : : /**
+ 35 : : * @notice Initializes the RuleAddressSet contract.
+ 36 : : * @param forwarderIrrevocable Address of the ERC2771 forwarder (for meta-transactions).
+ 37 : : */
+ 38 : : constructor(address forwarderIrrevocable) MetaTxModuleStandalone(forwarderIrrevocable) {}
+ 39 : :
+ 40 : : /*//////////////////////////////////////////////////////////////
+ 41 : : CORE LOGIC
+ 42 : : //////////////////////////////////////////////////////////////*/
+ 43 : :
+ 44 : : /**
+ 45 : : * @notice Adds multiple addresses to the set.
+ 46 : : * @dev
+ 47 : : * - Does not revert if an address is already listed.
+ 48 : : * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`.
+ 49 : : * @param targetAddresses Array of addresses to be added.
+ 50 : : */
+ 51 : 275 : function addAddresses(address[] calldata targetAddresses) public onlyAddressListAdd {
+ 52 : 274 : _addAddresses(targetAddresses);
+ 53 : 274 : emit AddAddresses(targetAddresses);
+ 54 : : }
55 : :
56 : : /**
- 57 : : * @notice Adds multiple addresses to the set.
+ 57 : : * @notice Removes multiple addresses from the set.
58 : : * @dev
- 59 : : * - Does not revert if an address is already listed.
- 60 : : * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`.
- 61 : : * @param targetAddresses Array of addresses to be added.
+ 59 : : * - Does not revert if an address is not listed.
+ 60 : : * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`.
+ 61 : : * @param targetAddresses Array of addresses to remove.
62 : : */
- 63 : 17 : function addAddresses(address[] calldata targetAddresses) public onlyRole(ADDRESS_LIST_ADD_ROLE) {
- 64 : 16 : _addAddresses(targetAddresses);
- 65 : 16 : emit AddAddresses(targetAddresses);
+ 63 : 260 : function removeAddresses(address[] calldata targetAddresses) public onlyAddressListRemove {
+ 64 : 259 : _removeAddresses(targetAddresses);
+ 65 : 259 : emit RemoveAddresses(targetAddresses);
66 : : }
67 : :
68 : : /**
- 69 : : * @notice Removes multiple addresses from the set.
+ 69 : : * @notice Adds a single address to the set.
70 : : * @dev
- 71 : : * - Does not revert if an address is not listed.
- 72 : : * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`.
- 73 : : * @param targetAddresses Array of addresses to remove.
+ 71 : : * - Reverts if the address is already listed.
+ 72 : : * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`.
+ 73 : : * @param targetAddress The address to be added.
74 : : */
- 75 : 4 : function removeAddresses(address[] calldata targetAddresses) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) {
- 76 : 3 : _removeAddresses(targetAddresses);
- 77 : 3 : emit RemoveAddresses(targetAddresses);
- 78 : : }
- 79 : :
- 80 : : /**
- 81 : : * @notice Adds a single address to the set.
- 82 : : * @dev
- 83 : : * - Reverts if the address is already listed.
- 84 : : * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`.
- 85 : : * @param targetAddress The address to be added.
- 86 : : */
- 87 : 52 : function addAddress(address targetAddress) public onlyRole(ADDRESS_LIST_ADD_ROLE) {
- 88 [ + ]: 51 : if (_isAddressListed(targetAddress)) {
- 89 : 1 : revert RuleAddressSet_AddressAlreadyListed();
- 90 : : }
- 91 : 50 : _addAddress(targetAddress);
- 92 : 50 : emit AddAddress(targetAddress);
- 93 : : }
- 94 : :
- 95 : : /**
- 96 : : * @notice Removes a single address from the set.
- 97 : : * @dev
- 98 : : * - Reverts if the address is not listed.
- 99 : : * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`.
- 100 : : * @param targetAddress The address to be removed.
- 101 : : */
- 102 : 3 : function removeAddress(address targetAddress) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) {
- 103 [ + ]: 2 : if (!_isAddressListed(targetAddress)) {
- 104 : 1 : revert RuleAddressSet_AddressNotFound();
- 105 : : }
- 106 : 1 : _removeAddress(targetAddress);
- 107 : 1 : emit RemoveAddress(targetAddress);
- 108 : : }
+ 75 : 105 : function addAddress(address targetAddress) public onlyAddressListAdd {
+ 76 [ + + ]: 102 : require(!_isAddressListed(targetAddress), RuleAddressSet_AddressAlreadyListed());
+ 77 : 101 : _addAddress(targetAddress);
+ 78 : 101 : emit AddAddress(targetAddress);
+ 79 : : }
+ 80 : :
+ 81 : : /**
+ 82 : : * @notice Removes a single address from the set.
+ 83 : : * @dev
+ 84 : : * - Reverts if the address is not listed.
+ 85 : : * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`.
+ 86 : : * @param targetAddress The address to be removed.
+ 87 : : */
+ 88 : 8 : function removeAddress(address targetAddress) public onlyAddressListRemove {
+ 89 [ + + ]: 5 : require(_isAddressListed(targetAddress), RuleAddressSet_AddressNotFound());
+ 90 : 4 : _removeAddress(targetAddress);
+ 91 : 4 : emit RemoveAddress(targetAddress);
+ 92 : : }
+ 93 : :
+ 94 : : /*//////////////////////////////////////////////////////////////
+ 95 : : ACCESS CONTROL
+ 96 : : //////////////////////////////////////////////////////////////*/
+ 97 : :
+ 98 : 275 : modifier onlyAddressListAdd() {
+ 99 : 275 : _authorizeAddressListAdd();
+ 100 : : _;
+ 101 : : }
+ 102 : :
+ 103 : 8 : modifier onlyAddressListRemove() {
+ 104 : 8 : _authorizeAddressListRemove();
+ 105 : : _;
+ 106 : : }
+ 107 : :
+ 108 : : function _authorizeAddressListAdd() internal view virtual;
109 : :
- 110 : : /**
- 111 : : * @notice Returns the total number of currently listed addresses.
- 112 : : * @return count The number of listed addresses.
- 113 : : */
- 114 : 24 : function listedAddressCount() public view returns (uint256 count) {
- 115 : 24 : count = _listedAddressCount();
- 116 : : }
- 117 : :
- 118 : : /**
- 119 : : * @notice Checks whether a specific address is currently listed.
- 120 : : * @param targetAddress The address to check.
- 121 : : * @return isListed True if listed, false otherwise.
- 122 : : */
- 123 : 0 : function contains(address targetAddress) public view override(IIdentityRegistryContains) returns (bool isListed) {
- 124 : 0 : isListed = _isAddressListed(targetAddress);
- 125 : : }
- 126 : :
- 127 : : /**
- 128 : : * @notice Checks whether a specific address is currently listed.
- 129 : : * @param targetAddress The address to check.
- 130 : : * @return isListed True if listed, false otherwise.
- 131 : : */
- 132 : 60 : function isAddressListed(address targetAddress) public view returns (bool isListed) {
- 133 : 219 : isListed = _isAddressListed(targetAddress);
- 134 : : }
- 135 : :
- 136 : : /**
- 137 : : * @notice Checks multiple addresses in a single call.
- 138 : : * @param targetAddresses Array of addresses to check.
- 139 : : * @return results Array of booleans corresponding to listing status.
- 140 : : */
- 141 : 84 : function areAddressesListed(address[] memory targetAddresses) public view returns (bool[] memory results) {
- 142 : 84 : results = new bool[](targetAddresses.length);
- 143 : 84 : for (uint256 i = 0; i < targetAddresses.length; ++i) {
- 144 : 191 : results[i] = _isAddressListed(targetAddresses[i]);
- 145 : : }
- 146 : : }
- 147 : : /*//////////////////////////////////////////////////////////////
- 148 : : ERC-2771 META TX
- 149 : : //////////////////////////////////////////////////////////////*/
- 150 : :
- 151 : : /// @inheritdoc ERC2771Context
- 152 : 207 : function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
- 153 : 207 : return ERC2771Context._msgSender();
- 154 : : }
- 155 : :
- 156 : : /// @inheritdoc ERC2771Context
- 157 : 0 : function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) {
- 158 : 0 : return ERC2771Context._msgData();
- 159 : : }
- 160 : :
- 161 : : /// @inheritdoc ERC2771Context
- 162 : 207 : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
- 163 : 207 : return ERC2771Context._contextSuffixLength();
- 164 : : }
- 165 : : }
+ 110 : : function _authorizeAddressListRemove() internal view virtual;
+ 111 : :
+ 112 : : /**
+ 113 : : * @notice Returns the total number of currently listed addresses.
+ 114 : : * @return count The number of listed addresses.
+ 115 : : */
+ 116 : 536 : function listedAddressCount() public view returns (uint256 count) {
+ 117 : 536 : count = _listedAddressCount();
+ 118 : : }
+ 119 : :
+ 120 : : /**
+ 121 : : * @notice Checks whether a specific address is currently listed.
+ 122 : : * @param targetAddress The address to check.
+ 123 : : * @return isListed True if listed, false otherwise.
+ 124 : : */
+ 125 : 2 : function contains(address targetAddress) public view override(IIdentityRegistryContains) returns (bool isListed) {
+ 126 : 2 : isListed = _isAddressListed(targetAddress);
+ 127 : : }
+ 128 : :
+ 129 : : /**
+ 130 : : * @notice Checks whether a specific address is currently listed.
+ 131 : : * @param targetAddress The address to check.
+ 132 : : * @return isListed True if listed, false otherwise.
+ 133 : : */
+ 134 : 67 : function isAddressListed(address targetAddress) public view returns (bool isListed) {
+ 135 : 383 : isListed = _isAddressListed(targetAddress);
+ 136 : : }
+ 137 : :
+ 138 : : /**
+ 139 : : * @notice Checks multiple addresses in a single call.
+ 140 : : * @param targetAddresses Array of addresses to check.
+ 141 : : * @return results Array of booleans corresponding to listing status.
+ 142 : : */
+ 143 : 108 : function areAddressesListed(address[] memory targetAddresses) public view returns (bool[] memory results) {
+ 144 : 108 : results = new bool[](targetAddresses.length);
+ 145 : 108 : for (uint256 i = 0; i < targetAddresses.length; ++i) {
+ 146 : 244 : results[i] = _isAddressListed(targetAddresses[i]);
+ 147 : : }
+ 148 : : }
+ 149 : : /*//////////////////////////////////////////////////////////////
+ 150 : : ERC-2771 META TX
+ 151 : : //////////////////////////////////////////////////////////////*/
+ 152 : :
+ 153 : : /// @inheritdoc ERC2771Context
+ 154 : 882 : function _msgSender() internal view virtual override(ERC2771Context) returns (address sender) {
+ 155 : 882 : return ERC2771Context._msgSender();
+ 156 : : }
+ 157 : :
+ 158 : : /// @inheritdoc ERC2771Context
+ 159 : 4 : function _msgData() internal view virtual override(ERC2771Context) returns (bytes calldata) {
+ 160 : 4 : return ERC2771Context._msgData();
+ 161 : : }
+ 162 : :
+ 163 : : /// @inheritdoc ERC2771Context
+ 164 : 886 : function _contextSuffixLength() internal view virtual override(ERC2771Context) returns (uint256) {
+ 165 : 886 : return ERC2771Context._contextSuffixLength();
+ 166 : : }
+ 167 : : }
@@ -241,7 +243,7 @@
diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html
similarity index 56%
rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html
rename to doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html
index 715669b..a58da58 100644
--- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html
+++ b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol - functions
-
+ LCOV - lcov.info - abstract/RuleAddressSet/RuleAddressSetInternal.sol - functions
+
LCOV - code coverage report
-
+
-
+
@@ -31,13 +31,13 @@
-
-
+
+
-
+
@@ -49,54 +49,54 @@
-
-
-
+
+
+
-
+
-
+
diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html
similarity index 56%
rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html
rename to doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html
index bfbd673..c1510d8 100644
--- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html
+++ b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol - functions
-
+ LCOV - lcov.info - abstract/RuleAddressSet/RuleAddressSetInternal.sol - functions
+
LCOV - code coverage report
-
+
-
+
@@ -31,13 +31,13 @@
-
-
+
+
-
+
@@ -49,54 +49,54 @@
-
-
-
+
+
+
-
+
-
+
diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html
similarity index 67%
rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html
rename to doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html
index c60105a..9518c01 100644
--- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html
+++ b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol
-
+ LCOV - lcov.info - abstract/RuleAddressSet/RuleAddressSetInternal.sol
+
LCOV - code coverage report
-
+
-
+
@@ -31,13 +31,13 @@
-
-
+
+
-
+
@@ -49,16 +49,16 @@
-
-
-
+
+
+
-
+
-
+
@@ -103,59 +103,77 @@
32 : : * - Does not revert if an address is already listed.
33 : : * - Skips existing entries silently.
34 : : * @param addressesToAdd The array of addresses to add.
- 35 : : */
- 36 : 16 : function _addAddresses(address[] calldata addressesToAdd) internal {
- 37 : 16 : for (uint256 i = 0; i < addressesToAdd.length; ++i) {
- 38 : 34 : _listedAddresses.add(addressesToAdd[i]);
- 39 : : }
- 40 : : }
- 41 : :
- 42 : : /**
- 43 : : * @notice Removes multiple addresses from the set.
- 44 : : * @dev
- 45 : : * - Does not revert if an address is not found.
- 46 : : * - Skips non-existing entries silently.
- 47 : : * @param addressesToRemove The array of addresses to remove.
- 48 : : */
- 49 : 3 : function _removeAddresses(address[] calldata addressesToRemove) internal {
- 50 : 3 : for (uint256 i = 0; i < addressesToRemove.length; ++i) {
- 51 : 7 : _listedAddresses.remove(addressesToRemove[i]);
- 52 : : }
- 53 : : }
- 54 : :
- 55 : : /**
- 56 : : * @notice Adds a single address to the set.
- 57 : : * @param targetAddress The address to add.
- 58 : : */
- 59 : 50 : function _addAddress(address targetAddress) internal {
- 60 : 50 : _listedAddresses.add(targetAddress);
- 61 : : }
- 62 : :
- 63 : : /**
- 64 : : * @notice Removes a single address from the set.
- 65 : : * @param targetAddress The address to remove.
- 66 : : */
- 67 : 1 : function _removeAddress(address targetAddress) internal {
- 68 : 1 : _listedAddresses.remove(targetAddress);
- 69 : : }
- 70 : :
- 71 : : /**
- 72 : : * @notice Returns the total number of listed addresses.
- 73 : : * @return count The number of listed addresses.
- 74 : : */
- 75 : 24 : function _listedAddressCount() internal view returns (uint256 count) {
- 76 : 24 : count = _listedAddresses.length();
- 77 : : }
- 78 : :
- 79 : : /**
- 80 : : * @notice Checks if an address is listed.
- 81 : : * @param targetAddress The address to check.
- 82 : : * @return isListed True if the address is listed, false otherwise.
- 83 : : */
- 84 : 463 : function _isAddressListed(address targetAddress) internal view returns (bool isListed) {
- 85 : 463 : isListed = _listedAddresses.contains(targetAddress);
- 86 : : }
- 87 : : }
+ 35 : : * @return added The number of newly added addresses.
+ 36 : : * @return skipped The number of addresses that were already listed.
+ 37 : : */
+ 38 : 274 : function _addAddresses(address[] calldata addressesToAdd)
+ 39 : : internal
+ 40 : : returns (uint256 added, uint256 skipped)
+ 41 : : {
+ 42 : 274 : for (uint256 i = 0; i < addressesToAdd.length; ++i) {
+ 43 [ + + ]: 806 : if (_listedAddresses.add(addressesToAdd[i])) {
+ 44 : 548 : added += 1;
+ 45 : : } else {
+ 46 : 258 : skipped += 1;
+ 47 : : }
+ 48 : : }
+ 49 : : }
+ 50 : :
+ 51 : : /**
+ 52 : : * @notice Removes multiple addresses from the set.
+ 53 : : * @dev
+ 54 : : * - Does not revert if an address is not found.
+ 55 : : * - Skips non-existing entries silently.
+ 56 : : * @param addressesToRemove The array of addresses to remove.
+ 57 : : * @return removed The number of addresses removed.
+ 58 : : * @return skipped The number of addresses that were not listed.
+ 59 : : */
+ 60 : 259 : function _removeAddresses(address[] calldata addressesToRemove)
+ 61 : : internal
+ 62 : : returns (uint256 removed, uint256 skipped)
+ 63 : : {
+ 64 : 259 : for (uint256 i = 0; i < addressesToRemove.length; ++i) {
+ 65 [ + + ]: 775 : if (_listedAddresses.remove(addressesToRemove[i])) {
+ 66 : 518 : removed += 1;
+ 67 : : } else {
+ 68 : 257 : skipped += 1;
+ 69 : : }
+ 70 : : }
+ 71 : : }
+ 72 : :
+ 73 : : /**
+ 74 : : * @notice Adds a single address to the set.
+ 75 : : * @param targetAddress The address to add.
+ 76 : : */
+ 77 : 101 : function _addAddress(address targetAddress) internal virtual {
+ 78 : 101 : _listedAddresses.add(targetAddress);
+ 79 : : }
+ 80 : :
+ 81 : : /**
+ 82 : : * @notice Removes a single address from the set.
+ 83 : : * @param targetAddress The address to remove.
+ 84 : : */
+ 85 : 4 : function _removeAddress(address targetAddress) internal virtual {
+ 86 : 4 : _listedAddresses.remove(targetAddress);
+ 87 : : }
+ 88 : :
+ 89 : : /**
+ 90 : : * @notice Returns the total number of listed addresses.
+ 91 : : * @return count The number of listed addresses.
+ 92 : : */
+ 93 : 536 : function _listedAddressCount() internal view virtual returns (uint256 count) {
+ 94 : 536 : count = _listedAddresses.length();
+ 95 : : }
+ 96 : :
+ 97 : : /**
+ 98 : : * @notice Checks if an address is listed.
+ 99 : : * @param targetAddress The address to check.
+ 100 : : * @return isListed True if the address is listed, false otherwise.
+ 101 : : */
+ 102 : 738 : function _isAddressListed(address targetAddress) internal view virtual returns (bool isListed) {
+ 103 : 738 : isListed = _listedAddresses.contains(targetAddress);
+ 104 : : }
+ 105 : : }
@@ -163,7 +181,7 @@
diff --git a/doc/coverage/coverage/validation/abstract/index-sort-b.html b/doc/coverage/coverage/abstract/RuleAddressSet/index-sort-b.html
similarity index 74%
rename from doc/coverage/coverage/validation/abstract/index-sort-b.html
rename to doc/coverage/coverage/abstract/RuleAddressSet/index-sort-b.html
index 5fe0919..f299290 100644
--- a/doc/coverage/coverage/validation/abstract/index-sort-b.html
+++ b/doc/coverage/coverage/abstract/RuleAddressSet/index-sort-b.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/abstract
+ LCOV - lcov.info - abstract/RuleAddressSet
@@ -19,7 +19,7 @@
diff --git a/doc/coverage/coverage/validation/abstract/index-sort-f.html b/doc/coverage/coverage/abstract/RuleAddressSet/index-sort-f.html
similarity index 74%
rename from doc/coverage/coverage/validation/abstract/index-sort-f.html
rename to doc/coverage/coverage/abstract/RuleAddressSet/index-sort-f.html
index b7e1816..3713f5e 100644
--- a/doc/coverage/coverage/validation/abstract/index-sort-f.html
+++ b/doc/coverage/coverage/abstract/RuleAddressSet/index-sort-f.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/abstract
+ LCOV - lcov.info - abstract/RuleAddressSet
@@ -19,7 +19,7 @@
diff --git a/doc/coverage/coverage/validation/abstract/index-sort-l.html b/doc/coverage/coverage/abstract/RuleAddressSet/index-sort-l.html
similarity index 74%
rename from doc/coverage/coverage/validation/abstract/index-sort-l.html
rename to doc/coverage/coverage/abstract/RuleAddressSet/index-sort-l.html
index f752721..2a0de5c 100644
--- a/doc/coverage/coverage/validation/abstract/index-sort-l.html
+++ b/doc/coverage/coverage/abstract/RuleAddressSet/index-sort-l.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/abstract
+ LCOV - lcov.info - abstract/RuleAddressSet
@@ -19,7 +19,7 @@
diff --git a/doc/coverage/coverage/validation/abstract/index.html b/doc/coverage/coverage/abstract/RuleAddressSet/index.html
similarity index 74%
rename from doc/coverage/coverage/validation/abstract/index.html
rename to doc/coverage/coverage/abstract/RuleAddressSet/index.html
index 34817f4..9eb35f0 100644
--- a/doc/coverage/coverage/validation/abstract/index.html
+++ b/doc/coverage/coverage/abstract/RuleAddressSet/index.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/abstract
+ LCOV - lcov.info - abstract/RuleAddressSet
@@ -19,7 +19,7 @@
diff --git a/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.func-sort-c.html b/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.func-sort-c.html
new file mode 100644
index 0000000..d226506
--- /dev/null
+++ b/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.func-sort-c.html
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/RuleERC2980/RuleERC2980Internal.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.func.html b/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.func.html
new file mode 100644
index 0000000..446e1ca
--- /dev/null
+++ b/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.func.html
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/RuleERC2980/RuleERC2980Internal.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.gcov.html b/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.gcov.html
new file mode 100644
index 0000000..324d892
--- /dev/null
+++ b/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.gcov.html
@@ -0,0 +1,205 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/RuleERC2980/RuleERC2980Internal.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/RuleERC2980/index-sort-b.html b/doc/coverage/coverage/abstract/RuleERC2980/index-sort-b.html
new file mode 100644
index 0000000..446dbb6
--- /dev/null
+++ b/doc/coverage/coverage/abstract/RuleERC2980/index-sort-b.html
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/RuleERC2980
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filename
+ Line Coverage
+ Functions
+ Branches
+
+
+ RuleERC2980Internal.sol
+
+
+
+ 100.0 %
+ 36 / 36
+ 100.0 %
+ 12 / 12
+ 100.0 %
+ 8 / 8
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/RuleERC2980/index-sort-f.html b/doc/coverage/coverage/abstract/RuleERC2980/index-sort-f.html
new file mode 100644
index 0000000..774722e
--- /dev/null
+++ b/doc/coverage/coverage/abstract/RuleERC2980/index-sort-f.html
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/RuleERC2980
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filename
+ Line Coverage
+ Functions
+ Branches
+
+
+ RuleERC2980Internal.sol
+
+
+
+ 100.0 %
+ 36 / 36
+ 100.0 %
+ 12 / 12
+ 100.0 %
+ 8 / 8
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/RuleERC2980/index-sort-l.html b/doc/coverage/coverage/abstract/RuleERC2980/index-sort-l.html
new file mode 100644
index 0000000..c94493f
--- /dev/null
+++ b/doc/coverage/coverage/abstract/RuleERC2980/index-sort-l.html
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/RuleERC2980
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filename
+ Line Coverage
+ Functions
+ Branches
+
+
+ RuleERC2980Internal.sol
+
+
+
+ 100.0 %
+ 36 / 36
+ 100.0 %
+ 12 / 12
+ 100.0 %
+ 8 / 8
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/RuleERC2980/index.html b/doc/coverage/coverage/abstract/RuleERC2980/index.html
new file mode 100644
index 0000000..07b52e2
--- /dev/null
+++ b/doc/coverage/coverage/abstract/RuleERC2980/index.html
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/RuleERC2980
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filename
+ Line Coverage
+ Functions
+ Branches
+
+
+ RuleERC2980Internal.sol
+
+
+
+ 100.0 %
+ 36 / 36
+ 100.0 %
+ 12 / 12
+ 100.0 %
+ 8 / 8
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.func-sort-c.html b/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.func-sort-c.html
new file mode 100644
index 0000000..72252b1
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.func-sort-c.html
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleBlacklistBase.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.func.html b/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.func.html
new file mode 100644
index 0000000..44a9b55
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.func.html
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleBlacklistBase.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.gcov.html b/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.gcov.html
new file mode 100644
index 0000000..a3fe955
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.gcov.html
@@ -0,0 +1,210 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleBlacklistBase.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Branch data Line data Source code
+
+ 1 : : // SPDX-License-Identifier: MPL-2.0
+ 2 : : pragma solidity ^0.8.20;
+ 3 : :
+ 4 : : import {RuleAddressSet} from "../RuleAddressSet/RuleAddressSet.sol";
+ 5 : : import {RuleNFTAdapter} from "../core/RuleNFTAdapter.sol";
+ 6 : : import {RuleTransferValidation} from "../core/RuleTransferValidation.sol";
+ 7 : : import {RuleBlacklistInvariantStorage} from "../RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol";
+ 8 : : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+ 9 : : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+ 10 : : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+ 11 : : import {IRule} from "RuleEngine/interfaces/IRule.sol";
+ 12 : :
+ 13 : : /**
+ 14 : : * @title RuleBlacklistBase
+ 15 : : * @notice Core blacklist logic without access-control policy.
+ 16 : : */
+ 17 : : abstract contract RuleBlacklistBase is RuleAddressSet, RuleNFTAdapter, RuleBlacklistInvariantStorage {
+ 18 : : constructor(address forwarderIrrevocable) RuleAddressSet(forwarderIrrevocable) {}
+ 19 : :
+ 20 : 106 : function _detectTransferRestriction(address from, address to, uint256 /* value */ )
+ 21 : : internal
+ 22 : : view
+ 23 : : override
+ 24 : : returns (uint8)
+ 25 : : {
+ 26 [ + + ]: 106 : if (isAddressListed(from)) {
+ 27 : 23 : return CODE_ADDRESS_FROM_IS_BLACKLISTED;
+ 28 [ + ]: 83 : } else if (isAddressListed(to)) {
+ 29 : 19 : return CODE_ADDRESS_TO_IS_BLACKLISTED;
+ 30 : : }
+ 31 : 64 : return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 32 : : }
+ 33 : :
+ 34 : 22 : function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+ 35 : : internal
+ 36 : : view
+ 37 : : override
+ 38 : : returns (uint8)
+ 39 : : {
+ 40 [ + ]: 22 : if (isAddressListed(spender)) {
+ 41 : 8 : return CODE_ADDRESS_SPENDER_IS_BLACKLISTED;
+ 42 : : }
+ 43 : 14 : return _detectTransferRestriction(from, to, value);
+ 44 : : }
+ 45 : :
+ 46 : 4 : function canReturnTransferRestrictionCode(uint8 restrictionCode)
+ 47 : : public
+ 48 : : pure
+ 49 : : virtual
+ 50 : : override(IRule)
+ 51 : : returns (bool)
+ 52 : : {
+ 53 : 4 : return restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED || restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED
+ 54 : 1 : || restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED;
+ 55 : : }
+ 56 : :
+ 57 : 12 : function messageForTransferRestriction(uint8 restrictionCode)
+ 58 : : public
+ 59 : : pure
+ 60 : : virtual
+ 61 : : override(IERC1404)
+ 62 : : returns (string memory)
+ 63 : : {
+ 64 [ + + ]: 12 : if (restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED) {
+ 65 : 5 : return TEXT_ADDRESS_FROM_IS_BLACKLISTED;
+ 66 [ + + ]: 7 : } else if (restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED) {
+ 67 : 3 : return TEXT_ADDRESS_TO_IS_BLACKLISTED;
+ 68 [ + + ]: 4 : } else if (restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED) {
+ 69 : 1 : return TEXT_ADDRESS_SPENDER_IS_BLACKLISTED;
+ 70 : : } else {
+ 71 : 3 : return TEXT_CODE_NOT_FOUND;
+ 72 : : }
+ 73 : : }
+ 74 : :
+ 75 : 61 : function supportsInterface(bytes4 interfaceId) public view virtual override(RuleTransferValidation) returns (bool) {
+ 76 : 61 : return RuleTransferValidation.supportsInterface(interfaceId);
+ 77 : : }
+ 78 : :
+ 79 : : /**
+ 80 : : * @inheritdoc IERC3643IComplianceContract
+ 81 : : * @dev Validation only; does not modify state.
+ 82 : : */
+ 83 : 58 : function transferred(address from, address to, uint256 value)
+ 84 : : public
+ 85 : : view
+ 86 : : virtual
+ 87 : : override(IERC3643IComplianceContract)
+ 88 : : {
+ 89 : 58 : _transferred(from, to, value);
+ 90 : : }
+ 91 : :
+ 92 : : /**
+ 93 : : * @inheritdoc IRuleEngine
+ 94 : : * @dev Validation only; does not modify state.
+ 95 : : */
+ 96 : 2 : function transferred(address spender, address from, address to, uint256 value)
+ 97 : : public
+ 98 : : view
+ 99 : : virtual
+ 100 : : override(IRuleEngine)
+ 101 : : {
+ 102 : 2 : _transferredFrom(spender, from, to, value);
+ 103 : : }
+ 104 : :
+ 105 : 61 : function _transferred(address from, address to, uint256 value) internal view virtual override {
+ 106 : 61 : uint8 code = _detectTransferRestriction(from, to, value);
+ 107 [ + + ]: 61 : require(
+ 108 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+ 109 : : RuleBlacklist_InvalidTransfer(address(this), from, to, value, code)
+ 110 : : );
+ 111 : : }
+ 112 : :
+ 113 : 4 : function _transferredFrom(address spender, address from, address to, uint256 value)
+ 114 : : internal
+ 115 : : view
+ 116 : : virtual
+ 117 : : override
+ 118 : : {
+ 119 : 4 : uint8 code = _detectTransferRestrictionFrom(spender, from, to, value);
+ 120 [ + + ]: 4 : require(
+ 121 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+ 122 : : RuleBlacklist_InvalidTransferFrom(address(this), spender, from, to, value, code)
+ 123 : : );
+ 124 : : }
+ 125 : : }
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.func-sort-c.html b/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.func-sort-c.html
new file mode 100644
index 0000000..b58d1b5
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.func-sort-c.html
@@ -0,0 +1,213 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleERC2980Base.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.func.html b/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.func.html
new file mode 100644
index 0000000..fa4bcca
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.func.html
@@ -0,0 +1,213 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleERC2980Base.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.gcov.html b/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.gcov.html
new file mode 100644
index 0000000..89784e8
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.gcov.html
@@ -0,0 +1,473 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleERC2980Base.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Branch data Line data Source code
+
+ 1 : : // SPDX-License-Identifier: MPL-2.0
+ 2 : : pragma solidity ^0.8.20;
+ 3 : :
+ 4 : : import {MetaTxModuleStandalone, ERC2771Context} from "../../../../modules/MetaTxModuleStandalone.sol";
+ 5 : : import {RuleERC2980Internal} from "../RuleERC2980/RuleERC2980Internal.sol";
+ 6 : : import {RuleERC2980InvariantStorage} from "../RuleERC2980/invariantStorage/RuleERC2980InvariantStorage.sol";
+ 7 : : import {RuleNFTAdapter} from "../core/RuleNFTAdapter.sol";
+ 8 : : import {RuleTransferValidation} from "../core/RuleTransferValidation.sol";
+ 9 : : /* ==== Interfaces === */
+ 10 : : import {IERC2980} from "../../../interfaces/IERC2980.sol";
+ 11 : : import {IIdentityRegistryVerified} from "../../../interfaces/IIdentityRegistry.sol";
+ 12 : : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+ 13 : : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+ 14 : : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+ 15 : : import {IRule} from "RuleEngine/interfaces/IRule.sol";
+ 16 : :
+ 17 : : /**
+ 18 : : * @title RuleERC2980Base
+ 19 : : * @notice Core ERC-2980 Swiss Compliant transfer restriction logic combining a whitelist and a frozenlist.
+ 20 : : * @dev
+ 21 : : * Transfer logic (frozenlist takes priority over whitelist):
+ 22 : : * 1. If `from`, `to`, or `spender` is frozen → transfer is blocked.
+ 23 : : * 2. If `to` is not whitelisted → transfer is blocked.
+ 24 : : * Note: `from` does NOT need to be whitelisted to send tokens it already holds.
+ 25 : : *
+ 26 : : * Provides public management functions for both lists with abstract authorization hooks
+ 27 : : * so concrete subclasses can plug in their preferred access-control mechanism.
+ 28 : : */
+ 29 : : abstract contract RuleERC2980Base is
+ 30 : : MetaTxModuleStandalone,
+ 31 : : RuleERC2980Internal,
+ 32 : : RuleERC2980InvariantStorage,
+ 33 : : RuleNFTAdapter,
+ 34 : : IERC2980,
+ 35 : : IIdentityRegistryVerified
+ 36 : : {
+ 37 : : /*//////////////////////////////////////////////////////////////
+ 38 : : CONSTRUCTOR
+ 39 : : //////////////////////////////////////////////////////////////*/
+ 40 : :
+ 41 : : constructor(address forwarderIrrevocable) MetaTxModuleStandalone(forwarderIrrevocable) {}
+ 42 : :
+ 43 : : /*//////////////////////////////////////////////////////////////
+ 44 : : TRANSFER RESTRICTION LOGIC
+ 45 : : //////////////////////////////////////////////////////////////*/
+ 46 : :
+ 47 : 22 : function _detectTransferRestriction(address from, address to, uint256 /* value */ )
+ 48 : : internal
+ 49 : : view
+ 50 : : virtual
+ 51 : : override
+ 52 : : returns (uint8)
+ 53 : : {
+ 54 : : // Frozenlist check has priority
+ 55 [ + + ]: 22 : if (_isFrozen(from)) {
+ 56 : 4 : return CODE_ADDRESS_FROM_IS_FROZEN;
+ 57 [ + ]: 18 : } else if (_isFrozen(to)) {
+ 58 : 4 : return CODE_ADDRESS_TO_IS_FROZEN;
+ 59 : : }
+ 60 : : // Whitelist check: only the recipient must be whitelisted
+ 61 [ + ]: 14 : if (!_isWhitelisted(to)) {
+ 62 : 4 : return CODE_ADDRESS_TO_NOT_WHITELISTED;
+ 63 : : }
+ 64 : 10 : return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 65 : : }
+ 66 : :
+ 67 : 8 : function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+ 68 : : internal
+ 69 : : view
+ 70 : : virtual
+ 71 : : override
+ 72 : : returns (uint8)
+ 73 : : {
+ 74 [ + ]: 8 : if (_isFrozen(spender)) {
+ 75 : 4 : return CODE_ADDRESS_SPENDER_IS_FROZEN;
+ 76 : : }
+ 77 : 4 : return _detectTransferRestriction(from, to, value);
+ 78 : : }
+ 79 : :
+ 80 : : /*//////////////////////////////////////////////////////////////
+ 81 : : ERC-3643 / IRuleEngine HOOKS
+ 82 : : //////////////////////////////////////////////////////////////*/
+ 83 : :
+ 84 : 4 : function transferred(address from, address to, uint256 value)
+ 85 : : public
+ 86 : : view
+ 87 : : virtual
+ 88 : : override(IERC3643IComplianceContract)
+ 89 : : {
+ 90 : 4 : _transferred(from, to, value);
+ 91 : : }
+ 92 : :
+ 93 : 2 : function transferred(address spender, address from, address to, uint256 value)
+ 94 : : public
+ 95 : : view
+ 96 : : virtual
+ 97 : : override(IRuleEngine)
+ 98 : : {
+ 99 : 2 : _transferredFrom(spender, from, to, value);
+ 100 : : }
+ 101 : :
+ 102 : 5 : function _transferred(address from, address to, uint256 value) internal view virtual override {
+ 103 : 5 : uint8 code = _detectTransferRestriction(from, to, value);
+ 104 [ + + ]: 5 : require(
+ 105 : : code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+ 106 : : RuleERC2980_InvalidTransfer(address(this), from, to, value, code)
+ 107 : : );
+ 108 : : }
+ 109 : :
+ 110 : 3 : function _transferredFrom(address spender, address from, address to, uint256 value)
+ 111 : : internal
+ 112 : : view
+ 113 : : virtual
+ 114 : : override
+ 115 : : {
+ 116 : 3 : uint8 code = _detectTransferRestrictionFrom(spender, from, to, value);
+ 117 [ + + ]: 3 : require(
+ 118 : : code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+ 119 : : RuleERC2980_InvalidTransferFrom(address(this), spender, from, to, value, code)
+ 120 : : );
+ 121 : : }
+ 122 : :
+ 123 : : /*//////////////////////////////////////////////////////////////
+ 124 : : RESTRICTION CODE HELPERS
+ 125 : : //////////////////////////////////////////////////////////////*/
+ 126 : :
+ 127 : 5 : function canReturnTransferRestrictionCode(uint8 restrictionCode)
+ 128 : : public
+ 129 : : pure
+ 130 : : virtual
+ 131 : : override(IRule)
+ 132 : : returns (bool)
+ 133 : : {
+ 134 : 5 : return restrictionCode == CODE_ADDRESS_FROM_IS_FROZEN || restrictionCode == CODE_ADDRESS_TO_IS_FROZEN
+ 135 : 3 : || restrictionCode == CODE_ADDRESS_SPENDER_IS_FROZEN
+ 136 : 2 : || restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED;
+ 137 : : }
+ 138 : :
+ 139 : 5 : function messageForTransferRestriction(uint8 restrictionCode)
+ 140 : : public
+ 141 : : pure
+ 142 : : virtual
+ 143 : : override(IERC1404)
+ 144 : : returns (string memory)
+ 145 : : {
+ 146 [ + + ]: 5 : if (restrictionCode == CODE_ADDRESS_FROM_IS_FROZEN) {
+ 147 : 1 : return TEXT_ADDRESS_FROM_IS_FROZEN;
+ 148 [ + + ]: 4 : } else if (restrictionCode == CODE_ADDRESS_TO_IS_FROZEN) {
+ 149 : 1 : return TEXT_ADDRESS_TO_IS_FROZEN;
+ 150 [ + + ]: 3 : } else if (restrictionCode == CODE_ADDRESS_SPENDER_IS_FROZEN) {
+ 151 : 1 : return TEXT_ADDRESS_SPENDER_IS_FROZEN;
+ 152 [ + + ]: 2 : } else if (restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) {
+ 153 : 1 : return TEXT_ADDRESS_TO_NOT_WHITELISTED;
+ 154 : : } else {
+ 155 : 1 : return TEXT_CODE_NOT_FOUND;
+ 156 : : }
+ 157 : : }
+ 158 : :
+ 159 : : /*//////////////////////////////////////////////////////////////
+ 160 : : WHITELIST MANAGEMENT
+ 161 : : //////////////////////////////////////////////////////////////*/
+ 162 : :
+ 163 : : /**
+ 164 : : * @notice Adds multiple addresses to the whitelist.
+ 165 : : * @dev Does not revert if an address is already listed.
+ 166 : : */
+ 167 : 6 : function addWhitelistAddresses(address[] calldata targetAddresses) public onlyWhitelistAdd {
+ 168 : 4 : _addWhitelistAddresses(targetAddresses);
+ 169 : 4 : emit AddWhitelistAddresses(targetAddresses);
+ 170 : : }
+ 171 : :
+ 172 : : /**
+ 173 : : * @notice Removes multiple addresses from the whitelist.
+ 174 : : * @dev Does not revert if an address is not listed.
+ 175 : : */
+ 176 : 4 : function removeWhitelistAddresses(address[] calldata targetAddresses) public onlyWhitelistRemove {
+ 177 : 3 : _removeWhitelistAddresses(targetAddresses);
+ 178 : 3 : emit RemoveWhitelistAddresses(targetAddresses);
+ 179 : : }
+ 180 : :
+ 181 : : /**
+ 182 : : * @notice Adds a single address to the whitelist.
+ 183 : : * @dev
+ 184 : : * Reverts if the address is already listed.
+ 185 : : * Deviation from ERC-2980 `Whitelistable` example interface: the spec's `addAddressToWhitelist`
+ 186 : : * returns `false` on duplicates instead of reverting. This implementation follows the codebase
+ 187 : : * convention of reverting on invalid single-item operations.
+ 188 : : */
+ 189 : 43 : function addWhitelistAddress(address targetAddress) public onlyWhitelistAdd {
+ 190 [ + + ]: 40 : require(!_isWhitelisted(targetAddress), RuleERC2980_AddressAlreadyListed());
+ 191 : 39 : _addWhitelistAddress(targetAddress);
+ 192 : 39 : emit AddWhitelistAddress(targetAddress);
+ 193 : : }
+ 194 : :
+ 195 : : /**
+ 196 : : * @notice Removes a single address from the whitelist.
+ 197 : : * @dev
+ 198 : : * Reverts if the address is not listed.
+ 199 : : * Deviation from ERC-2980 `Whitelistable` example interface: the spec's `removeAddressFromWhitelist`
+ 200 : : * returns `false` when not found instead of reverting. This implementation follows the codebase
+ 201 : : * convention of reverting on invalid single-item operations.
+ 202 : : */
+ 203 : 7 : function removeWhitelistAddress(address targetAddress) public onlyWhitelistRemove {
+ 204 [ + + ]: 5 : require(_isWhitelisted(targetAddress), RuleERC2980_AddressNotFound());
+ 205 : 4 : _removeWhitelistAddress(targetAddress);
+ 206 : 4 : emit RemoveWhitelistAddress(targetAddress);
+ 207 : : }
+ 208 : :
+ 209 : : /**
+ 210 : : * @notice Returns the number of whitelisted addresses.
+ 211 : : */
+ 212 : 5 : function whitelistAddressCount() public view returns (uint256) {
+ 213 : 5 : return _whitelistCount();
+ 214 : : }
+ 215 : :
+ 216 : : /**
+ 217 : : * @notice Returns true if the address is in the whitelist.
+ 218 : : */
+ 219 : 13 : function isWhitelisted(address targetAddress) public view returns (bool) {
+ 220 : 13 : return _isWhitelisted(targetAddress);
+ 221 : : }
+ 222 : :
+ 223 : : /**
+ 224 : : * @notice ERC-2980 getter: returns true if the address is whitelisted.
+ 225 : : */
+ 226 : 5 : function whitelist(address _operator) public view virtual override(IERC2980) returns (bool) {
+ 227 : 5 : return _isWhitelisted(_operator);
+ 228 : : }
+ 229 : :
+ 230 : : /**
+ 231 : : * @notice Returns true if the address is whitelisted (identity-verified).
+ 232 : : * @dev Reflects whitelist membership only. Frozen status is intentionally excluded:
+ 233 : : * freezing is a temporary enforcement action and does not revoke identity verification.
+ 234 : : */
+ 235 : 3 : function isVerified(address targetAddress)
+ 236 : : public
+ 237 : : view
+ 238 : : virtual
+ 239 : : override(IIdentityRegistryVerified)
+ 240 : : returns (bool)
+ 241 : : {
+ 242 : 3 : return _isWhitelisted(targetAddress);
+ 243 : : }
+ 244 : :
+ 245 : : /**
+ 246 : : * @notice Checks multiple addresses for whitelist membership.
+ 247 : : */
+ 248 : 1 : function areWhitelisted(address[] memory targetAddresses) public view returns (bool[] memory results) {
+ 249 : 1 : results = new bool[](targetAddresses.length);
+ 250 : 1 : for (uint256 i = 0; i < targetAddresses.length; ++i) {
+ 251 : 2 : results[i] = _isWhitelisted(targetAddresses[i]);
+ 252 : : }
+ 253 : : }
+ 254 : :
+ 255 : : /*//////////////////////////////////////////////////////////////
+ 256 : : FROZENLIST MANAGEMENT
+ 257 : : //////////////////////////////////////////////////////////////*/
+ 258 : :
+ 259 : : /**
+ 260 : : * @notice Adds multiple addresses to the frozenlist.
+ 261 : : * @dev Does not revert if an address is already listed.
+ 262 : : */
+ 263 : 6 : function addFrozenlistAddresses(address[] calldata targetAddresses) public onlyFrozenlistAdd {
+ 264 : 4 : _addFrozenlistAddresses(targetAddresses);
+ 265 : 4 : emit AddFrozenlistAddresses(targetAddresses);
+ 266 : : }
+ 267 : :
+ 268 : : /**
+ 269 : : * @notice Removes multiple addresses from the frozenlist.
+ 270 : : * @dev Does not revert if an address is not listed.
+ 271 : : */
+ 272 : 2 : function removeFrozenlistAddresses(address[] calldata targetAddresses) public onlyFrozenlistRemove {
+ 273 : 2 : _removeFrozenlistAddresses(targetAddresses);
+ 274 : 2 : emit RemoveFrozenlistAddresses(targetAddresses);
+ 275 : : }
+ 276 : :
+ 277 : : /**
+ 278 : : * @notice Adds a single address to the frozenlist.
+ 279 : : * @dev
+ 280 : : * Reverts if the address is already listed.
+ 281 : : * Deviation from ERC-2980 `Freezable` example interface: the spec's `addAddressToFrozenlist`
+ 282 : : * returns `false` on duplicates instead of reverting. This implementation follows the codebase
+ 283 : : * convention of reverting on invalid single-item operations.
+ 284 : : */
+ 285 : 22 : function addFrozenlistAddress(address targetAddress) public onlyFrozenlistAdd {
+ 286 [ + + ]: 19 : require(!_isFrozen(targetAddress), RuleERC2980_AddressAlreadyListed());
+ 287 : 18 : _addFrozenlistAddress(targetAddress);
+ 288 : 18 : emit AddFrozenlistAddress(targetAddress);
+ 289 : : }
+ 290 : :
+ 291 : : /**
+ 292 : : * @notice Removes a single address from the frozenlist.
+ 293 : : * @dev
+ 294 : : * Reverts if the address is not listed.
+ 295 : : * Deviation from ERC-2980 `Freezable` example interface: the spec's `removeAddressFromFrozenlist`
+ 296 : : * returns `false` when not found instead of reverting. This implementation follows the codebase
+ 297 : : * convention of reverting on invalid single-item operations.
+ 298 : : */
+ 299 : 7 : function removeFrozenlistAddress(address targetAddress) public onlyFrozenlistRemove {
+ 300 [ + + ]: 5 : require(_isFrozen(targetAddress), RuleERC2980_AddressNotFound());
+ 301 : 4 : _removeFrozenlistAddress(targetAddress);
+ 302 : 4 : emit RemoveFrozenlistAddress(targetAddress);
+ 303 : : }
+ 304 : :
+ 305 : : /**
+ 306 : : * @notice Returns the number of frozen addresses.
+ 307 : : */
+ 308 : 4 : function frozenlistAddressCount() public view returns (uint256) {
+ 309 : 4 : return _frozenlistCount();
+ 310 : : }
+ 311 : :
+ 312 : : /**
+ 313 : : * @notice Returns true if the address is in the frozenlist.
+ 314 : : */
+ 315 : 12 : function isFrozen(address targetAddress) public view returns (bool) {
+ 316 : 12 : return _isFrozen(targetAddress);
+ 317 : : }
+ 318 : :
+ 319 : : /**
+ 320 : : * @notice ERC-2980 getter: returns true if the address is frozen.
+ 321 : : */
+ 322 : 4 : function frozenlist(address _operator) public view virtual override(IERC2980) returns (bool) {
+ 323 : 4 : return _isFrozen(_operator);
+ 324 : : }
+ 325 : :
+ 326 : : /**
+ 327 : : * @notice Checks multiple addresses for frozenlist membership.
+ 328 : : */
+ 329 : 1 : function areFrozen(address[] memory targetAddresses) public view returns (bool[] memory results) {
+ 330 : 1 : results = new bool[](targetAddresses.length);
+ 331 : 1 : for (uint256 i = 0; i < targetAddresses.length; ++i) {
+ 332 : 2 : results[i] = _isFrozen(targetAddresses[i]);
+ 333 : : }
+ 334 : : }
+ 335 : :
+ 336 : : /*//////////////////////////////////////////////////////////////
+ 337 : : INTERFACE SUPPORT
+ 338 : : //////////////////////////////////////////////////////////////*/
+ 339 : :
+ 340 : 1 : function supportsInterface(bytes4 interfaceId) public view virtual override(RuleTransferValidation) returns (bool) {
+ 341 : 1 : return RuleTransferValidation.supportsInterface(interfaceId);
+ 342 : : }
+ 343 : :
+ 344 : : /*//////////////////////////////////////////////////////////////
+ 345 : : ACCESS CONTROL
+ 346 : : //////////////////////////////////////////////////////////////*/
+ 347 : :
+ 348 : 6 : modifier onlyWhitelistAdd() {
+ 349 : 6 : _authorizeWhitelistAdd();
+ 350 : : _;
+ 351 : : }
+ 352 : :
+ 353 : 7 : modifier onlyWhitelistRemove() {
+ 354 : 7 : _authorizeWhitelistRemove();
+ 355 : : _;
+ 356 : : }
+ 357 : :
+ 358 : 6 : modifier onlyFrozenlistAdd() {
+ 359 : 6 : _authorizeFrozenlistAdd();
+ 360 : : _;
+ 361 : : }
+ 362 : :
+ 363 : 2 : modifier onlyFrozenlistRemove() {
+ 364 : 2 : _authorizeFrozenlistRemove();
+ 365 : : _;
+ 366 : : }
+ 367 : :
+ 368 : : function _authorizeWhitelistAdd() internal view virtual;
+ 369 : : function _authorizeWhitelistRemove() internal view virtual;
+ 370 : : function _authorizeFrozenlistAdd() internal view virtual;
+ 371 : : function _authorizeFrozenlistRemove() internal view virtual;
+ 372 : :
+ 373 : : /*//////////////////////////////////////////////////////////////
+ 374 : : ERC-2771 META TX
+ 375 : : //////////////////////////////////////////////////////////////*/
+ 376 : :
+ 377 : 267 : function _msgSender() internal view virtual override(ERC2771Context) returns (address sender) {
+ 378 : 267 : return ERC2771Context._msgSender();
+ 379 : : }
+ 380 : :
+ 381 : 2 : function _msgData() internal view virtual override(ERC2771Context) returns (bytes calldata) {
+ 382 : 2 : return ERC2771Context._msgData();
+ 383 : : }
+ 384 : :
+ 385 : 269 : function _contextSuffixLength() internal view virtual override(ERC2771Context) returns (uint256) {
+ 386 : 269 : return ERC2771Context._contextSuffixLength();
+ 387 : : }
+ 388 : : }
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.func-sort-c.html b/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.func-sort-c.html
new file mode 100644
index 0000000..2aa4d9c
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.func-sort-c.html
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleIdentityRegistryBase.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.func.html b/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.func.html
new file mode 100644
index 0000000..9fdf83a
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.func.html
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleIdentityRegistryBase.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.gcov.html b/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.gcov.html
new file mode 100644
index 0000000..a9ee475
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.gcov.html
@@ -0,0 +1,229 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleIdentityRegistryBase.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Branch data Line data Source code
+
+ 1 : : // SPDX-License-Identifier: MPL-2.0
+ 2 : : pragma solidity ^0.8.20;
+ 3 : :
+ 4 : : import {RuleNFTAdapter} from "../core/RuleNFTAdapter.sol";
+ 5 : : import {RuleIdentityRegistryInvariantStorage} from "../invariant/RuleIdentityRegistryInvariantStorage.sol";
+ 6 : : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+ 7 : : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+ 8 : : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+ 9 : : import {IIdentityRegistryVerified} from "../../../interfaces/IIdentityRegistry.sol";
+ 10 : :
+ 11 : : /**
+ 12 : : * @title RuleIdentityRegistryBase
+ 13 : : * @notice Checks the ERC-3643 Identity Registry for transfer participants when configured.
+ 14 : : * @dev Burns (to == address(0)) are allowed even if the sender is not verified.
+ 15 : : */
+ 16 : : abstract contract RuleIdentityRegistryBase is RuleNFTAdapter, RuleIdentityRegistryInvariantStorage {
+ 17 : : IIdentityRegistryVerified public identityRegistry;
+ 18 : :
+ 19 : 26 : constructor(address identityRegistry_) {
+ 20 [ + ]: 26 : if (identityRegistry_ != address(0)) {
+ 21 : 25 : identityRegistry = IIdentityRegistryVerified(identityRegistry_);
+ 22 : : }
+ 23 : : }
+ 24 : :
+ 25 : 4 : function setIdentityRegistry(address newRegistry) public onlyIdentityRegistryManager {
+ 26 [ + + ]: 2 : require(newRegistry != address(0), RuleIdentityRegistry_RegistryAddressZeroNotAllowed());
+ 27 : 1 : identityRegistry = IIdentityRegistryVerified(newRegistry);
+ 28 : 1 : emit IdentityRegistryUpdated(newRegistry);
+ 29 : : }
+ 30 : :
+ 31 : 5 : function clearIdentityRegistry() public onlyIdentityRegistryManager {
+ 32 : 3 : identityRegistry = IIdentityRegistryVerified(address(0));
+ 33 : 3 : emit IdentityRegistryUpdated(address(0));
+ 34 : : }
+ 35 : :
+ 36 : 16 : function _detectTransferRestriction(address from, address to, uint256 /* value */)
+ 37 : : internal
+ 38 : : view
+ 39 : : override
+ 40 : : returns (uint8)
+ 41 : : {
+ 42 [ + ]: 16 : if (address(identityRegistry) == address(0)) {
+ 43 : 3 : return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 44 : : }
+ 45 [ + ]: 13 : if (to == address(0)) {
+ 46 : 2 : return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 47 : : }
+ 48 : :
+ 49 [ + ]: 11 : if (from != address(0) && !identityRegistry.isVerified(from)) {
+ 50 : 4 : return CODE_ADDRESS_FROM_NOT_VERIFIED;
+ 51 : : }
+ 52 [ + ]: 7 : if (to != address(0) && !identityRegistry.isVerified(to)) {
+ 53 : 1 : return CODE_ADDRESS_TO_NOT_VERIFIED;
+ 54 : : }
+ 55 : 6 : return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 56 : : }
+ 57 : :
+ 58 : 9 : function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+ 59 : : internal
+ 60 : : view
+ 61 : : override
+ 62 : : returns (uint8)
+ 63 : : {
+ 64 [ + ]: 9 : if (address(identityRegistry) == address(0)) {
+ 65 : 1 : return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 66 : : }
+ 67 [ + ]: 8 : if (to == address(0)) {
+ 68 : 1 : return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 69 : : }
+ 70 [ + ]: 7 : if (spender != address(0) && !identityRegistry.isVerified(spender)) {
+ 71 : 4 : return CODE_ADDRESS_SPENDER_NOT_VERIFIED;
+ 72 : : }
+ 73 : 3 : return _detectTransferRestriction(from, to, value);
+ 74 : : }
+ 75 : :
+ 76 : 2 : function transferred(address from, address to, uint256 value)
+ 77 : : public
+ 78 : : view
+ 79 : : override(IERC3643IComplianceContract)
+ 80 : : {
+ 81 : 2 : _transferred(from, to, value);
+ 82 : : }
+ 83 : :
+ 84 : 2 : function transferred(address spender, address from, address to, uint256 value)
+ 85 : : public
+ 86 : : view
+ 87 : : override(IRuleEngine)
+ 88 : : {
+ 89 : 2 : _transferredFrom(spender, from, to, value);
+ 90 : : }
+ 91 : :
+ 92 : 2 : function _transferred(address from, address to, uint256 value) internal view virtual override {
+ 93 : 2 : uint8 code = _detectTransferRestriction(from, to, value);
+ 94 [ + + ]: 2 : require(
+ 95 : : code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+ 96 : : RuleIdentityRegistry_InvalidTransfer(address(this), from, to, value, code)
+ 97 : : );
+ 98 : : }
+ 99 : :
+ 100 : 2 : function _transferredFrom(address spender, address from, address to, uint256 value)
+ 101 : : internal
+ 102 : : view
+ 103 : : virtual
+ 104 : : override
+ 105 : : {
+ 106 : 2 : uint8 code = _detectTransferRestrictionFrom(spender, from, to, value);
+ 107 [ + + ]: 2 : require(
+ 108 : : code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+ 109 : : RuleIdentityRegistry_InvalidTransferFrom(address(this), spender, from, to, value, code)
+ 110 : : );
+ 111 : : }
+ 112 : :
+ 113 : 4 : function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override returns (bool) {
+ 114 : 4 : return restrictionCode == CODE_ADDRESS_FROM_NOT_VERIFIED || restrictionCode == CODE_ADDRESS_TO_NOT_VERIFIED
+ 115 : 2 : || restrictionCode == CODE_ADDRESS_SPENDER_NOT_VERIFIED;
+ 116 : : }
+ 117 : :
+ 118 : 4 : function messageForTransferRestriction(uint8 restrictionCode)
+ 119 : : public
+ 120 : : pure
+ 121 : : override(IERC1404)
+ 122 : : returns (string memory)
+ 123 : : {
+ 124 [ + + ]: 4 : if (restrictionCode == CODE_ADDRESS_FROM_NOT_VERIFIED) {
+ 125 : 1 : return TEXT_ADDRESS_FROM_NOT_VERIFIED;
+ 126 [ + + ]: 3 : } else if (restrictionCode == CODE_ADDRESS_TO_NOT_VERIFIED) {
+ 127 : 1 : return TEXT_ADDRESS_TO_NOT_VERIFIED;
+ 128 [ + ]: 2 : } else if (restrictionCode == CODE_ADDRESS_SPENDER_NOT_VERIFIED) {
+ 129 : 1 : return TEXT_ADDRESS_SPENDER_NOT_VERIFIED;
+ 130 : : }
+ 131 : 1 : return TEXT_CODE_NOT_FOUND;
+ 132 : : }
+ 133 : :
+ 134 : : /*//////////////////////////////////////////////////////////////
+ 135 : : ACCESS CONTROL
+ 136 : : //////////////////////////////////////////////////////////////*/
+ 137 : :
+ 138 : 5 : modifier onlyIdentityRegistryManager() {
+ 139 : 5 : _authorizeIdentityRegistryManager();
+ 140 : : _;
+ 141 : : }
+ 142 : :
+ 143 : : function _authorizeIdentityRegistryManager() internal view virtual;
+ 144 : : }
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.func-sort-c.html b/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.func-sort-c.html
new file mode 100644
index 0000000..b09fc06
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.func-sort-c.html
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleMaxTotalSupplyBase.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.func.html b/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.func.html
new file mode 100644
index 0000000..d697da8
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.func.html
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleMaxTotalSupplyBase.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.gcov.html b/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.gcov.html
new file mode 100644
index 0000000..d9659ad
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.gcov.html
@@ -0,0 +1,204 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleMaxTotalSupplyBase.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Branch data Line data Source code
+
+ 1 : : // SPDX-License-Identifier: MPL-2.0
+ 2 : : pragma solidity ^0.8.20;
+ 3 : :
+ 4 : : import {RuleMaxTotalSupplyInvariantStorage} from "../invariant/RuleMaxTotalSupplyInvariantStorage.sol";
+ 5 : : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+ 6 : : import {ITotalSupply} from "../../../interfaces/ITotalSupply.sol";
+ 7 : : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+ 8 : : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+ 9 : : import {RuleTransferValidation} from "../core/RuleTransferValidation.sol";
+ 10 : :
+ 11 : : /**
+ 12 : : * @title RuleMaxTotalSupplyBase
+ 13 : : * @notice Restricts minting so that total supply never exceeds a maximum value.
+ 14 : : */
+ 15 : : abstract contract RuleMaxTotalSupplyBase is RuleTransferValidation, RuleMaxTotalSupplyInvariantStorage {
+ 16 : : /// @dev tokenContract is trusted to return a correct totalSupply.
+ 17 : : ITotalSupply public tokenContract;
+ 18 : : uint256 public maxTotalSupply;
+ 19 : :
+ 20 : 25 : constructor(address tokenContract_, uint256 maxTotalSupply_) {
+ 21 [ + + ]: 25 : require(tokenContract_ != address(0), RuleMaxTotalSupply_TokenAddressZeroNotAllowed());
+ 22 : 24 : tokenContract = ITotalSupply(tokenContract_);
+ 23 : 24 : maxTotalSupply = maxTotalSupply_;
+ 24 : : }
+ 25 : :
+ 26 : 260 : function setMaxTotalSupply(uint256 newMaxTotalSupply) public onlyMaxTotalSupplyManager {
+ 27 : 258 : maxTotalSupply = newMaxTotalSupply;
+ 28 : 258 : emit MaxTotalSupplyUpdated(newMaxTotalSupply);
+ 29 : : }
+ 30 : :
+ 31 : 4 : function setTokenContract(address newTokenContract) public onlyMaxTotalSupplyManager {
+ 32 [ + + ]: 2 : require(newTokenContract != address(0), RuleMaxTotalSupply_TokenAddressZeroNotAllowed());
+ 33 : 1 : tokenContract = ITotalSupply(newTokenContract);
+ 34 : 1 : emit TokenContractUpdated(newTokenContract);
+ 35 : : }
+ 36 : :
+ 37 : 271 : function _detectTransferRestriction(address from, address /* to */, uint256 value)
+ 38 : : internal
+ 39 : : view
+ 40 : : override
+ 41 : : returns (uint8)
+ 42 : : {
+ 43 [ + ]: 271 : if (from == address(0)) {
+ 44 : 268 : uint256 currentSupply = tokenContract.totalSupply();
+ 45 [ + ]: 268 : if (currentSupply + value > maxTotalSupply) {
+ 46 : 179 : return CODE_MAX_TOTAL_SUPPLY_EXCEEDED;
+ 47 : : }
+ 48 : : }
+ 49 : 92 : return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 50 : : }
+ 51 : :
+ 52 : 2 : function _detectTransferRestrictionFrom(address, address from, address to, uint256 value)
+ 53 : : internal
+ 54 : : view
+ 55 : : override
+ 56 : : returns (uint8)
+ 57 : : {
+ 58 : 2 : return _detectTransferRestriction(from, to, value);
+ 59 : : }
+ 60 : :
+ 61 : 2 : function transferred(address from, address to, uint256 value)
+ 62 : : public
+ 63 : : view
+ 64 : : override(IERC3643IComplianceContract)
+ 65 : : {
+ 66 : 2 : _transferred(from, to, value);
+ 67 : : }
+ 68 : :
+ 69 : 2 : function transferred(address spender, address from, address to, uint256 value)
+ 70 : : public
+ 71 : : view
+ 72 : : override(IRuleEngine)
+ 73 : : {
+ 74 : 2 : _transferredFrom(spender, from, to, value);
+ 75 : : }
+ 76 : :
+ 77 : 2 : function _transferred(address from, address to, uint256 value) internal view virtual {
+ 78 : 2 : uint8 code = _detectTransferRestriction(from, to, value);
+ 79 [ + + ]: 2 : require(
+ 80 : : code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+ 81 : : RuleMaxTotalSupply_InvalidTransfer(address(this), from, to, value, code)
+ 82 : : );
+ 83 : : }
+ 84 : :
+ 85 : 2 : function _transferredFrom(address spender, address from, address to, uint256 value) internal view virtual {
+ 86 : 2 : uint8 code = _detectTransferRestrictionFrom(spender, from, to, value);
+ 87 [ + + ]: 2 : require(
+ 88 : : code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+ 89 : : RuleMaxTotalSupply_InvalidTransferFrom(address(this), spender, from, to, value, code)
+ 90 : : );
+ 91 : : }
+ 92 : :
+ 93 : 2 : function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override returns (bool) {
+ 94 : 2 : return restrictionCode == CODE_MAX_TOTAL_SUPPLY_EXCEEDED;
+ 95 : : }
+ 96 : :
+ 97 : 2 : function messageForTransferRestriction(uint8 restrictionCode)
+ 98 : : public
+ 99 : : pure
+ 100 : : override(IERC1404)
+ 101 : : returns (string memory)
+ 102 : : {
+ 103 [ + ]: 2 : if (restrictionCode == CODE_MAX_TOTAL_SUPPLY_EXCEEDED) {
+ 104 : 1 : return TEXT_MAX_TOTAL_SUPPLY_EXCEEDED;
+ 105 : : }
+ 106 : 1 : return TEXT_CODE_NOT_FOUND;
+ 107 : : }
+ 108 : :
+ 109 : : /*//////////////////////////////////////////////////////////////
+ 110 : : ACCESS CONTROL
+ 111 : : //////////////////////////////////////////////////////////////*/
+ 112 : :
+ 113 : 260 : modifier onlyMaxTotalSupplyManager() {
+ 114 : 260 : _authorizeMaxTotalSupplyManager();
+ 115 : : _;
+ 116 : : }
+ 117 : :
+ 118 : : function _authorizeMaxTotalSupplyManager() internal view virtual;
+ 119 : : }
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.func-sort-c.html b/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.func-sort-c.html
new file mode 100644
index 0000000..9280236
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.func-sort-c.html
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleSanctionsListBase.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.func.html b/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.func.html
new file mode 100644
index 0000000..7fac67d
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.func.html
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleSanctionsListBase.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.gcov.html b/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.gcov.html
new file mode 100644
index 0000000..aa0ff72
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.gcov.html
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleSanctionsListBase.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Branch data Line data Source code
+
+ 1 : : // SPDX-License-Identifier: MPL-2.0
+ 2 : : pragma solidity ^0.8.20;
+ 3 : :
+ 4 : : import {MetaTxModuleStandalone} from "../../../../modules/MetaTxModuleStandalone.sol";
+ 5 : : import {RuleSanctionsListInvariantStorage} from "../invariant/RuleSanctionsListInvariantStorage.sol";
+ 6 : : import {RuleNFTAdapter} from "../core/RuleNFTAdapter.sol";
+ 7 : : import {ISanctionsList} from "../../../interfaces/ISanctionsList.sol";
+ 8 : : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+ 9 : : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+ 10 : : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+ 11 : : import {IRule} from "RuleEngine/interfaces/IRule.sol";
+ 12 : :
+ 13 : : /**
+ 14 : : * @title RuleSanctionsListBase
+ 15 : : * @notice Compliance rule enforcing sanctions-screening for token transfers.
+ 16 : : */
+ 17 : : abstract contract RuleSanctionsListBase is MetaTxModuleStandalone, RuleNFTAdapter, RuleSanctionsListInvariantStorage {
+ 18 : : ISanctionsList public sanctionsList;
+ 19 : :
+ 20 : 46 : constructor(address forwarderIrrevocable, ISanctionsList sanctionContractOracle_)
+ 21 : : MetaTxModuleStandalone(forwarderIrrevocable)
+ 22 : : {
+ 23 [ + ]: 45 : if (address(sanctionContractOracle_) != address(0)) {
+ 24 : 20 : _setSanctionListOracle(sanctionContractOracle_);
+ 25 : : }
+ 26 : : }
+ 27 : :
+ 28 : 84 : function _detectTransferRestriction(address from, address to, uint256 /* value */)
+ 29 : : internal
+ 30 : : view
+ 31 : : override
+ 32 : : returns (uint8)
+ 33 : : {
+ 34 [ + ]: 84 : if (address(sanctionsList) != address(0)) {
+ 35 [ + + ]: 77 : if (sanctionsList.isSanctioned(from)) {
+ 36 : 10 : return CODE_ADDRESS_FROM_IS_SANCTIONED;
+ 37 [ + ]: 67 : } else if (sanctionsList.isSanctioned(to)) {
+ 38 : 12 : return CODE_ADDRESS_TO_IS_SANCTIONED;
+ 39 : : }
+ 40 : : }
+ 41 : 62 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+ 42 : : }
+ 43 : :
+ 44 : 16 : function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+ 45 : : internal
+ 46 : : view
+ 47 : : virtual
+ 48 : : override
+ 49 : : returns (uint8)
+ 50 : : {
+ 51 [ + ]: 16 : if (address(sanctionsList) != address(0)) {
+ 52 [ + ]: 15 : if (sanctionsList.isSanctioned(spender)) {
+ 53 : 6 : return CODE_ADDRESS_SPENDER_IS_SANCTIONED;
+ 54 : : }
+ 55 : 9 : return _detectTransferRestriction(from, to, value);
+ 56 : : }
+ 57 : 1 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+ 58 : : }
+ 59 : :
+ 60 : 3 : function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override(IRule) returns (bool) {
+ 61 : 3 : return restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED || restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED
+ 62 : 1 : || restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED;
+ 63 : : }
+ 64 : :
+ 65 : 4 : function messageForTransferRestriction(uint8 restrictionCode)
+ 66 : : public
+ 67 : : pure
+ 68 : : override(IERC1404)
+ 69 : : returns (string memory)
+ 70 : : {
+ 71 [ + + ]: 4 : if (restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED) {
+ 72 : 1 : return TEXT_ADDRESS_FROM_IS_SANCTIONED;
+ 73 [ + + ]: 3 : } else if (restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED) {
+ 74 : 1 : return TEXT_ADDRESS_TO_IS_SANCTIONED;
+ 75 [ + ]: 2 : } else if (restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED) {
+ 76 : 1 : return TEXT_ADDRESS_SPENDER_IS_SANCTIONED;
+ 77 : : }
+ 78 : 1 : return TEXT_CODE_NOT_FOUND;
+ 79 : : }
+ 80 : :
+ 81 : 17 : function setSanctionListOracle(ISanctionsList sanctionContractOracle_) public virtual onlySanctionListManager {
+ 82 [ + + ]: 15 : require(address(sanctionContractOracle_) != address(0), RuleSanctionsList_OracleAddressZeroNotAllowed());
+ 83 : 14 : _setSanctionListOracle(sanctionContractOracle_);
+ 84 : : }
+ 85 : :
+ 86 : 3 : function clearSanctionListOracle() public virtual onlySanctionListManager {
+ 87 : 3 : _setSanctionListOracle(ISanctionsList(address(0)));
+ 88 : : }
+ 89 : :
+ 90 : 43 : function transferred(address from, address to, uint256 value)
+ 91 : : public
+ 92 : : view
+ 93 : : override(IERC3643IComplianceContract)
+ 94 : : {
+ 95 : 43 : _transferred(from, to, value);
+ 96 : : }
+ 97 : :
+ 98 : 2 : function transferred(address spender, address from, address to, uint256 value)
+ 99 : : public
+ 100 : : view
+ 101 : : override(IRuleEngine)
+ 102 : : {
+ 103 : 2 : _transferredFrom(spender, from, to, value);
+ 104 : : }
+ 105 : :
+ 106 : 47 : function _transferred(address from, address to, uint256 value) internal view virtual override {
+ 107 : 47 : uint8 code = _detectTransferRestriction(from, to, value);
+ 108 [ + + ]: 47 : require(
+ 109 : : code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+ 110 : : RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code)
+ 111 : : );
+ 112 : : }
+ 113 : :
+ 114 : 3 : function _transferredFrom(address spender, address from, address to, uint256 value)
+ 115 : : internal
+ 116 : : view
+ 117 : : virtual
+ 118 : : override
+ 119 : : {
+ 120 : 3 : uint8 code = _detectTransferRestrictionFrom(spender, from, to, value);
+ 121 [ + + ]: 3 : require(
+ 122 : : code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+ 123 : : RuleSanctionsList_InvalidTransferFrom(address(this), spender, from, to, value, code)
+ 124 : : );
+ 125 : : }
+ 126 : :
+ 127 : 37 : function _setSanctionListOracle(ISanctionsList sanctionContractOracle_) internal virtual {
+ 128 : 37 : sanctionsList = sanctionContractOracle_;
+ 129 : 37 : emit SetSanctionListOracle(sanctionContractOracle_);
+ 130 : : }
+ 131 : :
+ 132 : : /*//////////////////////////////////////////////////////////////
+ 133 : : ACCESS CONTROL
+ 134 : : //////////////////////////////////////////////////////////////*/
+ 135 : :
+ 136 : 3 : modifier onlySanctionListManager() {
+ 137 : 3 : _authorizeSanctionListManager();
+ 138 : : _;
+ 139 : : }
+ 140 : :
+ 141 : : function _authorizeSanctionListManager() internal view virtual;
+ 142 : : }
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.func-sort-c.html b/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.func-sort-c.html
new file mode 100644
index 0000000..33acb11
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.func-sort-c.html
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleWhitelistBase.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.func.html b/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.func.html
new file mode 100644
index 0000000..d99a4bf
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.func.html
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleWhitelistBase.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.gcov.html b/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.gcov.html
new file mode 100644
index 0000000..cb753c6
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.gcov.html
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleWhitelistBase.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Branch data Line data Source code
+
+ 1 : : // SPDX-License-Identifier: MPL-2.0
+ 2 : : pragma solidity ^0.8.20;
+ 3 : :
+ 4 : : import {RuleAddressSet} from "../RuleAddressSet/RuleAddressSet.sol";
+ 5 : : import {RuleWhitelistShared} from "../core/RuleWhitelistShared.sol";
+ 6 : : import {RuleTransferValidation} from "../core/RuleTransferValidation.sol";
+ 7 : : import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+ 8 : : import {IIdentityRegistryVerified} from "../../../interfaces/IIdentityRegistry.sol";
+ 9 : :
+ 10 : : /**
+ 11 : : * @title RuleWhitelistBase
+ 12 : : * @notice Core whitelist logic without access-control policy.
+ 13 : : */
+ 14 : : abstract contract RuleWhitelistBase is RuleAddressSet, RuleWhitelistShared, IIdentityRegistryVerified {
+ 15 : 157 : constructor(address forwarderIrrevocable, bool checkSpender_) RuleAddressSet(forwarderIrrevocable) {
+ 16 : 157 : checkSpender = checkSpender_;
+ 17 : : }
+ 18 : :
+ 19 : 51 : function _detectTransferRestriction(address from, address to, uint256 /* value */ )
+ 20 : : internal
+ 21 : : view
+ 22 : : virtual
+ 23 : : override
+ 24 : : returns (uint8)
+ 25 : : {
+ 26 [ + + ]: 51 : if (!isAddressListed(from)) {
+ 27 : 13 : return CODE_ADDRESS_FROM_NOT_WHITELISTED;
+ 28 [ + ]: 38 : } else if (!isAddressListed(to)) {
+ 29 : 10 : return CODE_ADDRESS_TO_NOT_WHITELISTED;
+ 30 : : }
+ 31 : 28 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+ 32 : : }
+ 33 : :
+ 34 : 18 : function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+ 35 : : internal
+ 36 : : view
+ 37 : : virtual
+ 38 : : override
+ 39 : : returns (uint8)
+ 40 : : {
+ 41 [ + ]: 18 : if (checkSpender && !isAddressListed(spender)) {
+ 42 : 8 : return CODE_ADDRESS_SPENDER_NOT_WHITELISTED;
+ 43 : : }
+ 44 : 10 : return _detectTransferRestriction(from, to, value);
+ 45 : : }
+ 46 : :
+ 47 : :
+ 48 : 2 : function isVerified(address targetAddress)
+ 49 : : public
+ 50 : : view
+ 51 : : virtual
+ 52 : : override(IIdentityRegistryVerified)
+ 53 : : returns (bool isListed)
+ 54 : : {
+ 55 : 2 : isListed = _isAddressListed(targetAddress);
+ 56 : : }
+ 57 : :
+ 58 : 3 : function setCheckSpender(bool value) public virtual onlyCheckSpenderManager {
+ 59 : 2 : _setCheckSpender(value);
+ 60 : 2 : emit CheckSpenderUpdated(value);
+ 61 : : }
+ 62 : :
+ 63 : 2 : function _setCheckSpender(bool value) internal virtual {
+ 64 : 2 : checkSpender = value;
+ 65 : : }
+ 66 : :
+ 67 : 27 : function supportsInterface(bytes4 interfaceId) public view virtual override(RuleTransferValidation) returns (bool) {
+ 68 : 27 : return RuleTransferValidation.supportsInterface(interfaceId);
+ 69 : : }
+ 70 : :
+ 71 : : /*//////////////////////////////////////////////////////////////
+ 72 : : ACCESS CONTROL
+ 73 : : //////////////////////////////////////////////////////////////*/
+ 74 : :
+ 75 : 3 : modifier onlyCheckSpenderManager() {
+ 76 : 3 : _authorizeCheckSpenderManager();
+ 77 : : _;
+ 78 : : }
+ 79 : :
+ 80 : : function _authorizeCheckSpenderManager() internal view virtual;
+ 81 : : }
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.func-sort-c.html b/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.func-sort-c.html
new file mode 100644
index 0000000..62a206a
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.func-sort-c.html
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleWhitelistWrapperBase.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.func.html b/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.func.html
new file mode 100644
index 0000000..643e123
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.func.html
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base/RuleWhitelistWrapperBase.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html b/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.gcov.html
similarity index 55%
rename from doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html
rename to doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.gcov.html
index 1d03613..2a4e421 100644
--- a/doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html
+++ b/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.gcov.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - validation/RuleSanctionsList.sol
-
+ LCOV - lcov.info - abstract/base/RuleWhitelistWrapperBase.sol
+
LCOV - code coverage report
-
+
-
+
@@ -31,34 +31,34 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
+
+
-
+
-
+
@@ -73,266 +73,249 @@
2 : :
3 : : pragma solidity ^0.8.20;
4 : :
- 5 : : import {AccessControl} from "OZ/access/AccessControl.sol";
- 6 : : /* ==== Abtract contracts === */
- 7 : : import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../modules/MetaTxModuleStandalone.sol";
- 8 : : import {AccessControlModuleStandalone} from "../../modules/AccessControlModuleStandalone.sol";
- 9 : : import {RuleSanctionsListInvariantStorage} from "./abstract/RuleSanctionsListInvariantStorage.sol";
- 10 : : import {RuleValidateTransfer, RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol";
- 11 : : /* ==== Interfaces === */
- 12 : : import {ISanctionsList} from "../interfaces/ISanctionsList.sol";
- 13 : : import {IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol";
+ 5 : : /* ==== OpenZeppelin === */
+ 6 : : import {AccessControl} from "OZ/access/AccessControl.sol";
+ 7 : : /* ==== Abstract contracts === */
+ 8 : : import {MetaTxModuleStandalone, ERC2771Context} from "../../../../modules/MetaTxModuleStandalone.sol";
+ 9 : : import {Context} from "OZ/utils/Context.sol";
+ 10 : : import {RuleWhitelistShared} from "../core/RuleWhitelistShared.sol";
+ 11 : : import {RuleTransferValidation} from "../core/RuleTransferValidation.sol";
+ 12 : : /* ==== RuleEngine === */
+ 13 : : import {RulesManagementModule} from "RuleEngine/modules/RulesManagementModule.sol";
14 : : /* ==== CMTAT === */
15 : : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
- 16 : : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
- 17 : : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
- 18 : : /* ==== IRuleEngine === */
- 19 : : import {IRule} from "RuleEngine/interfaces/IRule.sol";
- 20 : :
- 21 : :
- 22 : : /**
- 23 : : * @title RuleSanctionsList
- 24 : : * @notice Compliance rule enforcing sanctions-screening for token transfers.
- 25 : : * @dev
- 26 : : * This rule integrates a sanctions-oracle (e.g., Chainalysis) and blocks
- 27 : : * transfers when:
- 28 : : * - the sender is sanctioned,
- 29 : : * - the recipient is sanctioned,
- 30 : : * - or the spender/operator is sanctioned.
- 31 : : *
- 32 : : * Features:
- 33 : : * - Supports ERC-1404, ERC-3643 (transferred) and ERC-7943 non-fungible compliance flows.
- 34 : : * - Oracle address can be updated by accounts holding `SANCTIONLIST_ROLE`.
- 35 : : * - Zero oracle address disables sanctions checks (all transfers allowed).
- 36 : : *
- 37 : : * The rule is designed for RuleEngine or for direct integration with
- 38 : : * CMTAT / ERC-3643 compliant tokens.
- 39 : : */
- 40 : : contract RuleSanctionsList is
- 41 : : AccessControlModuleStandalone,
- 42 : : MetaTxModuleStandalone,
- 43 : : RuleValidateTransfer,
- 44 : : RuleSanctionsListInvariantStorage
- 45 : : {
- 46 : : ISanctionsList public sanctionsList;
- 47 : :
- 48 : : /*//////////////////////////////////////////////////////////////
- 49 : : CONSTRUCTOR
- 50 : : //////////////////////////////////////////////////////////////*/
- 51 : : /**
- 52 : : * @param admin Address of the contract (Access Control)
- 53 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
- 54 : : */
- 55 : 17 : constructor(address admin, address forwarderIrrevocable, ISanctionsList sanctionContractOracle_)
- 56 : : MetaTxModuleStandalone(forwarderIrrevocable)
- 57 : : AccessControlModuleStandalone(admin)
- 58 : : {
- 59 [ + ]: 16 : if (address(sanctionContractOracle_) != address(0)) {
- 60 : 1 : _setSanctionListOracle(sanctionContractOracle_);
- 61 : : }
- 62 : : }
- 63 : :
- 64 : : /* ============ View Functions ============ */
- 65 : :
- 66 : : /**
- 67 : : * @notice Check if an addres is in the SanctionsList or not
- 68 : : * @param from the origin address
- 69 : : * @param to the destination address
- 70 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
- 71 : : *
- 72 : : */
- 73 : 17 : function detectTransferRestriction(address from, address to, uint256 /*value */ )
- 74 : : public
- 75 : : view
- 76 : : override(IERC1404)
- 77 : : returns (uint8)
- 78 : : {
- 79 [ + ]: 35 : if (address(sanctionsList) != address(0)) {
- 80 [ + + ]: 30 : if (sanctionsList.isSanctioned(from)) {
- 81 : 6 : return CODE_ADDRESS_FROM_IS_SANCTIONED;
- 82 [ + ]: 24 : } else if (sanctionsList.isSanctioned(to)) {
- 83 : 10 : return CODE_ADDRESS_TO_IS_SANCTIONED;
- 84 : : }
- 85 : : }
- 86 : 19 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- 87 : : }
+ 16 : : /* ==== Interfaces === */
+ 17 : : import {IAddressList} from "../../../interfaces/IAddressList.sol";
+ 18 : : import {IIdentityRegistryVerified} from "../../../interfaces/IIdentityRegistry.sol";
+ 19 : :
+ 20 : : /**
+ 21 : : * @title Wrapper to call several different whitelist rules (base)
+ 22 : : * @dev Child rules must implement {IAddressList}.
+ 23 : : */
+ 24 : : abstract contract RuleWhitelistWrapperBase is
+ 25 : : RulesManagementModule,
+ 26 : : MetaTxModuleStandalone,
+ 27 : : RuleWhitelistShared,
+ 28 : : IIdentityRegistryVerified
+ 29 : : {
+ 30 : : /*//////////////////////////////////////////////////////////////
+ 31 : : CONSTRUCTOR
+ 32 : : //////////////////////////////////////////////////////////////*/
+ 33 : : /**
+ 34 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
+ 35 : : */
+ 36 : 44 : constructor(address forwarderIrrevocable, bool checkSpender_)
+ 37 : : MetaTxModuleStandalone(forwarderIrrevocable)
+ 38 : : {
+ 39 : 44 : checkSpender = checkSpender_;
+ 40 : : }
+ 41 : :
+ 42 : : /* ============ View Functions ============ */
+ 43 : : /**
+ 44 : : * @notice Go through all the whitelist rules to know if a restriction exists on the transfer
+ 45 : : * @param from the origin address
+ 46 : : * @param to the destination address
+ 47 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
+ 48 : : *
+ 49 : : */
+ 50 : 34 : function _detectTransferRestriction(address from, address to, uint256 /* value */)
+ 51 : : internal
+ 52 : : view
+ 53 : : virtual
+ 54 : : override
+ 55 : : returns (uint8)
+ 56 : : {
+ 57 : 34 : address[] memory targetAddress = new address[](2);
+ 58 : 34 : targetAddress[0] = from;
+ 59 : 34 : targetAddress[1] = to;
+ 60 : :
+ 61 : 34 : bool[] memory result = _detectTransferRestrictionForTargets(targetAddress);
+ 62 [ + + ]: 34 : if (!result[0]) {
+ 63 : 13 : return CODE_ADDRESS_FROM_NOT_WHITELISTED;
+ 64 [ + + ]: 21 : } else if (!result[1]) {
+ 65 : 8 : return CODE_ADDRESS_TO_NOT_WHITELISTED;
+ 66 : : } else {
+ 67 : 13 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+ 68 : : }
+ 69 : : }
+ 70 : :
+ 71 : 20 : function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+ 72 : : internal
+ 73 : : view
+ 74 : : virtual
+ 75 : : override
+ 76 : : returns (uint8)
+ 77 : : {
+ 78 [ + ]: 20 : if (!checkSpender) {
+ 79 : 1 : return _detectTransferRestriction(from, to, value);
+ 80 : : }
+ 81 : :
+ 82 : 19 : address[] memory targetAddress = new address[](3);
+ 83 : 19 : targetAddress[0] = from;
+ 84 : 19 : targetAddress[1] = to;
+ 85 : 19 : targetAddress[2] = spender;
+ 86 : :
+ 87 : 19 : bool[] memory result = _detectTransferRestrictionForTargets(targetAddress);
88 : :
- 89 : : /**
- 90 : : * @inheritdoc IERC7943NonFungibleComplianceExtend
- 91 : : */
- 92 : 9 : function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value)
- 93 : : public
- 94 : : view
- 95 : : virtual
- 96 : : override(IERC7943NonFungibleComplianceExtend)
- 97 : : returns (uint8)
- 98 : : {
- 99 : 9 : return detectTransferRestriction(from, to, value);
- 100 : : }
+ 89 [ + + ]: 19 : if (!result[0]) {
+ 90 : 1 : return CODE_ADDRESS_FROM_NOT_WHITELISTED;
+ 91 [ + + ]: 18 : } else if (!result[1]) {
+ 92 : 1 : return CODE_ADDRESS_TO_NOT_WHITELISTED;
+ 93 [ + + ]: 17 : } else if (!result[2]) {
+ 94 : 8 : return CODE_ADDRESS_SPENDER_NOT_WHITELISTED;
+ 95 : : } else {
+ 96 : 9 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+ 97 : : }
+ 98 : : }
+ 99 : :
+ 100 : : // ERC-7943 tokenId overloads are provided by {RuleNFTAdapter} via RuleWhitelistShared.
101 : :
- 102 : : /**
- 103 : : * @inheritdoc IERC1404Extend
- 104 : : */
- 105 : 11 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
- 106 : : public
- 107 : : view
- 108 : : virtual
- 109 : : override(IERC1404Extend)
- 110 : : returns (uint8)
- 111 : : {
- 112 [ + ]: 14 : if (address(sanctionsList) != address(0)) {
- 113 [ + + ]: 13 : if (sanctionsList.isSanctioned(spender)) {
- 114 : 4 : return CODE_ADDRESS_SPENDER_IS_SANCTIONED;
- 115 : : } else {
- 116 : 9 : return detectTransferRestriction(from, to, value);
- 117 : : }
- 118 : : }
- 119 : 1 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- 120 : : }
- 121 : :
- 122 : 3 : function detectTransferRestrictionFrom(
- 123 : : address spender,
- 124 : : address from,
- 125 : : address to,
- 126 : : uint256, /* tokenId */
- 127 : : uint256 value
- 128 : : ) public view virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) {
- 129 : 3 : return detectTransferRestrictionFrom(spender, from, to, value);
- 130 : : }
- 131 : :
- 132 : : /**
- 133 : : * @notice To know if the restriction code is valid for this rule or not.
- 134 : : * @param restrictionCode The target restriction code
- 135 : : * @return true if the restriction code is known, false otherwise
- 136 : : *
- 137 : : */
- 138 : 3 : function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override(IRule) returns (bool) {
- 139 : 3 : return restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED || restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED
- 140 : 1 : || restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED;
- 141 : : }
- 142 : :
- 143 : : /**
- 144 : : * @notice Return the corresponding message
- 145 : : * @param restrictionCode The target restriction code
- 146 : : * @return true if the transfer is valid, false otherwise
- 147 : : *
- 148 : : */
- 149 : 4 : function messageForTransferRestriction(uint8 restrictionCode)
- 150 : : public
- 151 : : pure
- 152 : : virtual
- 153 : : override(IERC1404)
- 154 : : returns (string memory)
- 155 : : {
- 156 [ + + ]: 4 : if (restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED) {
- 157 : 1 : return TEXT_ADDRESS_FROM_IS_SANCTIONED;
- 158 [ + + ]: 3 : } else if (restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED) {
- 159 : 1 : return TEXT_ADDRESS_TO_IS_SANCTIONED;
- 160 [ + + ]: 2 : } else if (restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED) {
- 161 : 1 : return TEXT_ADDRESS_SPENDER_IS_SANCTIONED;
- 162 : : } else {
- 163 : 1 : return TEXT_CODE_NOT_FOUND;
- 164 : : }
- 165 : : }
- 166 : :
- 167 : 0 : function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) {
- 168 : 0 : return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId);
- 169 : : }
- 170 : :
- 171 : : /* ============ State Functions ============ */
- 172 : : /**
- 173 : : * @notice Set the oracle contract
- 174 : : * @param sanctionContractOracle_ address of your oracle contract
- 175 : : * @dev zero address is authorized to authorize all transfers
- 176 : : */
- 177 : 14 : function setSanctionListOracle(ISanctionsList sanctionContractOracle_) public virtual onlyRole(SANCTIONLIST_ROLE) {
- 178 : 13 : _setSanctionListOracle(sanctionContractOracle_);
- 179 : : }
- 180 : :
- 181 : : /**
- 182 : : * @inheritdoc IERC3643IComplianceContract
- 183 : : */
- 184 : 3 : function transferred(address from, address to, uint256 value)
- 185 : : public
- 186 : : view
- 187 : : virtual
- 188 : : override(IERC3643IComplianceContract)
- 189 : : {
- 190 : 7 : uint8 code = this.detectTransferRestriction(from, to, value);
- 191 [ + + ]: 7 : require(
- 192 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
- 193 : : RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code)
- 194 : : );
- 195 : : }
- 196 : :
- 197 : :
- 198 : : /**
- 199 : : * @inheritdoc IRuleEngine
- 200 : : */
- 201 : 2 : function transferred(address spender, address from, address to, uint256 value)
- 202 : : public
- 203 : : view
- 204 : : virtual
- 205 : : override(IRuleEngine)
- 206 : : {
- 207 : 3 : uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value);
- 208 [ + + ]: 3 : require(
- 209 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
- 210 : : RuleSanctionsList_InvalidTransferFrom(address(this), spender, from, to, value, code)
- 211 : : );
- 212 : : }
- 213 : :
- 214 : 1 : function transferred(address spender, address from, address to, uint256 /* tokenId */,uint256 value)
- 215 : : public
- 216 : : view
- 217 : : virtual
- 218 : : override(IERC7943NonFungibleComplianceExtend)
- 219 : : {
- 220 : 1 : transferred(spender, from, to, value);
- 221 : : }
+ 102 : 62 : function supportsInterface(bytes4 interfaceId)
+ 103 : : public
+ 104 : : view
+ 105 : : virtual
+ 106 : : override(AccessControl, RuleTransferValidation)
+ 107 : : returns (bool)
+ 108 : : {
+ 109 : 62 : return AccessControl.supportsInterface(interfaceId) || RuleTransferValidation.supportsInterface(interfaceId);
+ 110 : : }
+ 111 : :
+ 112 : : /**
+ 113 : : * @notice Returns true if the address is listed in at least one child whitelist rule.
+ 114 : : * @dev Delegates to the same child-rule scan used by transfer restriction checks.
+ 115 : : */
+ 116 : 4 : function isVerified(address targetAddress)
+ 117 : : public
+ 118 : : view
+ 119 : : virtual
+ 120 : : override(IIdentityRegistryVerified)
+ 121 : : returns (bool)
+ 122 : : {
+ 123 : 4 : address[] memory targets = new address[](1);
+ 124 : 4 : targets[0] = targetAddress;
+ 125 : 4 : bool[] memory result = _detectTransferRestrictionForTargets(targets);
+ 126 : 4 : return result[0];
+ 127 : : }
+ 128 : :
+ 129 : : /* ============ Access control ============ */
+ 130 : :
+ 131 : : /**
+ 132 : : * @notice Sets whether the rule should enforce spender-based checks.
+ 133 : : * @dev
+ 134 : : * - Restricted to holders of the manager role.
+ 135 : : * - Updates the internal `checkSpender` flag.
+ 136 : : * - Emits a {CheckSpenderUpdated} event.
+ 137 : : * @param value The new state of the `checkSpender` flag.
+ 138 : : */
+ 139 : 4 : function setCheckSpender(bool value) public virtual onlyCheckSpenderManager {
+ 140 : 3 : _setCheckSpender(value);
+ 141 : 3 : emit CheckSpenderUpdated(value);
+ 142 : : }
+ 143 : :
+ 144 : 13 : function _transferred(address from, address to, uint256 value)
+ 145 : : internal
+ 146 : : view
+ 147 : : virtual
+ 148 : : override(RulesManagementModule, RuleWhitelistShared)
+ 149 : : {
+ 150 : 13 : RuleWhitelistShared._transferred(from, to, value);
+ 151 : : }
+ 152 : :
+ 153 : 1 : function _transferred(address spender, address from, address to, uint256 value)
+ 154 : : internal
+ 155 : : view
+ 156 : : virtual
+ 157 : : override(RulesManagementModule)
+ 158 : : {
+ 159 : 1 : RuleWhitelistShared._transferredFrom(spender, from, to, value);
+ 160 : : }
+ 161 : :
+ 162 : : /*//////////////////////////////////////////////////////////////
+ 163 : : INTERNAL/PRIVATE FUNCTIONS
+ 164 : : //////////////////////////////////////////////////////////////*/
+ 165 : :
+ 166 : : /**
+ 167 : : * @notice Evaluates target addresses across all child rules.
+ 168 : : * @param targetAddress Addresses to validate (from/to[/spender]).
+ 169 : : * @return result Boolean array aligned with targetAddress indicating if each address is listed.
+ 170 : : */
+ 171 : 57 : function _detectTransferRestrictionForTargets(address[] memory targetAddress)
+ 172 : : internal
+ 173 : : view
+ 174 : : virtual
+ 175 : : returns (bool[] memory)
+ 176 : : {
+ 177 : 57 : uint256 rulesLength = rulesCount();
+ 178 : 57 : bool[] memory result = new bool[](targetAddress.length);
+ 179 : 57 : for (uint256 i = 0; i < rulesLength; ++i) {
+ 180 : : // Call the whitelist rules
+ 181 : : // Gas cost grows with the number of rules. Keep the wrapper list bounded.
+ 182 : 105 : bool[] memory isListed = IAddressList(rule(i)).areAddressesListed(targetAddress);
+ 183 : 105 : for (uint256 j = 0; j < targetAddress.length; ++j) {
+ 184 [ + ]: 85 : if (isListed[j]) {
+ 185 : 85 : result[j] = true;
+ 186 : : }
+ 187 : : }
+ 188 : :
+ 189 : : // Break early if all listed
+ 190 : 105 : bool allListed = true;
+ 191 : 105 : for (uint256 k = 0; k < result.length; ++k) {
+ 192 [ + ]: 201 : if (!result[k]) {
+ 193 : 81 : allListed = false;
+ 194 : 81 : break;
+ 195 : : }
+ 196 : : }
+ 197 [ + ]: 24 : if (allListed) {
+ 198 : 24 : break;
+ 199 : : }
+ 200 : : }
+ 201 : 57 : return result;
+ 202 : : }
+ 203 : :
+ 204 : : /**
+ 205 : : * @notice Internal helper to update the `checkSpender` flag.
+ 206 : : * @param value New flag value.
+ 207 : : */
+ 208 : 3 : function _setCheckSpender(bool value) internal virtual {
+ 209 : 3 : checkSpender = value;
+ 210 : : }
+ 211 : :
+ 212 : : /*//////////////////////////////////////////////////////////////
+ 213 : : ACCESS CONTROL
+ 214 : : //////////////////////////////////////////////////////////////*/
+ 215 : :
+ 216 : 4 : modifier onlyCheckSpenderManager() {
+ 217 : 4 : _authorizeCheckSpenderManager();
+ 218 : : _;
+ 219 : : }
+ 220 : :
+ 221 : : function _authorizeCheckSpenderManager() internal virtual;
222 : :
- 223 : 4 : function transferred(address from, address to, uint256 /* tokenId */,uint256 value)
- 224 : : public
- 225 : : view
- 226 : : virtual
- 227 : : override(IERC7943NonFungibleComplianceExtend)
- 228 : : {
- 229 : 4 : transferred(from, to, value);
- 230 : : }
- 231 : : /*//////////////////////////////////////////////////////////////
- 232 : : INTERNAL FUNCTIONS
- 233 : : //////////////////////////////////////////////////////////////*/
- 234 : :
- 235 : 14 : function _setSanctionListOracle(ISanctionsList sanctionContractOracle_) internal {
- 236 : 14 : sanctionsList = sanctionContractOracle_;
- 237 : 14 : emit SetSanctionListOracle(sanctionContractOracle_);
- 238 : : }
- 239 : :
- 240 : : /*//////////////////////////////////////////////////////////////
- 241 : : ERC-2771
- 242 : : //////////////////////////////////////////////////////////////*/
- 243 : :
- 244 : : /**
- 245 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 246 : : */
- 247 : 30 : function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
- 248 : 30 : return ERC2771Context._msgSender();
- 249 : : }
- 250 : :
- 251 : : /**
- 252 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 253 : : */
- 254 : 0 : function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) {
- 255 : 0 : return ERC2771Context._msgData();
- 256 : : }
- 257 : :
- 258 : : /**
- 259 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 260 : : */
- 261 : 30 : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
- 262 : 30 : return ERC2771Context._contextSuffixLength();
- 263 : : }
- 264 : : }
+ 223 : : /*//////////////////////////////////////////////////////////////
+ 224 : : ERC-2771
+ 225 : : //////////////////////////////////////////////////////////////*/
+ 226 : :
+ 227 : : /**
+ 228 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
+ 229 : : */
+ 230 : 145 : function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) {
+ 231 : 145 : return ERC2771Context._msgSender();
+ 232 : : }
+ 233 : :
+ 234 : : /**
+ 235 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
+ 236 : : */
+ 237 : 2 : function _msgData() internal view virtual override(ERC2771Context, Context) returns (bytes calldata) {
+ 238 : 2 : return ERC2771Context._msgData();
+ 239 : : }
+ 240 : :
+ 241 : : /**
+ 242 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
+ 243 : : */
+ 244 : 147 : function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) {
+ 245 : 147 : return ERC2771Context._contextSuffixLength();
+ 246 : : }
+ 247 : : }
@@ -340,7 +323,7 @@
diff --git a/doc/coverage/coverage/abstract/base/index-sort-b.html b/doc/coverage/coverage/abstract/base/index-sort-b.html
new file mode 100644
index 0000000..c0dd6a1
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/index-sort-b.html
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/index-sort-f.html b/doc/coverage/coverage/abstract/base/index-sort-f.html
new file mode 100644
index 0000000..fd1f168
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/index-sort-f.html
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/index-sort-l.html b/doc/coverage/coverage/abstract/base/index-sort-l.html
new file mode 100644
index 0000000..10250aa
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/index-sort-l.html
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/base/index.html b/doc/coverage/coverage/abstract/base/index.html
new file mode 100644
index 0000000..a56fb4a
--- /dev/null
+++ b/doc/coverage/coverage/abstract/base/index.html
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/base
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.func-sort-c.html b/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.func-sort-c.html
new file mode 100644
index 0000000..2a2a676
--- /dev/null
+++ b/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.func-sort-c.html
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/core/RuleNFTAdapter.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.func.html b/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.func.html
new file mode 100644
index 0000000..0ee21a8
--- /dev/null
+++ b/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.func.html
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/core/RuleNFTAdapter.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html b/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.gcov.html
similarity index 52%
rename from doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html
rename to doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.gcov.html
index 09c1d37..ea62082 100644
--- a/doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html
+++ b/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.gcov.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - validation/RuleWhitelist.sol
-
+ LCOV - lcov.info - abstract/core/RuleNFTAdapter.sol
+
LCOV - code coverage report
-
+
-
+
@@ -31,34 +31,34 @@
-
-
+
+
-
+
-
-
-
+
+
+
-
-
+
+
-
+
-
+
@@ -72,149 +72,135 @@
1 : : // SPDX-License-Identifier: MPL-2.0
2 : : pragma solidity ^0.8.20;
3 : :
- 4 : : import {AccessControl} from "OZ/access/AccessControl.sol";
- 5 : : /* ==== Abtract contracts === */
- 6 : : import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol";
- 7 : : import {RuleWhitelistCommon, RuleValidateTransfer} from "./abstract/RuleWhitelistCommon.sol";
- 8 : : /* ==== CMTAT === */
- 9 : : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
- 10 : : /* ==== Interfaces === */
- 11 : : import {IIdentityRegistryVerified} from "../interfaces/IIdentityRegistry.sol";
- 12 : : import {
- 13 : : IERC7943NonFungibleCompliance,
- 14 : : IERC7943NonFungibleComplianceExtend
- 15 : : } from "../interfaces/IERC7943NonFungibleCompliance.sol";
- 16 : :
- 17 : : /**
- 18 : : * @title Rule Whitelist
- 19 : : * @notice Manages a whitelist of authorized addresses and enforces whitelist-based transfer restrictions.
- 20 : : * @dev
- 21 : : * - Inherits core address management logic from {RuleAddressSet}.
- 22 : : * - Integrates restriction code logic from {RuleWhitelistCommon}.
- 23 : : * - Implements {IERC1404} to return specific restriction codes for non-whitelisted transfers.
- 24 : : */
- 25 : : contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistryVerified {
- 26 : : /*//////////////////////////////////////////////////////////////
- 27 : : CONSTRUCTOR
- 28 : : //////////////////////////////////////////////////////////////*/
- 29 : : /**
- 30 : : * @param admin Address of the contract (Access Control)
- 31 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
- 32 : : */
- 33 : 102 : constructor(address admin, address forwarderIrrevocable, bool checkSpender_)
- 34 : : RuleAddressSet(admin, forwarderIrrevocable)
- 35 : : {
- 36 : 101 : checkSpender = checkSpender_;
- 37 : : }
- 38 : :
- 39 : : /* ============ View Functions ============ */
- 40 : :
- 41 : : /**
- 42 : : * @notice Detects whether a transfer between two addresses is allowed under the whitelist rule.
- 43 : : * @dev
- 44 : : * - Returns a restriction code indicating why a transfer is blocked.
- 45 : : * - Implements the `IERC1404.detectTransferRestriction` interface.
- 46 : : * @param from The address sending tokens.
- 47 : : * @param to The address receiving tokens.
- 48 : : * @return code Restriction code (e.g., `TRANSFER_OK` or specific whitelist rejection).
- 49 : : *
- 50 : : * | Condition | Returned Code |
- 51 : : * |------------|---------------|
- 52 : : * | `from` not whitelisted | `CODE_ADDRESS_FROM_NOT_WHITELISTED` |
- 53 : : * | `to` not whitelisted | `CODE_ADDRESS_TO_NOT_WHITELISTED` |
- 54 : : * | Both whitelisted | `TRANSFER_OK` |
- 55 : : */
- 56 : 20 : function detectTransferRestriction(address from, address to, uint256 /* value */ )
- 57 : : public
- 58 : : view
- 59 : : virtual
- 60 : : override(IERC1404)
- 61 : : returns (uint8 code)
- 62 : : {
- 63 [ + + ]: 33 : if (!isAddressListed(from)) {
- 64 : 11 : return CODE_ADDRESS_FROM_NOT_WHITELISTED;
- 65 [ + + ]: 22 : } else if (!isAddressListed(to)) {
- 66 : 6 : return CODE_ADDRESS_TO_NOT_WHITELISTED;
- 67 : : } else {
- 68 : 16 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- 69 : : }
- 70 : : }
- 71 : :
- 72 : : /**
- 73 : : * @inheritdoc IERC7943NonFungibleComplianceExtend
- 74 : : */
- 75 : 7 : function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value)
- 76 : : public
- 77 : : view
- 78 : : virtual
- 79 : : override(IERC7943NonFungibleComplianceExtend)
- 80 : : returns (uint8)
- 81 : : {
- 82 : 7 : return detectTransferRestriction(from, to, value);
- 83 : : }
- 84 : :
- 85 : : /**
- 86 : : * @notice Detects transfer restriction for delegated transfers (`transferFrom`).
- 87 : : * @dev
- 88 : : * - Checks the `spender`, `from`, and `to` addresses for whitelist compliance.
- 89 : : * - Implements `IERC1404Extend.detectTransferRestrictionFrom`.
- 90 : : * @param spender The address initiating the transfer on behalf of another.
- 91 : : * @param from The address from which tokens are transferred.
- 92 : : * @param to The address receiving the tokens.
- 93 : : * @param value The amount being transferred (unused in this check).
- 94 : : * @return code Restriction code, or `TRANSFER_OK` if all parties are whitelisted.
- 95 : : *
- 96 : : * | Condition | Returned Code |
- 97 : : * |------------|---------------|
- 98 : : * | `spender` not whitelisted | `CODE_ADDRESS_SPENDER_NOT_WHITELISTED` |
- 99 : : * | `from` or `to` not whitelisted | respective restriction code from `detectTransferRestriction` |
- 100 : : * | All whitelisted | `TRANSFER_OK` |
- 101 : : */
- 102 : 10 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
- 103 : : public
- 104 : : view
+ 4 : : import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+ 5 : : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+ 6 : : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+ 7 : : import {
+ 8 : : IERC7943NonFungibleCompliance,
+ 9 : : IERC7943NonFungibleComplianceExtend
+ 10 : : } from "../../../interfaces/IERC7943NonFungibleCompliance.sol";
+ 11 : : import {RuleTransferValidation} from "./RuleTransferValidation.sol";
+ 12 : : import {ITransferContext} from "../../../interfaces/ITransferContext.sol";
+ 13 : :
+ 14 : : /**
+ 15 : : * @title Rule NFT Adapter
+ 16 : : * @notice Provides ERC-7943 overloads for rules that already implement core transfer checks.
+ 17 : : * @dev Delegates tokenId overloads to RuleTransferValidation's internal hooks.
+ 18 : : */
+ 19 : : abstract contract RuleNFTAdapter is RuleTransferValidation, IERC7943NonFungibleComplianceExtend, ITransferContext {
+ 20 : : bytes4 internal constant TRANSFERRED_SELECTOR_ERC3643 =
+ 21 : : IERC3643IComplianceContract.transferred.selector;
+ 22 : : bytes4 internal constant TRANSFERRED_SELECTOR_RULE_ENGINE =
+ 23 : : IRuleEngine.transferred.selector;
+ 24 : : bytes4 internal constant TRANSFERRED_SELECTOR_ERC7943 =
+ 25 : : bytes4(keccak256("transferred(address,address,uint256,uint256)"));
+ 26 : : bytes4 internal constant TRANSFERRED_SELECTOR_ERC7943_FROM =
+ 27 : : bytes4(keccak256("transferred(address,address,address,uint256,uint256)"));
+ 28 : : /**
+ 29 : : * @notice Internal hook for post-transfer validation or state updates.
+ 30 : : */
+ 31 : : function _transferred(address from, address to, uint256 value) internal virtual;
+ 32 : :
+ 33 : : /**
+ 34 : : * @notice Internal hook for post-transfer validation or state updates (spender-aware).
+ 35 : : */
+ 36 : : function _transferredFrom(address spender, address from, address to, uint256 value) internal virtual;
+ 37 : : /**
+ 38 : : * @inheritdoc IERC7943NonFungibleComplianceExtend
+ 39 : : */
+ 40 : 16 : function detectTransferRestriction(address from, address to, uint256 /* tokenId */, uint256 value)
+ 41 : : public
+ 42 : : view
+ 43 : : virtual
+ 44 : : override(IERC7943NonFungibleComplianceExtend)
+ 45 : : returns (uint8)
+ 46 : : {
+ 47 : 16 : return _detectTransferRestriction(from, to, value);
+ 48 : : }
+ 49 : :
+ 50 : : /**
+ 51 : : * @inheritdoc IERC7943NonFungibleComplianceExtend
+ 52 : : */
+ 53 : 12 : function detectTransferRestrictionFrom(
+ 54 : : address spender,
+ 55 : : address from,
+ 56 : : address to,
+ 57 : : uint256 /* tokenId */,
+ 58 : : uint256 value
+ 59 : : ) public view virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) {
+ 60 : 12 : return _detectTransferRestrictionFrom(spender, from, to, value);
+ 61 : : }
+ 62 : :
+ 63 : : /**
+ 64 : : * @inheritdoc IERC7943NonFungibleCompliance
+ 65 : : */
+ 66 : 14 : function canTransfer(address from, address to, uint256 /* tokenId */, uint256 amount)
+ 67 : : public
+ 68 : : view
+ 69 : : override(IERC7943NonFungibleCompliance)
+ 70 : : returns (bool)
+ 71 : : {
+ 72 : 14 : return _detectTransferRestriction(from, to, amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 73 : : }
+ 74 : :
+ 75 : : /**
+ 76 : : * @inheritdoc IERC7943NonFungibleComplianceExtend
+ 77 : : */
+ 78 : 10 : function canTransferFrom(address spender, address from, address to, uint256 /* tokenId */, uint256 value)
+ 79 : : public
+ 80 : : view
+ 81 : : virtual
+ 82 : : override(IERC7943NonFungibleComplianceExtend)
+ 83 : : returns (bool)
+ 84 : : {
+ 85 : 10 : return _detectTransferRestrictionFrom(spender, from, to, value)
+ 86 : : == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 87 : : }
+ 88 : :
+ 89 : : /**
+ 90 : : * @inheritdoc IERC7943NonFungibleComplianceExtend
+ 91 : : */
+ 92 : 13 : function transferred(address from, address to, uint256 /* tokenId */, uint256 value)
+ 93 : : public
+ 94 : : virtual
+ 95 : : override(IERC7943NonFungibleComplianceExtend)
+ 96 : : {
+ 97 : 13 : _transferred(from, to, value);
+ 98 : : }
+ 99 : :
+ 100 : : /**
+ 101 : : * @inheritdoc IERC7943NonFungibleComplianceExtend
+ 102 : : */
+ 103 : 8 : function transferred(address spender, address from, address to, uint256 /* tokenId */, uint256 value)
+ 104 : : public
105 : : virtual
- 106 : : override(IERC1404Extend)
- 107 : : returns (uint8 code)
- 108 : : {
- 109 [ + ]: 12 : if (checkSpender && !isAddressListed(spender)) {
- 110 : 6 : return CODE_ADDRESS_SPENDER_NOT_WHITELISTED;
- 111 : : }
- 112 : 6 : return detectTransferRestriction(from, to, value);
- 113 : : }
- 114 : :
- 115 : : /**
- 116 : : * @inheritdoc IERC7943NonFungibleComplianceExtend
- 117 : : */
- 118 : 2 : function detectTransferRestrictionFrom(
- 119 : : address spender,
- 120 : : address from,
- 121 : : address to,
- 122 : : uint256, /* tokenId */
- 123 : : uint256 value
- 124 : : ) public view override(IERC7943NonFungibleComplianceExtend) returns (uint8) {
- 125 : 2 : return detectTransferRestrictionFrom(spender, from, to, value);
- 126 : : }
- 127 : :
- 128 : : /**
- 129 : : * @notice Checks whether a specific address is currently listed.
- 130 : : * @param targetAddress The address to check.
- 131 : : * @return isListed True if listed, false otherwise.
- 132 : : */
- 133 : 0 : function isVerified(address targetAddress)
- 134 : : public
- 135 : : view
- 136 : : virtual
- 137 : : override(IIdentityRegistryVerified)
- 138 : : returns (bool isListed)
- 139 : : {
- 140 : 0 : isListed = _isAddressListed(targetAddress);
- 141 : : }
- 142 : :
- 143 : 0 : function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) {
- 144 : 0 : return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId);
- 145 : : }
- 146 : : }
+ 106 : : override(IERC7943NonFungibleComplianceExtend)
+ 107 : : {
+ 108 : 8 : _transferredFrom(spender, from, to, value);
+ 109 : : }
+ 110 : :
+ 111 : : /**
+ 112 : : * @inheritdoc ITransferContext
+ 113 : : */
+ 114 : 2 : function transferred(MultiTokenTransferContext calldata ctx) external virtual override {
+ 115 [ + + ]: 2 : if (ctx.sender != address(0)) {
+ 116 : 1 : _transferredFrom(ctx.sender, ctx.from, ctx.to, ctx.value);
+ 117 : : } else {
+ 118 : 1 : _transferred(ctx.from, ctx.to, ctx.value);
+ 119 : : }
+ 120 : : }
+ 121 : :
+ 122 : : /**
+ 123 : : * @inheritdoc ITransferContext
+ 124 : : */
+ 125 : 2 : function transferred(FungibleTransferContext calldata ctx) external virtual override {
+ 126 [ + + ]: 2 : if (ctx.sender != address(0)) {
+ 127 : 1 : _transferredFrom(ctx.sender, ctx.from, ctx.to, ctx.value);
+ 128 : : } else {
+ 129 : 1 : _transferred(ctx.from, ctx.to, ctx.value);
+ 130 : : }
+ 131 : : }
+ 132 : : }
@@ -222,7 +208,7 @@
diff --git a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html b/doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.func-sort-c.html
similarity index 62%
rename from doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html
rename to doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.func-sort-c.html
index 93f72fb..13a68b1 100644
--- a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html
+++ b/doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.func-sort-c.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/abstract/RuleValidateTransfer.sol - functions
+ LCOV - lcov.info - abstract/core/RuleTransferValidation.sol - functions
@@ -19,7 +19,7 @@
-
+
@@ -31,18 +31,18 @@
-
-
+
+
-
+
-
-
+
+
@@ -65,28 +65,28 @@
diff --git a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html b/doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.func.html
similarity index 62%
rename from doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html
rename to doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.func.html
index f811a3f..91fe5a9 100644
--- a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html
+++ b/doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.func.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/abstract/RuleValidateTransfer.sol - functions
+ LCOV - lcov.info - abstract/core/RuleTransferValidation.sol - functions
@@ -19,7 +19,7 @@
diff --git a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html b/doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.gcov.html
similarity index 66%
rename from doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html
rename to doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.gcov.html
index 174dc57..67c4f57 100644
--- a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html
+++ b/doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.gcov.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/abstract/RuleValidateTransfer.sol
+ LCOV - lcov.info - abstract/core/RuleTransferValidation.sol
@@ -19,7 +19,7 @@
-
+
@@ -31,18 +31,18 @@
-
-
+
+
-
+
-
-
+
+
@@ -74,86 +74,104 @@
3 : : pragma solidity ^0.8.20;
4 : :
5 : : /* ==== CMTAT === */
- 6 : : import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+ 6 : : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
7 : : import {IERC3643ComplianceRead} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
8 : : import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol";
9 : : /* ==== RuleEngine === */
10 : : import {IRule} from "RuleEngine/interfaces/IRule.sol";
- 11 : : import {
- 12 : : IERC7943NonFungibleCompliance,
- 13 : : IERC7943NonFungibleComplianceExtend
- 14 : : } from "../../interfaces/IERC7943NonFungibleCompliance.sol";
- 15 : :
- 16 : : abstract contract RuleValidateTransfer is IERC7943NonFungibleComplianceExtend, IRule {
- 17 : : /**
- 18 : : * @notice Validate a transfer
- 19 : : * @param from the origin address
- 20 : : * @param to the destination address
- 21 : : * @param tokenId ERC-721 or ERC-1155 token Id
- 22 : : * @param amount to transfer, 1 for NFT
- 23 : : * @return isValid => true if the transfer is valid, false otherwise
- 24 : : *
- 25 : : */
- 26 : 14 : function canTransfer(address from, address to, uint256 tokenId, uint256 amount)
- 27 : : public
- 28 : : view
- 29 : : override(IERC7943NonFungibleCompliance)
- 30 : : returns (bool isValid)
- 31 : : {
- 32 : : // does not work without `this` keyword => "Undeclared identifier"
- 33 : 14 : return this.detectTransferRestriction(from, to, tokenId, amount)
- 34 : : == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
- 35 : : }
- 36 : :
- 37 : : /**
- 38 : : * @notice Validate a transfer
- 39 : : * @param from the origin address
- 40 : : * @param to the destination address
- 41 : : * @param amount to transfer
- 42 : : * @return isValid => true if the transfer is valid, false otherwise
- 43 : : *
- 44 : : */
- 45 : 14 : function canTransfer(address from, address to, uint256 amount)
- 46 : : public
- 47 : : view
- 48 : : override(IERC3643ComplianceRead)
- 49 : : returns (bool isValid)
- 50 : : {
- 51 : : // does not work without `this` keyword => "Undeclared identifier"
- 52 : 14 : return this.detectTransferRestriction(from, to, amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
- 53 : : }
- 54 : :
- 55 : : /**
- 56 : : * @inheritdoc IERC7551Compliance
- 57 : : */
- 58 : 10 : function canTransferFrom(address spender, address from, address to, uint256 value)
- 59 : : public
- 60 : : view
- 61 : : virtual
- 62 : : override(IERC7551Compliance)
- 63 : : returns (bool)
- 64 : : {
- 65 : 20 : return this.detectTransferRestrictionFrom(spender, from, to, value)
- 66 : : == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 11 : : import {RuleInterfaceId} from "RuleEngine/modules/library/RuleInterfaceId.sol";
+ 12 : : /* ==== Modules === */
+ 13 : : import {VersionModule} from "../../../../modules/VersionModule.sol";
+ 14 : :
+ 15 : : abstract contract RuleTransferValidation is VersionModule, IERC1404Extend, IERC3643ComplianceRead, IERC7551Compliance, IRule {
+ 16 : : /**
+ 17 : : * @notice Internal transfer restriction check.
+ 18 : : * @param from the origin address
+ 19 : : * @param to the destination address
+ 20 : : * @param value amount to transfer
+ 21 : : * @return restrictionCode The restriction code for this rule.
+ 22 : : */
+ 23 : : function _detectTransferRestriction(address from, address to, uint256 value)
+ 24 : : internal
+ 25 : : view
+ 26 : : virtual
+ 27 : : returns (uint8 restrictionCode);
+ 28 : :
+ 29 : : /**
+ 30 : : * @notice Internal transfer restriction check for spender-initiated transfers.
+ 31 : : * @param spender the caller executing the transfer
+ 32 : : * @param from the origin address
+ 33 : : * @param to the destination address
+ 34 : : * @param value amount to transfer
+ 35 : : * @return restrictionCode The restriction code for this rule.
+ 36 : : */
+ 37 : : function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+ 38 : : internal
+ 39 : : view
+ 40 : : virtual
+ 41 : : returns (uint8 restrictionCode);
+ 42 : :
+ 43 : : /**
+ 44 : : * @inheritdoc IERC1404
+ 45 : : */
+ 46 : 348 : function detectTransferRestriction(address from, address to, uint256 value)
+ 47 : : public
+ 48 : : view
+ 49 : : virtual
+ 50 : : override(IERC1404)
+ 51 : : returns (uint8)
+ 52 : : {
+ 53 : 348 : return _detectTransferRestriction(from, to, value);
+ 54 : : }
+ 55 : :
+ 56 : : /**
+ 57 : : * @inheritdoc IERC1404Extend
+ 58 : : */
+ 59 : 36 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+ 60 : : public
+ 61 : : view
+ 62 : : virtual
+ 63 : : override(IERC1404Extend)
+ 64 : : returns (uint8)
+ 65 : : {
+ 66 : 36 : return _detectTransferRestrictionFrom(spender, from, to, value);
67 : : }
68 : :
69 : : /**
- 70 : : * @inheritdoc IERC7943NonFungibleComplianceExtend
- 71 : : */
- 72 : 10 : function canTransferFrom(address spender, address from, address to, uint256 tokenId, uint256 value)
- 73 : : public
- 74 : : view
- 75 : : virtual
- 76 : : override(IERC7943NonFungibleComplianceExtend)
- 77 : : returns (bool)
- 78 : : {
- 79 : 10 : return canTransferFrom(spender, from, to, value);
- 80 : : }
- 81 : :
- 82 : 0 : function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
- 83 : 0 : return interfaceId == type(IRule).interfaceId;
+ 70 : : * @notice Validate a transfer
+ 71 : : * @param from the origin address
+ 72 : : * @param to the destination address
+ 73 : : * @param amount to transfer
+ 74 : : * @return isValid => true if the transfer is valid, false otherwise
+ 75 : : *
+ 76 : : */
+ 77 : 20 : function canTransfer(address from, address to, uint256 amount)
+ 78 : : public
+ 79 : : view
+ 80 : : override(IERC3643ComplianceRead)
+ 81 : : returns (bool isValid)
+ 82 : : {
+ 83 : 20 : return _detectTransferRestriction(from, to, amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
84 : : }
- 85 : : }
+ 85 : :
+ 86 : : /**
+ 87 : : * @inheritdoc IERC7551Compliance
+ 88 : : */
+ 89 : 12 : function canTransferFrom(address spender, address from, address to, uint256 value)
+ 90 : : public
+ 91 : : view
+ 92 : : virtual
+ 93 : : override(IERC7551Compliance)
+ 94 : : returns (bool)
+ 95 : : {
+ 96 : 12 : return _detectTransferRestrictionFrom(spender, from, to, value)
+ 97 : : == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 98 : : }
+ 99 : :
+ 100 : 195 : function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
+ 101 : 195 : return interfaceId == type(IRule).interfaceId || interfaceId == RuleInterfaceId.IRULE_INTERFACE_ID;
+ 102 : : }
+ 103 : : }
diff --git a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html b/doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.func-sort-c.html
similarity index 71%
rename from doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html
rename to doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.func-sort-c.html
index bf6dc6f..588fc1b 100644
--- a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html
+++ b/doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.func-sort-c.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/abstract/RuleWhitelistCommon.sol - functions
+ LCOV - lcov.info - abstract/core/RuleWhitelistShared.sol - functions
@@ -19,7 +19,7 @@
-
+
@@ -37,7 +37,7 @@
-
+
@@ -65,32 +65,32 @@
diff --git a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html b/doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.func.html
similarity index 71%
rename from doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html
rename to doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.func.html
index 2fda202..956fe25 100644
--- a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html
+++ b/doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.func.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/abstract/RuleWhitelistCommon.sol - functions
+ LCOV - lcov.info - abstract/core/RuleWhitelistShared.sol - functions
@@ -19,7 +19,7 @@
diff --git a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html b/doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.gcov.html
similarity index 82%
rename from doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html
rename to doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.gcov.html
index 746edeb..e0552e4 100644
--- a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html
+++ b/doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.gcov.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/abstract/RuleWhitelistCommon.sol
+ LCOV - lcov.info - abstract/core/RuleWhitelistShared.sol
@@ -19,7 +19,7 @@
-
+
@@ -37,7 +37,7 @@
-
+
@@ -76,122 +76,115 @@
5 : : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
6 : : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
7 : : /* ==== Abstract contracts === */
- 8 : : import {RuleWhitelistInvariantStorage} from "./RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol";
- 9 : : import {RuleValidateTransfer} from "./RuleValidateTransfer.sol";
- 10 : : /* ==== Interface === */
- 11 : : import {
- 12 : : IERC7943NonFungibleCompliance,
- 13 : : IERC7943NonFungibleComplianceExtend
- 14 : : } from "../../interfaces/IERC7943NonFungibleCompliance.sol";
- 15 : :
- 16 : : /**
- 17 : : * @title Rule Whitelist Common
- 18 : : * @notice Provides common logic for validating whitelist-based transfer restrictions.
- 19 : : * @dev
- 20 : : * - Implements ERC-3643–compatible `transferred` hooks to enforce whitelist checks.
- 21 : : * - Defines utility functions for restriction code validation and message mapping.
- 22 : : * - Inherits restriction code constants and messages from {RuleWhitelistInvariantStorage}.
- 23 : : */
- 24 : : abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInvariantStorage {
- 25 : : /**
- 26 : : * Indicate if the spender is verified or not
- 27 : : */
- 28 : : bool public checkSpender;
- 29 : :
- 30 : : /* ============ View Functions ============ */
- 31 : : /**
- 32 : : * @notice Checks whether a restriction code is recognized by this rule.
- 33 : : * @dev
- 34 : : * Used to verify if a returned restriction code belongs to the whitelist rule.
- 35 : : * @param restrictionCode The restriction code to validate.
- 36 : : * @return isKnown True if the restriction code is recognized by this rule, false otherwise.
- 37 : : */
- 38 : 10 : function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override returns (bool isKnown) {
- 39 : 10 : return restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED
- 40 : 5 : || restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED || restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED;
- 41 : : }
- 42 : :
- 43 : : /**
- 44 : : * @notice Returns the human-readable message corresponding to a restriction code.
- 45 : : * @dev
- 46 : : * Returns a descriptive text that explains why a transfer was restricted.
- 47 : : * @param restrictionCode The restriction code to decode.
- 48 : : * @return message A human-readable explanation of the restriction.
- 49 : : */
- 50 : 14 : function messageForTransferRestriction(uint8 restrictionCode)
- 51 : : external
- 52 : : pure
- 53 : : override
- 54 : : returns (string memory message)
- 55 : : {
- 56 [ + + ]: 14 : if (restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) {
- 57 : 6 : return TEXT_ADDRESS_FROM_NOT_WHITELISTED;
- 58 [ + + ]: 8 : } else if (restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) {
- 59 : 4 : return TEXT_ADDRESS_TO_NOT_WHITELISTED;
- 60 [ + + ]: 4 : } else if (restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED) {
- 61 : 2 : return TEXT_ADDRESS_SPENDER_NOT_WHITELISTED;
- 62 : : } else {
- 63 : 2 : return TEXT_CODE_NOT_FOUND;
- 64 : : }
- 65 : : }
- 66 : :
- 67 : : /* ============ State Functions ============ */
- 68 : :
- 69 : : /**
- 70 : : * @notice ERC-3643 hook called when a transfer occurs.
- 71 : : * @dev
- 72 : : * - Validates that both `from` and `to` addresses are whitelisted.
- 73 : : * - Reverts if any restriction code other than `TRANSFER_OK` is returned.
- 74 : : * - Should be called during token transfer logic to enforce whitelist compliance.
- 75 : : * @param from The address sending tokens.
- 76 : : * @param to The address receiving tokens.
- 77 : : * @param value The token amount being transferred.
- 78 : : */
- 79 : 17 : function transferred(address from, address to, uint256 value) public view override(IERC3643IComplianceContract) {
- 80 : 22 : uint8 code = this.detectTransferRestriction(from, to, value);
- 81 [ + + ]: 22 : require(
- 82 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
- 83 : : RuleWhitelist_InvalidTransfer(address(this), from, to, value, code)
- 84 : : );
- 85 : : }
- 86 : :
- 87 : : /**
- 88 : : * @notice hook called when a delegated transfer occurs (`transferFrom`).
- 89 : : * @dev
- 90 : : * - Validates that `spender`, `from`, and `to` are all whitelisted.
- 91 : : * - Reverts if any restriction code other than `TRANSFER_OK` is returned.
- 92 : : * @param spender The address performing the transfer on behalf of another.
- 93 : : * @param from The address from which tokens are transferred.
- 94 : : * @param to The recipient address.
- 95 : : * @param value The token amount being transferred.
- 96 : : */
- 97 : 4 : function transferred(address spender, address from, address to, uint256 value) public view override(IRuleEngine) {
- 98 : 8 : uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value);
- 99 [ + + ]: 8 : require(
- 100 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
- 101 : : RuleWhitelist_InvalidTransferFrom(address(this), spender, from, to, value, code)
- 102 : : );
- 103 : : }
- 104 : :
- 105 : :
- 106 : 4 : function transferred(address spender, address from, address to, uint256 /* tokenId */,uint256 value)
- 107 : : public
- 108 : : view
- 109 : : virtual
- 110 : : override(IERC7943NonFungibleComplianceExtend)
- 111 : : {
- 112 : 4 : transferred(spender, from, to, value);
+ 8 : : import {RuleWhitelistInvariantStorage} from "../RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol";
+ 9 : : import {RuleNFTAdapter} from "./RuleNFTAdapter.sol";
+ 10 : :
+ 11 : : /**
+ 12 : : * @title Rule Whitelist Shared
+ 13 : : * @notice Provides common logic for validating whitelist-based transfer restrictions.
+ 14 : : * @dev
+ 15 : : * - Implements ERC-3643–compatible `transferred` hooks to enforce whitelist checks.
+ 16 : : * - Defines utility functions for restriction code validation and message mapping.
+ 17 : : * - Inherits restriction code constants and messages from {RuleWhitelistInvariantStorage}.
+ 18 : : */
+ 19 : : abstract contract RuleWhitelistShared is RuleNFTAdapter, RuleWhitelistInvariantStorage {
+ 20 : : /**
+ 21 : : * Indicate if the spender is verified or not
+ 22 : : */
+ 23 : : bool public checkSpender;
+ 24 : :
+ 25 : : /* ============ View Functions ============ */
+ 26 : : /**
+ 27 : : * @notice Checks whether a restriction code is recognized by this rule.
+ 28 : : * @dev
+ 29 : : * Used to verify if a returned restriction code belongs to the whitelist rule.
+ 30 : : * @param restrictionCode The restriction code to validate.
+ 31 : : * @return isKnown True if the restriction code is recognized by this rule, false otherwise.
+ 32 : : */
+ 33 : 10 : function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override returns (bool isKnown) {
+ 34 : 10 : return restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED
+ 35 : 5 : || restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED || restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED;
+ 36 : : }
+ 37 : :
+ 38 : : /**
+ 39 : : * @notice Returns the human-readable message corresponding to a restriction code.
+ 40 : : * @dev
+ 41 : : * Returns a descriptive text that explains why a transfer was restricted.
+ 42 : : * @param restrictionCode The restriction code to decode.
+ 43 : : * @return message A human-readable explanation of the restriction.
+ 44 : : */
+ 45 : 14 : function messageForTransferRestriction(uint8 restrictionCode)
+ 46 : : external
+ 47 : : pure
+ 48 : : override
+ 49 : : returns (string memory message)
+ 50 : : {
+ 51 [ + + ]: 14 : if (restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) {
+ 52 : 6 : return TEXT_ADDRESS_FROM_NOT_WHITELISTED;
+ 53 [ + + ]: 8 : } else if (restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) {
+ 54 : 4 : return TEXT_ADDRESS_TO_NOT_WHITELISTED;
+ 55 [ + + ]: 4 : } else if (restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED) {
+ 56 : 2 : return TEXT_ADDRESS_SPENDER_NOT_WHITELISTED;
+ 57 : : } else {
+ 58 : 2 : return TEXT_CODE_NOT_FOUND;
+ 59 : : }
+ 60 : : }
+ 61 : :
+ 62 : : /* ============ State Functions ============ */
+ 63 : :
+ 64 : : /**
+ 65 : : * @notice ERC-3643 hook called when a transfer occurs.
+ 66 : : * @dev
+ 67 : : * - Validates that both `from` and `to` addresses are whitelisted.
+ 68 : : * - Reverts if any restriction code other than `TRANSFER_OK` is returned.
+ 69 : : * - Validation only; does not modify state.
+ 70 : : * - Should be called during token transfer logic to enforce whitelist compliance.
+ 71 : : * @param from The address sending tokens.
+ 72 : : * @param to The address receiving tokens.
+ 73 : : * @param value The token amount being transferred.
+ 74 : : */
+ 75 : 19 : function transferred(address from, address to, uint256 value) public view override(IERC3643IComplianceContract) {
+ 76 : 19 : _transferred(from, to, value);
+ 77 : : }
+ 78 : :
+ 79 : : /**
+ 80 : : * @notice hook called when a delegated transfer occurs (`transferFrom`).
+ 81 : : * @dev
+ 82 : : * - Validates that `spender`, `from`, and `to` are all whitelisted.
+ 83 : : * - Reverts if any restriction code other than `TRANSFER_OK` is returned.
+ 84 : : * - Validation only; does not modify state.
+ 85 : : * @param spender The address performing the transfer on behalf of another.
+ 86 : : * @param from The address from which tokens are transferred.
+ 87 : : * @param to The recipient address.
+ 88 : : * @param value The token amount being transferred.
+ 89 : : */
+ 90 : 4 : function transferred(address spender, address from, address to, uint256 value) public view override(IRuleEngine) {
+ 91 : 4 : _transferredFrom(spender, from, to, value);
+ 92 : : }
+ 93 : :
+ 94 : 26 : function _transferred(address from, address to, uint256 value) internal view virtual override {
+ 95 : 26 : uint8 code = _detectTransferRestriction(from, to, value);
+ 96 [ + + ]: 26 : require(
+ 97 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+ 98 : : RuleWhitelist_InvalidTransfer(address(this), from, to, value, code)
+ 99 : : );
+ 100 : : }
+ 101 : :
+ 102 : 11 : function _transferredFrom(address spender, address from, address to, uint256 value)
+ 103 : : internal
+ 104 : : view
+ 105 : : virtual
+ 106 : : override
+ 107 : : {
+ 108 : 11 : uint8 code = _detectTransferRestrictionFrom(spender, from, to, value);
+ 109 [ + + ]: 11 : require(
+ 110 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+ 111 : : RuleWhitelist_InvalidTransferFrom(address(this), spender, from, to, value, code)
+ 112 : : );
113 : : }
114 : :
- 115 : 5 : function transferred(address from, address to, uint256 /* tokenId */,uint256 value)
- 116 : : public
- 117 : : view
- 118 : : virtual
- 119 : : override(IERC7943NonFungibleComplianceExtend)
- 120 : : {
- 121 : 5 : transferred(from, to, value);
- 122 : : }
- 123 : : }
+ 115 : :
+ 116 : : }
diff --git a/doc/coverage/coverage/abstract/core/index-sort-b.html b/doc/coverage/coverage/abstract/core/index-sort-b.html
new file mode 100644
index 0000000..226fe72
--- /dev/null
+++ b/doc/coverage/coverage/abstract/core/index-sort-b.html
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/core
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filename
+ Line Coverage
+ Functions
+ Branches
+
+
+ RuleTransferValidation.sol
+
+
+
+ 100.0 %
+ 10 / 10
+ 100.0 %
+ 5 / 5
+ -
+ 0 / 0
+
+
+ RuleNFTAdapter.sol
+
+
+
+ 100.0 %
+ 20 / 20
+ 100.0 %
+ 8 / 8
+ 100.0 %
+ 4 / 4
+
+
+ RuleWhitelistShared.sol
+
+
+
+ 100.0 %
+ 21 / 21
+ 100.0 %
+ 6 / 6
+ 100.0 %
+ 10 / 10
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/core/index-sort-f.html b/doc/coverage/coverage/abstract/core/index-sort-f.html
new file mode 100644
index 0000000..e680dc9
--- /dev/null
+++ b/doc/coverage/coverage/abstract/core/index-sort-f.html
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/core
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filename
+ Line Coverage
+ Functions
+ Branches
+
+
+ RuleTransferValidation.sol
+
+
+
+ 100.0 %
+ 10 / 10
+ 100.0 %
+ 5 / 5
+ -
+ 0 / 0
+
+
+ RuleWhitelistShared.sol
+
+
+
+ 100.0 %
+ 21 / 21
+ 100.0 %
+ 6 / 6
+ 100.0 %
+ 10 / 10
+
+
+ RuleNFTAdapter.sol
+
+
+
+ 100.0 %
+ 20 / 20
+ 100.0 %
+ 8 / 8
+ 100.0 %
+ 4 / 4
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/core/index-sort-l.html b/doc/coverage/coverage/abstract/core/index-sort-l.html
new file mode 100644
index 0000000..e557c1e
--- /dev/null
+++ b/doc/coverage/coverage/abstract/core/index-sort-l.html
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/core
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filename
+ Line Coverage
+ Functions
+ Branches
+
+
+ RuleTransferValidation.sol
+
+
+
+ 100.0 %
+ 10 / 10
+ 100.0 %
+ 5 / 5
+ -
+ 0 / 0
+
+
+ RuleNFTAdapter.sol
+
+
+
+ 100.0 %
+ 20 / 20
+ 100.0 %
+ 8 / 8
+ 100.0 %
+ 4 / 4
+
+
+ RuleWhitelistShared.sol
+
+
+
+ 100.0 %
+ 21 / 21
+ 100.0 %
+ 6 / 6
+ 100.0 %
+ 10 / 10
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/abstract/core/index.html b/doc/coverage/coverage/abstract/core/index.html
new file mode 100644
index 0000000..be497f9
--- /dev/null
+++ b/doc/coverage/coverage/abstract/core/index.html
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+ LCOV - lcov.info - abstract/core
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filename
+ Line Coverage
+ Functions
+ Branches
+
+
+ RuleNFTAdapter.sol
+
+
+
+ 100.0 %
+ 20 / 20
+ 100.0 %
+ 8 / 8
+ 100.0 %
+ 4 / 4
+
+
+ RuleTransferValidation.sol
+
+
+
+ 100.0 %
+ 10 / 10
+ 100.0 %
+ 5 / 5
+ -
+ 0 / 0
+
+
+ RuleWhitelistShared.sol
+
+
+
+ 100.0 %
+ 21 / 21
+ 100.0 %
+ 6 / 6
+ 100.0 %
+ 10 / 10
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleBlacklist.sol.func-sort-c.html
similarity index 61%
rename from doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html
rename to doc/coverage/coverage/deployment/RuleBlacklist.sol.func-sort-c.html
index 09bb6da..7a9f3cd 100644
--- a/doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html
+++ b/doc/coverage/coverage/deployment/RuleBlacklist.sol.func-sort-c.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/RuleBlacklist.sol - functions
+ LCOV - lcov.info - deployment/RuleBlacklist.sol - functions
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -69,48 +69,28 @@
Hit count
- RuleBlacklist.supportsInterface
- 0
-
-
- RuleBlacklist.transferred.1
- 2
-
-
- RuleBlacklist.transferred.2
- 2
-
-
- RuleBlacklist.transferred.3
- 3
-
-
- RuleBlacklist.canReturnTransferRestrictionCode
- 4
-
-
- RuleBlacklist.detectTransferRestrictionFrom.1
- 4
+ RuleBlacklist._authorizeAddressListRemove
+ 1
- RuleBlacklist.detectTransferRestriction.1
- 7
+ RuleBlacklist._msgData
+ 1
- RuleBlacklist.messageForTransferRestriction
- 8
+ RuleBlacklist._authorizeAddressListAdd
+ 28
- RuleBlacklist.transferred.0
- 9
+ RuleBlacklist._msgSender
+ 83
- RuleBlacklist.detectTransferRestrictionFrom.0
- 16
+ RuleBlacklist._contextSuffixLength
+ 84
- RuleBlacklist.detectTransferRestriction.0
- 22
+ RuleBlacklist.supportsInterface
+ 91
diff --git a/doc/coverage/coverage/validation/RuleBlacklist.sol.func.html b/doc/coverage/coverage/deployment/RuleBlacklist.sol.func.html
similarity index 61%
rename from doc/coverage/coverage/validation/RuleBlacklist.sol.func.html
rename to doc/coverage/coverage/deployment/RuleBlacklist.sol.func.html
index 7644183..a7a1b13 100644
--- a/doc/coverage/coverage/validation/RuleBlacklist.sol.func.html
+++ b/doc/coverage/coverage/deployment/RuleBlacklist.sol.func.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/RuleBlacklist.sol - functions
+ LCOV - lcov.info - deployment/RuleBlacklist.sol - functions
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -69,48 +69,28 @@
Hit count
- RuleBlacklist.canReturnTransferRestrictionCode
- 4
-
-
- RuleBlacklist.detectTransferRestriction.0
- 22
-
-
- RuleBlacklist.detectTransferRestriction.1
- 7
-
-
- RuleBlacklist.detectTransferRestrictionFrom.0
- 16
-
-
- RuleBlacklist.detectTransferRestrictionFrom.1
- 4
-
-
- RuleBlacklist.messageForTransferRestriction
- 8
+ RuleBlacklist._authorizeAddressListAdd
+ 28
- RuleBlacklist.supportsInterface
- 0
+ RuleBlacklist._authorizeAddressListRemove
+ 1
- RuleBlacklist.transferred.0
- 9
+ RuleBlacklist._contextSuffixLength
+ 84
- RuleBlacklist.transferred.1
- 2
+ RuleBlacklist._msgData
+ 1
- RuleBlacklist.transferred.2
- 2
+ RuleBlacklist._msgSender
+ 83
- RuleBlacklist.transferred.3
- 3
+ RuleBlacklist.supportsInterface
+ 91
diff --git a/doc/coverage/coverage/deployment/RuleBlacklist.sol.gcov.html b/doc/coverage/coverage/deployment/RuleBlacklist.sol.gcov.html
new file mode 100644
index 0000000..1f3c2dd
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleBlacklist.sol.gcov.html
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleBlacklist.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.func-sort-c.html
new file mode 100644
index 0000000..4f6c52b
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.func-sort-c.html
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleBlacklistOwnable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.func.html b/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.func.html
new file mode 100644
index 0000000..3adf440
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.func.html
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleBlacklistOwnable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.gcov.html b/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.gcov.html
new file mode 100644
index 0000000..1c015a0
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.gcov.html
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleBlacklistOwnable2Step.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleERC2980.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleERC2980.sol.func-sort-c.html
new file mode 100644
index 0000000..5982600
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleERC2980.sol.func-sort-c.html
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleERC2980.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleERC2980.sol.func.html b/doc/coverage/coverage/deployment/RuleERC2980.sol.func.html
new file mode 100644
index 0000000..2fc8959
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleERC2980.sol.func.html
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleERC2980.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleERC2980.sol.gcov.html b/doc/coverage/coverage/deployment/RuleERC2980.sol.gcov.html
new file mode 100644
index 0000000..44437e3
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleERC2980.sol.gcov.html
@@ -0,0 +1,168 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleERC2980.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.func-sort-c.html
new file mode 100644
index 0000000..6a57dc8
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.func-sort-c.html
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleERC2980Ownable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.func.html b/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.func.html
new file mode 100644
index 0000000..06ea5a4
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.func.html
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleERC2980Ownable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.gcov.html b/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.gcov.html
new file mode 100644
index 0000000..58cf267
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.gcov.html
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleERC2980Ownable2Step.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.func-sort-c.html
new file mode 100644
index 0000000..c671fdf
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.func-sort-c.html
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleIdentityRegistry.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.func.html b/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.func.html
new file mode 100644
index 0000000..03a6311
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.func.html
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleIdentityRegistry.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.gcov.html b/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.gcov.html
new file mode 100644
index 0000000..29c87c5
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.gcov.html
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleIdentityRegistry.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.func-sort-c.html
new file mode 100644
index 0000000..f0edaeb
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.func-sort-c.html
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleIdentityRegistryOwnable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.func.html b/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.func.html
new file mode 100644
index 0000000..f36b6a3
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.func.html
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleIdentityRegistryOwnable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.gcov.html b/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.gcov.html
new file mode 100644
index 0000000..c5464a5
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.gcov.html
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleIdentityRegistryOwnable2Step.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.func-sort-c.html
new file mode 100644
index 0000000..3d362ea
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.func-sort-c.html
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleMaxTotalSupply.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.func.html b/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.func.html
new file mode 100644
index 0000000..461eca6
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.func.html
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleMaxTotalSupply.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.gcov.html b/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.gcov.html
new file mode 100644
index 0000000..6933e67
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.gcov.html
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleMaxTotalSupply.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.func-sort-c.html
new file mode 100644
index 0000000..8f2bc94
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.func-sort-c.html
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleMaxTotalSupplyOwnable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.func.html b/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.func.html
new file mode 100644
index 0000000..9d21145
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.func.html
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleMaxTotalSupplyOwnable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.gcov.html b/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.gcov.html
new file mode 100644
index 0000000..e3cdd2f
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.gcov.html
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleMaxTotalSupplyOwnable2Step.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleSanctionsList.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleSanctionsList.sol.func-sort-c.html
new file mode 100644
index 0000000..1594a91
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleSanctionsList.sol.func-sort-c.html
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleSanctionsList.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleSanctionsList.sol.func.html b/doc/coverage/coverage/deployment/RuleSanctionsList.sol.func.html
new file mode 100644
index 0000000..dcf5ed0
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleSanctionsList.sol.func.html
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleSanctionsList.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleSanctionsList.sol.gcov.html b/doc/coverage/coverage/deployment/RuleSanctionsList.sol.gcov.html
new file mode 100644
index 0000000..5b789dd
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleSanctionsList.sol.gcov.html
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleSanctionsList.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Branch data Line data Source code
+
+ 1 : : // SPDX-License-Identifier: MPL-2.0
+ 2 : : pragma solidity ^0.8.20;
+ 3 : :
+ 4 : : import {AccessControlEnumerable} from "OZ/access/extensions/AccessControlEnumerable.sol";
+ 5 : : import {Context} from "OZ/utils/Context.sol";
+ 6 : : import {AccessControlModuleStandalone} from "../../../modules/AccessControlModuleStandalone.sol";
+ 7 : : import {MetaTxModuleStandalone, ERC2771Context} from "../../../modules/MetaTxModuleStandalone.sol";
+ 8 : : import {RuleSanctionsListBase} from "../abstract/base/RuleSanctionsListBase.sol";
+ 9 : : import {RuleTransferValidation} from "../abstract/core/RuleTransferValidation.sol";
+ 10 : : import {ISanctionsList} from "../../interfaces/ISanctionsList.sol";
+ 11 : :
+ 12 : : /**
+ 13 : : * @title RuleSanctionsList
+ 14 : : * @notice Compliance rule enforcing sanctions-screening for token transfers.
+ 15 : : */
+ 16 : : contract RuleSanctionsList is AccessControlModuleStandalone, RuleSanctionsListBase {
+ 17 : : /**
+ 18 : : * @param admin Address of the contract (Access Control)
+ 19 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
+ 20 : : */
+ 21 : : constructor(address admin, address forwarderIrrevocable, ISanctionsList sanctionContractOracle_)
+ 22 : : AccessControlModuleStandalone(admin)
+ 23 : : RuleSanctionsListBase(forwarderIrrevocable, sanctionContractOracle_)
+ 24 : : {}
+ 25 : :
+ 26 : 58 : function supportsInterface(bytes4 interfaceId)
+ 27 : : public
+ 28 : : view
+ 29 : : virtual
+ 30 : : override(AccessControlEnumerable, RuleTransferValidation)
+ 31 : : returns (bool)
+ 32 : : {
+ 33 : 58 : return AccessControlEnumerable.supportsInterface(interfaceId)
+ 34 : 39 : || RuleTransferValidation.supportsInterface(interfaceId);
+ 35 : : }
+ 36 : :
+ 37 : : /*//////////////////////////////////////////////////////////////
+ 38 : : ACCESS CONTROL
+ 39 : : //////////////////////////////////////////////////////////////*/
+ 40 : :
+ 41 : 17 : function _authorizeSanctionListManager() internal view virtual override onlyRole(SANCTIONLIST_ROLE) {}
+ 42 : :
+ 43 : : /*//////////////////////////////////////////////////////////////
+ 44 : : ERC-2771
+ 45 : : //////////////////////////////////////////////////////////////*/
+ 46 : :
+ 47 : 57 : function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) {
+ 48 : 57 : return ERC2771Context._msgSender();
+ 49 : : }
+ 50 : :
+ 51 : 1 : function _msgData() internal view virtual override(ERC2771Context, Context) returns (bytes calldata) {
+ 52 : 1 : return ERC2771Context._msgData();
+ 53 : : }
+ 54 : :
+ 55 : 58 : function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) {
+ 56 : 58 : return ERC2771Context._contextSuffixLength();
+ 57 : : }
+ 58 : : }
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.func-sort-c.html
new file mode 100644
index 0000000..d9f05d7
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.func-sort-c.html
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleSanctionsListOwnable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.func.html b/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.func.html
new file mode 100644
index 0000000..62bd796
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.func.html
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleSanctionsListOwnable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.gcov.html b/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.gcov.html
new file mode 100644
index 0000000..9cba0d5
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.gcov.html
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleSanctionsListOwnable2Step.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleWhitelist.sol.func-sort-c.html
similarity index 73%
rename from doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html
rename to doc/coverage/coverage/deployment/RuleWhitelist.sol.func-sort-c.html
index f9af8e7..86d6201 100644
--- a/doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html
+++ b/doc/coverage/coverage/deployment/RuleWhitelist.sol.func-sort-c.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/RuleWhitelist.sol - functions
+ LCOV - lcov.info - deployment/RuleWhitelist.sol - functions
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
+
+
-
-
-
+
+
+
@@ -69,32 +69,32 @@
Hit count
- RuleWhitelist.isVerified
- 0
+ RuleWhitelist._authorizeCheckSpenderManager
+ 1
- RuleWhitelist.supportsInterface
- 0
+ RuleWhitelist._msgData
+ 1
- RuleWhitelist.detectTransferRestrictionFrom.1
- 2
+ RuleWhitelist.supportsInterface
+ 40
- RuleWhitelist.detectTransferRestriction.1
- 7
+ RuleWhitelist._authorizeAddressListRemove
+ 263
- RuleWhitelist.detectTransferRestrictionFrom.0
- 10
+ RuleWhitelist._authorizeAddressListAdd
+ 348
- RuleWhitelist.detectTransferRestriction.0
- 20
+ RuleWhitelist._msgSender
+ 772
- RuleWhitelist.constructor
- 102
+ RuleWhitelist._contextSuffixLength
+ 773
diff --git a/doc/coverage/coverage/validation/RuleWhitelist.sol.func.html b/doc/coverage/coverage/deployment/RuleWhitelist.sol.func.html
similarity index 73%
rename from doc/coverage/coverage/validation/RuleWhitelist.sol.func.html
rename to doc/coverage/coverage/deployment/RuleWhitelist.sol.func.html
index e3f8fe0..b216e14 100644
--- a/doc/coverage/coverage/validation/RuleWhitelist.sol.func.html
+++ b/doc/coverage/coverage/deployment/RuleWhitelist.sol.func.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/RuleWhitelist.sol - functions
+ LCOV - lcov.info - deployment/RuleWhitelist.sol - functions
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
+
+
-
-
-
+
+
+
@@ -69,32 +69,32 @@
Hit count
- RuleWhitelist.constructor
- 102
+ RuleWhitelist._authorizeAddressListAdd
+ 348
- RuleWhitelist.detectTransferRestriction.0
- 20
+ RuleWhitelist._authorizeAddressListRemove
+ 263
- RuleWhitelist.detectTransferRestriction.1
- 7
+ RuleWhitelist._authorizeCheckSpenderManager
+ 1
- RuleWhitelist.detectTransferRestrictionFrom.0
- 10
+ RuleWhitelist._contextSuffixLength
+ 773
- RuleWhitelist.detectTransferRestrictionFrom.1
- 2
+ RuleWhitelist._msgData
+ 1
- RuleWhitelist.isVerified
- 0
+ RuleWhitelist._msgSender
+ 772
- RuleWhitelist.supportsInterface
- 0
+ RuleWhitelist.supportsInterface
+ 40
diff --git a/doc/coverage/coverage/deployment/RuleWhitelist.sol.gcov.html b/doc/coverage/coverage/deployment/RuleWhitelist.sol.gcov.html
new file mode 100644
index 0000000..ca176dc
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleWhitelist.sol.gcov.html
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleWhitelist.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Branch data Line data Source code
+
+ 1 : : // SPDX-License-Identifier: MPL-2.0
+ 2 : : pragma solidity ^0.8.20;
+ 3 : :
+ 4 : : import {AccessControlEnumerable} from "OZ/access/extensions/AccessControlEnumerable.sol";
+ 5 : : import {Context} from "OZ/utils/Context.sol";
+ 6 : : /* ==== Abstract contracts === */
+ 7 : : import {AccessControlModuleStandalone} from "../../../modules/AccessControlModuleStandalone.sol";
+ 8 : : import {RuleWhitelistBase} from "../abstract/base/RuleWhitelistBase.sol";
+ 9 : : import {RuleAddressSet} from "../abstract/RuleAddressSet/RuleAddressSet.sol";
+ 10 : : /* ==== CMTAT === */
+ 11 : :
+ 12 : : /**
+ 13 : : * @title Rule Whitelist
+ 14 : : * @notice Manages a whitelist of authorized addresses and enforces whitelist-based transfer restrictions.
+ 15 : : * @dev
+ 16 : : * - Inherits core address management logic from {RuleAddressSet}.
+ 17 : : * - Integrates restriction code logic from {RuleWhitelistShared}.
+ 18 : : * - Implements {IERC1404} to return specific restriction codes for non-whitelisted transfers.
+ 19 : : */
+ 20 : : contract RuleWhitelist is RuleWhitelistBase, AccessControlModuleStandalone {
+ 21 : : /*//////////////////////////////////////////////////////////////
+ 22 : : CONSTRUCTOR
+ 23 : : //////////////////////////////////////////////////////////////*/
+ 24 : : /**
+ 25 : : * @param admin Address of the contract (Access Control)
+ 26 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
+ 27 : : */
+ 28 : : constructor(address admin, address forwarderIrrevocable, bool checkSpender_)
+ 29 : : RuleWhitelistBase(forwarderIrrevocable, checkSpender_)
+ 30 : : AccessControlModuleStandalone(admin)
+ 31 : : {
+ 32 : : // no-op
+ 33 : : }
+ 34 : :
+ 35 : : /* ============ View Functions ============ */
+ 36 : :
+ 37 : : /**
+ 38 : : * @notice Indicates whether this contract supports a given interface.
+ 39 : : * @param interfaceId The interface identifier, as specified in ERC-165.
+ 40 : : * @return supported True if the interface is supported.
+ 41 : : */
+ 42 : 40 : function supportsInterface(bytes4 interfaceId)
+ 43 : : public
+ 44 : : view
+ 45 : : virtual
+ 46 : : override(AccessControlEnumerable, RuleWhitelistBase)
+ 47 : : returns (bool)
+ 48 : : {
+ 49 : 40 : return AccessControlEnumerable.supportsInterface(interfaceId) || RuleWhitelistBase.supportsInterface(interfaceId);
+ 50 : : }
+ 51 : :
+ 52 : : /*//////////////////////////////////////////////////////////////
+ 53 : : ACCESS CONTROL
+ 54 : : //////////////////////////////////////////////////////////////*/
+ 55 : :
+ 56 : 1 : function _authorizeCheckSpenderManager() internal view virtual override onlyRole(DEFAULT_ADMIN_ROLE) {}
+ 57 : :
+ 58 : 348 : function _authorizeAddressListAdd() internal view virtual override onlyRole(ADDRESS_LIST_ADD_ROLE) {}
+ 59 : :
+ 60 : 263 : function _authorizeAddressListRemove() internal view virtual override onlyRole(ADDRESS_LIST_REMOVE_ROLE) {}
+ 61 : :
+ 62 : 772 : function _msgSender() internal view virtual override(Context, RuleAddressSet) returns (address sender) {
+ 63 : 772 : return super._msgSender();
+ 64 : : }
+ 65 : :
+ 66 : 1 : function _msgData() internal view virtual override(Context, RuleAddressSet) returns (bytes calldata) {
+ 67 : 1 : return super._msgData();
+ 68 : : }
+ 69 : :
+ 70 : 773 : function _contextSuffixLength() internal view virtual override(Context, RuleAddressSet) returns (uint256) {
+ 71 : 773 : return super._contextSuffixLength();
+ 72 : : }
+ 73 : : }
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.func-sort-c.html
new file mode 100644
index 0000000..1d0cde2
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.func-sort-c.html
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleWhitelistOwnable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.func.html b/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.func.html
new file mode 100644
index 0000000..aaac14d
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.func.html
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleWhitelistOwnable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.gcov.html b/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.gcov.html
new file mode 100644
index 0000000..e0f2605
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.gcov.html
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleWhitelistOwnable2Step.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.func-sort-c.html
similarity index 64%
rename from doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html
rename to doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.func-sort-c.html
index 19a2bf6..b118fa8 100644
--- a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html
+++ b/doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.func-sort-c.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/RuleWhitelistWrapper.sol - functions
+ LCOV - lcov.info - deployment/RuleWhitelistWrapper.sol - functions
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
+
+
-
-
-
+
+
+
@@ -69,48 +69,40 @@
Hit count
- RuleWhitelistWrapper._msgData
- 0
+ RuleWhitelistWrapper._msgData
+ 1
- RuleWhitelistWrapper.supportsInterface
- 0
+ RuleWhitelistWrapper._revokeRole
+ 1
- RuleWhitelistWrapper.detectTransferRestrictionFrom.1
+ RuleWhitelistWrapper._authorizeCheckSpenderManager
2
- RuleWhitelistWrapper.detectTransferRestriction.1
- 4
-
-
- RuleWhitelistWrapper.detectTransferRestrictionFrom.0
- 10
-
-
- RuleWhitelistWrapper.hasRole
- 20
+ RuleWhitelistWrapper._grantRole
+ 38
- RuleWhitelistWrapper.detectTransferRestriction.0
- 21
+ RuleWhitelistWrapper.hasRole
+ 38
- RuleWhitelistWrapper.constructor
- 22
+ RuleWhitelistWrapper.supportsInterface
+ 46
- RuleWhitelistWrapper._detectTransferRestriction
- 37
+ RuleWhitelistWrapper._onlyRulesManager
+ 90
- RuleWhitelistWrapper._contextSuffixLength
- 80
+ RuleWhitelistWrapper._msgSender
+ 133
- RuleWhitelistWrapper._msgSender
- 80
+ RuleWhitelistWrapper._contextSuffixLength
+ 134
diff --git a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html b/doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.func.html
similarity index 64%
rename from doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html
rename to doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.func.html
index 4994cad..c7034ec 100644
--- a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html
+++ b/doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.func.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - validation/RuleWhitelistWrapper.sol - functions
+ LCOV - lcov.info - deployment/RuleWhitelistWrapper.sol - functions
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
+
+
-
-
-
+
+
+
@@ -69,48 +69,40 @@
Hit count
- RuleWhitelistWrapper._contextSuffixLength
- 80
-
-
- RuleWhitelistWrapper._detectTransferRestriction
- 37
-
-
- RuleWhitelistWrapper._msgData
- 0
+ RuleWhitelistWrapper._authorizeCheckSpenderManager
+ 2
- RuleWhitelistWrapper._msgSender
- 80
+ RuleWhitelistWrapper._contextSuffixLength
+ 134
- RuleWhitelistWrapper.constructor
- 22
+ RuleWhitelistWrapper._grantRole
+ 38
- RuleWhitelistWrapper.detectTransferRestriction.0
- 21
+ RuleWhitelistWrapper._msgData
+ 1
- RuleWhitelistWrapper.detectTransferRestriction.1
- 4
+ RuleWhitelistWrapper._msgSender
+ 133
- RuleWhitelistWrapper.detectTransferRestrictionFrom.0
- 10
+ RuleWhitelistWrapper._onlyRulesManager
+ 90
- RuleWhitelistWrapper.detectTransferRestrictionFrom.1
- 2
+ RuleWhitelistWrapper._revokeRole
+ 1
- RuleWhitelistWrapper.hasRole
- 20
+ RuleWhitelistWrapper.hasRole
+ 38
- RuleWhitelistWrapper.supportsInterface
- 0
+ RuleWhitelistWrapper.supportsInterface
+ 46
diff --git a/doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.gcov.html b/doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.gcov.html
new file mode 100644
index 0000000..fee07c5
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.gcov.html
@@ -0,0 +1,183 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleWhitelistWrapper.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Branch data Line data Source code
+
+ 1 : : // SPDX-License-Identifier: MPL-2.0
+ 2 : :
+ 3 : : pragma solidity ^0.8.20;
+ 4 : :
+ 5 : : /* ==== OpenZeppelin === */
+ 6 : : import {AccessControl} from "OZ/access/AccessControl.sol";
+ 7 : : import {AccessControlEnumerable} from "OZ/access/extensions/AccessControlEnumerable.sol";
+ 8 : : import {Context} from "OZ/utils/Context.sol";
+ 9 : : /* ==== Abstract contracts === */
+ 10 : : import {AccessControlModuleStandalone} from "../../../modules/AccessControlModuleStandalone.sol";
+ 11 : : import {RuleWhitelistWrapperBase} from "../abstract/base/RuleWhitelistWrapperBase.sol";
+ 12 : :
+ 13 : : /**
+ 14 : : * @title Wrapper to call several different whitelist rules
+ 15 : : */
+ 16 : : contract RuleWhitelistWrapper is
+ 17 : : RuleWhitelistWrapperBase,
+ 18 : : AccessControlModuleStandalone
+ 19 : : {
+ 20 : : /*//////////////////////////////////////////////////////////////
+ 21 : : CONSTRUCTOR
+ 22 : : //////////////////////////////////////////////////////////////*/
+ 23 : : /**
+ 24 : : * @param admin Address of the contract (Access Control)
+ 25 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
+ 26 : : */
+ 27 : : constructor(address admin, address forwarderIrrevocable, bool checkSpender_)
+ 28 : : RuleWhitelistWrapperBase(forwarderIrrevocable, checkSpender_)
+ 29 : : AccessControlModuleStandalone(admin)
+ 30 : : {}
+ 31 : :
+ 32 : : /* ============ Access control ============ */
+ 33 : :
+ 34 : : /**
+ 35 : : * @dev Returns `true` if `account` has been granted `role`.
+ 36 : : */
+ 37 : 38 : function hasRole(bytes32 role, address account)
+ 38 : : public
+ 39 : : view
+ 40 : : virtual
+ 41 : : override(AccessControl, AccessControlModuleStandalone)
+ 42 : : returns (bool)
+ 43 : : {
+ 44 : 134 : return AccessControlModuleStandalone.hasRole(role, account);
+ 45 : : }
+ 46 : :
+ 47 : 2 : function _authorizeCheckSpenderManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {}
+ 48 : :
+ 49 : : /**
+ 50 : : * @dev Restrict rules management to the dedicated role.
+ 51 : : */
+ 52 : 90 : function _onlyRulesManager() internal virtual override onlyRole(RULES_MANAGEMENT_ROLE) {}
+ 53 : :
+ 54 : : /*//////////////////////////////////////////////////////////////
+ 55 : : ERC-2771
+ 56 : : //////////////////////////////////////////////////////////////*/
+ 57 : :
+ 58 : 133 : function _msgSender() internal view virtual override(RuleWhitelistWrapperBase, Context) returns (address sender) {
+ 59 : 133 : return RuleWhitelistWrapperBase._msgSender();
+ 60 : : }
+ 61 : :
+ 62 : 1 : function _msgData() internal view virtual override(RuleWhitelistWrapperBase, Context) returns (bytes calldata) {
+ 63 : 1 : return RuleWhitelistWrapperBase._msgData();
+ 64 : : }
+ 65 : :
+ 66 : 134 : function _contextSuffixLength() internal view virtual override(RuleWhitelistWrapperBase, Context) returns (uint256) {
+ 67 : 134 : return RuleWhitelistWrapperBase._contextSuffixLength();
+ 68 : : }
+ 69 : :
+ 70 : 46 : function supportsInterface(bytes4 interfaceId)
+ 71 : : public
+ 72 : : view
+ 73 : : virtual
+ 74 : : override(AccessControlEnumerable, RuleWhitelistWrapperBase)
+ 75 : : returns (bool)
+ 76 : : {
+ 77 : 46 : return RuleWhitelistWrapperBase.supportsInterface(interfaceId)
+ 78 : 16 : || AccessControlEnumerable.supportsInterface(interfaceId);
+ 79 : : }
+ 80 : :
+ 81 : 38 : function _grantRole(bytes32 role, address account)
+ 82 : : internal
+ 83 : : virtual
+ 84 : : override(AccessControl, AccessControlEnumerable)
+ 85 : : returns (bool)
+ 86 : : {
+ 87 : 38 : return AccessControlEnumerable._grantRole(role, account);
+ 88 : : }
+ 89 : :
+ 90 : 1 : function _revokeRole(bytes32 role, address account)
+ 91 : : internal
+ 92 : : virtual
+ 93 : : override(AccessControl, AccessControlEnumerable)
+ 94 : : returns (bool)
+ 95 : : {
+ 96 : 1 : return AccessControlEnumerable._revokeRole(role, account);
+ 97 : : }
+ 98 : : }
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.func-sort-c.html
new file mode 100644
index 0000000..b67a8e6
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.func-sort-c.html
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleWhitelistWrapperOwnable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.func.html b/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.func.html
new file mode 100644
index 0000000..b704ccc
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.func.html
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleWhitelistWrapperOwnable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.gcov.html b/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.gcov.html
new file mode 100644
index 0000000..211abff
--- /dev/null
+++ b/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.gcov.html
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment/RuleWhitelistWrapperOwnable2Step.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/index-sort-b.html b/doc/coverage/coverage/deployment/index-sort-b.html
new file mode 100644
index 0000000..ebfc836
--- /dev/null
+++ b/doc/coverage/coverage/deployment/index-sort-b.html
@@ -0,0 +1,263 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/index-sort-f.html b/doc/coverage/coverage/deployment/index-sort-f.html
new file mode 100644
index 0000000..a3d26c0
--- /dev/null
+++ b/doc/coverage/coverage/deployment/index-sort-f.html
@@ -0,0 +1,263 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/index-sort-l.html b/doc/coverage/coverage/deployment/index-sort-l.html
new file mode 100644
index 0000000..6ace07a
--- /dev/null
+++ b/doc/coverage/coverage/deployment/index-sort-l.html
@@ -0,0 +1,263 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/deployment/index.html b/doc/coverage/coverage/deployment/index.html
new file mode 100644
index 0000000..e2cc395
--- /dev/null
+++ b/doc/coverage/coverage/deployment/index.html
@@ -0,0 +1,263 @@
+
+
+
+
+
+
+ LCOV - lcov.info - deployment
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func-sort-c.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func-sort-c.html
index 5ee975a..6e237b7 100644
--- a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func-sort-c.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func-sort-c.html
@@ -31,13 +31,13 @@
-
-
+
+
-
+
@@ -49,8 +49,8 @@
-
-
+
+
@@ -69,12 +69,12 @@
Hit count
- AccessControlModuleStandalone.constructor
- 161
+ AccessControlModuleStandalone.constructor
+ 396
AccessControlModuleStandalone.hasRole
- 228
+ 507
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func.html
index 5e3e889..ce374e8 100644
--- a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func.html
@@ -31,13 +31,13 @@
-
-
+
+
-
+
@@ -49,8 +49,8 @@
-
-
+
+
@@ -69,12 +69,12 @@
Hit count
- AccessControlModuleStandalone.constructor
- 161
+ AccessControlModuleStandalone.constructor
+ 396
AccessControlModuleStandalone.hasRole
- 228
+ 507
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.gcov.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.gcov.html
index 001fd5e..0ff4430 100644
--- a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.gcov.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.gcov.html
@@ -31,13 +31,13 @@
-
-
+
+
-
+
@@ -49,8 +49,8 @@
-
-
+
+
@@ -75,29 +75,29 @@
4 : :
5 : : /* ==== OpenZeppelin === */
6 : : import {AccessControl} from "OZ/access/AccessControl.sol";
- 7 : :
- 8 : : abstract contract AccessControlModuleStandalone is AccessControl {
- 9 : : error AccessControlModuleStandalone_AddressZeroNotAllowed();
- 10 : : /* ============ Constructor ============ */
- 11 : : /**
- 12 : : * @notice Assigns the provided address as the default admin.
- 13 : : * @dev
- 14 : : * - Reverts if `admin` is the zero address.
- 15 : : * - Grants `DEFAULT_ADMIN_ROLE` to `admin`.
- 16 : : * The return value of `_grantRole` is intentionally ignored, as it returns `false`
- 17 : : * only when the role was already granted.
- 18 : : *
- 19 : : * @param admin The address that will receive the `DEFAULT_ADMIN_ROLE`.
- 20 : : */
- 21 : :
- 22 : 161 : constructor(address admin) {
- 23 [ + ]: 161 : if (admin == address(0)) {
- 24 : 4 : revert AccessControlModuleStandalone_AddressZeroNotAllowed();
- 25 : : }
+ 7 : : import {IAccessControl} from "OZ/access/IAccessControl.sol";
+ 8 : : import {AccessControlEnumerable} from "OZ/access/extensions/AccessControlEnumerable.sol";
+ 9 : :
+ 10 : : abstract contract AccessControlModuleStandalone is AccessControlEnumerable {
+ 11 : : error AccessControlModuleStandalone_AddressZeroNotAllowed();
+ 12 : : /* ============ Constructor ============ */
+ 13 : : /**
+ 14 : : * @notice Assigns the provided address as the default admin.
+ 15 : : * @dev
+ 16 : : * - Reverts if `admin` is the zero address.
+ 17 : : * - Grants `DEFAULT_ADMIN_ROLE` to `admin`.
+ 18 : : * The return value of `_grantRole` is intentionally ignored, as it returns `false`
+ 19 : : * only when the role was already granted.
+ 20 : : *
+ 21 : : * @param admin The address that will receive the `DEFAULT_ADMIN_ROLE`.
+ 22 : : */
+ 23 : :
+ 24 : 396 : constructor(address admin) {
+ 25 [ + + ]: 396 : require(admin != address(0), AccessControlModuleStandalone_AddressZeroNotAllowed());
26 : : // we don't check the return value
27 : : // _grantRole attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
28 : : // return false only if the admin has already the role
- 29 : 157 : _grantRole(DEFAULT_ADMIN_ROLE, admin);
+ 29 : 391 : _grantRole(DEFAULT_ADMIN_ROLE, admin);
30 : : }
31 : :
32 : : /*//////////////////////////////////////////////////////////////
@@ -106,15 +106,22 @@
35 : : /**
36 : : * @dev Returns `true` if `account` has been granted `role`.
37 : : */
- 38 : 228 : function hasRole(bytes32 role, address account) public view virtual override(AccessControl) returns (bool) {
- 39 : : // The Default Admin has all roles
- 40 [ + + ]: 328 : if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
- 41 : 152 : return true;
- 42 : : } else {
- 43 : 176 : return AccessControl.hasRole(role, account);
- 44 : : }
- 45 : : }
- 46 : : }
+ 38 : 507 : function hasRole(bytes32 role, address account)
+ 39 : : public
+ 40 : : view
+ 41 : : virtual
+ 42 : : override(AccessControl, IAccessControl)
+ 43 : : returns (bool)
+ 44 : : {
+ 45 : : // Dev note: default admin is treated as having all roles but may not appear in enumerable role members.
+ 46 : : // The Default Admin has all roles
+ 47 [ + + ]: 3597 : if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
+ 48 : 3110 : return true;
+ 49 : : } else {
+ 50 : 487 : return AccessControl.hasRole(role, account);
+ 51 : : }
+ 52 : : }
+ 53 : : }
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.func-sort-c.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.func-sort-c.html
new file mode 100644
index 0000000..9a3a841
--- /dev/null
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.func-sort-c.html
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.func.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.func.html
new file mode 100644
index 0000000..ba069d3
--- /dev/null
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.func.html
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.gcov.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.gcov.html
new file mode 100644
index 0000000..21cb955
--- /dev/null
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.gcov.html
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-b.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-b.html
index 6514966..1c2b511 100644
--- a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-b.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-b.html
@@ -31,17 +31,17 @@
-
-
+
+
-
+
-
-
+
+
@@ -49,8 +49,8 @@
-
-
+
+
@@ -81,17 +81,29 @@
Functions
Branches
+
+ VersionModule.sol
+
+
+
+ 100.0 %
+ 2 / 2
+ 100.0 %
+ 1 / 1
+ -
+ 0 / 0
+
AccessControlModuleStandalone.sol
100.0 %
- 8 / 8
+ 7 / 7
100.0 %
2 / 2
100.0 %
- 3 / 3
+ 4 / 4
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-f.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-f.html
index d593422..250be9c 100644
--- a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-f.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-f.html
@@ -31,17 +31,17 @@
-
-
+
+
-
+
-
-
+
+
@@ -49,8 +49,8 @@
-
-
+
+
@@ -81,17 +81,29 @@
Functions
Branches
+
+ VersionModule.sol
+
+
+
+ 100.0 %
+ 2 / 2
+ 100.0 %
+ 1 / 1
+ -
+ 0 / 0
+
AccessControlModuleStandalone.sol
100.0 %
- 8 / 8
+ 7 / 7
100.0 %
2 / 2
100.0 %
- 3 / 3
+ 4 / 4
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-l.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-l.html
index 42bb733..38d71c7 100644
--- a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-l.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-l.html
@@ -31,17 +31,17 @@
-
-
+
+
-
+
-
-
+
+
@@ -49,8 +49,8 @@
-
-
+
+
@@ -81,17 +81,29 @@
Functions
Branches
+
+ VersionModule.sol
+
+
+
+ 100.0 %
+ 2 / 2
+ 100.0 %
+ 1 / 1
+ -
+ 0 / 0
+
AccessControlModuleStandalone.sol
100.0 %
- 8 / 8
+ 7 / 7
100.0 %
2 / 2
100.0 %
- 3 / 3
+ 4 / 4
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index.html
index 7bed3a1..e1ab118 100644
--- a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index.html
@@ -31,17 +31,17 @@
-
-
+
+
-
+
-
-
+
+
@@ -49,8 +49,8 @@
-
-
+
+
@@ -87,11 +87,23 @@
100.0 %
- 8 / 8
+ 7 / 7
+ 100.0 %
+ 2 / 2
+ 100.0 %
+ 4 / 4
+
+
+ VersionModule.sol
+
+
+
100.0 %
2 / 2
100.0 %
- 3 / 3
+ 1 / 1
+ -
+ 0 / 0
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.func-sort-c.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.func-sort-c.html
new file mode 100644
index 0000000..79562b0
--- /dev/null
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.func-sort-c.html
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.func.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.func.html
new file mode 100644
index 0000000..a785d77
--- /dev/null
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.func.html
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.gcov.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.gcov.html
new file mode 100644
index 0000000..c7dd5c5
--- /dev/null
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.gcov.html
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Branch data Line data Source code
+
+ 1 : : // SPDX-License-Identifier: MPL-2.0
+ 2 : : pragma solidity ^0.8.20;
+ 3 : :
+ 4 : : import {AccessControlEnumerable} from "OZ/access/extensions/AccessControlEnumerable.sol";
+ 5 : : import {IERC165} from "OZ/utils/introspection/IERC165.sol";
+ 6 : : import {IRule} from "RuleEngine/interfaces/IRule.sol";
+ 7 : : import {RuleInterfaceId} from "RuleEngine/modules/library/RuleInterfaceId.sol";
+ 8 : : import {AccessControlModuleStandalone} from "../../modules/AccessControlModuleStandalone.sol";
+ 9 : : import {ERC3643ComplianceModule} from "RuleEngine/modules/ERC3643ComplianceModule.sol";
+ 10 : : import {RuleConditionalTransferLightBase} from "./abstract/RuleConditionalTransferLightBase.sol";
+ 11 : :
+ 12 : : /**
+ 13 : : * @title ConditionalTransferLight
+ 14 : : * @dev Requires operator approval for each transfer. Same transfer (from, to, value)
+ 15 : : * can be approved multiple times to allow repeated transfers.
+ 16 : : */
+ 17 : : contract RuleConditionalTransferLight is
+ 18 : : AccessControlModuleStandalone,
+ 19 : : ERC3643ComplianceModule,
+ 20 : : RuleConditionalTransferLightBase
+ 21 : : {
+ 22 : : /**
+ 23 : : * @param admin Address of the contract admin.
+ 24 : : */
+ 25 : : constructor(address admin) AccessControlModuleStandalone(admin) {}
+ 26 : :
+ 27 : 18 : function supportsInterface(bytes4 interfaceId)
+ 28 : : public
+ 29 : : view
+ 30 : : virtual
+ 31 : : override(AccessControlEnumerable, IERC165)
+ 32 : : returns (bool)
+ 33 : : {
+ 34 : 18 : return interfaceId == RuleInterfaceId.IRULE_INTERFACE_ID || interfaceId == type(IRule).interfaceId
+ 35 : 11 : || AccessControlEnumerable.supportsInterface(interfaceId);
+ 36 : : }
+ 37 : :
+ 38 : 1 : function created(address to, uint256 value) external onlyBoundToken {
+ 39 : 1 : _transferred(address(0), to, value);
+ 40 : : }
+ 41 : :
+ 42 : 1 : function destroyed(address from, uint256 value) external onlyBoundToken {
+ 43 : 1 : _transferred(from, address(0), value);
+ 44 : : }
+ 45 : :
+ 46 : 1947 : function _authorizeTransferApproval() internal view virtual override onlyRole(OPERATOR_ROLE) {}
+ 47 : :
+ 48 : 857 : function _authorizeTransferExecution() internal view virtual override {
+ 49 [ + + ]: 857 : require(
+ 50 : : isTokenBound(_msgSender()),
+ 51 : : RuleConditionalTransferLight_TransferExecutorUnauthorized(_msgSender())
+ 52 : : );
+ 53 : : }
+ 54 : :
+ 55 : 19 : function _onlyComplianceManager() internal virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) {}
+ 56 : : }
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.func-sort-c.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.func-sort-c.html
new file mode 100644
index 0000000..b181ee1
--- /dev/null
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.func-sort-c.html
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.func.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.func.html
new file mode 100644
index 0000000..60b99de
--- /dev/null
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.func.html
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.gcov.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.gcov.html
new file mode 100644
index 0000000..b0a0b09
--- /dev/null
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.gcov.html
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.func-sort-c.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.func-sort-c.html
new file mode 100644
index 0000000..d8df2c5
--- /dev/null
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.func-sort-c.html
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.func.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.func.html
new file mode 100644
index 0000000..bd1a0a3
--- /dev/null
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.func.html
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.gcov.html
similarity index 50%
rename from doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html
rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.gcov.html
index 9ee3de4..4dc44fd 100644
--- a/doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.gcov.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - validation/RuleBlacklist.sol
-
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol
+
LCOV - code coverage report
-
+
-
+
@@ -31,34 +31,34 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
+
+
-
+
-
+
@@ -70,192 +70,193 @@
Branch data Line data Source code
1 : : // SPDX-License-Identifier: MPL-2.0
- 2 : :
- 3 : : pragma solidity ^0.8.20;
- 4 : :
- 5 : : import {AccessControl} from "OZ/access/AccessControl.sol";
- 6 : : /* ==== Abtract contracts === */
- 7 : : import {RuleBlacklistInvariantStorage} from
- 8 : : "./abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol";
- 9 : : import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol";
- 10 : : import {RuleValidateTransfer, RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol";
- 11 : : /* ==== Interfaces === */
- 12 : : import {IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol";
- 13 : : /* ==== CMTAT === */
- 14 : : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
- 15 : : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
- 16 : : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
- 17 : : /* ==== IRuleEngine === */
- 18 : : import {IRule} from "RuleEngine/interfaces/IRule.sol";
- 19 : :
- 20 : : /**
- 21 : : * @title a blacklist manager
- 22 : : */
- 23 : : contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInvariantStorage {
- 24 : : /*//////////////////////////////////////////////////////////////
- 25 : : CONSTRUCTOR
- 26 : : //////////////////////////////////////////////////////////////*/
- 27 : : /**
- 28 : : * @param admin Address of the contract (Access Control)
- 29 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
- 30 : : */
- 31 : : constructor(address admin, address forwarderIrrevocable) RuleAddressSet(admin, forwarderIrrevocable) {}
- 32 : :
- 33 : : /* ============ View Functions ============ */
- 34 : : /**
- 35 : : * @notice Check if an addres is in the whitelist or not
- 36 : : * @param from the origin address
- 37 : : * @param to the destination address
- 38 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
- 39 : : *
- 40 : : */
- 41 : 22 : function detectTransferRestriction(address from, address to, uint256 /* value */ )
- 42 : : public
- 43 : : view
- 44 : : override(IERC1404)
- 45 : : returns (uint8)
- 46 : : {
- 47 [ + + ]: 43 : if (isAddressListed(from)) {
- 48 : 14 : return CODE_ADDRESS_FROM_IS_BLACKLISTED;
- 49 [ + + ]: 29 : } else if (isAddressListed(to)) {
- 50 : 13 : return CODE_ADDRESS_TO_IS_BLACKLISTED;
- 51 : : } else {
- 52 : 16 : return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
- 53 : : }
- 54 : : }
- 55 : :
- 56 : : /*
- 57 : : * @inheritdoc IERC7943NonFungibleComplianceExtend
- 58 : : */
- 59 : 7 : function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value)
- 60 : : public
- 61 : : view
- 62 : : override(IERC7943NonFungibleComplianceExtend)
- 63 : : returns (uint8)
- 64 : : {
- 65 : 7 : return detectTransferRestriction(from, to, value);
- 66 : : }
- 67 : :
- 68 : : /*
- 69 : : * @inheritdoc IERC1404Extend
- 70 : : */
- 71 : 16 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
- 72 : : public
- 73 : : view
- 74 : : override(IERC1404Extend)
- 75 : : returns (uint8)
- 76 : : {
- 77 [ + + ]: 20 : if (isAddressListed(spender)) {
- 78 : 6 : return CODE_ADDRESS_SPENDER_IS_BLACKLISTED;
- 79 : : } else {
- 80 : 14 : return detectTransferRestriction(from, to, value);
- 81 : : }
- 82 : : }
- 83 : :
- 84 : : /**
- 85 : : * @inheritdoc IERC7943NonFungibleComplianceExtend
- 86 : : */
- 87 : 4 : function detectTransferRestrictionFrom(
- 88 : : address spender,
- 89 : : address from,
- 90 : : address to,
- 91 : : uint256, /* tokenId */
- 92 : : uint256 value
- 93 : : ) public view override(IERC7943NonFungibleComplianceExtend) returns (uint8) {
- 94 : 4 : return detectTransferRestrictionFrom(spender, from, to, value);
- 95 : : }
- 96 : :
- 97 : : /**
- 98 : : * @notice To know if the restriction code is valid for this rule or not.
- 99 : : * @param _restrictionCode The target restriction code
- 100 : : * @return true if the restriction code is known, false otherwise
- 101 : : *
- 102 : : */
- 103 : 4 : function canReturnTransferRestrictionCode(uint8 _restrictionCode)
- 104 : : public
- 105 : : pure
- 106 : : virtual
- 107 : : override(IRule)
- 108 : : returns (bool)
- 109 : : {
- 110 : 4 : return _restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED
- 111 : 2 : || _restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED || _restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED;
- 112 : : }
- 113 : :
- 114 : : /**
- 115 : : * @notice Return the corresponding message
- 116 : : * @param _restrictionCode The target restriction code
- 117 : : * @return true if the transfer is valid, false otherwise
- 118 : : *
- 119 : : */
- 120 : 8 : function messageForTransferRestriction(uint8 _restrictionCode)
+ 2 : : pragma solidity ^0.8.20;
+ 3 : :
+ 4 : : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+ 5 : : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+ 6 : : import {IERC3643ComplianceRead, IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+ 7 : : import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol";
+ 8 : : import {IRule} from "RuleEngine/interfaces/IRule.sol";
+ 9 : : import {ITransferContext} from "../../interfaces/ITransferContext.sol";
+ 10 : : import {IERC20} from "OZ/token/ERC20/IERC20.sol";
+ 11 : : import {
+ 12 : : RuleConditionalTransferLightInvariantStorage
+ 13 : : } from "./RuleConditionalTransferLightInvariantStorage.sol";
+ 14 : : import {VersionModule} from "../../../modules/VersionModule.sol";
+ 15 : :
+ 16 : : /**
+ 17 : : * @title RuleConditionalTransferLightBase
+ 18 : : * @dev Requires operator approval for each transfer. Same transfer (from, to, value)
+ 19 : : * can be approved multiple times to allow repeated transfers.
+ 20 : : */
+ 21 : : abstract contract RuleConditionalTransferLightBase is VersionModule, RuleConditionalTransferLightInvariantStorage, IRule {
+ 22 : : // Mapping from transfer hash to approval count
+ 23 : : mapping(bytes32 => uint256) public approvalCounts;
+ 24 : :
+ 25 : 1940 : function approveTransfer(address from, address to, uint256 value) public onlyTransferApprover {
+ 26 : 1941 : bytes32 transferHash = _transferHash(from, to, value);
+ 27 : 1941 : approvalCounts[transferHash] += 1;
+ 28 : 1941 : emit TransferApproved(from, to, value, approvalCounts[transferHash]);
+ 29 : : }
+ 30 : :
+ 31 : 4 : function cancelTransferApproval(address from, address to, uint256 value) public onlyTransferApprover {
+ 32 : 3 : bytes32 transferHash = _transferHash(from, to, value);
+ 33 : 3 : uint256 count = approvalCounts[transferHash];
+ 34 [ + + ]: 3 : require(count != 0, TransferApprovalNotFound());
+ 35 : 2 : approvalCounts[transferHash] = count - 1;
+ 36 : 2 : emit TransferApprovalCancelled(from, to, value, approvalCounts[transferHash]);
+ 37 : : }
+ 38 : :
+ 39 : : /**
+ 40 : : * @notice Approves and performs a transferFrom using this rule as spender.
+ 41 : : * @dev Requires `from` to have approved this contract on the token.
+ 42 : : * @dev This function is only safe for tokens that call back `transferred()` during transfer.
+ 43 : : * @dev CEI is intentionally inverted so the approval exists for the callback.
+ 44 : : */
+ 45 : 4 : function approveAndTransferIfAllowed(address token, address from, address to, uint256 value)
+ 46 : : public
+ 47 : : onlyTransferApprover
+ 48 : : returns (bool)
+ 49 : : {
+ 50 [ + + ]: 4 : require(token != address(0), RuleConditionalTransferLight_TokenAddressZeroNotAllowed());
+ 51 : :
+ 52 : 3 : approveTransfer(from, to, value);
+ 53 : :
+ 54 : 3 : uint256 allowed = IERC20(token).allowance(from, address(this));
+ 55 [ + + ]: 3 : require(
+ 56 : : allowed >= value,
+ 57 : : RuleConditionalTransferLight_InsufficientAllowance(token, from, allowed, value)
+ 58 : : );
+ 59 : :
+ 60 : 2 : bool success = IERC20(token).transferFrom(from, to, value);
+ 61 [ + + ]: 2 : require(success, RuleConditionalTransferLight_TransferFailed());
+ 62 : 1 : return true;
+ 63 : : }
+ 64 : :
+ 65 : 264 : function approvedCount(address from, address to, uint256 value) public view returns (uint256) {
+ 66 : 264 : bytes32 transferHash = _transferHash(from, to, value);
+ 67 : 264 : return approvalCounts[transferHash];
+ 68 : : }
+ 69 : :
+ 70 : 856 : function transferred(address from, address to, uint256 value)
+ 71 : : public
+ 72 : : override(IERC3643IComplianceContract)
+ 73 : : onlyTransferExecutor
+ 74 : : {
+ 75 : 854 : _transferred(from, to, value);
+ 76 : : }
+ 77 : :
+ 78 : 1 : function transferred(address /* spender */, address from, address to, uint256 value)
+ 79 : : public
+ 80 : : override(IRuleEngine)
+ 81 : : onlyTransferExecutor
+ 82 : : {
+ 83 : 1 : _transferred(from, to, value);
+ 84 : : }
+ 85 : :
+ 86 : 7 : function detectTransferRestriction(address from, address to, uint256 value)
+ 87 : : public
+ 88 : : view
+ 89 : : override(IERC1404)
+ 90 : : returns (uint8)
+ 91 : : {
+ 92 [ + ]: 13 : if (from == address(0) || to == address(0)) {
+ 93 : 4 : return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 94 : : }
+ 95 : 9 : bytes32 transferHash = _transferHash(from, to, value);
+ 96 [ + ]: 9 : if (approvalCounts[transferHash] == 0) {
+ 97 : 6 : return CODE_TRANSFER_REQUEST_NOT_APPROVED;
+ 98 : : }
+ 99 : 3 : return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 100 : : }
+ 101 : :
+ 102 : 1 : function detectTransferRestrictionFrom(address /* spender */, address from, address to, uint256 value)
+ 103 : : public
+ 104 : : view
+ 105 : : override(IERC1404Extend)
+ 106 : : returns (uint8)
+ 107 : : {
+ 108 : 2 : return detectTransferRestriction(from, to, value);
+ 109 : : }
+ 110 : :
+ 111 : 4 : function canTransfer(address from, address to, uint256 value)
+ 112 : : public
+ 113 : : view
+ 114 : : override(IERC3643ComplianceRead)
+ 115 : : returns (bool)
+ 116 : : {
+ 117 : 4 : return detectTransferRestriction(from, to, value) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 118 : : }
+ 119 : :
+ 120 : 1 : function canTransferFrom(address spender, address from, address to, uint256 value)
121 : : public
- 122 : : pure
- 123 : : virtual
- 124 : : override(IERC1404)
- 125 : : returns (string memory)
- 126 : : {
- 127 [ + + ]: 8 : if (_restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED) {
- 128 : 3 : return TEXT_ADDRESS_FROM_IS_BLACKLISTED;
- 129 [ + + ]: 5 : } else if (_restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED) {
- 130 : 2 : return TEXT_ADDRESS_TO_IS_BLACKLISTED;
- 131 [ + + ]: 3 : } else if (_restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED) {
- 132 : 1 : return TEXT_ADDRESS_SPENDER_IS_BLACKLISTED;
- 133 : : } else {
- 134 : 2 : return TEXT_CODE_NOT_FOUND;
- 135 : : }
- 136 : : }
- 137 : :
- 138 : 0 : function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) {
- 139 : 0 : return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId);
- 140 : : }
- 141 : :
- 142 : : /* ============ State Functions ============ */
- 143 : :
- 144 : 9 : function transferred(address from, address to, uint256 value)
- 145 : : public
- 146 : : view
- 147 : : virtual
- 148 : : override(IERC3643IComplianceContract)
- 149 : : {
- 150 : 12 : uint8 code = this.detectTransferRestriction(from, to, value);
- 151 [ + + ]: 12 : require(
- 152 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
- 153 : : RuleBlacklist_InvalidTransfer(address(this), from, to, value, code)
- 154 : : );
- 155 : : }
- 156 : :
- 157 : 2 : function transferred(address spender, address from, address to, uint256 value)
- 158 : : public
- 159 : : view
- 160 : : virtual
- 161 : : override(IRuleEngine)
- 162 : : {
- 163 : 4 : uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value);
- 164 [ + + ]: 4 : require(
- 165 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
- 166 : : RuleBlacklist_InvalidTransferFrom(address(this), spender, from, to, value, code)
- 167 : : );
- 168 : : }
- 169 : :
- 170 : 2 : function transferred(address spender, address from, address to, uint256 /* tokenId */,uint256 value)
- 171 : : public
- 172 : : view
- 173 : : virtual
- 174 : : override(IERC7943NonFungibleComplianceExtend)
- 175 : : {
- 176 : 2 : transferred(spender, from, to, value);
- 177 : : }
- 178 : :
- 179 : 3 : function transferred(address from, address to, uint256 /* tokenId */,uint256 value)
- 180 : : public
- 181 : : view
- 182 : : virtual
- 183 : : override(IERC7943NonFungibleComplianceExtend)
- 184 : : {
- 185 : 3 : transferred(from, to, value);
- 186 : : }
- 187 : : }
+ 122 : : view
+ 123 : : override(IERC7551Compliance)
+ 124 : : returns (bool)
+ 125 : : {
+ 126 : 1 : return detectTransferRestrictionFrom(spender, from, to, value)
+ 127 : : == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ 128 : : }
+ 129 : :
+ 130 : 1 : function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override(IRule) returns (bool) {
+ 131 : 1 : return restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED;
+ 132 : : }
+ 133 : :
+ 134 : 2 : function messageForTransferRestriction(uint8 restrictionCode)
+ 135 : : external
+ 136 : : pure
+ 137 : : override(IERC1404)
+ 138 : : returns (string memory)
+ 139 : : {
+ 140 [ + ]: 2 : if (restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED) {
+ 141 : 1 : return TEXT_TRANSFER_REQUEST_NOT_APPROVED;
+ 142 : : }
+ 143 : 1 : return TEXT_CODE_NOT_FOUND;
+ 144 : : }
+ 145 : :
+ 146 : 3 : function transferred(ITransferContext.FungibleTransferContext calldata ctx) external onlyTransferExecutor {
+ 147 : 3 : _transferredFromContext(ctx);
+ 148 : : }
+ 149 : :
+ 150 : 3 : function _transferredFromContext(ITransferContext.FungibleTransferContext calldata ctx) internal virtual {
+ 151 : 3 : _transferred(ctx.from, ctx.to, ctx.value);
+ 152 : : }
+ 153 : :
+ 154 : 860 : function _transferred(address from, address to, uint256 value) internal virtual {
+ 155 [ + ]: 860 : if (from == address(0) || to == address(0)) {
+ 156 : 860 : return;
+ 157 : : }
+ 158 : 846 : bytes32 transferHash = _transferHash(from, to, value);
+ 159 : 846 : uint256 count = approvalCounts[transferHash];
+ 160 : :
+ 161 [ + + ]: 846 : require(count != 0, TransferNotApproved());
+ 162 : :
+ 163 : 843 : approvalCounts[transferHash] = count - 1;
+ 164 : 843 : emit TransferExecuted(from, to, value, approvalCounts[transferHash]);
+ 165 : : }
+ 166 : :
+ 167 : 3063 : function _transferHash(address from, address to, uint256 value) internal pure virtual returns (bytes32 hash) {
+ 168 : 3063 : return keccak256(abi.encodePacked(from, to, value));
+ 169 : : }
+ 170 : :
+ 171 : : /*//////////////////////////////////////////////////////////////
+ 172 : : ACCESS CONTROL
+ 173 : : //////////////////////////////////////////////////////////////*/
+ 174 : :
+ 175 : 4 : modifier onlyTransferApprover() {
+ 176 : 4 : _authorizeTransferApproval();
+ 177 : : _;
+ 178 : : }
+ 179 : :
+ 180 : 3 : modifier onlyTransferExecutor() {
+ 181 : 3 : _authorizeTransferExecution();
+ 182 : : _;
+ 183 : : }
+ 184 : :
+ 185 : : function _authorizeTransferApproval() internal view virtual;
+ 186 : :
+ 187 : : function _authorizeTransferExecution() internal view virtual;
+ 188 : : }
@@ -263,7 +264,7 @@
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-b.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-b.html
new file mode 100644
index 0000000..1481813
--- /dev/null
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-b.html
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filename
+ Line Coverage
+ Functions
+ Branches
+
+
+ RuleConditionalTransferLightBase.sol
+
+
+
+ 100.0 %
+ 62 / 62
+ 100.0 %
+ 18 / 18
+ 100.0 %
+ 14 / 14
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-f.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-f.html
new file mode 100644
index 0000000..3d54907
--- /dev/null
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-f.html
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filename
+ Line Coverage
+ Functions
+ Branches
+
+
+ RuleConditionalTransferLightBase.sol
+
+
+
+ 100.0 %
+ 62 / 62
+ 100.0 %
+ 18 / 18
+ 100.0 %
+ 14 / 14
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-l.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-l.html
new file mode 100644
index 0000000..90e3217
--- /dev/null
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-l.html
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filename
+ Line Coverage
+ Functions
+ Branches
+
+
+ RuleConditionalTransferLightBase.sol
+
+
+
+ 100.0 %
+ 62 / 62
+ 100.0 %
+ 18 / 18
+ 100.0 %
+ 14 / 14
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index.html
new file mode 100644
index 0000000..1a454a5
--- /dev/null
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index.html
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filename
+ Line Coverage
+ Functions
+ Branches
+
+
+ RuleConditionalTransferLightBase.sol
+
+
+
+ 100.0 %
+ 62 / 62
+ 100.0 %
+ 18 / 18
+ 100.0 %
+ 14 / 14
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-b.html
similarity index 54%
rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html
rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-b.html
index fe9d655..4c73cf0 100644
--- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-b.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - validation/abstract/RuleAddressSet
-
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation
+
LCOV - code coverage report
-
+
-
+
@@ -31,18 +31,18 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
@@ -53,12 +53,12 @@
-
+
-
+
@@ -76,32 +76,32 @@
- Filename
- Line Coverage
- Functions
- Branches
+ Filename
+ Line Coverage
+ Functions
+ Branches
- RuleAddressSetInternal.sol
+ RuleConditionalTransferLightOwnable2Step.sol
-
+
100.0 %
- 14 / 14
+ 5 / 5
100.0 %
- 6 / 6
+ 3 / 3
-
0 / 0
- RuleAddressSet.sol
+ RuleConditionalTransferLight.sol
-
+
- 87.5 %
- 28 / 32
- 81.8 %
- 9 / 11
+ 100.0 %
+ 11 / 11
+ 100.0 %
+ 6 / 6
100.0 %
2 / 2
@@ -110,7 +110,7 @@
diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-f.html
similarity index 54%
rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html
rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-f.html
index b79046b..eba8d47 100644
--- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-f.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - validation/abstract/RuleAddressSet
-
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation
+
LCOV - code coverage report
-
+
-
+
@@ -31,18 +31,18 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
@@ -53,12 +53,12 @@
-
+
-
+
@@ -76,41 +76,41 @@
- Filename
- Line Coverage
- Functions
- Branches
+ Filename
+ Line Coverage
+ Functions
+ Branches
- RuleAddressSet.sol
+ RuleConditionalTransferLightOwnable2Step.sol
-
+
- 87.5 %
- 28 / 32
- 81.8 %
- 9 / 11
100.0 %
- 2 / 2
+ 5 / 5
+ 100.0 %
+ 3 / 3
+ -
+ 0 / 0
- RuleAddressSetInternal.sol
+ RuleConditionalTransferLight.sol
-
+
100.0 %
- 14 / 14
+ 11 / 11
100.0 %
6 / 6
- -
- 0 / 0
+ 100.0 %
+ 2 / 2
diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-l.html
similarity index 54%
rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html
rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-l.html
index 7506cec..90bdb37 100644
--- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-l.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - validation/abstract/RuleAddressSet
-
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation
+
LCOV - code coverage report
-
+
-
+
@@ -31,18 +31,18 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
@@ -53,12 +53,12 @@
-
+
-
+
@@ -76,41 +76,41 @@
- Filename
- Line Coverage
- Functions
- Branches
+ Filename
+ Line Coverage
+ Functions
+ Branches
- RuleAddressSet.sol
+ RuleConditionalTransferLightOwnable2Step.sol
-
+
- 87.5 %
- 28 / 32
- 81.8 %
- 9 / 11
100.0 %
- 2 / 2
+ 5 / 5
+ 100.0 %
+ 3 / 3
+ -
+ 0 / 0
- RuleAddressSetInternal.sol
+ RuleConditionalTransferLight.sol
-
+
100.0 %
- 14 / 14
+ 11 / 11
100.0 %
6 / 6
- -
- 0 / 0
+ 100.0 %
+ 2 / 2
diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index.html
similarity index 54%
rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html
rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index.html
index 4c0f604..8abcc29 100644
--- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - validation/abstract/RuleAddressSet
-
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation
+
LCOV - code coverage report
-
+
-
+
@@ -31,18 +31,18 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
@@ -53,12 +53,12 @@
-
+
-
+
@@ -76,32 +76,32 @@
- Filename
- Line Coverage
- Functions
- Branches
+ Filename
+ Line Coverage
+ Functions
+ Branches
- RuleAddressSet.sol
+ RuleConditionalTransferLight.sol
-
+
- 87.5 %
- 28 / 32
- 81.8 %
- 9 / 11
+ 100.0 %
+ 11 / 11
+ 100.0 %
+ 6 / 6
100.0 %
2 / 2
- RuleAddressSetInternal.sol
+ RuleConditionalTransferLightOwnable2Step.sol
-
+
100.0 %
- 14 / 14
+ 5 / 5
100.0 %
- 6 / 6
+ 3 / 3
-
0 / 0
@@ -110,7 +110,7 @@
diff --git a/doc/coverage/coverage/index-sort-b.html b/doc/coverage/coverage/index-sort-b.html
index 2c38638..c0fea9e 100644
--- a/doc/coverage/coverage/index-sort-b.html
+++ b/doc/coverage/coverage/index-sort-b.html
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,26 +82,26 @@
Branches
- validation
+ deployment
-
+
- 89.9 %
- 151 / 168
- 84.8 %
- 39 / 46
- 94.3 %
- 50 / 53
+ 100.0 %
+ 112 / 112
+ 100.0 %
+ 68 / 68
+ -
+ 0 / 0
- validation/abstract/RuleAddressSet
+ /home/ryan/Pictures/dev/Rules/src/rules/operation
-
+
- 91.3 %
- 42 / 46
- 88.2 %
- 15 / 17
+ 100.0 %
+ 16 / 16
+ 100.0 %
+ 9 / 9
100.0 %
2 / 2
@@ -111,23 +111,71 @@
100.0 %
+ 9 / 9
+ 100.0 %
+ 3 / 3
+ 100.0 %
+ 4 / 4
+
+
+ abstract/RuleERC2980
+
+
+
+ 100.0 %
+ 36 / 36
+ 100.0 %
+ 12 / 12
+ 100.0 %
8 / 8
+
+
+ abstract/RuleAddressSet
+
+
+
100.0 %
- 2 / 2
+ 52 / 52
100.0 %
- 3 / 3
+ 19 / 19
+ 100.0 %
+ 8 / 8
+
+
+ abstract/core
+
+
+
+ 100.0 %
+ 51 / 51
+ 100.0 %
+ 19 / 19
+ 100.0 %
+ 14 / 14
- validation/abstract
+ /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract
-
+
- 93.5 %
- 29 / 31
- 90.9 %
- 10 / 11
100.0 %
- 10 / 10
+ 62 / 62
+ 100.0 %
+ 18 / 18
+ 100.0 %
+ 14 / 14
+
+
+ abstract/base
+
+
+
+ 100.0 %
+ 360 / 360
+ 100.0 %
+ 101 / 101
+ 100.0 %
+ 105 / 105
diff --git a/doc/coverage/coverage/index-sort-f.html b/doc/coverage/coverage/index-sort-f.html
index ddafc17..4733fa7 100644
--- a/doc/coverage/coverage/index-sort-f.html
+++ b/doc/coverage/coverage/index-sort-f.html
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,52 +82,100 @@
Branches
- validation
+ /home/ryan/Pictures/dev/Rules/src/modules
-
+
- 89.9 %
- 151 / 168
- 84.8 %
- 39 / 46
- 94.3 %
- 50 / 53
+ 100.0 %
+ 9 / 9
+ 100.0 %
+ 3 / 3
+ 100.0 %
+ 4 / 4
- validation/abstract/RuleAddressSet
+ /home/ryan/Pictures/dev/Rules/src/rules/operation
-
+
- 91.3 %
- 42 / 46
- 88.2 %
- 15 / 17
+ 100.0 %
+ 16 / 16
+ 100.0 %
+ 9 / 9
100.0 %
2 / 2
- validation/abstract
+ abstract/RuleERC2980
+
+
+
+ 100.0 %
+ 36 / 36
+ 100.0 %
+ 12 / 12
+ 100.0 %
+ 8 / 8
+
+
+ /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract
-
+
- 93.5 %
- 29 / 31
- 90.9 %
- 10 / 11
100.0 %
- 10 / 10
+ 62 / 62
+ 100.0 %
+ 18 / 18
+ 100.0 %
+ 14 / 14
- /home/ryan/Pictures/dev/Rules/src/modules
+ abstract/core
100.0 %
+ 51 / 51
+ 100.0 %
+ 19 / 19
+ 100.0 %
+ 14 / 14
+
+
+ abstract/RuleAddressSet
+
+
+
+ 100.0 %
+ 52 / 52
+ 100.0 %
+ 19 / 19
+ 100.0 %
8 / 8
+
+
+ deployment
+
+
+
100.0 %
- 2 / 2
+ 112 / 112
100.0 %
- 3 / 3
+ 68 / 68
+ -
+ 0 / 0
+
+
+ abstract/base
+
+
+
+ 100.0 %
+ 360 / 360
+ 100.0 %
+ 101 / 101
+ 100.0 %
+ 105 / 105
diff --git a/doc/coverage/coverage/index-sort-l.html b/doc/coverage/coverage/index-sort-l.html
index 53eb3c2..73dd95c 100644
--- a/doc/coverage/coverage/index-sort-l.html
+++ b/doc/coverage/coverage/index-sort-l.html
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,52 +82,100 @@
Branches
- validation
+ /home/ryan/Pictures/dev/Rules/src/modules
-
+
- 89.9 %
- 151 / 168
- 84.8 %
- 39 / 46
- 94.3 %
- 50 / 53
+ 100.0 %
+ 9 / 9
+ 100.0 %
+ 3 / 3
+ 100.0 %
+ 4 / 4
- validation/abstract/RuleAddressSet
+ /home/ryan/Pictures/dev/Rules/src/rules/operation
-
+
- 91.3 %
- 42 / 46
- 88.2 %
- 15 / 17
+ 100.0 %
+ 16 / 16
+ 100.0 %
+ 9 / 9
100.0 %
2 / 2
- validation/abstract
+ abstract/RuleERC2980
+
+
+
+ 100.0 %
+ 36 / 36
+ 100.0 %
+ 12 / 12
+ 100.0 %
+ 8 / 8
+
+
+ abstract/core
-
+
- 93.5 %
- 29 / 31
- 90.9 %
- 10 / 11
100.0 %
- 10 / 10
+ 51 / 51
+ 100.0 %
+ 19 / 19
+ 100.0 %
+ 14 / 14
- /home/ryan/Pictures/dev/Rules/src/modules
+ abstract/RuleAddressSet
100.0 %
+ 52 / 52
+ 100.0 %
+ 19 / 19
+ 100.0 %
8 / 8
+
+
+ /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract
+
+
+
100.0 %
- 2 / 2
+ 62 / 62
100.0 %
- 3 / 3
+ 18 / 18
+ 100.0 %
+ 14 / 14
+
+
+ deployment
+
+
+
+ 100.0 %
+ 112 / 112
+ 100.0 %
+ 68 / 68
+ -
+ 0 / 0
+
+
+ abstract/base
+
+
+
+ 100.0 %
+ 360 / 360
+ 100.0 %
+ 101 / 101
+ 100.0 %
+ 105 / 105
diff --git a/doc/coverage/coverage/index.html b/doc/coverage/coverage/index.html
index d70aabb..209f17b 100644
--- a/doc/coverage/coverage/index.html
+++ b/doc/coverage/coverage/index.html
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -87,47 +87,95 @@
100.0 %
- 8 / 8
+ 9 / 9
+ 100.0 %
+ 3 / 3
+ 100.0 %
+ 4 / 4
+
+
+ /home/ryan/Pictures/dev/Rules/src/rules/operation
+
+
+
+ 100.0 %
+ 16 / 16
+ 100.0 %
+ 9 / 9
100.0 %
2 / 2
+
+
+ /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract
+
+
+
100.0 %
- 3 / 3
+ 62 / 62
+ 100.0 %
+ 18 / 18
+ 100.0 %
+ 14 / 14
- validation
+ abstract/RuleAddressSet
-
+
- 89.9 %
- 151 / 168
- 84.8 %
- 39 / 46
- 94.3 %
- 50 / 53
+ 100.0 %
+ 52 / 52
+ 100.0 %
+ 19 / 19
+ 100.0 %
+ 8 / 8
- validation/abstract
+ abstract/RuleERC2980
-
+
- 93.5 %
- 29 / 31
- 90.9 %
- 10 / 11
100.0 %
- 10 / 10
+ 36 / 36
+ 100.0 %
+ 12 / 12
+ 100.0 %
+ 8 / 8
- validation/abstract/RuleAddressSet
+ abstract/base
-
+
- 91.3 %
- 42 / 46
- 88.2 %
- 15 / 17
100.0 %
- 2 / 2
+ 360 / 360
+ 100.0 %
+ 101 / 101
+ 100.0 %
+ 105 / 105
+
+
+ abstract/core
+
+
+
+ 100.0 %
+ 51 / 51
+ 100.0 %
+ 19 / 19
+ 100.0 %
+ 14 / 14
+
+
+ deployment
+
+
+
+ 100.0 %
+ 112 / 112
+ 100.0 %
+ 68 / 68
+ -
+ 0 / 0
diff --git a/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html b/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html
deleted file mode 100644
index 3e4edde..0000000
--- a/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html
+++ /dev/null
@@ -1,149 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - validation/RuleSanctionsList.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/validation/RuleSanctionsList.sol.func.html b/doc/coverage/coverage/validation/RuleSanctionsList.sol.func.html
deleted file mode 100644
index 03d8771..0000000
--- a/doc/coverage/coverage/validation/RuleSanctionsList.sol.func.html
+++ /dev/null
@@ -1,149 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - validation/RuleSanctionsList.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html
deleted file mode 100644
index 325f5a0..0000000
--- a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html
+++ /dev/null
@@ -1,285 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - validation/RuleWhitelistWrapper.sol
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Branch data Line data Source code
-
- 1 : : // SPDX-License-Identifier: MPL-2.0
- 2 : :
- 3 : : pragma solidity ^0.8.20;
- 4 : :
- 5 : : /* ==== OpenZeppelin === */
- 6 : : import {AccessControl} from "OZ/access/AccessControl.sol";
- 7 : : /* ==== Abtract contracts === */
- 8 : : import {AccessControlModuleStandalone} from "../../modules/AccessControlModuleStandalone.sol";
- 9 : : import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../modules/MetaTxModuleStandalone.sol";
- 10 : : import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol";
- 11 : : import {RuleWhitelistCommon, RuleValidateTransfer} from "./abstract/RuleWhitelistCommon.sol";
- 12 : : /* ==== RuleEngine === */
- 13 : : import {RulesManagementModule} from "RuleEngine/modules/RulesManagementModule.sol";
- 14 : : /* ==== CMTAT === */
- 15 : : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
- 16 : : /* ==== Interfaces === */
- 17 : : import {
- 18 : : IERC7943NonFungibleCompliance,
- 19 : : IERC7943NonFungibleComplianceExtend
- 20 : : } from "../interfaces/IERC7943NonFungibleCompliance.sol";
- 21 : :
- 22 : : /**
- 23 : : * @title Wrapper to call several different whitelist rules
- 24 : : */
- 25 : : contract RuleWhitelistWrapper is
- 26 : : RulesManagementModule,
- 27 : : AccessControlModuleStandalone,
- 28 : : MetaTxModuleStandalone,
- 29 : : RuleWhitelistCommon
- 30 : : {
- 31 : : /*//////////////////////////////////////////////////////////////
- 32 : : CONSTRUCTOR
- 33 : : //////////////////////////////////////////////////////////////*/
- 34 : : /**
- 35 : : * @param admin Address of the contract (Access Control)
- 36 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
- 37 : : */
- 38 : 22 : constructor(address admin, address forwarderIrrevocable, bool checkSpender_)
- 39 : : MetaTxModuleStandalone(forwarderIrrevocable)
- 40 : : AccessControlModuleStandalone(admin)
- 41 : : {
- 42 : 20 : checkSpender = checkSpender_;
- 43 : : }
- 44 : :
- 45 : : /* ============ View Functions ============ */
- 46 : : /**
- 47 : : * @notice Go through all the whitelist rules to know if a restriction exists on the transfer
- 48 : : * @param from the origin address
- 49 : : * @param to the destination address
- 50 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
- 51 : : *
- 52 : : */
- 53 : 21 : function detectTransferRestriction(address from, address to, uint256 /*value*/ )
- 54 : : public
- 55 : : view
- 56 : : virtual
- 57 : : override(IERC1404)
- 58 : : returns (uint8)
- 59 : : {
- 60 : 25 : address[] memory targetAddress = new address[](2);
- 61 : 25 : targetAddress[0] = from;
- 62 : 25 : targetAddress[1] = to;
- 63 : :
- 64 : 25 : bool[] memory result = _detectTransferRestriction(targetAddress);
- 65 [ + + ]: 25 : if (!result[0]) {
- 66 : 9 : return CODE_ADDRESS_FROM_NOT_WHITELISTED;
- 67 [ + + ]: 16 : } else if (!result[1]) {
- 68 : 6 : return CODE_ADDRESS_TO_NOT_WHITELISTED;
- 69 : : } else {
- 70 : 10 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- 71 : : }
- 72 : : }
- 73 : :
- 74 : 4 : function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value)
- 75 : : public
- 76 : : view
- 77 : : virtual
- 78 : : override(IERC7943NonFungibleComplianceExtend)
- 79 : : returns (uint8)
- 80 : : {
- 81 : 4 : return detectTransferRestriction(from, to, value);
- 82 : : }
- 83 : :
- 84 : 10 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
- 85 : : public
- 86 : : view
- 87 : : virtual
- 88 : : override(IERC1404Extend)
- 89 : : returns (uint8)
- 90 : : {
- 91 [ # ]: 12 : if (!checkSpender) {
- 92 : 0 : return detectTransferRestriction(from, to, value);
- 93 : : }
- 94 : :
- 95 : 12 : address[] memory targetAddress = new address[](3);
- 96 : 12 : targetAddress[0] = from;
- 97 : 12 : targetAddress[1] = to;
- 98 : 12 : targetAddress[2] = spender;
- 99 : :
- 100 : 12 : bool[] memory result = _detectTransferRestriction(targetAddress);
- 101 : :
- 102 [ # + ]: 12 : if (!result[0]) {
- 103 : 0 : return CODE_ADDRESS_FROM_NOT_WHITELISTED;
- 104 [ # + ]: 12 : } else if (!result[1]) {
- 105 : 0 : return CODE_ADDRESS_TO_NOT_WHITELISTED;
- 106 [ + + ]: 12 : } else if (!result[2]) {
- 107 : 6 : return CODE_ADDRESS_SPENDER_NOT_WHITELISTED;
- 108 : : } else {
- 109 : 6 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- 110 : : }
- 111 : : }
- 112 : :
- 113 : : /**
- 114 : : * @inheritdoc IERC7943NonFungibleComplianceExtend
- 115 : : */
- 116 : 2 : function detectTransferRestrictionFrom(
- 117 : : address spender,
- 118 : : address from,
- 119 : : address to,
- 120 : : uint256, /* tokenId */
- 121 : : uint256 value
- 122 : : ) public view virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) {
- 123 : 2 : return detectTransferRestrictionFrom(spender, from, to, value);
- 124 : : }
- 125 : :
- 126 : : /* ============ Access control ============ */
- 127 : :
- 128 : : /**
- 129 : : * @dev Returns `true` if `account` has been granted `role`.
- 130 : : */
- 131 : 20 : function hasRole(bytes32 role, address account)
- 132 : : public
- 133 : : view
- 134 : : virtual
- 135 : : override(AccessControl, AccessControlModuleStandalone)
- 136 : : returns (bool)
- 137 : : {
- 138 : 80 : return AccessControlModuleStandalone.hasRole(role, account);
- 139 : : }
- 140 : :
- 141 : : /*//////////////////////////////////////////////////////////////
- 142 : : INTERNAL/PRIVATE FUNCTIONS
- 143 : : //////////////////////////////////////////////////////////////*/
- 144 : :
- 145 : 37 : function _detectTransferRestriction(address[] memory targetAddress) internal view returns (bool[] memory) {
- 146 : 37 : uint256 rulesLength = rulesCount();
- 147 : 37 : bool[] memory result = new bool[](targetAddress.length);
- 148 : 37 : for (uint256 i = 0; i < rulesLength; ++i) {
- 149 : : // Call the whitelist rules
- 150 : 81 : bool[] memory isListed = RuleAddressSet(rule(i)).areAddressesListed(targetAddress);
- 151 : 81 : for (uint256 j = 0; j < targetAddress.length; ++j) {
- 152 [ + ]: 58 : if (isListed[j]) {
- 153 : 58 : result[j] = true;
- 154 : : }
- 155 : : }
- 156 : :
- 157 : : // Break early if all listed
- 158 : 81 : bool allListed = true;
- 159 : 81 : for (uint256 k = 0; k < result.length; ++k) {
- 160 [ + ]: 159 : if (!result[k]) {
- 161 : 65 : allListed = false;
- 162 : 65 : break;
- 163 : : }
- 164 : : }
- 165 [ + ]: 16 : if (allListed) {
- 166 : 16 : break;
- 167 : : }
- 168 : : }
- 169 : 37 : return result;
- 170 : : }
- 171 : :
- 172 : 0 : function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) {
- 173 : 0 : return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId);
- 174 : : }
- 175 : :
- 176 : : /*//////////////////////////////////////////////////////////////
- 177 : : ERC-2771
- 178 : : //////////////////////////////////////////////////////////////*/
- 179 : :
- 180 : : /**
- 181 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 182 : : */
- 183 : 80 : function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
- 184 : 80 : return ERC2771Context._msgSender();
- 185 : : }
- 186 : :
- 187 : : /**
- 188 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 189 : : */
- 190 : 0 : function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) {
- 191 : 0 : return ERC2771Context._msgData();
- 192 : : }
- 193 : :
- 194 : : /**
- 195 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 196 : : */
- 197 : 80 : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
- 198 : 80 : return ERC2771Context._contextSuffixLength();
- 199 : : }
- 200 : : }
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/validation/index-sort-b.html b/doc/coverage/coverage/validation/index-sort-b.html
deleted file mode 100644
index 944c1e9..0000000
--- a/doc/coverage/coverage/validation/index-sort-b.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - validation
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleWhitelistWrapper.sol
-
-
-
- 87.7 %
- 50 / 57
- 81.8 %
- 9 / 11
- 78.6 %
- 11 / 14
-
-
- RuleWhitelist.sol
-
-
-
- 80.0 %
- 16 / 20
- 71.4 %
- 5 / 7
- 100.0 %
- 5 / 5
-
-
- RuleBlacklist.sol
-
-
-
- 94.6 %
- 35 / 37
- 90.9 %
- 10 / 11
- 100.0 %
- 16 / 16
-
-
- RuleSanctionsList.sol
-
-
-
- 92.6 %
- 50 / 54
- 88.2 %
- 15 / 17
- 100.0 %
- 18 / 18
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/validation/index-sort-f.html b/doc/coverage/coverage/validation/index-sort-f.html
deleted file mode 100644
index 803ea1c..0000000
--- a/doc/coverage/coverage/validation/index-sort-f.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - validation
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleWhitelist.sol
-
-
-
- 80.0 %
- 16 / 20
- 71.4 %
- 5 / 7
- 100.0 %
- 5 / 5
-
-
- RuleWhitelistWrapper.sol
-
-
-
- 87.7 %
- 50 / 57
- 81.8 %
- 9 / 11
- 78.6 %
- 11 / 14
-
-
- RuleSanctionsList.sol
-
-
-
- 92.6 %
- 50 / 54
- 88.2 %
- 15 / 17
- 100.0 %
- 18 / 18
-
-
- RuleBlacklist.sol
-
-
-
- 94.6 %
- 35 / 37
- 90.9 %
- 10 / 11
- 100.0 %
- 16 / 16
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/validation/index-sort-l.html b/doc/coverage/coverage/validation/index-sort-l.html
deleted file mode 100644
index b4d9395..0000000
--- a/doc/coverage/coverage/validation/index-sort-l.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - validation
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleWhitelist.sol
-
-
-
- 80.0 %
- 16 / 20
- 71.4 %
- 5 / 7
- 100.0 %
- 5 / 5
-
-
- RuleWhitelistWrapper.sol
-
-
-
- 87.7 %
- 50 / 57
- 81.8 %
- 9 / 11
- 78.6 %
- 11 / 14
-
-
- RuleSanctionsList.sol
-
-
-
- 92.6 %
- 50 / 54
- 88.2 %
- 15 / 17
- 100.0 %
- 18 / 18
-
-
- RuleBlacklist.sol
-
-
-
- 94.6 %
- 35 / 37
- 90.9 %
- 10 / 11
- 100.0 %
- 16 / 16
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/validation/index.html b/doc/coverage/coverage/validation/index.html
deleted file mode 100644
index bffbd19..0000000
--- a/doc/coverage/coverage/validation/index.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - validation
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleBlacklist.sol
-
-
-
- 94.6 %
- 35 / 37
- 90.9 %
- 10 / 11
- 100.0 %
- 16 / 16
-
-
- RuleSanctionsList.sol
-
-
-
- 92.6 %
- 50 / 54
- 88.2 %
- 15 / 17
- 100.0 %
- 18 / 18
-
-
- RuleWhitelist.sol
-
-
-
- 80.0 %
- 16 / 20
- 71.4 %
- 5 / 7
- 100.0 %
- 5 / 5
-
-
- RuleWhitelistWrapper.sol
-
-
-
- 87.7 %
- 50 / 57
- 81.8 %
- 9 / 11
- 78.6 %
- 11 / 14
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/lcov.info b/doc/coverage/lcov.info
index 3c88298..f8b64c2 100644
--- a/doc/coverage/lcov.info
+++ b/doc/coverage/lcov.info
@@ -1,550 +1,1261 @@
TN:
SF:src/modules/AccessControlModuleStandalone.sol
-DA:22,161
-FN:22,AccessControlModuleStandalone.constructor
-FNDA:161,AccessControlModuleStandalone.constructor
-DA:23,161
-BRDA:23,0,0,4
-DA:24,4
-DA:29,157
-DA:38,228
+DA:24,396
+FN:24,AccessControlModuleStandalone.constructor
+FNDA:396,AccessControlModuleStandalone.constructor
+DA:25,396
+BRDA:25,0,0,5
+BRDA:25,0,1,391
+DA:29,391
+DA:38,507
FN:38,AccessControlModuleStandalone.hasRole
-FNDA:228,AccessControlModuleStandalone.hasRole
-DA:40,328
-BRDA:40,1,0,152
-BRDA:40,1,1,176
-DA:41,152
-DA:43,176
+FNDA:507,AccessControlModuleStandalone.hasRole
+DA:47,3597
+BRDA:47,1,0,3110
+BRDA:47,1,1,487
+DA:48,3110
+DA:50,487
FNF:2
FNH:2
-LF:8
-LH:8
-BRF:3
-BRH:3
-end_of_record
-TN:
-SF:src/rules/validation/RuleBlacklist.sol
-DA:41,22
-FN:41,RuleBlacklist.detectTransferRestriction.0
-FNDA:22,RuleBlacklist.detectTransferRestriction.0
-DA:47,43
-BRDA:47,0,0,14
-BRDA:47,0,1,16
-DA:48,14
-DA:49,29
-BRDA:49,1,0,13
-BRDA:49,1,1,16
-DA:50,13
-DA:52,16
-DA:59,7
-FN:59,RuleBlacklist.detectTransferRestriction.1
-FNDA:7,RuleBlacklist.detectTransferRestriction.1
-DA:65,7
-DA:71,16
-FN:71,RuleBlacklist.detectTransferRestrictionFrom.0
-FNDA:16,RuleBlacklist.detectTransferRestrictionFrom.0
-DA:77,20
-BRDA:77,2,0,6
-BRDA:77,2,1,14
-DA:78,6
-DA:80,14
-DA:87,4
-FN:87,RuleBlacklist.detectTransferRestrictionFrom.1
-FNDA:4,RuleBlacklist.detectTransferRestrictionFrom.1
-DA:94,4
-DA:103,4
-FN:103,RuleBlacklist.canReturnTransferRestrictionCode
-FNDA:4,RuleBlacklist.canReturnTransferRestrictionCode
-DA:110,4
-DA:111,2
-DA:120,8
-FN:120,RuleBlacklist.messageForTransferRestriction
-FNDA:8,RuleBlacklist.messageForTransferRestriction
-DA:127,8
-BRDA:127,3,0,3
-BRDA:127,3,1,2
-DA:128,3
-DA:129,5
-BRDA:129,4,0,2
-BRDA:129,4,1,2
-DA:130,2
-DA:131,3
-BRDA:131,5,0,1
-BRDA:131,5,1,2
-DA:132,1
+LF:7
+LH:7
+BRF:4
+BRH:4
+end_of_record
+TN:
+SF:src/modules/VersionModule.sol
+DA:14,7
+FN:14,VersionModule.version
+FNDA:7,VersionModule.version
+DA:15,7
+FNF:1
+FNH:1
+LF:2
+LH:2
+BRF:0
+BRH:0
+end_of_record
+TN:
+SF:src/rules/operation/RuleConditionalTransferLight.sol
+DA:27,18
+FN:27,RuleConditionalTransferLight.supportsInterface
+FNDA:18,RuleConditionalTransferLight.supportsInterface
+DA:34,18
+DA:35,11
+DA:38,1
+FN:38,RuleConditionalTransferLight.created
+FNDA:1,RuleConditionalTransferLight.created
+DA:39,1
+DA:42,1
+FN:42,RuleConditionalTransferLight.destroyed
+FNDA:1,RuleConditionalTransferLight.destroyed
+DA:43,1
+DA:46,1947
+FN:46,RuleConditionalTransferLight._authorizeTransferApproval
+FNDA:1947,RuleConditionalTransferLight._authorizeTransferApproval
+DA:48,857
+FN:48,RuleConditionalTransferLight._authorizeTransferExecution
+FNDA:857,RuleConditionalTransferLight._authorizeTransferExecution
+DA:49,857
+BRDA:49,0,0,1
+BRDA:49,0,1,856
+DA:55,19
+FN:55,RuleConditionalTransferLight._onlyComplianceManager
+FNDA:19,RuleConditionalTransferLight._onlyComplianceManager
+FNF:6
+FNH:6
+LF:11
+LH:11
+BRF:2
+BRH:2
+end_of_record
+TN:
+SF:src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol
+DA:21,4
+FN:21,RuleConditionalTransferLightOwnable2Step.supportsInterface
+FNDA:4,RuleConditionalTransferLightOwnable2Step.supportsInterface
+DA:22,4
+DA:23,2
+DA:26,4
+FN:26,RuleConditionalTransferLightOwnable2Step._authorizeTransferApproval
+FNDA:4,RuleConditionalTransferLightOwnable2Step._authorizeTransferApproval
+DA:28,3
+FN:28,RuleConditionalTransferLightOwnable2Step._authorizeTransferExecution
+FNDA:3,RuleConditionalTransferLightOwnable2Step._authorizeTransferExecution
+FNF:3
+FNH:3
+LF:5
+LH:5
+BRF:0
+BRH:0
+end_of_record
+TN:
+SF:src/rules/operation/abstract/RuleConditionalTransferLightBase.sol
+DA:25,1940
+FN:25,RuleConditionalTransferLightBase.approveTransfer
+FNDA:1940,RuleConditionalTransferLightBase.approveTransfer
+DA:26,1941
+DA:27,1941
+DA:28,1941
+DA:31,4
+FN:31,RuleConditionalTransferLightBase.cancelTransferApproval
+FNDA:4,RuleConditionalTransferLightBase.cancelTransferApproval
+DA:32,3
+DA:33,3
+DA:34,3
+BRDA:34,0,0,1
+BRDA:34,0,1,2
+DA:35,2
+DA:36,2
+DA:45,4
+FN:45,RuleConditionalTransferLightBase.approveAndTransferIfAllowed
+FNDA:4,RuleConditionalTransferLightBase.approveAndTransferIfAllowed
+DA:50,4
+BRDA:50,1,0,1
+BRDA:50,1,1,3
+DA:52,3
+DA:54,3
+DA:55,3
+BRDA:55,2,0,1
+BRDA:55,2,1,2
+DA:60,2
+DA:61,2
+BRDA:61,3,0,1
+BRDA:61,3,1,1
+DA:62,1
+DA:65,264
+FN:65,RuleConditionalTransferLightBase.approvedCount
+FNDA:264,RuleConditionalTransferLightBase.approvedCount
+DA:66,264
+DA:67,264
+DA:70,856
+FN:70,RuleConditionalTransferLightBase.transferred.0
+FNDA:856,RuleConditionalTransferLightBase.transferred.0
+DA:75,854
+DA:78,1
+FN:78,RuleConditionalTransferLightBase.transferred.1
+FNDA:1,RuleConditionalTransferLightBase.transferred.1
+DA:83,1
+DA:86,7
+FN:86,RuleConditionalTransferLightBase.detectTransferRestriction
+FNDA:7,RuleConditionalTransferLightBase.detectTransferRestriction
+DA:92,13
+BRDA:92,4,0,4
+DA:93,4
+DA:95,9
+DA:96,9
+BRDA:96,5,0,6
+DA:97,6
+DA:99,3
+DA:102,1
+FN:102,RuleConditionalTransferLightBase.detectTransferRestrictionFrom
+FNDA:1,RuleConditionalTransferLightBase.detectTransferRestrictionFrom
+DA:108,2
+DA:111,4
+FN:111,RuleConditionalTransferLightBase.canTransfer
+FNDA:4,RuleConditionalTransferLightBase.canTransfer
+DA:117,4
+DA:120,1
+FN:120,RuleConditionalTransferLightBase.canTransferFrom
+FNDA:1,RuleConditionalTransferLightBase.canTransferFrom
+DA:126,1
+DA:130,1
+FN:130,RuleConditionalTransferLightBase.canReturnTransferRestrictionCode
+FNDA:1,RuleConditionalTransferLightBase.canReturnTransferRestrictionCode
+DA:131,1
DA:134,2
-DA:138,0
-FN:138,RuleBlacklist.supportsInterface
-FNDA:0,RuleBlacklist.supportsInterface
-DA:139,0
-DA:144,9
-FN:144,RuleBlacklist.transferred.0
-FNDA:9,RuleBlacklist.transferred.0
-DA:150,12
-DA:151,12
-BRDA:151,6,0,8
-BRDA:151,6,1,4
-DA:157,2
-FN:157,RuleBlacklist.transferred.1
-FNDA:2,RuleBlacklist.transferred.1
-DA:163,4
-DA:164,4
-BRDA:164,7,0,2
-BRDA:164,7,1,2
-DA:170,2
-FN:170,RuleBlacklist.transferred.2
-FNDA:2,RuleBlacklist.transferred.2
-DA:176,2
-DA:179,3
-FN:179,RuleBlacklist.transferred.3
-FNDA:3,RuleBlacklist.transferred.3
-DA:185,3
-FNF:11
-FNH:10
-LF:37
-LH:35
-BRF:16
-BRH:16
-end_of_record
-TN:
-SF:src/rules/validation/RuleSanctionsList.sol
-DA:55,17
-FN:55,RuleSanctionsList.constructor
-FNDA:17,RuleSanctionsList.constructor
-DA:59,16
-BRDA:59,0,0,1
-DA:60,1
-DA:73,17
-FN:73,RuleSanctionsList.detectTransferRestriction.0
-FNDA:17,RuleSanctionsList.detectTransferRestriction.0
-DA:79,35
-BRDA:79,1,0,30
-DA:80,30
-BRDA:80,2,0,6
-BRDA:80,2,1,14
-DA:81,6
-DA:82,24
-BRDA:82,3,0,10
-DA:83,10
-DA:86,19
-DA:92,9
-FN:92,RuleSanctionsList.detectTransferRestriction.1
-FNDA:9,RuleSanctionsList.detectTransferRestriction.1
-DA:99,9
-DA:105,11
-FN:105,RuleSanctionsList.detectTransferRestrictionFrom.0
-FNDA:11,RuleSanctionsList.detectTransferRestrictionFrom.0
-DA:112,14
-BRDA:112,4,0,13
-DA:113,13
-BRDA:113,5,0,4
-BRDA:113,5,1,9
-DA:114,4
-DA:116,9
-DA:119,1
-DA:122,3
-FN:122,RuleSanctionsList.detectTransferRestrictionFrom.1
-FNDA:3,RuleSanctionsList.detectTransferRestrictionFrom.1
-DA:129,3
-DA:138,3
-FN:138,RuleSanctionsList.canReturnTransferRestrictionCode
-FNDA:3,RuleSanctionsList.canReturnTransferRestrictionCode
-DA:139,3
-DA:140,1
-DA:149,4
-FN:149,RuleSanctionsList.messageForTransferRestriction
-FNDA:4,RuleSanctionsList.messageForTransferRestriction
-DA:156,4
-BRDA:156,6,0,1
-BRDA:156,6,1,1
-DA:157,1
-DA:158,3
-BRDA:158,7,0,1
-BRDA:158,7,1,1
-DA:159,1
-DA:160,2
-BRDA:160,8,0,1
-BRDA:160,8,1,1
-DA:161,1
-DA:163,1
-DA:167,0
-FN:167,RuleSanctionsList.supportsInterface
-FNDA:0,RuleSanctionsList.supportsInterface
-DA:168,0
-DA:177,14
-FN:177,RuleSanctionsList.setSanctionListOracle
-FNDA:14,RuleSanctionsList.setSanctionListOracle
-DA:178,13
-DA:184,3
-FN:184,RuleSanctionsList.transferred.0
-FNDA:3,RuleSanctionsList.transferred.0
-DA:190,7
-DA:191,7
-BRDA:191,9,0,4
-BRDA:191,9,1,3
-DA:201,2
-FN:201,RuleSanctionsList.transferred.1
-FNDA:2,RuleSanctionsList.transferred.1
-DA:207,3
-DA:208,3
-BRDA:208,10,0,2
-BRDA:208,10,1,1
-DA:214,1
-FN:214,RuleSanctionsList.transferred.2
-FNDA:1,RuleSanctionsList.transferred.2
-DA:220,1
-DA:223,4
-FN:223,RuleSanctionsList.transferred.3
-FNDA:4,RuleSanctionsList.transferred.3
-DA:229,4
-DA:235,14
-FN:235,RuleSanctionsList._setSanctionListOracle
-FNDA:14,RuleSanctionsList._setSanctionListOracle
-DA:236,14
-DA:237,14
-DA:247,30
-FN:247,RuleSanctionsList._msgSender
-FNDA:30,RuleSanctionsList._msgSender
-DA:248,30
-DA:254,0
-FN:254,RuleSanctionsList._msgData
-FNDA:0,RuleSanctionsList._msgData
-DA:255,0
-DA:261,30
-FN:261,RuleSanctionsList._contextSuffixLength
-FNDA:30,RuleSanctionsList._contextSuffixLength
-DA:262,30
-FNF:17
-FNH:15
-LF:54
-LH:50
-BRF:18
-BRH:18
+FN:134,RuleConditionalTransferLightBase.messageForTransferRestriction
+FNDA:2,RuleConditionalTransferLightBase.messageForTransferRestriction
+DA:140,2
+BRDA:140,6,0,1
+DA:141,1
+DA:143,1
+DA:146,3
+FN:146,RuleConditionalTransferLightBase.transferred.2
+FNDA:3,RuleConditionalTransferLightBase.transferred.2
+DA:147,3
+DA:150,3
+FN:150,RuleConditionalTransferLightBase._transferredFromContext
+FNDA:3,RuleConditionalTransferLightBase._transferredFromContext
+DA:151,3
+DA:154,860
+FN:154,RuleConditionalTransferLightBase._transferred
+FNDA:860,RuleConditionalTransferLightBase._transferred
+DA:155,860
+BRDA:155,7,0,860
+DA:156,860
+DA:158,846
+DA:159,846
+DA:161,846
+BRDA:161,8,0,3
+BRDA:161,8,1,843
+DA:163,843
+DA:164,843
+DA:167,3063
+FN:167,RuleConditionalTransferLightBase._transferHash
+FNDA:3063,RuleConditionalTransferLightBase._transferHash
+DA:168,3063
+DA:175,4
+FN:175,RuleConditionalTransferLightBase.onlyTransferApprover
+FNDA:4,RuleConditionalTransferLightBase.onlyTransferApprover
+DA:176,4
+DA:180,3
+FN:180,RuleConditionalTransferLightBase.onlyTransferExecutor
+FNDA:3,RuleConditionalTransferLightBase.onlyTransferExecutor
+DA:181,3
+FNF:18
+FNH:18
+LF:62
+LH:62
+BRF:14
+BRH:14
end_of_record
TN:
-SF:src/rules/validation/RuleWhitelist.sol
-DA:33,102
-FN:33,RuleWhitelist.constructor
-FNDA:102,RuleWhitelist.constructor
-DA:36,101
-DA:56,20
-FN:56,RuleWhitelist.detectTransferRestriction.0
-FNDA:20,RuleWhitelist.detectTransferRestriction.0
-DA:63,33
-BRDA:63,0,0,11
-BRDA:63,0,1,16
-DA:64,11
-DA:65,22
-BRDA:65,1,0,6
-BRDA:65,1,1,16
-DA:66,6
-DA:68,16
-DA:75,7
-FN:75,RuleWhitelist.detectTransferRestriction.1
-FNDA:7,RuleWhitelist.detectTransferRestriction.1
-DA:82,7
-DA:102,10
-FN:102,RuleWhitelist.detectTransferRestrictionFrom.0
-FNDA:10,RuleWhitelist.detectTransferRestrictionFrom.0
-DA:109,12
-BRDA:109,2,0,6
-DA:110,6
-DA:112,6
-DA:118,2
-FN:118,RuleWhitelist.detectTransferRestrictionFrom.1
-FNDA:2,RuleWhitelist.detectTransferRestrictionFrom.1
+SF:src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol
+DA:51,275
+FN:51,RuleAddressSet.addAddresses
+FNDA:275,RuleAddressSet.addAddresses
+DA:52,274
+DA:53,274
+DA:63,260
+FN:63,RuleAddressSet.removeAddresses
+FNDA:260,RuleAddressSet.removeAddresses
+DA:64,259
+DA:65,259
+DA:75,105
+FN:75,RuleAddressSet.addAddress
+FNDA:105,RuleAddressSet.addAddress
+DA:76,102
+BRDA:76,0,0,1
+BRDA:76,0,1,101
+DA:77,101
+DA:78,101
+DA:88,8
+FN:88,RuleAddressSet.removeAddress
+FNDA:8,RuleAddressSet.removeAddress
+DA:89,5
+BRDA:89,1,0,1
+BRDA:89,1,1,4
+DA:90,4
+DA:91,4
+DA:98,275
+FN:98,RuleAddressSet.onlyAddressListAdd
+FNDA:275,RuleAddressSet.onlyAddressListAdd
+DA:99,275
+DA:103,8
+FN:103,RuleAddressSet.onlyAddressListRemove
+FNDA:8,RuleAddressSet.onlyAddressListRemove
+DA:104,8
+DA:116,536
+FN:116,RuleAddressSet.listedAddressCount
+FNDA:536,RuleAddressSet.listedAddressCount
+DA:117,536
DA:125,2
-DA:133,0
-FN:133,RuleWhitelist.isVerified
-FNDA:0,RuleWhitelist.isVerified
-DA:140,0
-DA:143,0
-FN:143,RuleWhitelist.supportsInterface
-FNDA:0,RuleWhitelist.supportsInterface
-DA:144,0
-FNF:7
-FNH:5
-LF:20
-LH:16
-BRF:5
-BRH:5
-end_of_record
-TN:
-SF:src/rules/validation/RuleWhitelistWrapper.sol
-DA:38,22
-FN:38,RuleWhitelistWrapper.constructor
-FNDA:22,RuleWhitelistWrapper.constructor
-DA:42,20
-DA:53,21
-FN:53,RuleWhitelistWrapper.detectTransferRestriction.0
-FNDA:21,RuleWhitelistWrapper.detectTransferRestriction.0
-DA:60,25
-DA:61,25
-DA:62,25
-DA:64,25
-DA:65,25
-BRDA:65,0,0,9
-BRDA:65,0,1,10
-DA:66,9
-DA:67,16
-BRDA:67,1,0,6
-BRDA:67,1,1,10
-DA:68,6
-DA:70,10
-DA:74,4
-FN:74,RuleWhitelistWrapper.detectTransferRestriction.1
-FNDA:4,RuleWhitelistWrapper.detectTransferRestriction.1
-DA:81,4
-DA:84,10
-FN:84,RuleWhitelistWrapper.detectTransferRestrictionFrom.0
-FNDA:10,RuleWhitelistWrapper.detectTransferRestrictionFrom.0
-DA:91,12
-BRDA:91,2,0,-
-DA:92,0
-DA:95,12
-DA:96,12
-DA:97,12
-DA:98,12
-DA:100,12
-DA:102,12
-BRDA:102,3,0,-
-BRDA:102,3,1,6
-DA:103,0
-DA:104,12
-BRDA:104,4,0,-
-BRDA:104,4,1,6
-DA:105,0
-DA:106,12
-BRDA:106,5,0,6
-BRDA:106,5,1,6
-DA:107,6
-DA:109,6
-DA:116,2
-FN:116,RuleWhitelistWrapper.detectTransferRestrictionFrom.1
-FNDA:2,RuleWhitelistWrapper.detectTransferRestrictionFrom.1
-DA:123,2
-DA:131,20
-FN:131,RuleWhitelistWrapper.hasRole
-FNDA:20,RuleWhitelistWrapper.hasRole
-DA:138,80
-DA:145,37
-FN:145,RuleWhitelistWrapper._detectTransferRestriction
-FNDA:37,RuleWhitelistWrapper._detectTransferRestriction
-DA:146,37
-DA:147,37
-DA:148,37
-DA:150,81
-DA:151,81
-DA:152,58
-BRDA:152,6,0,58
-DA:153,58
-DA:158,81
-DA:159,81
-DA:160,159
-BRDA:160,7,0,65
-DA:161,65
-DA:162,65
-DA:165,16
-BRDA:165,8,0,16
-DA:166,16
-DA:169,37
-DA:172,0
-FN:172,RuleWhitelistWrapper.supportsInterface
-FNDA:0,RuleWhitelistWrapper.supportsInterface
-DA:173,0
-DA:183,80
-FN:183,RuleWhitelistWrapper._msgSender
-FNDA:80,RuleWhitelistWrapper._msgSender
-DA:184,80
-DA:190,0
-FN:190,RuleWhitelistWrapper._msgData
-FNDA:0,RuleWhitelistWrapper._msgData
-DA:191,0
-DA:197,80
-FN:197,RuleWhitelistWrapper._contextSuffixLength
-FNDA:80,RuleWhitelistWrapper._contextSuffixLength
-DA:198,80
-FNF:11
+FN:125,RuleAddressSet.contains
+FNDA:2,RuleAddressSet.contains
+DA:126,2
+DA:134,67
+FN:134,RuleAddressSet.isAddressListed
+FNDA:67,RuleAddressSet.isAddressListed
+DA:135,383
+DA:143,108
+FN:143,RuleAddressSet.areAddressesListed
+FNDA:108,RuleAddressSet.areAddressesListed
+DA:144,108
+DA:145,108
+DA:146,244
+DA:154,882
+FN:154,RuleAddressSet._msgSender
+FNDA:882,RuleAddressSet._msgSender
+DA:155,882
+DA:159,4
+FN:159,RuleAddressSet._msgData
+FNDA:4,RuleAddressSet._msgData
+DA:160,4
+DA:164,886
+FN:164,RuleAddressSet._contextSuffixLength
+FNDA:886,RuleAddressSet._contextSuffixLength
+DA:165,886
+FNF:13
+FNH:13
+LF:34
+LH:34
+BRF:4
+BRH:4
+end_of_record
+TN:
+SF:src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol
+DA:38,274
+FN:38,RuleAddressSetInternal._addAddresses
+FNDA:274,RuleAddressSetInternal._addAddresses
+DA:42,274
+DA:43,806
+BRDA:43,0,0,548
+BRDA:43,0,1,258
+DA:44,548
+DA:46,258
+DA:60,259
+FN:60,RuleAddressSetInternal._removeAddresses
+FNDA:259,RuleAddressSetInternal._removeAddresses
+DA:64,259
+DA:65,775
+BRDA:65,1,0,518
+BRDA:65,1,1,257
+DA:66,518
+DA:68,257
+DA:77,101
+FN:77,RuleAddressSetInternal._addAddress
+FNDA:101,RuleAddressSetInternal._addAddress
+DA:78,101
+DA:85,4
+FN:85,RuleAddressSetInternal._removeAddress
+FNDA:4,RuleAddressSetInternal._removeAddress
+DA:86,4
+DA:93,536
+FN:93,RuleAddressSetInternal._listedAddressCount
+FNDA:536,RuleAddressSetInternal._listedAddressCount
+DA:94,536
+DA:102,738
+FN:102,RuleAddressSetInternal._isAddressListed
+FNDA:738,RuleAddressSetInternal._isAddressListed
+DA:103,738
+FNF:6
+FNH:6
+LF:18
+LH:18
+BRF:4
+BRH:4
+end_of_record
+TN:
+SF:src/rules/validation/abstract/RuleERC2980/RuleERC2980Internal.sol
+DA:33,4
+FN:33,RuleERC2980Internal._addWhitelistAddresses
+FNDA:4,RuleERC2980Internal._addWhitelistAddresses
+DA:37,4
+DA:38,6
+BRDA:38,0,0,5
+BRDA:38,0,1,1
+DA:39,5
+DA:41,1
+DA:46,3
+FN:46,RuleERC2980Internal._removeWhitelistAddresses
+FNDA:3,RuleERC2980Internal._removeWhitelistAddresses
+DA:50,3
+DA:51,3
+BRDA:51,1,0,2
+BRDA:51,1,1,1
+DA:52,2
+DA:54,1
+DA:59,39
+FN:59,RuleERC2980Internal._addWhitelistAddress
+FNDA:39,RuleERC2980Internal._addWhitelistAddress
+DA:60,39
+DA:63,4
+FN:63,RuleERC2980Internal._removeWhitelistAddress
+FNDA:4,RuleERC2980Internal._removeWhitelistAddress
+DA:64,4
+DA:67,82
+FN:67,RuleERC2980Internal._isWhitelisted
+FNDA:82,RuleERC2980Internal._isWhitelisted
+DA:68,82
+DA:71,5
+FN:71,RuleERC2980Internal._whitelistCount
+FNDA:5,RuleERC2980Internal._whitelistCount
+DA:72,5
+DA:79,4
+FN:79,RuleERC2980Internal._addFrozenlistAddresses
+FNDA:4,RuleERC2980Internal._addFrozenlistAddresses
+DA:83,4
+DA:84,6
+BRDA:84,2,0,5
+BRDA:84,2,1,1
+DA:85,5
+DA:87,1
+DA:92,2
+FN:92,RuleERC2980Internal._removeFrozenlistAddresses
+FNDA:2,RuleERC2980Internal._removeFrozenlistAddresses
+DA:96,2
+DA:97,2
+BRDA:97,3,0,1
+BRDA:97,3,1,1
+DA:98,1
+DA:100,1
+DA:105,18
+FN:105,RuleERC2980Internal._addFrozenlistAddress
+FNDA:18,RuleERC2980Internal._addFrozenlistAddress
+DA:106,18
+DA:109,4
+FN:109,RuleERC2980Internal._removeFrozenlistAddress
+FNDA:4,RuleERC2980Internal._removeFrozenlistAddress
+DA:110,4
+DA:113,90
+FN:113,RuleERC2980Internal._isFrozen
+FNDA:90,RuleERC2980Internal._isFrozen
+DA:114,90
+DA:117,4
+FN:117,RuleERC2980Internal._frozenlistCount
+FNDA:4,RuleERC2980Internal._frozenlistCount
+DA:118,4
+FNF:12
+FNH:12
+LF:36
+LH:36
+BRF:8
+BRH:8
+end_of_record
+TN:
+SF:src/rules/validation/abstract/base/RuleBlacklistBase.sol
+DA:20,106
+FN:20,RuleBlacklistBase._detectTransferRestriction
+FNDA:106,RuleBlacklistBase._detectTransferRestriction
+DA:26,106
+BRDA:26,0,0,23
+BRDA:26,0,1,64
+DA:27,23
+DA:28,83
+BRDA:28,1,0,19
+DA:29,19
+DA:31,64
+DA:34,22
+FN:34,RuleBlacklistBase._detectTransferRestrictionFrom
+FNDA:22,RuleBlacklistBase._detectTransferRestrictionFrom
+DA:40,22
+BRDA:40,2,0,8
+DA:41,8
+DA:43,14
+DA:46,4
+FN:46,RuleBlacklistBase.canReturnTransferRestrictionCode
+FNDA:4,RuleBlacklistBase.canReturnTransferRestrictionCode
+DA:53,4
+DA:54,1
+DA:57,12
+FN:57,RuleBlacklistBase.messageForTransferRestriction
+FNDA:12,RuleBlacklistBase.messageForTransferRestriction
+DA:64,12
+BRDA:64,3,0,5
+BRDA:64,3,1,3
+DA:65,5
+DA:66,7
+BRDA:66,4,0,3
+BRDA:66,4,1,3
+DA:67,3
+DA:68,4
+BRDA:68,5,0,1
+BRDA:68,5,1,3
+DA:69,1
+DA:71,3
+DA:75,61
+FN:75,RuleBlacklistBase.supportsInterface
+FNDA:61,RuleBlacklistBase.supportsInterface
+DA:76,61
+DA:83,58
+FN:83,RuleBlacklistBase.transferred.0
+FNDA:58,RuleBlacklistBase.transferred.0
+DA:89,58
+DA:96,2
+FN:96,RuleBlacklistBase.transferred.1
+FNDA:2,RuleBlacklistBase.transferred.1
+DA:102,2
+DA:105,61
+FN:105,RuleBlacklistBase._transferred
+FNDA:61,RuleBlacklistBase._transferred
+DA:106,61
+DA:107,61
+BRDA:107,6,0,15
+BRDA:107,6,1,46
+DA:113,4
+FN:113,RuleBlacklistBase._transferredFrom
+FNDA:4,RuleBlacklistBase._transferredFrom
+DA:119,4
+DA:120,4
+BRDA:120,7,0,2
+BRDA:120,7,1,2
+FNF:9
FNH:9
-LF:57
-LH:50
+LF:33
+LH:33
BRF:14
-BRH:11
+BRH:14
end_of_record
TN:
-SF:src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol
-DA:63,17
-FN:63,RuleAddressSet.addAddresses
-FNDA:17,RuleAddressSet.addAddresses
-DA:64,16
-DA:65,16
+SF:src/rules/validation/abstract/base/RuleERC2980Base.sol
+DA:47,22
+FN:47,RuleERC2980Base._detectTransferRestriction
+FNDA:22,RuleERC2980Base._detectTransferRestriction
+DA:55,22
+BRDA:55,0,0,4
+BRDA:55,0,1,14
+DA:56,4
+DA:57,18
+BRDA:57,1,0,4
+DA:58,4
+DA:61,14
+BRDA:61,2,0,4
+DA:62,4
+DA:64,10
+DA:67,8
+FN:67,RuleERC2980Base._detectTransferRestrictionFrom
+FNDA:8,RuleERC2980Base._detectTransferRestrictionFrom
+DA:74,8
+BRDA:74,3,0,4
DA:75,4
-FN:75,RuleAddressSet.removeAddresses
-FNDA:4,RuleAddressSet.removeAddresses
-DA:76,3
-DA:77,3
-DA:87,52
-FN:87,RuleAddressSet.addAddress
-FNDA:52,RuleAddressSet.addAddress
-DA:88,51
-BRDA:88,0,0,1
-DA:89,1
-DA:91,50
-DA:92,50
-DA:102,3
-FN:102,RuleAddressSet.removeAddress
-FNDA:3,RuleAddressSet.removeAddress
+DA:77,4
+DA:84,4
+FN:84,RuleERC2980Base.transferred.0
+FNDA:4,RuleERC2980Base.transferred.0
+DA:90,4
+DA:93,2
+FN:93,RuleERC2980Base.transferred.1
+FNDA:2,RuleERC2980Base.transferred.1
+DA:99,2
+DA:102,5
+FN:102,RuleERC2980Base._transferred
+FNDA:5,RuleERC2980Base._transferred
+DA:103,5
+DA:104,5
+BRDA:104,4,0,3
+BRDA:104,4,1,2
+DA:110,3
+FN:110,RuleERC2980Base._transferredFrom
+FNDA:3,RuleERC2980Base._transferredFrom
+DA:116,3
+DA:117,3
+BRDA:117,5,0,1
+BRDA:117,5,1,2
+DA:127,5
+FN:127,RuleERC2980Base.canReturnTransferRestrictionCode
+FNDA:5,RuleERC2980Base.canReturnTransferRestrictionCode
+DA:134,5
+DA:135,3
+DA:136,2
+DA:139,5
+FN:139,RuleERC2980Base.messageForTransferRestriction
+FNDA:5,RuleERC2980Base.messageForTransferRestriction
+DA:146,5
+BRDA:146,6,0,1
+BRDA:146,6,1,1
+DA:147,1
+DA:148,4
+BRDA:148,7,0,1
+BRDA:148,7,1,1
+DA:149,1
+DA:150,3
+BRDA:150,8,0,1
+BRDA:150,8,1,1
+DA:151,1
+DA:152,2
+BRDA:152,9,0,1
+BRDA:152,9,1,1
+DA:153,1
+DA:155,1
+DA:167,6
+FN:167,RuleERC2980Base.addWhitelistAddresses
+FNDA:6,RuleERC2980Base.addWhitelistAddresses
+DA:168,4
+DA:169,4
+DA:176,4
+FN:176,RuleERC2980Base.removeWhitelistAddresses
+FNDA:4,RuleERC2980Base.removeWhitelistAddresses
+DA:177,3
+DA:178,3
+DA:189,43
+FN:189,RuleERC2980Base.addWhitelistAddress
+FNDA:43,RuleERC2980Base.addWhitelistAddress
+DA:190,40
+BRDA:190,10,0,1
+BRDA:190,10,1,39
+DA:191,39
+DA:192,39
+DA:203,7
+FN:203,RuleERC2980Base.removeWhitelistAddress
+FNDA:7,RuleERC2980Base.removeWhitelistAddress
+DA:204,5
+BRDA:204,11,0,1
+BRDA:204,11,1,4
+DA:205,4
+DA:206,4
+DA:212,5
+FN:212,RuleERC2980Base.whitelistAddressCount
+FNDA:5,RuleERC2980Base.whitelistAddressCount
+DA:213,5
+DA:219,13
+FN:219,RuleERC2980Base.isWhitelisted
+FNDA:13,RuleERC2980Base.isWhitelisted
+DA:220,13
+DA:226,5
+FN:226,RuleERC2980Base.whitelist
+FNDA:5,RuleERC2980Base.whitelist
+DA:227,5
+DA:235,3
+FN:235,RuleERC2980Base.isVerified
+FNDA:3,RuleERC2980Base.isVerified
+DA:242,3
+DA:248,1
+FN:248,RuleERC2980Base.areWhitelisted
+FNDA:1,RuleERC2980Base.areWhitelisted
+DA:249,1
+DA:250,1
+DA:251,2
+DA:263,6
+FN:263,RuleERC2980Base.addFrozenlistAddresses
+FNDA:6,RuleERC2980Base.addFrozenlistAddresses
+DA:264,4
+DA:265,4
+DA:272,2
+FN:272,RuleERC2980Base.removeFrozenlistAddresses
+FNDA:2,RuleERC2980Base.removeFrozenlistAddresses
+DA:273,2
+DA:274,2
+DA:285,22
+FN:285,RuleERC2980Base.addFrozenlistAddress
+FNDA:22,RuleERC2980Base.addFrozenlistAddress
+DA:286,19
+BRDA:286,12,0,1
+BRDA:286,12,1,18
+DA:287,18
+DA:288,18
+DA:299,7
+FN:299,RuleERC2980Base.removeFrozenlistAddress
+FNDA:7,RuleERC2980Base.removeFrozenlistAddress
+DA:300,5
+BRDA:300,13,0,1
+BRDA:300,13,1,4
+DA:301,4
+DA:302,4
+DA:308,4
+FN:308,RuleERC2980Base.frozenlistAddressCount
+FNDA:4,RuleERC2980Base.frozenlistAddressCount
+DA:309,4
+DA:315,12
+FN:315,RuleERC2980Base.isFrozen
+FNDA:12,RuleERC2980Base.isFrozen
+DA:316,12
+DA:322,4
+FN:322,RuleERC2980Base.frozenlist
+FNDA:4,RuleERC2980Base.frozenlist
+DA:323,4
+DA:329,1
+FN:329,RuleERC2980Base.areFrozen
+FNDA:1,RuleERC2980Base.areFrozen
+DA:330,1
+DA:331,1
+DA:332,2
+DA:340,1
+FN:340,RuleERC2980Base.supportsInterface
+FNDA:1,RuleERC2980Base.supportsInterface
+DA:341,1
+DA:348,6
+FN:348,RuleERC2980Base.onlyWhitelistAdd
+FNDA:6,RuleERC2980Base.onlyWhitelistAdd
+DA:349,6
+DA:353,7
+FN:353,RuleERC2980Base.onlyWhitelistRemove
+FNDA:7,RuleERC2980Base.onlyWhitelistRemove
+DA:354,7
+DA:358,6
+FN:358,RuleERC2980Base.onlyFrozenlistAdd
+FNDA:6,RuleERC2980Base.onlyFrozenlistAdd
+DA:359,6
+DA:363,2
+FN:363,RuleERC2980Base.onlyFrozenlistRemove
+FNDA:2,RuleERC2980Base.onlyFrozenlistRemove
+DA:364,2
+DA:377,267
+FN:377,RuleERC2980Base._msgSender
+FNDA:267,RuleERC2980Base._msgSender
+DA:378,267
+DA:381,2
+FN:381,RuleERC2980Base._msgData
+FNDA:2,RuleERC2980Base._msgData
+DA:382,2
+DA:385,269
+FN:385,RuleERC2980Base._contextSuffixLength
+FNDA:269,RuleERC2980Base._contextSuffixLength
+DA:386,269
+FNF:33
+FNH:33
+LF:102
+LH:102
+BRF:25
+BRH:25
+end_of_record
+TN:
+SF:src/rules/validation/abstract/base/RuleIdentityRegistryBase.sol
+DA:19,26
+FN:19,RuleIdentityRegistryBase.constructor
+FNDA:26,RuleIdentityRegistryBase.constructor
+DA:20,26
+BRDA:20,0,0,25
+DA:21,25
+DA:25,4
+FN:25,RuleIdentityRegistryBase.setIdentityRegistry
+FNDA:4,RuleIdentityRegistryBase.setIdentityRegistry
+DA:26,2
+BRDA:26,1,0,1
+BRDA:26,1,1,1
+DA:27,1
+DA:28,1
+DA:31,5
+FN:31,RuleIdentityRegistryBase.clearIdentityRegistry
+FNDA:5,RuleIdentityRegistryBase.clearIdentityRegistry
+DA:32,3
+DA:33,3
+DA:36,16
+FN:36,RuleIdentityRegistryBase._detectTransferRestriction
+FNDA:16,RuleIdentityRegistryBase._detectTransferRestriction
+DA:42,16
+BRDA:42,2,0,3
+DA:43,3
+DA:45,13
+BRDA:45,3,0,2
+DA:46,2
+DA:49,11
+BRDA:49,4,0,4
+DA:50,4
+DA:52,7
+BRDA:52,5,0,1
+DA:53,1
+DA:55,6
+DA:58,9
+FN:58,RuleIdentityRegistryBase._detectTransferRestrictionFrom
+FNDA:9,RuleIdentityRegistryBase._detectTransferRestrictionFrom
+DA:64,9
+BRDA:64,6,0,1
+DA:65,1
+DA:67,8
+BRDA:67,7,0,1
+DA:68,1
+DA:70,7
+BRDA:70,8,0,4
+DA:71,4
+DA:73,3
+DA:76,2
+FN:76,RuleIdentityRegistryBase.transferred.0
+FNDA:2,RuleIdentityRegistryBase.transferred.0
+DA:81,2
+DA:84,2
+FN:84,RuleIdentityRegistryBase.transferred.1
+FNDA:2,RuleIdentityRegistryBase.transferred.1
+DA:89,2
+DA:92,2
+FN:92,RuleIdentityRegistryBase._transferred
+FNDA:2,RuleIdentityRegistryBase._transferred
+DA:93,2
+DA:94,2
+BRDA:94,9,0,1
+BRDA:94,9,1,1
+DA:100,2
+FN:100,RuleIdentityRegistryBase._transferredFrom
+FNDA:2,RuleIdentityRegistryBase._transferredFrom
+DA:106,2
+DA:107,2
+BRDA:107,10,0,1
+BRDA:107,10,1,1
+DA:113,4
+FN:113,RuleIdentityRegistryBase.canReturnTransferRestrictionCode
+FNDA:4,RuleIdentityRegistryBase.canReturnTransferRestrictionCode
+DA:114,4
+DA:115,2
+DA:118,4
+FN:118,RuleIdentityRegistryBase.messageForTransferRestriction
+FNDA:4,RuleIdentityRegistryBase.messageForTransferRestriction
+DA:124,4
+BRDA:124,11,0,1
+BRDA:124,11,1,1
+DA:125,1
+DA:126,3
+BRDA:126,12,0,1
+BRDA:126,12,1,1
+DA:127,1
+DA:128,2
+BRDA:128,13,0,1
+DA:129,1
+DA:131,1
+DA:138,5
+FN:138,RuleIdentityRegistryBase.onlyIdentityRegistryManager
+FNDA:5,RuleIdentityRegistryBase.onlyIdentityRegistryManager
+DA:139,5
+FNF:12
+FNH:12
+LF:51
+LH:51
+BRF:19
+BRH:19
+end_of_record
+TN:
+SF:src/rules/validation/abstract/base/RuleMaxTotalSupplyBase.sol
+DA:20,25
+FN:20,RuleMaxTotalSupplyBase.constructor
+FNDA:25,RuleMaxTotalSupplyBase.constructor
+DA:21,25
+BRDA:21,0,0,1
+BRDA:21,0,1,24
+DA:22,24
+DA:23,24
+DA:26,260
+FN:26,RuleMaxTotalSupplyBase.setMaxTotalSupply
+FNDA:260,RuleMaxTotalSupplyBase.setMaxTotalSupply
+DA:27,258
+DA:28,258
+DA:31,4
+FN:31,RuleMaxTotalSupplyBase.setTokenContract
+FNDA:4,RuleMaxTotalSupplyBase.setTokenContract
+DA:32,2
+BRDA:32,1,0,1
+BRDA:32,1,1,1
+DA:33,1
+DA:34,1
+DA:37,271
+FN:37,RuleMaxTotalSupplyBase._detectTransferRestriction
+FNDA:271,RuleMaxTotalSupplyBase._detectTransferRestriction
+DA:43,271
+BRDA:43,2,0,268
+DA:44,268
+DA:45,268
+BRDA:45,3,0,179
+DA:46,179
+DA:49,92
+DA:52,2
+FN:52,RuleMaxTotalSupplyBase._detectTransferRestrictionFrom
+FNDA:2,RuleMaxTotalSupplyBase._detectTransferRestrictionFrom
+DA:58,2
+DA:61,2
+FN:61,RuleMaxTotalSupplyBase.transferred.0
+FNDA:2,RuleMaxTotalSupplyBase.transferred.0
+DA:66,2
+DA:69,2
+FN:69,RuleMaxTotalSupplyBase.transferred.1
+FNDA:2,RuleMaxTotalSupplyBase.transferred.1
+DA:74,2
+DA:77,2
+FN:77,RuleMaxTotalSupplyBase._transferred
+FNDA:2,RuleMaxTotalSupplyBase._transferred
+DA:78,2
+DA:79,2
+BRDA:79,4,0,1
+BRDA:79,4,1,1
+DA:85,2
+FN:85,RuleMaxTotalSupplyBase._transferredFrom
+FNDA:2,RuleMaxTotalSupplyBase._transferredFrom
+DA:86,2
+DA:87,2
+BRDA:87,5,0,1
+BRDA:87,5,1,1
+DA:93,2
+FN:93,RuleMaxTotalSupplyBase.canReturnTransferRestrictionCode
+FNDA:2,RuleMaxTotalSupplyBase.canReturnTransferRestrictionCode
+DA:94,2
+DA:97,2
+FN:97,RuleMaxTotalSupplyBase.messageForTransferRestriction
+FNDA:2,RuleMaxTotalSupplyBase.messageForTransferRestriction
DA:103,2
-BRDA:103,1,0,1
+BRDA:103,6,0,1
DA:104,1
DA:106,1
-DA:107,1
-DA:114,24
-FN:114,RuleAddressSet.listedAddressCount
-FNDA:24,RuleAddressSet.listedAddressCount
-DA:115,24
-DA:123,0
-FN:123,RuleAddressSet.contains
-FNDA:0,RuleAddressSet.contains
-DA:124,0
-DA:132,60
-FN:132,RuleAddressSet.isAddressListed
-FNDA:60,RuleAddressSet.isAddressListed
-DA:133,219
-DA:141,84
-FN:141,RuleAddressSet.areAddressesListed
-FNDA:84,RuleAddressSet.areAddressesListed
-DA:142,84
-DA:143,84
-DA:144,191
-DA:152,207
-FN:152,RuleAddressSet._msgSender
-FNDA:207,RuleAddressSet._msgSender
-DA:153,207
-DA:157,0
-FN:157,RuleAddressSet._msgData
-FNDA:0,RuleAddressSet._msgData
-DA:158,0
-DA:162,207
-FN:162,RuleAddressSet._contextSuffixLength
-FNDA:207,RuleAddressSet._contextSuffixLength
-DA:163,207
-FNF:11
-FNH:9
-LF:32
-LH:28
-BRF:2
-BRH:2
+DA:113,260
+FN:113,RuleMaxTotalSupplyBase.onlyMaxTotalSupplyManager
+FNDA:260,RuleMaxTotalSupplyBase.onlyMaxTotalSupplyManager
+DA:114,260
+FNF:12
+FNH:12
+LF:37
+LH:37
+BRF:11
+BRH:11
end_of_record
TN:
-SF:src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol
-DA:36,16
-FN:36,RuleAddressSetInternal._addAddresses
-FNDA:16,RuleAddressSetInternal._addAddresses
-DA:37,16
-DA:38,34
-DA:49,3
-FN:49,RuleAddressSetInternal._removeAddresses
-FNDA:3,RuleAddressSetInternal._removeAddresses
-DA:50,3
-DA:51,7
-DA:59,50
-FN:59,RuleAddressSetInternal._addAddress
-FNDA:50,RuleAddressSetInternal._addAddress
-DA:60,50
-DA:67,1
-FN:67,RuleAddressSetInternal._removeAddress
-FNDA:1,RuleAddressSetInternal._removeAddress
-DA:68,1
-DA:75,24
-FN:75,RuleAddressSetInternal._listedAddressCount
-FNDA:24,RuleAddressSetInternal._listedAddressCount
-DA:76,24
-DA:84,463
-FN:84,RuleAddressSetInternal._isAddressListed
-FNDA:463,RuleAddressSetInternal._isAddressListed
-DA:85,463
-FNF:6
-FNH:6
-LF:14
-LH:14
-BRF:0
-BRH:0
+SF:src/rules/validation/abstract/base/RuleSanctionsListBase.sol
+DA:20,46
+FN:20,RuleSanctionsListBase.constructor
+FNDA:46,RuleSanctionsListBase.constructor
+DA:23,45
+BRDA:23,0,0,20
+DA:24,20
+DA:28,84
+FN:28,RuleSanctionsListBase._detectTransferRestriction
+FNDA:84,RuleSanctionsListBase._detectTransferRestriction
+DA:34,84
+BRDA:34,1,0,77
+DA:35,77
+BRDA:35,2,0,10
+BRDA:35,2,1,55
+DA:36,10
+DA:37,67
+BRDA:37,3,0,12
+DA:38,12
+DA:41,62
+DA:44,16
+FN:44,RuleSanctionsListBase._detectTransferRestrictionFrom
+FNDA:16,RuleSanctionsListBase._detectTransferRestrictionFrom
+DA:51,16
+BRDA:51,4,0,15
+DA:52,15
+BRDA:52,5,0,6
+DA:53,6
+DA:55,9
+DA:57,1
+DA:60,3
+FN:60,RuleSanctionsListBase.canReturnTransferRestrictionCode
+FNDA:3,RuleSanctionsListBase.canReturnTransferRestrictionCode
+DA:61,3
+DA:62,1
+DA:65,4
+FN:65,RuleSanctionsListBase.messageForTransferRestriction
+FNDA:4,RuleSanctionsListBase.messageForTransferRestriction
+DA:71,4
+BRDA:71,6,0,1
+BRDA:71,6,1,1
+DA:72,1
+DA:73,3
+BRDA:73,7,0,1
+BRDA:73,7,1,1
+DA:74,1
+DA:75,2
+BRDA:75,8,0,1
+DA:76,1
+DA:78,1
+DA:81,17
+FN:81,RuleSanctionsListBase.setSanctionListOracle
+FNDA:17,RuleSanctionsListBase.setSanctionListOracle
+DA:82,15
+BRDA:82,9,0,1
+BRDA:82,9,1,14
+DA:83,14
+DA:86,3
+FN:86,RuleSanctionsListBase.clearSanctionListOracle
+FNDA:3,RuleSanctionsListBase.clearSanctionListOracle
+DA:87,3
+DA:90,43
+FN:90,RuleSanctionsListBase.transferred.0
+FNDA:43,RuleSanctionsListBase.transferred.0
+DA:95,43
+DA:98,2
+FN:98,RuleSanctionsListBase.transferred.1
+FNDA:2,RuleSanctionsListBase.transferred.1
+DA:103,2
+DA:106,47
+FN:106,RuleSanctionsListBase._transferred
+FNDA:47,RuleSanctionsListBase._transferred
+DA:107,47
+DA:108,47
+BRDA:108,10,0,6
+BRDA:108,10,1,41
+DA:114,3
+FN:114,RuleSanctionsListBase._transferredFrom
+FNDA:3,RuleSanctionsListBase._transferredFrom
+DA:120,3
+DA:121,3
+BRDA:121,11,0,2
+BRDA:121,11,1,1
+DA:127,37
+FN:127,RuleSanctionsListBase._setSanctionListOracle
+FNDA:37,RuleSanctionsListBase._setSanctionListOracle
+DA:128,37
+DA:129,37
+DA:136,3
+FN:136,RuleSanctionsListBase.onlySanctionListManager
+FNDA:3,RuleSanctionsListBase.onlySanctionListManager
+DA:137,3
+FNF:13
+FNH:13
+LF:47
+LH:47
+BRF:18
+BRH:18
end_of_record
TN:
-SF:src/rules/validation/abstract/RuleValidateTransfer.sol
-DA:26,14
-FN:26,RuleValidateTransfer.canTransfer.0
-FNDA:14,RuleValidateTransfer.canTransfer.0
-DA:33,14
-DA:45,14
-FN:45,RuleValidateTransfer.canTransfer.1
-FNDA:14,RuleValidateTransfer.canTransfer.1
-DA:52,14
-DA:58,10
-FN:58,RuleValidateTransfer.canTransferFrom.0
-FNDA:10,RuleValidateTransfer.canTransferFrom.0
-DA:65,20
-DA:72,10
-FN:72,RuleValidateTransfer.canTransferFrom.1
-FNDA:10,RuleValidateTransfer.canTransferFrom.1
-DA:79,10
-DA:82,0
-FN:82,RuleValidateTransfer.supportsInterface
-FNDA:0,RuleValidateTransfer.supportsInterface
-DA:83,0
+SF:src/rules/validation/abstract/base/RuleWhitelistBase.sol
+DA:15,157
+FN:15,RuleWhitelistBase.constructor
+FNDA:157,RuleWhitelistBase.constructor
+DA:16,157
+DA:19,51
+FN:19,RuleWhitelistBase._detectTransferRestriction
+FNDA:51,RuleWhitelistBase._detectTransferRestriction
+DA:26,51
+BRDA:26,0,0,13
+BRDA:26,0,1,28
+DA:27,13
+DA:28,38
+BRDA:28,1,0,10
+DA:29,10
+DA:31,28
+DA:34,18
+FN:34,RuleWhitelistBase._detectTransferRestrictionFrom
+FNDA:18,RuleWhitelistBase._detectTransferRestrictionFrom
+DA:41,18
+BRDA:41,2,0,8
+DA:42,8
+DA:44,10
+DA:48,2
+FN:48,RuleWhitelistBase.isVerified
+FNDA:2,RuleWhitelistBase.isVerified
+DA:55,2
+DA:58,3
+FN:58,RuleWhitelistBase.setCheckSpender
+FNDA:3,RuleWhitelistBase.setCheckSpender
+DA:59,2
+DA:60,2
+DA:63,2
+FN:63,RuleWhitelistBase._setCheckSpender
+FNDA:2,RuleWhitelistBase._setCheckSpender
+DA:64,2
+DA:67,27
+FN:67,RuleWhitelistBase.supportsInterface
+FNDA:27,RuleWhitelistBase.supportsInterface
+DA:68,27
+DA:75,3
+FN:75,RuleWhitelistBase.onlyCheckSpenderManager
+FNDA:3,RuleWhitelistBase.onlyCheckSpenderManager
+DA:76,3
+FNF:8
+FNH:8
+LF:23
+LH:23
+BRF:4
+BRH:4
+end_of_record
+TN:
+SF:src/rules/validation/abstract/base/RuleWhitelistWrapperBase.sol
+DA:36,44
+FN:36,RuleWhitelistWrapperBase.constructor
+FNDA:44,RuleWhitelistWrapperBase.constructor
+DA:39,44
+DA:50,34
+FN:50,RuleWhitelistWrapperBase._detectTransferRestriction
+FNDA:34,RuleWhitelistWrapperBase._detectTransferRestriction
+DA:57,34
+DA:58,34
+DA:59,34
+DA:61,34
+DA:62,34
+BRDA:62,0,0,13
+BRDA:62,0,1,13
+DA:63,13
+DA:64,21
+BRDA:64,1,0,8
+BRDA:64,1,1,13
+DA:65,8
+DA:67,13
+DA:71,20
+FN:71,RuleWhitelistWrapperBase._detectTransferRestrictionFrom
+FNDA:20,RuleWhitelistWrapperBase._detectTransferRestrictionFrom
+DA:78,20
+BRDA:78,2,0,1
+DA:79,1
+DA:82,19
+DA:83,19
+DA:84,19
+DA:85,19
+DA:87,19
+DA:89,19
+BRDA:89,3,0,1
+BRDA:89,3,1,9
+DA:90,1
+DA:91,18
+BRDA:91,4,0,1
+BRDA:91,4,1,9
+DA:92,1
+DA:93,17
+BRDA:93,5,0,8
+BRDA:93,5,1,9
+DA:94,8
+DA:96,9
+DA:102,62
+FN:102,RuleWhitelistWrapperBase.supportsInterface
+FNDA:62,RuleWhitelistWrapperBase.supportsInterface
+DA:109,62
+DA:116,4
+FN:116,RuleWhitelistWrapperBase.isVerified
+FNDA:4,RuleWhitelistWrapperBase.isVerified
+DA:123,4
+DA:124,4
+DA:125,4
+DA:126,4
+DA:139,4
+FN:139,RuleWhitelistWrapperBase.setCheckSpender
+FNDA:4,RuleWhitelistWrapperBase.setCheckSpender
+DA:140,3
+DA:141,3
+DA:144,13
+FN:144,RuleWhitelistWrapperBase._transferred.0
+FNDA:13,RuleWhitelistWrapperBase._transferred.0
+DA:150,13
+DA:153,1
+FN:153,RuleWhitelistWrapperBase._transferred.1
+FNDA:1,RuleWhitelistWrapperBase._transferred.1
+DA:159,1
+DA:171,57
+FN:171,RuleWhitelistWrapperBase._detectTransferRestrictionForTargets
+FNDA:57,RuleWhitelistWrapperBase._detectTransferRestrictionForTargets
+DA:177,57
+DA:178,57
+DA:179,57
+DA:182,105
+DA:183,105
+DA:184,85
+BRDA:184,6,0,85
+DA:185,85
+DA:190,105
+DA:191,105
+DA:192,201
+BRDA:192,7,0,81
+DA:193,81
+DA:194,81
+DA:197,24
+BRDA:197,8,0,24
+DA:198,24
+DA:201,57
+DA:208,3
+FN:208,RuleWhitelistWrapperBase._setCheckSpender
+FNDA:3,RuleWhitelistWrapperBase._setCheckSpender
+DA:209,3
+DA:216,4
+FN:216,RuleWhitelistWrapperBase.onlyCheckSpenderManager
+FNDA:4,RuleWhitelistWrapperBase.onlyCheckSpenderManager
+DA:217,4
+DA:230,145
+FN:230,RuleWhitelistWrapperBase._msgSender
+FNDA:145,RuleWhitelistWrapperBase._msgSender
+DA:231,145
+DA:237,2
+FN:237,RuleWhitelistWrapperBase._msgData
+FNDA:2,RuleWhitelistWrapperBase._msgData
+DA:238,2
+DA:244,147
+FN:244,RuleWhitelistWrapperBase._contextSuffixLength
+FNDA:147,RuleWhitelistWrapperBase._contextSuffixLength
+DA:245,147
+FNF:14
+FNH:14
+LF:67
+LH:67
+BRF:14
+BRH:14
+end_of_record
+TN:
+SF:src/rules/validation/abstract/core/RuleNFTAdapter.sol
+DA:40,16
+FN:40,RuleNFTAdapter.detectTransferRestriction
+FNDA:16,RuleNFTAdapter.detectTransferRestriction
+DA:47,16
+DA:53,12
+FN:53,RuleNFTAdapter.detectTransferRestrictionFrom
+FNDA:12,RuleNFTAdapter.detectTransferRestrictionFrom
+DA:60,12
+DA:66,14
+FN:66,RuleNFTAdapter.canTransfer
+FNDA:14,RuleNFTAdapter.canTransfer
+DA:72,14
+DA:78,10
+FN:78,RuleNFTAdapter.canTransferFrom
+FNDA:10,RuleNFTAdapter.canTransferFrom
+DA:85,10
+DA:92,13
+FN:92,RuleNFTAdapter.transferred.0
+FNDA:13,RuleNFTAdapter.transferred.0
+DA:97,13
+DA:103,8
+FN:103,RuleNFTAdapter.transferred.1
+FNDA:8,RuleNFTAdapter.transferred.1
+DA:108,8
+DA:114,2
+FN:114,RuleNFTAdapter.transferred.2
+FNDA:2,RuleNFTAdapter.transferred.2
+DA:115,2
+BRDA:115,0,0,1
+BRDA:115,0,1,1
+DA:116,1
+DA:118,1
+DA:125,2
+FN:125,RuleNFTAdapter.transferred.3
+FNDA:2,RuleNFTAdapter.transferred.3
+DA:126,2
+BRDA:126,1,0,1
+BRDA:126,1,1,1
+DA:127,1
+DA:129,1
+FNF:8
+FNH:8
+LF:20
+LH:20
+BRF:4
+BRH:4
+end_of_record
+TN:
+SF:src/rules/validation/abstract/core/RuleTransferValidation.sol
+DA:46,348
+FN:46,RuleTransferValidation.detectTransferRestriction
+FNDA:348,RuleTransferValidation.detectTransferRestriction
+DA:53,348
+DA:59,36
+FN:59,RuleTransferValidation.detectTransferRestrictionFrom
+FNDA:36,RuleTransferValidation.detectTransferRestrictionFrom
+DA:66,36
+DA:77,20
+FN:77,RuleTransferValidation.canTransfer
+FNDA:20,RuleTransferValidation.canTransfer
+DA:83,20
+DA:89,12
+FN:89,RuleTransferValidation.canTransferFrom
+FNDA:12,RuleTransferValidation.canTransferFrom
+DA:96,12
+DA:100,195
+FN:100,RuleTransferValidation.supportsInterface
+FNDA:195,RuleTransferValidation.supportsInterface
+DA:101,195
FNF:5
-FNH:4
+FNH:5
LF:10
-LH:8
+LH:10
BRF:0
BRH:0
end_of_record
TN:
-SF:src/rules/validation/abstract/RuleWhitelistCommon.sol
-DA:38,10
-FN:38,RuleWhitelistCommon.canReturnTransferRestrictionCode
-FNDA:10,RuleWhitelistCommon.canReturnTransferRestrictionCode
-DA:39,10
-DA:40,5
-DA:50,14
-FN:50,RuleWhitelistCommon.messageForTransferRestriction
-FNDA:14,RuleWhitelistCommon.messageForTransferRestriction
-DA:56,14
-BRDA:56,0,0,6
-BRDA:56,0,1,2
-DA:57,6
-DA:58,8
-BRDA:58,1,0,4
-BRDA:58,1,1,2
-DA:59,4
-DA:60,4
-BRDA:60,2,0,2
-BRDA:60,2,1,2
-DA:61,2
-DA:63,2
-DA:79,17
-FN:79,RuleWhitelistCommon.transferred.0
-FNDA:17,RuleWhitelistCommon.transferred.0
-DA:80,22
-DA:81,22
-BRDA:81,3,0,14
-BRDA:81,3,1,8
-DA:97,4
-FN:97,RuleWhitelistCommon.transferred.1
-FNDA:4,RuleWhitelistCommon.transferred.1
-DA:98,8
-DA:99,8
-BRDA:99,4,0,4
-BRDA:99,4,1,4
-DA:106,4
-FN:106,RuleWhitelistCommon.transferred.2
-FNDA:4,RuleWhitelistCommon.transferred.2
-DA:112,4
-DA:115,5
-FN:115,RuleWhitelistCommon.transferred.3
-FNDA:5,RuleWhitelistCommon.transferred.3
-DA:121,5
+SF:src/rules/validation/abstract/core/RuleWhitelistShared.sol
+DA:33,10
+FN:33,RuleWhitelistShared.canReturnTransferRestrictionCode
+FNDA:10,RuleWhitelistShared.canReturnTransferRestrictionCode
+DA:34,10
+DA:35,5
+DA:45,14
+FN:45,RuleWhitelistShared.messageForTransferRestriction
+FNDA:14,RuleWhitelistShared.messageForTransferRestriction
+DA:51,14
+BRDA:51,0,0,6
+BRDA:51,0,1,2
+DA:52,6
+DA:53,8
+BRDA:53,1,0,4
+BRDA:53,1,1,2
+DA:54,4
+DA:55,4
+BRDA:55,2,0,2
+BRDA:55,2,1,2
+DA:56,2
+DA:58,2
+DA:75,19
+FN:75,RuleWhitelistShared.transferred.0
+FNDA:19,RuleWhitelistShared.transferred.0
+DA:76,19
+DA:90,4
+FN:90,RuleWhitelistShared.transferred.1
+FNDA:4,RuleWhitelistShared.transferred.1
+DA:91,4
+DA:94,26
+FN:94,RuleWhitelistShared._transferred
+FNDA:26,RuleWhitelistShared._transferred
+DA:95,26
+DA:96,26
+BRDA:96,3,0,14
+BRDA:96,3,1,12
+DA:102,11
+FN:102,RuleWhitelistShared._transferredFrom
+FNDA:11,RuleWhitelistShared._transferredFrom
+DA:108,11
+DA:109,11
+BRDA:109,4,0,4
+BRDA:109,4,1,7
FNF:6
FNH:6
LF:21
@@ -552,3 +1263,377 @@ LH:21
BRF:10
BRH:10
end_of_record
+TN:
+SF:src/rules/validation/deployment/RuleBlacklist.sol
+DA:28,91
+FN:28,RuleBlacklist.supportsInterface
+FNDA:91,RuleBlacklist.supportsInterface
+DA:35,91
+DA:38,28
+FN:38,RuleBlacklist._authorizeAddressListAdd
+FNDA:28,RuleBlacklist._authorizeAddressListAdd
+DA:40,1
+FN:40,RuleBlacklist._authorizeAddressListRemove
+FNDA:1,RuleBlacklist._authorizeAddressListRemove
+DA:42,83
+FN:42,RuleBlacklist._msgSender
+FNDA:83,RuleBlacklist._msgSender
+DA:43,83
+DA:46,1
+FN:46,RuleBlacklist._msgData
+FNDA:1,RuleBlacklist._msgData
+DA:47,1
+DA:50,84
+FN:50,RuleBlacklist._contextSuffixLength
+FNDA:84,RuleBlacklist._contextSuffixLength
+DA:51,84
+FNF:6
+FNH:6
+LF:10
+LH:10
+BRF:0
+BRH:0
+end_of_record
+TN:
+SF:src/rules/validation/deployment/RuleBlacklistOwnable2Step.sol
+DA:20,2
+FN:20,RuleBlacklistOwnable2Step._authorizeAddressListAdd
+FNDA:2,RuleBlacklistOwnable2Step._authorizeAddressListAdd
+DA:22,2
+FN:22,RuleBlacklistOwnable2Step._authorizeAddressListRemove
+FNDA:2,RuleBlacklistOwnable2Step._authorizeAddressListRemove
+DA:24,12
+FN:24,RuleBlacklistOwnable2Step._msgSender
+FNDA:12,RuleBlacklistOwnable2Step._msgSender
+DA:25,12
+DA:28,1
+FN:28,RuleBlacklistOwnable2Step._msgData
+FNDA:1,RuleBlacklistOwnable2Step._msgData
+DA:29,1
+DA:32,13
+FN:32,RuleBlacklistOwnable2Step._contextSuffixLength
+FNDA:13,RuleBlacklistOwnable2Step._contextSuffixLength
+DA:33,13
+FNF:5
+FNH:5
+LF:8
+LH:8
+BRF:0
+BRH:0
+end_of_record
+TN:
+SF:src/rules/validation/deployment/RuleERC2980.sol
+DA:50,1
+FN:50,RuleERC2980.supportsInterface
+FNDA:1,RuleERC2980.supportsInterface
+DA:57,1
+DA:64,42
+FN:64,RuleERC2980._authorizeWhitelistAdd
+FNDA:42,RuleERC2980._authorizeWhitelistAdd
+DA:66,8
+FN:66,RuleERC2980._authorizeWhitelistRemove
+FNDA:8,RuleERC2980._authorizeWhitelistRemove
+DA:68,22
+FN:68,RuleERC2980._authorizeFrozenlistAdd
+FNDA:22,RuleERC2980._authorizeFrozenlistAdd
+DA:70,7
+FN:70,RuleERC2980._authorizeFrozenlistRemove
+FNDA:7,RuleERC2980._authorizeFrozenlistRemove
+DA:72,237
+FN:72,RuleERC2980._msgSender
+FNDA:237,RuleERC2980._msgSender
+DA:73,237
+DA:76,1
+FN:76,RuleERC2980._msgData
+FNDA:1,RuleERC2980._msgData
+DA:77,1
+DA:80,238
+FN:80,RuleERC2980._contextSuffixLength
+FNDA:238,RuleERC2980._contextSuffixLength
+DA:81,238
+FNF:8
+FNH:8
+LF:12
+LH:12
+BRF:0
+BRH:0
+end_of_record
+TN:
+SF:src/rules/validation/deployment/RuleERC2980Ownable2Step.sol
+DA:20,7
+FN:20,RuleERC2980Ownable2Step._authorizeWhitelistAdd
+FNDA:7,RuleERC2980Ownable2Step._authorizeWhitelistAdd
+DA:22,3
+FN:22,RuleERC2980Ownable2Step._authorizeWhitelistRemove
+FNDA:3,RuleERC2980Ownable2Step._authorizeWhitelistRemove
+DA:24,6
+FN:24,RuleERC2980Ownable2Step._authorizeFrozenlistAdd
+FNDA:6,RuleERC2980Ownable2Step._authorizeFrozenlistAdd
+DA:26,2
+FN:26,RuleERC2980Ownable2Step._authorizeFrozenlistRemove
+FNDA:2,RuleERC2980Ownable2Step._authorizeFrozenlistRemove
+DA:28,30
+FN:28,RuleERC2980Ownable2Step._msgSender
+FNDA:30,RuleERC2980Ownable2Step._msgSender
+DA:29,30
+DA:32,1
+FN:32,RuleERC2980Ownable2Step._msgData
+FNDA:1,RuleERC2980Ownable2Step._msgData
+DA:33,1
+DA:36,31
+FN:36,RuleERC2980Ownable2Step._contextSuffixLength
+FNDA:31,RuleERC2980Ownable2Step._contextSuffixLength
+DA:37,31
+FNF:7
+FNH:7
+LF:10
+LH:10
+BRF:0
+BRH:0
+end_of_record
+TN:
+SF:src/rules/validation/deployment/RuleIdentityRegistry.sol
+DA:20,15
+FN:20,RuleIdentityRegistry.supportsInterface
+FNDA:15,RuleIdentityRegistry.supportsInterface
+DA:27,15
+DA:28,10
+DA:35,5
+FN:35,RuleIdentityRegistry._authorizeIdentityRegistryManager
+FNDA:5,RuleIdentityRegistry._authorizeIdentityRegistryManager
+FNF:2
+FNH:2
+LF:4
+LH:4
+BRF:0
+BRH:0
+end_of_record
+TN:
+SF:src/rules/validation/deployment/RuleIdentityRegistryOwnable2Step.sol
+DA:15,4
+FN:15,RuleIdentityRegistryOwnable2Step._authorizeIdentityRegistryManager
+FNDA:4,RuleIdentityRegistryOwnable2Step._authorizeIdentityRegistryManager
+FNF:1
+FNH:1
+LF:1
+LH:1
+BRF:0
+BRH:0
+end_of_record
+TN:
+SF:src/rules/validation/deployment/RuleMaxTotalSupply.sol
+DA:24,15
+FN:24,RuleMaxTotalSupply.supportsInterface
+FNDA:15,RuleMaxTotalSupply.supportsInterface
+DA:31,15
+DA:32,10
+DA:39,260
+FN:39,RuleMaxTotalSupply._authorizeMaxTotalSupplyManager
+FNDA:260,RuleMaxTotalSupply._authorizeMaxTotalSupplyManager
+FNF:2
+FNH:2
+LF:4
+LH:4
+BRF:0
+BRH:0
+end_of_record
+TN:
+SF:src/rules/validation/deployment/RuleMaxTotalSupplyOwnable2Step.sol
+DA:18,4
+FN:18,RuleMaxTotalSupplyOwnable2Step._authorizeMaxTotalSupplyManager
+FNDA:4,RuleMaxTotalSupplyOwnable2Step._authorizeMaxTotalSupplyManager
+FNF:1
+FNH:1
+LF:1
+LH:1
+BRF:0
+BRH:0
+end_of_record
+TN:
+SF:src/rules/validation/deployment/RuleSanctionsList.sol
+DA:26,58
+FN:26,RuleSanctionsList.supportsInterface
+FNDA:58,RuleSanctionsList.supportsInterface
+DA:33,58
+DA:34,39
+DA:41,17
+FN:41,RuleSanctionsList._authorizeSanctionListManager
+FNDA:17,RuleSanctionsList._authorizeSanctionListManager
+DA:47,57
+FN:47,RuleSanctionsList._msgSender
+FNDA:57,RuleSanctionsList._msgSender
+DA:48,57
+DA:51,1
+FN:51,RuleSanctionsList._msgData
+FNDA:1,RuleSanctionsList._msgData
+DA:52,1
+DA:55,58
+FN:55,RuleSanctionsList._contextSuffixLength
+FNDA:58,RuleSanctionsList._contextSuffixLength
+DA:56,58
+FNF:5
+FNH:5
+LF:10
+LH:10
+BRF:0
+BRH:0
+end_of_record
+TN:
+SF:src/rules/validation/deployment/RuleSanctionsListOwnable2Step.sol
+DA:21,3
+FN:21,RuleSanctionsListOwnable2Step._authorizeSanctionListManager
+FNDA:3,RuleSanctionsListOwnable2Step._authorizeSanctionListManager
+DA:23,11
+FN:23,RuleSanctionsListOwnable2Step._msgSender
+FNDA:11,RuleSanctionsListOwnable2Step._msgSender
+DA:24,11
+DA:27,1
+FN:27,RuleSanctionsListOwnable2Step._msgData
+FNDA:1,RuleSanctionsListOwnable2Step._msgData
+DA:28,1
+DA:31,13
+FN:31,RuleSanctionsListOwnable2Step._contextSuffixLength
+FNDA:13,RuleSanctionsListOwnable2Step._contextSuffixLength
+DA:32,13
+FNF:4
+FNH:4
+LF:7
+LH:7
+BRF:0
+BRH:0
+end_of_record
+TN:
+SF:src/rules/validation/deployment/RuleWhitelist.sol
+DA:42,40
+FN:42,RuleWhitelist.supportsInterface
+FNDA:40,RuleWhitelist.supportsInterface
+DA:49,40
+DA:56,1
+FN:56,RuleWhitelist._authorizeCheckSpenderManager
+FNDA:1,RuleWhitelist._authorizeCheckSpenderManager
+DA:58,348
+FN:58,RuleWhitelist._authorizeAddressListAdd
+FNDA:348,RuleWhitelist._authorizeAddressListAdd
+DA:60,263
+FN:60,RuleWhitelist._authorizeAddressListRemove
+FNDA:263,RuleWhitelist._authorizeAddressListRemove
+DA:62,772
+FN:62,RuleWhitelist._msgSender
+FNDA:772,RuleWhitelist._msgSender
+DA:63,772
+DA:66,1
+FN:66,RuleWhitelist._msgData
+FNDA:1,RuleWhitelist._msgData
+DA:67,1
+DA:70,773
+FN:70,RuleWhitelist._contextSuffixLength
+FNDA:773,RuleWhitelist._contextSuffixLength
+DA:71,773
+FNF:7
+FNH:7
+LF:11
+LH:11
+BRF:0
+BRH:0
+end_of_record
+TN:
+SF:src/rules/validation/deployment/RuleWhitelistOwnable2Step.sol
+DA:20,2
+FN:20,RuleWhitelistOwnable2Step._authorizeAddressListAdd
+FNDA:2,RuleWhitelistOwnable2Step._authorizeAddressListAdd
+DA:22,2
+FN:22,RuleWhitelistOwnable2Step._authorizeAddressListRemove
+FNDA:2,RuleWhitelistOwnable2Step._authorizeAddressListRemove
+DA:24,2
+FN:24,RuleWhitelistOwnable2Step._authorizeCheckSpenderManager
+FNDA:2,RuleWhitelistOwnable2Step._authorizeCheckSpenderManager
+DA:26,15
+FN:26,RuleWhitelistOwnable2Step._msgSender
+FNDA:15,RuleWhitelistOwnable2Step._msgSender
+DA:27,15
+DA:30,1
+FN:30,RuleWhitelistOwnable2Step._msgData
+FNDA:1,RuleWhitelistOwnable2Step._msgData
+DA:31,1
+DA:34,16
+FN:34,RuleWhitelistOwnable2Step._contextSuffixLength
+FNDA:16,RuleWhitelistOwnable2Step._contextSuffixLength
+DA:35,16
+FNF:6
+FNH:6
+LF:9
+LH:9
+BRF:0
+BRH:0
+end_of_record
+TN:
+SF:src/rules/validation/deployment/RuleWhitelistWrapper.sol
+DA:37,38
+FN:37,RuleWhitelistWrapper.hasRole
+FNDA:38,RuleWhitelistWrapper.hasRole
+DA:44,134
+DA:47,2
+FN:47,RuleWhitelistWrapper._authorizeCheckSpenderManager
+FNDA:2,RuleWhitelistWrapper._authorizeCheckSpenderManager
+DA:52,90
+FN:52,RuleWhitelistWrapper._onlyRulesManager
+FNDA:90,RuleWhitelistWrapper._onlyRulesManager
+DA:58,133
+FN:58,RuleWhitelistWrapper._msgSender
+FNDA:133,RuleWhitelistWrapper._msgSender
+DA:59,133
+DA:62,1
+FN:62,RuleWhitelistWrapper._msgData
+FNDA:1,RuleWhitelistWrapper._msgData
+DA:63,1
+DA:66,134
+FN:66,RuleWhitelistWrapper._contextSuffixLength
+FNDA:134,RuleWhitelistWrapper._contextSuffixLength
+DA:67,134
+DA:70,46
+FN:70,RuleWhitelistWrapper.supportsInterface
+FNDA:46,RuleWhitelistWrapper.supportsInterface
+DA:77,46
+DA:78,16
+DA:81,38
+FN:81,RuleWhitelistWrapper._grantRole
+FNDA:38,RuleWhitelistWrapper._grantRole
+DA:87,38
+DA:90,1
+FN:90,RuleWhitelistWrapper._revokeRole
+FNDA:1,RuleWhitelistWrapper._revokeRole
+DA:96,1
+FNF:9
+FNH:9
+LF:17
+LH:17
+BRF:0
+BRH:0
+end_of_record
+TN:
+SF:src/rules/validation/deployment/RuleWhitelistWrapperOwnable2Step.sol
+DA:28,2
+FN:28,RuleWhitelistWrapperOwnable2Step._authorizeCheckSpenderManager
+FNDA:2,RuleWhitelistWrapperOwnable2Step._authorizeCheckSpenderManager
+DA:33,2
+FN:33,RuleWhitelistWrapperOwnable2Step._onlyRulesManager
+FNDA:2,RuleWhitelistWrapperOwnable2Step._onlyRulesManager
+DA:39,12
+FN:39,RuleWhitelistWrapperOwnable2Step._msgSender
+FNDA:12,RuleWhitelistWrapperOwnable2Step._msgSender
+DA:40,12
+DA:43,1
+FN:43,RuleWhitelistWrapperOwnable2Step._msgData
+FNDA:1,RuleWhitelistWrapperOwnable2Step._msgData
+DA:44,1
+DA:47,13
+FN:47,RuleWhitelistWrapperOwnable2Step._contextSuffixLength
+FNDA:13,RuleWhitelistWrapperOwnable2Step._contextSuffixLength
+DA:48,13
+FNF:5
+FNH:5
+LF:8
+LH:8
+BRF:0
+BRH:0
+end_of_record
diff --git a/doc/schema/Rule-Rule.drawio.png b/doc/schema/Rule-Rule.drawio.png
new file mode 100644
index 0000000..c2f9799
Binary files /dev/null and b/doc/schema/Rule-Rule.drawio.png differ
diff --git a/doc/schema/Rule-RuleEngine.drawio.png b/doc/schema/Rule-RuleEngine.drawio.png
new file mode 100644
index 0000000..0498e66
Binary files /dev/null and b/doc/schema/Rule-RuleEngine.drawio.png differ
diff --git a/doc/schema/Rule.drawio b/doc/schema/Rule.drawio
new file mode 100644
index 0000000..40d0165
--- /dev/null
+++ b/doc/schema/Rule.drawio
@@ -0,0 +1 @@
+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
\ No newline at end of file
diff --git a/doc/schema/RuleEngine b/doc/schema/RuleEngine
deleted file mode 100644
index e908186..0000000
--- a/doc/schema/RuleEngine
+++ /dev/null
@@ -1 +0,0 @@
-1VpLc+I4EP41VO0e4rIkP/AxkMzMYac2NWEnm70JW4AqxqJkMcD8+pWxbCzJBEIwIblEar3s7q+/7hbuoeF8/ZXjxew7S0jag26y7qG7HoQA+VD+KySbUuL3+6VgymmiJu0Ej/Q3UUJXSZc0Ibk2UTCWCrrQhTHLMhILTYY5Zyt92oSl+qkLPCWW4DHGqS19oomYlVKIULAb+EbodFYdHfheOTLH1Wz1KvkMJ2zVEKH7HhpyxkTZmq+HJC20VymmXPdlz2j9ZJxk4pgF3og/hzzA5Gnz9/PLqj/65+d/N2qXXzhdqjcefh/djtQTi02lh9WMCvK4wHHRX0lb99BgJuap7AHZxPmi1P6Erok8b2A/XHUS4YKsGyL1sF8JmxPBN3KKGoWhUpyCDvD9sr/aGQJUc2ZNG1RCrIw/rffeqUc2lIbeoC1oaQs4guMsnxD+h2A9OKxG/7Q0SLLktgCk7MUpznMa6yrkbJklhe7uXNmTauObf2XnxnVcACvJczHseCisBHfr5oK7TbP3QDiV7024Eu61icB8SsRhlJBEcxbbcg3L+C2GqWScpFjQX7qLtRlLnfDAqHziGhgA6sCAyLB3zpY8JmpV0yOMjWBgICwyNioVY220xU792qfDCVlwGrEXkhVakzwl7WZiSFLIomgu5+ltLJg07KDwJyr56i88JukDy6mgLJNTxkwINm9MuE3ptBgQzPBdthQpzciwZtBXsXK8//qGlSpKb4AEtYAk6Mp5PUvb5/JRV3dP/4Bz7tVtidvDfnjQX/2r8tcA6UhA7on+GkQGpEysdOyvgYUg6MgOTbAgIxUGbExJI2yd04iYyh1jCQLCW/x0TpOk2GPASU5/4/F2vwI+i+L1ti/sD3r+XSugXnUA04Pr7EkdouUnbZ7tOqgfIt0UZ0HKDQy1XW/6+g5sMslJJ6b1LdP+WKbkPptKZrRM+gHJkN+/umQo7IxPgc6n4cmE+skSG9PIsI9OJErP3OiyRNm3oCG4bEFXpiyyCMNpbjvV9fBkBewz8KQXeUBnNPA+pHTPhJFlO4SdRJYRsahi3A+SC07jbab5MSkUWVNRM4VsPzfkuyVF5/1Jl38sl7hXRSaBb0UMx238GRseSy1916AWeFlqqbRsRGopqa5ZdljUsXYgap8hSEeGbiK74qlr14uUPMC+sFDKAlenLOi2ZDSX1ZZdj3sXp77uUh14VfQUmtcD3olFYWgWhf6FCelt9woZy4pkJcH5bAsFoGOkkD9gIVOdbCuBLpJSiTn2Ul9AQxtLKhyqwNlxQARHR8TrglzkehpSUFVDvRVykZleB8ZGXUOuvVqVEpuUPprWkffhtN5WqAapPHYwlo1p0SDO1JFTngr1pDQvbM23Gi3nyXPrqZaGpWKErsbSXYcsLW5oK4+f0DQ1RMfXNm120y17BtMBFxzOX7wW03X3e4sdkf3LFyPwlGoEdES+R3Pvdd0Bh4EVpc9RjUTmT0Heq0VOx7wM7VTAGzt8B9AhS1ouPi5zSVbnCM0MQS3rIkmARwL1unEKgrNUzZHBrMD8yXIPMiUw8KYxTd1p7X18qzoPtW8CZKPc8bywtwOs3xnsm0h/brrBG2DfFTcfnRhfF+YtEg3Ows0W5UfQOS5P3o/6szO2fVONxl0RtuMCXydt4KEuWPttX38chrX7OWENPg2s95A5NGPRu8hcdncfm5XTd9/sofv/AQ==
\ No newline at end of file
diff --git a/doc/schema/rule/IncomeVault-claimDividend.drawio.png b/doc/schema/rule/IncomeVault-claimDividend.drawio.png
deleted file mode 100644
index 3056bfe..0000000
Binary files a/doc/schema/rule/IncomeVault-claimDividend.drawio.png and /dev/null differ
diff --git a/doc/schema/rule/conditionalTransfer-Storage.drawio.png b/doc/schema/rule/conditionalTransfer-Storage.drawio.png
deleted file mode 100644
index 6fa3d10..0000000
Binary files a/doc/schema/rule/conditionalTransfer-Storage.drawio.png and /dev/null differ
diff --git a/doc/schema/rule/conditionalTransfer-automaticTransfer.drawio.png b/doc/schema/rule/conditionalTransfer-automaticTransfer.drawio.png
deleted file mode 100644
index 2a97df8..0000000
Binary files a/doc/schema/rule/conditionalTransfer-automaticTransfer.drawio.png and /dev/null differ
diff --git a/doc/schema/rule/conditionalTransfer-state machine.drawio.png b/doc/schema/rule/conditionalTransfer-state machine.drawio.png
deleted file mode 100644
index ff4388e..0000000
Binary files a/doc/schema/rule/conditionalTransfer-state machine.drawio.png and /dev/null differ
diff --git a/doc/schema/rule/conditionalTransfer.drawio b/doc/schema/rule/conditionalTransfer.drawio
deleted file mode 100644
index 9f632cc..0000000
--- a/doc/schema/rule/conditionalTransfer.drawio
+++ /dev/null
@@ -1 +0,0 @@
-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
\ No newline at end of file
diff --git a/doc/schema/rule/conditionalTransferCMTAT.drawio.png b/doc/schema/rule/conditionalTransferCMTAT.drawio.png
deleted file mode 100644
index 83cf658..0000000
Binary files a/doc/schema/rule/conditionalTransferCMTAT.drawio.png and /dev/null differ
diff --git a/doc/schema/rule/conditionalTransferTime.png b/doc/schema/rule/conditionalTransferTime.png
deleted file mode 100644
index 52eefdc..0000000
Binary files a/doc/schema/rule/conditionalTransferTime.png and /dev/null differ
diff --git a/doc/script/convert_links_for_pdf.sh b/doc/script/convert_links_for_pdf.sh
new file mode 100755
index 0000000..2f4d392
--- /dev/null
+++ b/doc/script/convert_links_for_pdf.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+# Script to replace relative markdown links with GitHub links for PDF generation
+# Preserves image links (they render in PDF) and external links
+
+set -e
+
+if [ -z "$1" ]; then
+ echo "Usage: $0 [input-file] [output-file]"
+ echo ""
+ echo "Example:"
+ echo " $0 https://github.com/CMTA/CMTAT/blob/v3.0.0"
+ echo " $0 https://github.com/CMTA/CMTAT/blob/v3.0.0 README.md README_UPDATE.md"
+ exit 1
+fi
+
+GITHUB_LINK="${1%/}" # Remove trailing slash if present
+INPUT_FILE="${2:-../../README.md}"
+OUTPUT_FILE="${3:-README_UPDATE.md}"
+
+if [ ! -f "$INPUT_FILE" ]; then
+ echo "Error: Input file '$INPUT_FILE' not found"
+ exit 1
+fi
+
+# Create a temporary file
+TMP_FILE=$(mktemp)
+cp "$INPUT_FILE" "$TMP_FILE"
+
+# Use a placeholder to avoid sed escaping issues
+PLACEHOLDER="__GITHUB_LINK__"
+
+# Step 1: Convert ALL relative links [text](./...) to placeholder
+sed -i -E "s|\[([^]]+)\]\(\./([^)]+)\)|[\1]($PLACEHOLDER/\2)|g" "$TMP_FILE"
+
+# Step 2: Restore image links back to relative (images render inline in PDF)
+for ext in png jpg jpeg gif svg ico webp bmp tiff; do
+ sed -i -E "s|\[([^]]+)\]\($PLACEHOLDER/([^)]+\.$ext)\)|[\1](./\2)|gi" "$TMP_FILE"
+done
+
+# Step 3: Replace placeholder with actual GitHub link
+sed -i "s|$PLACEHOLDER|$GITHUB_LINK|g" "$TMP_FILE"
+
+mv "$TMP_FILE" "$OUTPUT_FILE"
+
+echo "Created '$OUTPUT_FILE' with GitHub links pointing to:"
+echo " $GITHUB_LINK"
diff --git a/doc/security/accessControl/access-control-RuleEngine.png b/doc/security/accessControl/access-control-RuleEngine.png
deleted file mode 100644
index a711397..0000000
Binary files a/doc/security/accessControl/access-control-RuleEngine.png and /dev/null differ
diff --git a/doc/technical/RuleBlacklist.md b/doc/technical/RuleBlacklist.md
index 9ebe1aa..bace50e 100644
--- a/doc/technical/RuleBlacklist.md
+++ b/doc/technical/RuleBlacklist.md
@@ -69,4 +69,4 @@ Single-item operations (`addAddress`, `removeAddress`) revert on duplicate/missi
### Usage scenario
-The operator deploys `RuleBlacklist`, grants `ADDRESS_LIST_ADD_ROLE` to a compliance manager, and registers the rule in the `RuleEngine`. The compliance manager calls `addAddresses([badActor])`. Any transfer from, to, or by the blacklisted address is rejected with codes 36, 37, or 38.
+The operator deploys `RuleBlacklist`, grants `ADDRESS_LIST_ADD_ROLE` to a compliance manager, and registers the rule in the `RuleEngine`. The compliance manager calls `addAddresses([badActor])`. Any transfer from, to, or by the blacklisted address is rejected with codes 36, 37, or 38.rea
diff --git a/src/rules/operation/RuleConditionalTransferLight.sol b/src/rules/operation/RuleConditionalTransferLight.sol
index d32774d..e58a736 100644
--- a/src/rules/operation/RuleConditionalTransferLight.sol
+++ b/src/rules/operation/RuleConditionalTransferLight.sol
@@ -22,10 +22,7 @@ contract RuleConditionalTransferLight is
/**
* @param admin Address of the contract admin.
*/
- constructor(address admin) AccessControlModuleStandalone(admin) {
- require(admin != address(0), RuleConditionalTransferLight_AdminAddressZeroNotAllowed());
-
- }
+ constructor(address admin) AccessControlModuleStandalone(admin) {}
function supportsInterface(bytes4 interfaceId)
public
diff --git a/test/Coverage/DeploymentOperationCoverage.t.sol b/test/Coverage/DeploymentOperationCoverage.t.sol
new file mode 100644
index 0000000..f71291a
--- /dev/null
+++ b/test/Coverage/DeploymentOperationCoverage.t.sol
@@ -0,0 +1,195 @@
+// SPDX-License-Identifier: MPL-2.0
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {HelperContract} from "../HelperContract.sol";
+import {IERC165} from "OZ/utils/introspection/IERC165.sol";
+import {IRule} from "RuleEngine/interfaces/IRule.sol";
+import {RuleInterfaceId} from "RuleEngine/modules/library/RuleInterfaceId.sol";
+import {ISanctionsList} from "src/rules/interfaces/ISanctionsList.sol";
+import {RuleConditionalTransferLight} from "src/rules/operation/RuleConditionalTransferLight.sol";
+import {RuleConditionalTransferLightOwnable2Step} from "src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol";
+import {RuleBlacklist} from "src/rules/validation/deployment/RuleBlacklist.sol";
+import {RuleWhitelist} from "src/rules/validation/deployment/RuleWhitelist.sol";
+import {RuleWhitelistWrapper} from "src/rules/validation/deployment/RuleWhitelistWrapper.sol";
+import {RuleERC2980} from "src/rules/validation/deployment/RuleERC2980.sol";
+import {RuleSanctionsList} from "src/rules/validation/deployment/RuleSanctionsList.sol";
+import {RuleBlacklistOwnable2Step} from "src/rules/validation/deployment/RuleBlacklistOwnable2Step.sol";
+import {RuleWhitelistOwnable2Step} from "src/rules/validation/deployment/RuleWhitelistOwnable2Step.sol";
+import {RuleWhitelistWrapperOwnable2Step} from "src/rules/validation/deployment/RuleWhitelistWrapperOwnable2Step.sol";
+import {RuleERC2980Ownable2Step} from "src/rules/validation/deployment/RuleERC2980Ownable2Step.sol";
+
+contract RuleBlacklistHarness is RuleBlacklist {
+ constructor(address admin, address forwarderIrrevocable) RuleBlacklist(admin, forwarderIrrevocable) {}
+
+ function exposedMsgDataLength() external view returns (uint256) {
+ return _msgData().length;
+ }
+}
+
+contract RuleWhitelistHarness is RuleWhitelist {
+ constructor(address admin, address forwarderIrrevocable, bool checkSpender_)
+ RuleWhitelist(admin, forwarderIrrevocable, checkSpender_)
+ {}
+
+ function exposedMsgDataLength() external view returns (uint256) {
+ return _msgData().length;
+ }
+}
+
+contract RuleWhitelistWrapperHarness is RuleWhitelistWrapper {
+ constructor(address admin, address forwarderIrrevocable, bool checkSpender_)
+ RuleWhitelistWrapper(admin, forwarderIrrevocable, checkSpender_)
+ {}
+
+ function exposedMsgDataLength() external view returns (uint256) {
+ return _msgData().length;
+ }
+}
+
+contract RuleERC2980Harness is RuleERC2980 {
+ constructor(address admin, address forwarderIrrevocable) RuleERC2980(admin, forwarderIrrevocable) {}
+
+ function exposedMsgDataLength() external view returns (uint256) {
+ return _msgData().length;
+ }
+}
+
+contract RuleSanctionsListHarness is RuleSanctionsList {
+ constructor(address admin, address forwarderIrrevocable, ISanctionsList sanctionContractOracle_)
+ RuleSanctionsList(admin, forwarderIrrevocable, sanctionContractOracle_)
+ {}
+
+ function exposedMsgDataLength() external view returns (uint256) {
+ return _msgData().length;
+ }
+}
+
+contract RuleBlacklistOwnable2StepHarness is RuleBlacklistOwnable2Step {
+ constructor(address owner, address forwarderIrrevocable) RuleBlacklistOwnable2Step(owner, forwarderIrrevocable) {}
+
+ function exposedMsgDataLength() external view returns (uint256) {
+ return _msgData().length;
+ }
+}
+
+contract RuleWhitelistOwnable2StepHarness is RuleWhitelistOwnable2Step {
+ constructor(address owner, address forwarderIrrevocable, bool checkSpender_)
+ RuleWhitelistOwnable2Step(owner, forwarderIrrevocable, checkSpender_)
+ {}
+
+ function exposedMsgDataLength() external view returns (uint256) {
+ return _msgData().length;
+ }
+}
+
+contract RuleWhitelistWrapperOwnable2StepHarness is RuleWhitelistWrapperOwnable2Step {
+ constructor(address owner, address forwarderIrrevocable, bool checkSpender_)
+ RuleWhitelistWrapperOwnable2Step(owner, forwarderIrrevocable, checkSpender_)
+ {}
+
+ function exposedMsgDataLength() external view returns (uint256) {
+ return _msgData().length;
+ }
+}
+
+contract RuleERC2980Ownable2StepHarness is RuleERC2980Ownable2Step {
+ constructor(address owner, address forwarderIrrevocable) RuleERC2980Ownable2Step(owner, forwarderIrrevocable) {}
+
+ function exposedMsgDataLength() external view returns (uint256) {
+ return _msgData().length;
+ }
+}
+
+contract DeploymentCoverageExtraTest is Test, HelperContract {
+ function testDeploymentWrappersAndHooksCoverage() public {
+ RuleBlacklistHarness blacklist = new RuleBlacklistHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS);
+ RuleWhitelistHarness whitelist = new RuleWhitelistHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true);
+ RuleWhitelistWrapperHarness wrapper = new RuleWhitelistWrapperHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true);
+ RuleERC2980Harness erc2980 = new RuleERC2980Harness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS);
+ RuleSanctionsListHarness sanctions =
+ new RuleSanctionsListHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, ISanctionsList(ZERO_ADDRESS));
+
+ RuleBlacklistOwnable2StepHarness blacklistOwnable =
+ new RuleBlacklistOwnable2StepHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS);
+ RuleWhitelistOwnable2StepHarness whitelistOwnable =
+ new RuleWhitelistOwnable2StepHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true);
+ RuleWhitelistWrapperOwnable2StepHarness wrapperOwnable =
+ new RuleWhitelistWrapperOwnable2StepHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true);
+ RuleERC2980Ownable2StepHarness erc2980Ownable =
+ new RuleERC2980Ownable2StepHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS);
+
+ assertGe(blacklist.exposedMsgDataLength(), 4);
+ assertGe(whitelist.exposedMsgDataLength(), 4);
+ assertGe(wrapper.exposedMsgDataLength(), 4);
+ assertGe(erc2980.exposedMsgDataLength(), 4);
+ assertGe(sanctions.exposedMsgDataLength(), 4);
+ assertGe(blacklistOwnable.exposedMsgDataLength(), 4);
+ assertGe(whitelistOwnable.exposedMsgDataLength(), 4);
+ assertGe(wrapperOwnable.exposedMsgDataLength(), 4);
+ assertGe(erc2980Ownable.exposedMsgDataLength(), 4);
+
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ blacklist.addAddress(ADDRESS1);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ blacklist.removeAddress(ADDRESS1);
+
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ whitelist.setCheckSpender(false);
+
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ wrapper.setCheckSpender(false);
+
+ bytes32 rulesManagerRole = wrapper.RULES_MANAGEMENT_ROLE();
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ wrapper.grantRole(rulesManagerRole, ADDRESS1);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ wrapper.revokeRole(rulesManagerRole, ADDRESS1);
+
+ assertFalse(blacklist.supportsInterface(bytes4(0xdeadbeef)));
+ assertFalse(whitelist.supportsInterface(bytes4(0xdeadbeef)));
+ assertFalse(wrapper.supportsInterface(bytes4(0xdeadbeef)));
+ assertFalse(erc2980.supportsInterface(bytes4(0xdeadbeef)));
+ assertFalse(sanctions.supportsInterface(bytes4(0xdeadbeef)));
+ }
+}
+
+contract OperationCoverageExtraTest is Test, HelperContract {
+ function testConditionalTransferLightCreatedDestroyedAndInterfaces() public {
+ RuleConditionalTransferLight rule = new RuleConditionalTransferLight(DEFAULT_ADMIN_ADDRESS);
+
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ rule.bindToken(address(this));
+
+ rule.created(ADDRESS1, 1);
+ rule.destroyed(ADDRESS1, 1);
+
+ assertTrue(rule.supportsInterface(type(IRule).interfaceId));
+ assertTrue(rule.supportsInterface(RuleInterfaceId.IRULE_INTERFACE_ID));
+ assertFalse(rule.supportsInterface(bytes4(0xdeadbeef)));
+ }
+
+ function testConditionalTransferLightOwnableViewAndOverloads() public {
+ RuleConditionalTransferLightOwnable2Step rule =
+ new RuleConditionalTransferLightOwnable2Step(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+
+ vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+ rule.approveTransfer(ADDRESS1, ADDRESS2, 77);
+
+ vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+ rule.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 77);
+
+ assertEq(rule.approvedCount(ADDRESS1, ADDRESS2, 77), 0);
+ assertEq(rule.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 77), CODE_TRANSFER_REQUEST_NOT_APPROVED);
+ assertFalse(rule.canTransfer(ADDRESS1, ADDRESS2, 77));
+ assertFalse(rule.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 77));
+ assertTrue(rule.canReturnTransferRestrictionCode(CODE_TRANSFER_REQUEST_NOT_APPROVED));
+ assertEq(rule.messageForTransferRestriction(CODE_TRANSFER_REQUEST_NOT_APPROVED), TEXT_TRANSFER_REQUEST_NOT_APPROVED);
+ assertEq(rule.messageForTransferRestriction(CODE_NONEXISTENT), TEXT_CODE_NOT_FOUND);
+
+ assertTrue(rule.supportsInterface(type(IERC165).interfaceId));
+ assertTrue(rule.supportsInterface(type(IRule).interfaceId));
+ assertTrue(rule.supportsInterface(RuleInterfaceId.IRULE_INTERFACE_ID));
+ assertFalse(rule.supportsInterface(bytes4(0xdeadbeef)));
+ }
+}
diff --git a/test/RuleConditionalTransferLight/RuleConditionalTransferLightApproveAndTransfer.t.sol b/test/RuleConditionalTransferLight/RuleConditionalTransferLightApproveAndTransfer.t.sol
index ddb2087..24a2891 100644
--- a/test/RuleConditionalTransferLight/RuleConditionalTransferLightApproveAndTransfer.t.sol
+++ b/test/RuleConditionalTransferLight/RuleConditionalTransferLightApproveAndTransfer.t.sol
@@ -6,6 +6,22 @@ import {HelperContract} from "../HelperContract.sol";
import {RuleConditionalTransferLight} from "src/rules/operation/RuleConditionalTransferLight.sol";
import {MockERC20WithTransferContext} from "../utils/MockERC20WithTransferContext.sol";
+contract MockERC20TransferFromFalse {
+ mapping(address => mapping(address => uint256)) private _allowances;
+
+ function setAllowance(address owner, address spender, uint256 value) external {
+ _allowances[owner][spender] = value;
+ }
+
+ function allowance(address owner, address spender) external view returns (uint256) {
+ return _allowances[owner][spender];
+ }
+
+ function transferFrom(address, address, uint256) external pure returns (bool) {
+ return false;
+ }
+}
+
contract RuleConditionalTransferLightApproveAndTransfer is Test, HelperContract {
RuleConditionalTransferLight private rule;
MockERC20WithTransferContext private token;
@@ -33,4 +49,29 @@ contract RuleConditionalTransferLightApproveAndTransfer is Test, HelperContract
assertEq(token.balanceOf(ADDRESS2), 10);
assertEq(rule.approvedCount(ADDRESS1, ADDRESS2, 10), 0);
}
+
+ function testApproveAndTransferIfAllowedRevertsOnZeroToken() public {
+ vm.expectRevert(RuleConditionalTransferLight_TokenAddressZeroNotAllowed.selector);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ rule.approveAndTransferIfAllowed(ZERO_ADDRESS, ADDRESS1, ADDRESS2, 10);
+ }
+
+ function testApproveAndTransferIfAllowedRevertsOnInsufficientAllowance() public {
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleConditionalTransferLight_InsufficientAllowance.selector, address(token), ADDRESS1, 0, 10
+ )
+ );
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ rule.approveAndTransferIfAllowed(address(token), ADDRESS1, ADDRESS2, 10);
+ }
+
+ function testApproveAndTransferIfAllowedRevertsOnTransferFailure() public {
+ MockERC20TransferFromFalse failingToken = new MockERC20TransferFromFalse();
+ failingToken.setAllowance(ADDRESS1, address(rule), 10);
+
+ vm.expectRevert(RuleConditionalTransferLight_TransferFailed.selector);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ rule.approveAndTransferIfAllowed(address(failingToken), ADDRESS1, ADDRESS2, 10);
+ }
}
diff --git a/test/RuleConditionalTransferLight/RuleConditionalTransferLightRuleEngineIntegration.t.sol b/test/RuleConditionalTransferLight/RuleConditionalTransferLightRuleEngineIntegration.t.sol
index b6f599b..b93b76c 100644
--- a/test/RuleConditionalTransferLight/RuleConditionalTransferLightRuleEngineIntegration.t.sol
+++ b/test/RuleConditionalTransferLight/RuleConditionalTransferLightRuleEngineIntegration.t.sol
@@ -90,6 +90,7 @@ contract RuleConditionalTransferLightRuleEngineIntegration is Test, HelperContra
function testFuzz_ApproveAndConsume(address from, address to, uint96 value, uint8 approvals, uint8 consumes) public {
approvals = uint8(bound(approvals, 0, 20));
consumes = uint8(bound(consumes, 0, approvals));
+ bool isMintOrBurnPath = from == address(0) || to == address(0);
for (uint256 i = 0; i < approvals; ++i) {
vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
@@ -102,6 +103,7 @@ contract RuleConditionalTransferLightRuleEngineIntegration is Test, HelperContra
}
resUint256 = ruleConditionalTransferLight.approvedCount(from, to, value);
- assertEq(resUint256, approvals - consumes);
+ uint256 expectedCount = isMintOrBurnPath ? approvals : approvals - consumes;
+ assertEq(resUint256, expectedCount);
}
}
diff --git a/test/RuleConditionalTransferLight/RuleConditionalTransferLightUnit.t.sol b/test/RuleConditionalTransferLight/RuleConditionalTransferLightUnit.t.sol
index 4d730ee..d19f79b 100644
--- a/test/RuleConditionalTransferLight/RuleConditionalTransferLightUnit.t.sol
+++ b/test/RuleConditionalTransferLight/RuleConditionalTransferLightUnit.t.sol
@@ -14,6 +14,11 @@ contract RuleConditionalTransferLightUnit is Test, HelperContract {
rule.bindToken(ADDRESS3);
}
+ function testConstructorRevertsOnZeroAdmin() public {
+ vm.expectRevert();
+ new RuleConditionalTransferLight(address(0));
+ }
+
function testApproveTransfer_OnlyOperator() public {
vm.expectRevert();
vm.prank(ADDRESS1);
@@ -60,4 +65,18 @@ contract RuleConditionalTransferLightUnit is Test, HelperContract {
resBool = rule.canTransfer(ADDRESS1, ADDRESS2, 10);
assertEq(resBool, true);
}
+
+ function testDetectRestrictionMintOrBurnPathReturnsTransferOk() public {
+ resUint8 = rule.detectTransferRestriction(address(0), ADDRESS2, 10);
+ assertEq(resUint8, TRANSFER_OK);
+
+ resUint8 = rule.detectTransferRestriction(ADDRESS1, address(0), 10);
+ assertEq(resUint8, TRANSFER_OK);
+
+ resBool = rule.canTransfer(address(0), ADDRESS2, 10);
+ assertTrue(resBool);
+
+ resBool = rule.canTransfer(ADDRESS1, address(0), 10);
+ assertTrue(resBool);
+ }
}
diff --git a/test/RuleERC2980/RuleERC2980.t.sol b/test/RuleERC2980/RuleERC2980.t.sol
index 71fb707..bfebdfb 100644
--- a/test/RuleERC2980/RuleERC2980.t.sol
+++ b/test/RuleERC2980/RuleERC2980.t.sol
@@ -401,4 +401,36 @@ contract RuleERC2980Test is Test, HelperContract {
assertTrue(results[0]);
assertFalse(results[1]);
}
+
+ function testBatchOperationsSkipDuplicatesAndMissingEntries() public {
+ // Whitelist: duplicate entry should be skipped in batch add path.
+ address[] memory whitelistToAdd = new address[](1);
+ whitelistToAdd[0] = ADDRESS2; // already whitelisted in setUp
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleERC2980.addWhitelistAddresses(whitelistToAdd);
+ assertEq(ruleERC2980.whitelistAddressCount(), 1);
+
+ // Whitelist: removing a missing address should be skipped in batch remove path.
+ address[] memory whitelistToRemove = new address[](1);
+ whitelistToRemove[0] = ADDRESS3; // not whitelisted
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleERC2980.removeWhitelistAddresses(whitelistToRemove);
+ assertEq(ruleERC2980.whitelistAddressCount(), 1);
+
+ // Frozenlist: duplicate entry should be skipped in batch add path.
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleERC2980.addFrozenlistAddress(ADDRESS1);
+ address[] memory frozenToAdd = new address[](1);
+ frozenToAdd[0] = ADDRESS1; // already frozen
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleERC2980.addFrozenlistAddresses(frozenToAdd);
+ assertEq(ruleERC2980.frozenlistAddressCount(), 1);
+
+ // Frozenlist: removing a missing address should be skipped in batch remove path.
+ address[] memory frozenToRemove = new address[](1);
+ frozenToRemove[0] = ADDRESS3; // not frozen
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleERC2980.removeFrozenlistAddresses(frozenToRemove);
+ assertEq(ruleERC2980.frozenlistAddressCount(), 1);
+ }
}
diff --git a/test/RuleIdentityRegistry/Ownable/RuleIdentityRegistryOwnable2Step.t.sol b/test/RuleIdentityRegistry/Ownable/RuleIdentityRegistryOwnable2Step.t.sol
new file mode 100644
index 0000000..4f8b069
--- /dev/null
+++ b/test/RuleIdentityRegistry/Ownable/RuleIdentityRegistryOwnable2Step.t.sol
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: MPL-2.0
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {HelperContract} from "../../HelperContract.sol";
+import {Ownable2StepTestBase, IOwnable2StepLike} from "../../utils/Ownable2StepTestBase.sol";
+import {IdentityRegistryMock} from "../../utils/IdentityRegistryMock.sol";
+import {RuleIdentityRegistryOwnable2Step} from
+ "src/rules/validation/deployment/RuleIdentityRegistryOwnable2Step.sol";
+
+contract RuleIdentityRegistryOwnable2StepTest is Ownable2StepTestBase {
+ function _deployOwnable2Step() internal override returns (IOwnable2StepLike, address) {
+ address ownerAddr = WHITELIST_OPERATOR_ADDRESS;
+ IdentityRegistryMock registry = new IdentityRegistryMock();
+ RuleIdentityRegistryOwnable2Step rule = new RuleIdentityRegistryOwnable2Step(ownerAddr, address(registry));
+ return (IOwnable2StepLike(address(rule)), ownerAddr);
+ }
+}
+
+contract RuleIdentityRegistryOwnable2StepAccessControl is Test, HelperContract {
+ error OwnableUnauthorizedAccount(address account);
+
+ RuleIdentityRegistryOwnable2Step private rule;
+ IdentityRegistryMock private registry;
+
+ function setUp() public {
+ registry = new IdentityRegistryMock();
+ rule = new RuleIdentityRegistryOwnable2Step(WHITELIST_OPERATOR_ADDRESS, address(registry));
+ }
+
+ function testOwnerCanSetAndClearIdentityRegistry() public {
+ IdentityRegistryMock newRegistry = new IdentityRegistryMock();
+
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ rule.setIdentityRegistry(address(newRegistry));
+ assertEq(address(rule.identityRegistry()), address(newRegistry));
+
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ rule.clearIdentityRegistry();
+ assertEq(address(rule.identityRegistry()), ZERO_ADDRESS);
+ }
+
+ function testNonOwnerCannotManageIdentityRegistry() public {
+ vm.expectRevert(abi.encodeWithSelector(OwnableUnauthorizedAccount.selector, ATTACKER));
+ vm.prank(ATTACKER);
+ rule.setIdentityRegistry(address(registry));
+
+ vm.expectRevert(abi.encodeWithSelector(OwnableUnauthorizedAccount.selector, ATTACKER));
+ vm.prank(ATTACKER);
+ rule.clearIdentityRegistry();
+ }
+}
diff --git a/test/RuleIdentityRegistry/RuleIdentityRegistryUnit.t.sol b/test/RuleIdentityRegistry/RuleIdentityRegistryUnit.t.sol
index 3a886e1..f59db86 100644
--- a/test/RuleIdentityRegistry/RuleIdentityRegistryUnit.t.sol
+++ b/test/RuleIdentityRegistry/RuleIdentityRegistryUnit.t.sol
@@ -51,6 +51,14 @@ contract RuleIdentityRegistryUnit is Test, HelperContract {
assertEq(resUint8, CODE_ADDRESS_SPENDER_NOT_VERIFIED);
}
+ function testDetectRestrictionFrom_NoRegistry_ReturnsOk() public {
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ rule.clearIdentityRegistry();
+
+ resUint8 = rule.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 1);
+ assertEq(resUint8, TRANSFER_OK);
+ }
+
function testSetIdentityRegistry_RevertsOnZeroAddress() public {
vm.expectRevert(RuleIdentityRegistry_RegistryAddressZeroNotAllowed.selector);
vm.prank(DEFAULT_ADMIN_ADDRESS);
@@ -102,4 +110,35 @@ contract RuleIdentityRegistryUnit is Test, HelperContract {
);
rule.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 10);
}
+
+ function testTransferred_DoesNotRevertWhenValid() public {
+ registry.setVerified(ADDRESS1, true);
+ registry.setVerified(ADDRESS2, true);
+
+ rule.transferred(ADDRESS1, ADDRESS2, 10);
+ }
+
+ function testTransferredFrom_DoesNotRevertWhenValid() public {
+ registry.setVerified(ADDRESS1, true);
+ registry.setVerified(ADDRESS2, true);
+ registry.setVerified(ADDRESS3, true);
+
+ rule.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 10);
+ }
+
+ function testCanReturnTransferRestrictionCode() public view {
+ assertTrue(rule.canReturnTransferRestrictionCode(CODE_ADDRESS_FROM_NOT_VERIFIED));
+ assertTrue(rule.canReturnTransferRestrictionCode(CODE_ADDRESS_TO_NOT_VERIFIED));
+ assertTrue(rule.canReturnTransferRestrictionCode(CODE_ADDRESS_SPENDER_NOT_VERIFIED));
+ assertFalse(rule.canReturnTransferRestrictionCode(CODE_NONEXISTENT));
+ }
+
+ function testMessageForTransferRestriction() public view {
+ assertEq(rule.messageForTransferRestriction(CODE_ADDRESS_FROM_NOT_VERIFIED), TEXT_ADDRESS_FROM_NOT_VERIFIED);
+ assertEq(rule.messageForTransferRestriction(CODE_ADDRESS_TO_NOT_VERIFIED), TEXT_ADDRESS_TO_NOT_VERIFIED);
+ assertEq(
+ rule.messageForTransferRestriction(CODE_ADDRESS_SPENDER_NOT_VERIFIED), TEXT_ADDRESS_SPENDER_NOT_VERIFIED
+ );
+ assertEq(rule.messageForTransferRestriction(CODE_NONEXISTENT), TEXT_CODE_NOT_FOUND);
+ }
}
diff --git a/test/RuleMaxTotalSupply/Ownable/RuleMaxTotalSupplyOwnable2Step.t.sol b/test/RuleMaxTotalSupply/Ownable/RuleMaxTotalSupplyOwnable2Step.t.sol
new file mode 100644
index 0000000..b1028df
--- /dev/null
+++ b/test/RuleMaxTotalSupply/Ownable/RuleMaxTotalSupplyOwnable2Step.t.sol
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: MPL-2.0
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {HelperContract} from "../../HelperContract.sol";
+import {Ownable2StepTestBase, IOwnable2StepLike} from "../../utils/Ownable2StepTestBase.sol";
+import {TotalSupplyMock} from "../../utils/TotalSupplyMock.sol";
+import {RuleMaxTotalSupplyOwnable2Step} from "src/rules/validation/deployment/RuleMaxTotalSupplyOwnable2Step.sol";
+
+contract RuleMaxTotalSupplyOwnable2StepTest is Ownable2StepTestBase {
+ function _deployOwnable2Step() internal override returns (IOwnable2StepLike, address) {
+ address ownerAddr = WHITELIST_OPERATOR_ADDRESS;
+ TotalSupplyMock token = new TotalSupplyMock();
+ RuleMaxTotalSupplyOwnable2Step rule = new RuleMaxTotalSupplyOwnable2Step(ownerAddr, address(token), 100);
+ return (IOwnable2StepLike(address(rule)), ownerAddr);
+ }
+}
+
+contract RuleMaxTotalSupplyOwnable2StepAccessControl is Test, HelperContract {
+ error OwnableUnauthorizedAccount(address account);
+
+ RuleMaxTotalSupplyOwnable2Step private rule;
+ TotalSupplyMock private token;
+
+ function setUp() public {
+ token = new TotalSupplyMock();
+ rule = new RuleMaxTotalSupplyOwnable2Step(WHITELIST_OPERATOR_ADDRESS, address(token), 100);
+ }
+
+ function testOwnerCanManageMaxTotalSupply() public {
+ TotalSupplyMock newToken = new TotalSupplyMock();
+
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ rule.setMaxTotalSupply(150);
+ assertEq(rule.maxTotalSupply(), 150);
+
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ rule.setTokenContract(address(newToken));
+ assertEq(address(rule.tokenContract()), address(newToken));
+ }
+
+ function testNonOwnerCannotManageMaxTotalSupply() public {
+ vm.expectRevert(abi.encodeWithSelector(OwnableUnauthorizedAccount.selector, ATTACKER));
+ vm.prank(ATTACKER);
+ rule.setMaxTotalSupply(200);
+
+ vm.expectRevert(abi.encodeWithSelector(OwnableUnauthorizedAccount.selector, ATTACKER));
+ vm.prank(ATTACKER);
+ rule.setTokenContract(address(token));
+ }
+}
diff --git a/test/RuleMaxTotalSupply/RuleMaxTotalSupplyUnit.t.sol b/test/RuleMaxTotalSupply/RuleMaxTotalSupplyUnit.t.sol
index 62277c8..d4de2cc 100644
--- a/test/RuleMaxTotalSupply/RuleMaxTotalSupplyUnit.t.sol
+++ b/test/RuleMaxTotalSupply/RuleMaxTotalSupplyUnit.t.sol
@@ -87,4 +87,24 @@ contract RuleMaxTotalSupplyUnit is Test, HelperContract {
);
rule.transferred(ADDRESS3, ZERO_ADDRESS, ADDRESS1, 1);
}
+
+ function testTransferred_DoesNotRevertWhenValid() public {
+ token.setTotalSupply(90);
+ rule.transferred(ZERO_ADDRESS, ADDRESS1, 10);
+ }
+
+ function testTransferredFrom_DoesNotRevertWhenValid() public {
+ token.setTotalSupply(90);
+ rule.transferred(ADDRESS3, ZERO_ADDRESS, ADDRESS1, 10);
+ }
+
+ function testCanReturnTransferRestrictionCode() public view {
+ assertTrue(rule.canReturnTransferRestrictionCode(CODE_MAX_TOTAL_SUPPLY_EXCEEDED));
+ assertFalse(rule.canReturnTransferRestrictionCode(CODE_NONEXISTENT));
+ }
+
+ function testMessageForTransferRestriction() public view {
+ assertEq(rule.messageForTransferRestriction(CODE_MAX_TOTAL_SUPPLY_EXCEEDED), TEXT_MAX_TOTAL_SUPPLY_EXCEEDED);
+ assertEq(rule.messageForTransferRestriction(CODE_NONEXISTENT), TEXT_CODE_NOT_FOUND);
+ }
}
diff --git a/test/RuleSanctionList/Ownable/RuleSanctionsListOwnable2Step.t.sol b/test/RuleSanctionList/Ownable/RuleSanctionsListOwnable2Step.t.sol
new file mode 100644
index 0000000..090f0f3
--- /dev/null
+++ b/test/RuleSanctionList/Ownable/RuleSanctionsListOwnable2Step.t.sol
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: MPL-2.0
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {HelperContract} from "../../HelperContract.sol";
+import {Ownable2StepTestBase, IOwnable2StepLike} from "../../utils/Ownable2StepTestBase.sol";
+import {SanctionListOracle} from "../../utils/SanctionListOracle.sol";
+import {ISanctionsList} from "src/rules/interfaces/ISanctionsList.sol";
+import {RuleSanctionsListOwnable2Step} from "src/rules/validation/deployment/RuleSanctionsListOwnable2Step.sol";
+
+contract RuleSanctionsListOwnable2StepHarness is RuleSanctionsListOwnable2Step {
+ constructor(address owner, address forwarderIrrevocable, ISanctionsList sanctionContractOracle_)
+ RuleSanctionsListOwnable2Step(owner, forwarderIrrevocable, sanctionContractOracle_)
+ {}
+
+ function exposedMsgSender() external view returns (address) {
+ return _msgSender();
+ }
+
+ function exposedMsgData() external view returns (bytes memory) {
+ return _msgData();
+ }
+
+ function exposedContextSuffixLength() external view returns (uint256) {
+ return _contextSuffixLength();
+ }
+}
+
+contract RuleSanctionsListOwnable2StepTest is Ownable2StepTestBase {
+ function _deployOwnable2Step() internal override returns (IOwnable2StepLike, address) {
+ address ownerAddr = SANCTIONLIST_OPERATOR_ADDRESS;
+ RuleSanctionsListOwnable2Step rule =
+ new RuleSanctionsListOwnable2Step(ownerAddr, ZERO_ADDRESS, ISanctionsList(ZERO_ADDRESS));
+ return (IOwnable2StepLike(address(rule)), ownerAddr);
+ }
+}
+
+contract RuleSanctionsListOwnable2StepAccessControl is Test, HelperContract {
+ error OwnableUnauthorizedAccount(address account);
+
+ RuleSanctionsListOwnable2StepHarness private rule;
+ SanctionListOracle private oracle;
+
+ function setUp() public {
+ oracle = new SanctionListOracle();
+ rule = new RuleSanctionsListOwnable2StepHarness(
+ SANCTIONLIST_OPERATOR_ADDRESS, ZERO_ADDRESS, ISanctionsList(ZERO_ADDRESS)
+ );
+ }
+
+ function testOwnerCanSetAndClearOracle() public {
+ vm.prank(SANCTIONLIST_OPERATOR_ADDRESS);
+ rule.setSanctionListOracle(oracle);
+ assertEq(address(rule.sanctionsList()), address(oracle));
+
+ vm.prank(SANCTIONLIST_OPERATOR_ADDRESS);
+ rule.clearSanctionListOracle();
+ assertEq(address(rule.sanctionsList()), ZERO_ADDRESS);
+ }
+
+ function testNonOwnerCannotSetOracle() public {
+ vm.expectRevert(abi.encodeWithSelector(OwnableUnauthorizedAccount.selector, ATTACKER));
+ vm.prank(ATTACKER);
+ rule.setSanctionListOracle(oracle);
+ }
+
+ function testMetaTxOverridesAreReachable() public view {
+ assertEq(rule.exposedMsgSender(), address(this));
+ assertEq(rule.exposedContextSuffixLength(), 20);
+ assertGe(rule.exposedMsgData().length, 4);
+ }
+}
diff --git a/test/RuleWhitelist/RuleWhitelist.t.sol b/test/RuleWhitelist/RuleWhitelist.t.sol
index 35b0fa4..7ac30a0 100644
--- a/test/RuleWhitelist/RuleWhitelist.t.sol
+++ b/test/RuleWhitelist/RuleWhitelist.t.sol
@@ -64,6 +64,27 @@ contract RuleWhitelistTest is Test, HelperContract {
assertEq(resBool, true);
}
+ function testContainsReflectsListingStatus() public {
+ // Act - Assert
+ assertFalse(ruleWhitelist.contains(ADDRESS1));
+
+ // Arrange
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS1);
+
+ // Act - Assert
+ assertTrue(ruleWhitelist.contains(ADDRESS1));
+ }
+
+ function testIsVerifiedReflectsListingStatus() public {
+ assertFalse(ruleWhitelist.isVerified(ADDRESS1));
+
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS1);
+
+ assertTrue(ruleWhitelist.isVerified(ADDRESS1));
+ }
+
function testAddressesIsIndicatedAsWhitelisted() public {
// Arrange
_addAddresses();
diff --git a/test/RuleWhitelist/WhitelistWrapper.t.sol b/test/RuleWhitelist/WhitelistWrapper.t.sol
index 27d6271..cfc1f4a 100644
--- a/test/RuleWhitelist/WhitelistWrapper.t.sol
+++ b/test/RuleWhitelist/WhitelistWrapper.t.sol
@@ -10,6 +10,16 @@ import {RuleWhitelistWrapper} from "src/rules/validation/deployment/RuleWhitelis
* @title Integration test with the CMTAT
*/
+contract RuleWhitelistWrapperHarnessInternal is RuleWhitelistWrapper {
+ constructor(address admin, address forwarderIrrevocable, bool checkSpender_)
+ RuleWhitelistWrapper(admin, forwarderIrrevocable, checkSpender_)
+ {}
+
+ function exposedTransferredSpenderInternal(address spender, address from, address to, uint256 value) external view {
+ _transferred(spender, from, to, value);
+ }
+}
+
contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
uint256 constant ADDRESS1_BALANCE_INIT = 31;
uint256 constant ADDRESS2_BALANCE_INIT = 32;
@@ -221,6 +231,38 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
ruleWhitelistWrapper.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
}
+ function testDetectTransferRestrictionWithSpenderFromNotWhitelisted() public {
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS2);
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS3);
+
+ resUint8 = ruleWhitelistWrapper.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ assertEq(resUint8, CODE_ADDRESS_FROM_NOT_WHITELISTED);
+ }
+
+ function testDetectTransferRestrictionWithSpenderToNotWhitelisted() public {
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS1);
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS3);
+
+ resUint8 = ruleWhitelistWrapper.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED);
+ }
+
+ function testDetectTransferRestrictionFromIgnoresSpenderWhenCheckDisabled() public {
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelistWrapper.setCheckSpender(false);
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS1);
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS2);
+
+ resUint8 = ruleWhitelistWrapper.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ assertEq(resUint8, NO_ERROR);
+ }
+
function testDetectTransferRestrictionOk() public {
// Arrange
vm.prank(WHITELIST_OPERATOR_ADDRESS);
@@ -310,4 +352,21 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
new RuleWhitelistWrapper(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true);
assertFalse(emptyWrapper.isVerified(ADDRESS1));
}
+
+ function testInternalTransferredSpenderOverload() public {
+ RuleWhitelistWrapperHarnessInternal wrapperHarness =
+ new RuleWhitelistWrapperHarnessInternal(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true);
+ RuleWhitelist child = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true);
+
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ wrapperHarness.addRule(child);
+
+ vm.startPrank(WHITELIST_OPERATOR_ADDRESS);
+ child.addAddress(ADDRESS1);
+ child.addAddress(ADDRESS2);
+ child.addAddress(ADDRESS3);
+ vm.stopPrank();
+
+ wrapperHarness.exposedTransferredSpenderInternal(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ }
}
diff --git a/test/TransferContext/TransferContext.t.sol b/test/TransferContext/TransferContext.t.sol
index 3c55783..e05510b 100644
--- a/test/TransferContext/TransferContext.t.sol
+++ b/test/TransferContext/TransferContext.t.sol
@@ -72,4 +72,28 @@ contract TransferContextTest is Test, HelperContract {
vm.prank(ADDRESS3);
token.transferFromWithContext(ADDRESS1, ADDRESS2, 10, true, 0);
}
+
+ function testTransferFromContextFungibleWhitelist() public {
+ RuleWhitelist rule = _deployWhitelistRule();
+ token.setRule(address(rule));
+ token.mint(ADDRESS1, 100);
+
+ vm.prank(ADDRESS1);
+ token.approve(ADDRESS3, 10);
+
+ vm.prank(ADDRESS3);
+ token.transferFromWithContext(ADDRESS1, ADDRESS2, 10, true, 0);
+ }
+
+ function testTransferFromContextWithTokenIdWhitelist() public {
+ RuleWhitelist rule = _deployWhitelistRule();
+ token.setRule(address(rule));
+ token.mint(ADDRESS1, 100);
+
+ vm.prank(ADDRESS1);
+ token.approve(ADDRESS3, 10);
+
+ vm.prank(ADDRESS3);
+ token.transferFromWithContext(ADDRESS1, ADDRESS2, 10, false, 1);
+ }
}