```
-### Help
+#### Help
```shell
$ forge --help
$ anvil --help
$ cast --help
```
+
+
+
+## API
+
+### IRuleEngine
+
+> Each rule implements the IRuleEngine interface
+
+#### transferred
+
+```
+function transferred(address spender, address from, address to, uint256 value)
+ external;
+```
+
+Called during an ERC-20 token transfer
+ Used by rules to update internal state or enforce operation-based restrictions.
+
+##### Parameters
+
+| Name | Type | Description |
+| --------- | --------- | ------------------------------------------------------------ |
+| `spender` | `address` | Address executing the transfer (owner, operator, or approved). |
+| `from` | `address` | Current token holder. |
+| `to` | `address` | Recipient address. |
+| `value` | `uint256` | Amount transferred. |
+
+------
+
+### IERC1404
+
+#### detectTransferRestriction
+
+```
+function detectTransferRestriction(address from, address to, uint256 value)
+ external
+ view
+ returns (uint8);
+```
+
+Returns a restriction code describing why a transfer is blocked.
+
+##### Parameters
+
+| Name | Type | Description |
+| ------- | --------- | ------------------------- |
+| `from` | `address` | Sender address. |
+| `to` | `address` | Recipient address. |
+| `value` | `uint256` | Amount being transferred. |
+
+##### Returns
+
+| Name | Type | Description |
+| ----- | ------- | ---------------------------------------- |
+| `0` | `uint8` | Transfer allowed. |
+| other | `uint8` | Implementation-defined restriction code. |
+
+------
+
+#### messageForTransferRestriction
+
+```
+function messageForTransferRestriction(uint8 restrictionCode)
+ external
+ view
+ returns (string memory);
+```
+
+Returns a human-readable message associated with a restriction code.
+
+##### Parameters
+
+| Name | Type | Description |
+| ----------------- | ------- | --------------------------------------------------------- |
+| `restrictionCode` | `uint8` | Restriction code returned by `detectTransferRestriction`. |
+
+##### Returns
+
+| Name | Type | Description |
+| --------- | -------- | ------------------------------------- |
+| `message` | `string` | Explanation for the restriction code. |
+
+------
+
+### IERC1404Extend
+
+#### REJECTED_CODE_BASE
+
+```
+enum REJECTED_CODE_BASE {
+ TRANSFER_OK,
+ TRANSFER_REJECTED_DEACTIVATED,
+ TRANSFER_REJECTED_PAUSED,
+ TRANSFER_REJECTED_FROM_FROZEN,
+ TRANSFER_REJECTED_TO_FROZEN,
+ TRANSFER_REJECTED_SPENDER_FROZEN,
+ TRANSFER_REJECTED_FROM_INSUFFICIENT_ACTIVE_BALANCE
+}
+```
+
+Base transfer restriction codes used by ERC-1404 extensions.
+
+------
+
+#### detectTransferRestrictionFrom
+
+```
+function detectTransferRestrictionFrom(
+ address spender,
+ address from,
+ address to,
+ uint256 value
+)
+ external
+ view
+ returns (uint8);
+```
+
+Restriction code for transfers performed by a spender (approved operator).
+
+##### Parameters
+
+| Name | Type | Description |
+| --------- | --------- | -------------------------------- |
+| `spender` | `address` | Address performing the transfer. |
+| `from` | `address` | Current token owner. |
+| `to` | `address` | Recipient address. |
+| `value` | `uint256` | Transfer amount. |
+
+##### Returns
+
+| Name | Type | Description |
+| ------ | ------- | ---------------------------------------------------- |
+| `code` | `uint8` | 0 if transfer allowed, otherwise a restriction code. |
+
+------
+
+### IERC7551Compliance
+
+#### canTransferFrom
+
+```
+function canTransferFrom(address spender, address from, address to, uint256 value)
+ external
+ view
+ returns (bool);
+```
+
+Determines if a spender-initiated transfer is permitted.
+
+##### Parameters
+
+| Name | Type | Description |
+| --------- | --------- | -------------------------- |
+| `spender` | `address` | Caller executing transfer. |
+| `from` | `address` | Token owner. |
+| `to` | `address` | Recipient. |
+| `value` | `uint256` | Amount. |
+
+##### Returns
+
+| Name | Type | Description |
+| --------- | ------ | ----------------------------- |
+| `allowed` | `bool` | `true` if transfer permitted. |
+
+------
+
+### IERC3643ComplianceRead
+
+#### canTransfer
+
+```
+function canTransfer(address from, address to, uint256 value)
+ external
+ view
+ returns (bool isValid);
+```
+
+Returns whether a transfer is compliant.
+
+##### Parameters
+
+| Name | Type | Description |
+| ------- | --------- | ---------------- |
+| `from` | `address` | Sender. |
+| `to` | `address` | Receiver. |
+| `value` | `uint256` | Transfer amount. |
+
+##### Returns
+
+| Name | Type | Description |
+| --------- | ------ | -------------------- |
+| `isValid` | `bool` | `true` if compliant. |
+
+------
+
+### IERC3643IComplianceContract
+
+#### transferred
+
+```
+function transferred(address from, address to, uint256 value)
+ external;
+```
+
+Hook invoked during an ERC-20 token transfer.
+
+##### Parameters
+
+| Name | Type | Description |
+| ------- | --------- | ------------------- |
+| `from` | `address` | Previous owner. |
+| `to` | `address` | New owner. |
+| `value` | `uint256` | Amount transferred. |
+
+### Address List Management
+
+> This API is common to whitelist and blacklist rules
+
+#### addAddresses
+
+```
+function addAddresses(address[] calldata targetAddresses)
+ public
+ onlyRole(ADDRESS_LIST_ADD_ROLE)
+```
+
+##### Description
+
+Adds multiple addresses to the internal address set.
+
+##### Details
+
+- Does **not** revert if one or more addresses are already listed.
+- Restricted to callers holding the `ADDRESS_LIST_ADD_ROLE`.
+- Emits an `AddAddresses` event.
+
+##### Parameters
+
+| Name | Type | Description |
+| ----------------- | ----------- | ------------------------------------------ |
+| `targetAddresses` | `address[]` | Array of addresses to be added to the set. |
+
+------
+
+#### removeAddresses
+
+```
+function removeAddresses(address[] calldata targetAddresses)
+ public
+ onlyRole(ADDRESS_LIST_REMOVE_ROLE)
+```
+
+##### Description
+
+Removes multiple addresses from the internal set.
+
+##### Details
+
+- Does **not** revert if an address is not currently listed.
+- Restricted to callers holding the `ADDRESS_LIST_REMOVE_ROLE`.
+- Emits a `RemoveAddresses` event.
+
+##### Parameters
+
+| Name | Type | Description |
+| ----------------- | ----------- | --------------------------------- |
+| `targetAddresses` | `address[]` | Array of addresses to be removed. |
+
+------
+
+#### addAddress
+
+```
+function addAddress(address targetAddress)
+ public
+ onlyRole(ADDRESS_LIST_ADD_ROLE)
+```
+
+##### Description
+
+Adds a **single** address to the set.
+
+##### Details
+
+- **Reverts** if the address is already listed.
+- Restricted to callers holding the `ADDRESS_LIST_ADD_ROLE`.
+- Emits an `AddAddress` event.
+
+##### Parameters
+
+| Name | Type | Description |
+| --------------- | --------- | --------------- |
+| `targetAddress` | `address` | Address to add. |
+
+------
+
+#### removeAddress
+
+```
+function removeAddress(address targetAddress)
+ public
+ onlyRole(ADDRESS_LIST_REMOVE_ROLE)
+```
+
+##### Description
+
+Removes a **single** address from the set.
+
+##### Details
+
+- **Reverts** if the address is not listed.
+- Restricted to callers holding the `ADDRESS_LIST_REMOVE_ROLE`.
+- Emits a `RemoveAddress` event.
+
+##### Parameters
+
+| Name | Type | Description |
+| --------------- | --------- | ------------------ |
+| `targetAddress` | `address` | Address to remove. |
+
+------
+
+#### listedAddressCount
+
+```
+function listedAddressCount() public view returns (uint256 count)
+```
+
+##### Description
+
+Returns the total number of addresses currently listed in the internal set.
+
+##### Returns
+
+| Name | Type | Description |
+| ------- | --------- | --------------------------------- |
+| `count` | `uint256` | Total number of listed addresses. |
+
+------
+
+##### contains
+
+```
+function contains(address targetAddress)
+ public
+ view
+ override(IIdentityRegistryContains)
+ returns (bool isListed)
+```
+
+##### Description
+
+Checks whether a specific address is listed.
+ Implements `IIdentityRegistryContains`.
+
+##### Parameters
+
+| Name | Type | Description |
+| --------------- | --------- | ----------------- |
+| `targetAddress` | `address` | Address to check. |
+
+##### Returns
+
+| Name | Type | Description |
+| ---------- | ------ | --------------------------------------------------- |
+| `isListed` | `bool` | `true` if the address is listed, otherwise `false`. |
+
+------
+
+#### isAddressListed
+
+```
+function isAddressListed(address targetAddress)
+ public
+ view
+ returns (bool isListed)
+```
+
+##### Description
+
+Returns whether a given address is included in the internal set.
+
+##### Parameters
+
+| Name | Type | Description |
+| --------------- | --------- | ----------------- |
+| `targetAddress` | `address` | Address to check. |
+
+##### Returns
+
+| Name | Type | Description |
+| ---------- | ------ | --------------- |
+| `isListed` | `bool` | Listing status. |
+
+------
+
+#### areAddressesListed
+
+```
+function areAddressesListed(address[] memory targetAddresses)
+ public
+ view
+ returns (bool[] memory results)
+```
+
+##### Description
+
+Checks the listing status of multiple addresses in a single call.
+
+##### Parameters
+
+| Name | Type | Description |
+| ----------------- | ----------- | ---------------------------- |
+| `targetAddresses` | `address[]` | Array of addresses to check. |
+
+##### Returns
+
+| Name | Type | Description |
+| --------- | -------- | --------------------------------------------------- |
+| `results` | `bool[]` | Array of boolean listing results, aligned by index. |
+
+#### Details
+
+##### Null address
+
+It is possible to add the null address (0x0) to the blacklist. If it is the case, it will not be possible to mint and burn tokens.
+
+##### Duplicate address
+
+**addAddress**
+If the address already exists, the transaction is reverted to save gas.
+**addAddresses**
+If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert).
+
+##### NonExistent Address
+
+**removeAddress**
+If the address does not exist in the whitelist, the transaction is reverted to save gas.
+**removeAddresses**
+If the address does not exist in the whitelist, there is no change for this address. The transaction remains valid (no revert).
+
+
+
+### IERC7943NonFungibleCompliance
+
+Compliance interface for ERC-721 / ERC-1155–style non-fungible assets.
+ For ERC-721, `amount` must always be `1`.
+
+------
+
+#### Functions
+
+| Name | Description |
+| --------------- | ------------------------------------------------------------ |
+| **canTransfer** | Verifies whether a transfer is permitted according to the token’s compliance rules. |
+
+------
+
+#### canTransfer
+
+```
+function canTransfer(
+ address from,
+ address to,
+ uint256 tokenId,
+ uint256 amount
+) external view returns (bool allowed)
+```
+
+##### Description
+
+Verifies whether a token transfer is permitted according to the rule-based compliance logic.
+
+##### Details
+
+- Must not modify state.
+- May enforce checks such as allowlists, blocklists, freezing, transfer limits, regulatory rules.
+- Must return `false` if the transfer is not permitted.
+
+##### Parameters
+
+| Name | Type | Description |
+| --------- | --------- | ----------------------------------------- |
+| `from` | `address` | Current token owner. |
+| `to` | `address` | Receiving address. |
+| `tokenId` | `uint256` | Token ID. |
+| `amount` | `uint256` | Transfer amount (always `1` for ERC-721). |
+
+##### Returns
+
+| Name | Type | Description |
+| --------- | ------ | ------------------------------------------------- |
+| `allowed` | `bool` | `true` if transfer is allowed; otherwise `false`. |
+
+------
+
+### IERC7943NonFungibleComplianceExtend
+
+Extended compliance interface for ERC-721 / ERC-1155 non-fungible assets.
+ Adds restriction-code reporting, spender-aware checks, and a post-transfer hook.
+
+For ERC-721, `amount` / `value` must always be `1`.
+
+------
+
+#### Functions
+
+| Name | Description |
+| --------------------------------- | ------------------------------------------------------------ |
+| **detectTransferRestriction** | Returns a restriction code indicating why a transfer is blocked. |
+| **detectTransferRestrictionFrom** | Returns a restriction code for a spender-initiated transfer. |
+| **canTransferFrom** | Checks whether a spender-initiated transfer is allowed. |
+| **transferred** | Notifies the compliance engine that a transfer has occurred. |
+
+------
+
+#### detectTransferRestriction
+
+```
+function detectTransferRestriction(
+ address from,
+ address to,
+ uint256 tokenId,
+ uint256 amount
+) external view returns (uint8 code)
+```
+
+##### Description
+
+Returns a restriction code describing whether and why a transfer is blocked.
+
+##### Details
+
+- Must not modify state.
+- Must return `0` when the transfer is allowed.
+- Non-zero codes should follow ERC-1404 or similar standards.
+
+##### Parameters
+
+| Name | Type | Description |
+| --------- | --------- | ---------------------------------- |
+| `from` | `address` | Current token holder. |
+| `to` | `address` | Receiving address. |
+| `tokenId` | `uint256` | Token ID. |
+| `amount` | `uint256` | Transfer amount (`1` for ERC-721). |
+
+##### Returns
+
+| Name | Type | Description |
+| ------ | ------- | --------------------------------------------- |
+| `code` | `uint8` | `0` if allowed; otherwise a restriction code. |
+
+------
+
+#### detectTransferRestrictionFrom
+
+```
+function detectTransferRestrictionFrom(
+ address spender,
+ address from,
+ address to,
+ uint256 tokenId,
+ uint256 value
+) external view returns (uint8 code)
+```
+
+##### Description
+
+Returns a restriction code for a transfer initiated by a spender (approved operator or owner).
+
+##### Details
+
+- Must not modify state.
+- Must return `0` when the transfer is permitted.
+
+##### Parameters
+
+| Name | Type | Description |
+| --------- | --------- | ---------------------------------- |
+| `spender` | `address` | Address performing the transfer. |
+| `from` | `address` | Current owner. |
+| `to` | `address` | Recipient address. |
+| `tokenId` | `uint256` | Token ID being checked. |
+| `value` | `uint256` | Transfer amount (`1` for ERC-721). |
+
+##### Returns
+
+| Name | Type | Description |
+| ------ | ------- | ------------------------------------------- |
+| `code` | `uint8` | `0` if allowed; otherwise restriction code. |
+
+------
+
+#### canTransferFrom
+
+```
+function canTransferFrom(
+ address spender,
+ address from,
+ address to,
+ uint256 tokenId,
+ uint256 value
+) external view returns (bool allowed)
+```
+
+##### Description
+
+Checks whether a spender-initiated transfer is allowed under the compliance rules.
+
+##### Details
+
+- Must not modify state.
+- Should internally use `detectTransferRestrictionFrom`.
+
+##### Parameters
+
+| Name | Type | Description |
+| --------- | --------- | ---------------------------------------- |
+| `spender` | `address` | Address executing the transfer. |
+| `from` | `address` | Current owner. |
+| `to` | `address` | Recipient. |
+| `tokenId` | `uint256` | Token ID. |
+| `value` | `uint256` | Transfer amount (`1` for ERC-721 token). |
+
+##### Returns
+
+| Name | Type | Description |
+| --------- | ------ | ------------------------------ |
+| `allowed` | `bool` | `true` if transfer is allowed. |
+
+------
+
+#### transferred
+
+```
+function transferred(
+ address spender,
+ address from,
+ address to,
+ uint256 tokenId,
+ uint256 value
+) external
+```
+
+##### Description
+
+Signals to the compliance engine that a transfer has successfully occurred.
+
+##### Details
+
+- May modify compliance state.
+- Must be called by the token contract after a successful transfer.
+- Must revert if invoked by unauthorized callers.
+
+##### Parameters
+
+| Name | Type | Description |
+| --------- | --------- | ---------------------------------------- |
+| `spender` | `address` | Address executing the transfer. |
+| `from` | `address` | Previous owner. |
+| `to` | `address` | New owner. |
+| `tokenId` | `uint256` | Token transferred. |
+| `value` | `uint256` | Transfer amount (`1` for ERC-721 token). |
+
+### RuleSanctionsList
+
+Compliance rule enforcing sanctions-screening for token transfers.
+ Integrates a sanctions-oracle (e.g., Chainalysis) to block transfers when the sender, recipient, or spender is sanctioned.
+
+------
+
+#### Constructor
+
+```solidity
+constructor(address admin, address forwarderIrrevocable, ISanctionsList sanctionContractOracle_)
+```
+
+Initializes access control, meta-transaction forwarder, and optionally the sanctions oracle.
+
+#### setSanctionListOracle
+
+```solidity
+function setSanctionListOracle(ISanctionsList sanctionContractOracle_)
+ public
+ virtual
+ onlyRole(SANCTIONLIST_ROLE)
+```
+
+Set the sanctions-oracle contract used for transfer-restriction checks.
+
+##### Parameters
+
+| Name | Type | Description |
+| ------------------------- | ---------------- | ------------------------------------------------------------ |
+| `sanctionContractOracle_` | `ISanctionsList` | Address of the sanctions-oracle. Passing the zero address disables sanctions checks. |
+
+##### Description
+
+Updates the sanctions-oracle contract reference.
+ This function may only be called by accounts granted the `SANCTIONLIST_ROLE`.
+
+Setting the oracle to the zero address is permitted and effectively disables all sanctions-based transfer restrictions.
+
+##### Emits
+
+| Event | Description |
+| -------------------------------- | ----------------------------------------------------- |
+| `SetSanctionListOracle(address)` | Emitted when the sanctions-oracle address is updated. |
+
+
+
+## Intellectual property
+
+The code is copyright (c) Capital Market and Technology Association, 2022-2025, and is released under [Mozilla Public License 2.0](https://github.com/CMTA/CMTAT/blob/master/LICENSE.md).
diff --git a/doc/TOOLCHAIN.md b/doc/TOOLCHAIN.md
index f5d9cc1..64b6246 100644
--- a/doc/TOOLCHAIN.md
+++ b/doc/TOOLCHAIN.md
@@ -53,14 +53,6 @@ Warning:
## Generate documentation
-### [docgen](https://github.com/OpenZeppelin/solidity-docgen)
-
->Solidity-docgen is a program that extracts documentation for a Solidity project.
-
-```
-npx hardhat docgen
-```
-
### [sol2uml](https://github.com/naddison36/sol2uml)
>Generate UML for smart contracts
@@ -131,21 +123,9 @@ slither . --checklist --filter-paths "openzeppelin-contracts|test|CMTAT|forge-s
## Code style guidelines
-We use the following tools to ensure consistent coding style:
-
-[Prettier](https://github.com/prettier-solidity/prettier-plugin-solidity)
+We use `Foundry` to perform code style guidelines
-```
-npm run-script lint:sol:prettier
-```
-
-[Ethlint / Solium](https://github.com/duaraghav8/Ethlint)
-
-```
-npm run-script lint:sol
-npm run-script lint:sol:fix
-npm run-script lint:sol:test
-npm run-script lint:sol:test:fix
+```bash
+forge fmt
```
-The related components can be installed with `npm install` (see [package.json](./package.json)).
diff --git a/doc/codelist.md b/doc/codelist.md
deleted file mode 100644
index 2ad6da6..0000000
--- a/doc/codelist.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# Rule - Code list
-
-> It is very important that each rule uses an unique code
-
-Here the list of codes used by the different rules
-
-| Contract | Constant name | Value |
-| ----------------------- | ---------------------------------- | ----- |
-| All | TRANSFER_OK (from CMTAT) | 0 |
-| RuleWhitelist | CODE_ADDRESS_FROM_NOT_WHITELISTED | 21 |
-| RuleWhitelist | CODE_ADDRESS_TO_NOT_WHITELISTED | 22 |
-| RuleSanctionList | CODE_ADDRESS_FROM_IS_SANCTIONED | 31 |
-| RuleSanctionList | CODE_ADDRESS_TO_IS_SANCTIONED | 32 |
-| RuleBlacklist | CODE_ADDRESS_FROM_IS_BLACKLISTED | 41 |
-| RuleBlacklist | CODE_ADDRESS_TO_IS_BLACKLISTED | 42 |
-| RuleConditionalTransfer | CODE_TRANSFER_REQUEST_NOT_APPROVED | 51 |
-
-
-
-Warning: the CMTAT already uses the code 0-4 and the code 5-9 should be left free to allow further additions in the CMTAT
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func-sort-c.html
similarity index 58%
rename from doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func.html
rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func-sort-c.html
index b899bc1..5ee975a 100644
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func-sort-c.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - src/rules/validation/abstract/RuleWhitelistCommon.sol - functions
-
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol - functions
+
LCOV - code coverage report
-
+
-
+
@@ -37,7 +37,7 @@
-
+
@@ -49,38 +49,38 @@
-
-
+
+
-
+
-
+
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func.html
similarity index 56%
rename from doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html
rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func.html
index d40fb06..5e3e889 100644
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - src/rules/validation/abstract/RuleWhitelistCommon.sol - functions
-
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol - functions
+
LCOV - code coverage report
-
+
-
+
@@ -37,7 +37,7 @@
-
+
@@ -49,38 +49,38 @@
-
-
+
+
-
+
-
+
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.gcov.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.gcov.html
similarity index 52%
rename from doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.gcov.html
rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.gcov.html
index 20b596c..001fd5e 100644
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.gcov.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.gcov.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - src/rules/validation/abstract/RuleWhitelistCommon.sol
-
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol
+
LCOV - code coverage report
-
+
-
+
@@ -37,7 +37,7 @@
-
+
@@ -49,16 +49,16 @@
-
-
+
+
-
+
-
+
@@ -69,47 +69,52 @@
Branch data Line data Source code
- 1 : : // SPDX-License-Identifier: MPL-2.0
+ 1 : : //SPDX-License-Identifier: MPL-2.0
2 : :
3 : : pragma solidity ^0.8.20;
4 : :
- 5 : : import "./RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol";
- 6 : : import "./RuleValidateTransfer.sol";
+ 5 : : /* ==== OpenZeppelin === */
+ 6 : : import {AccessControl} from "OZ/access/AccessControl.sol";
7 : :
- 8 : : abstract contract RuleWhitelistCommon is
- 9 : : RuleValidateTransfer,
- 10 : : RuleWhitelistInvariantStorage
- 11 : : {
- 12 : : /**
- 13 : : * @notice To know if the restriction code is valid for this rule or not
- 14 : : * @param _restrictionCode The target restriction code
- 15 : : * @return true if the restriction code is known, false otherwise
- 16 : : **/
- 17 : : function canReturnTransferRestrictionCode(
- 18 : : uint8 _restrictionCode
- 19 : : ) external pure override returns (bool) {
- 20 : 12 : return
- 21 : 12 : _restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED ||
- 22 : 6 : _restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED;
- 23 : : }
- 24 : :
- 25 : : /**
- 26 : : * @notice Return the corresponding message
- 27 : : * @param _restrictionCode The target restriction code
- 28 : : * @return true if the transfer is valid, false otherwise
- 29 : : **/
- 30 : : function messageForTransferRestriction(
- 31 : : uint8 _restrictionCode
- 32 : : ) external pure override returns (string memory) {
- 33 [ + + ]: 10 : if (_restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) {
- 34 : 6 : return TEXT_ADDRESS_FROM_NOT_WHITELISTED;
- 35 [ + + ]: 4 : } else if (_restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) {
- 36 : 3 : return TEXT_ADDRESS_TO_NOT_WHITELISTED;
- 37 : : } else {
- 38 : 1 : return TEXT_CODE_NOT_FOUND;
- 39 : : }
- 40 : : }
- 41 : : }
+ 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 : : }
+ 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);
+ 30 : : }
+ 31 : :
+ 32 : : /*//////////////////////////////////////////////////////////////
+ 33 : : PUBLIC/EXTERNAL FUNCTIONS
+ 34 : : //////////////////////////////////////////////////////////////*/
+ 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 : : }
@@ -117,7 +122,7 @@
diff --git a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-b.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-b.html
similarity index 57%
rename from doc/coverage/coverage/src/rules/operation/abstract/index-sort-b.html
rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-b.html
index e47a898..6514966 100644
--- a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-b.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-b.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - src/rules/operation/abstract
-
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules
+
LCOV - code coverage report
-
+
-
+
@@ -31,17 +31,17 @@
-
-
+
+
-
+
-
-
+
+
@@ -49,16 +49,16 @@
-
-
+
+
-
+
-
+
@@ -76,29 +76,29 @@
- Filename
- Line Coverage
- Functions
- Branches
+ Filename
+ Line Coverage
+ Functions
+ Branches
- RuleConditionalTransferOperator.sol
+ AccessControlModuleStandalone.sol
-
+
100.0 %
- 113 / 113
+ 8 / 8
100.0 %
- 20 / 20
+ 2 / 2
100.0 %
- 31 / 31
+ 3 / 3
diff --git a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-f.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-f.html
similarity index 57%
rename from doc/coverage/coverage/src/rules/operation/abstract/index-sort-f.html
rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-f.html
index aaae3fc..d593422 100644
--- a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-f.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-f.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - src/rules/operation/abstract
-
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules
+
LCOV - code coverage report
-
+
-
+
@@ -31,17 +31,17 @@
-
-
+
+
-
+
-
-
+
+
@@ -49,16 +49,16 @@
-
-
+
+
-
+
-
+
@@ -76,29 +76,29 @@
- Filename
- Line Coverage
- Functions
- Branches
+ Filename
+ Line Coverage
+ Functions
+ Branches
- RuleConditionalTransferOperator.sol
+ AccessControlModuleStandalone.sol
-
+
100.0 %
- 113 / 113
+ 8 / 8
100.0 %
- 20 / 20
+ 2 / 2
100.0 %
- 31 / 31
+ 3 / 3
diff --git a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-l.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-l.html
similarity index 56%
rename from doc/coverage/coverage/src/rules/operation/abstract/index-sort-l.html
rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-l.html
index 2ec5b2c..42bb733 100644
--- a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-l.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-l.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - src/rules/operation/abstract
-
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules
+
LCOV - code coverage report
-
+
-
+
@@ -31,17 +31,17 @@
-
-
+
+
-
+
-
-
+
+
@@ -49,16 +49,16 @@
-
-
+
+
-
+
-
+
@@ -76,29 +76,29 @@
- Filename
- Line Coverage
- Functions
- Branches
+ Filename
+ Line Coverage
+ Functions
+ Branches
- RuleConditionalTransferOperator.sol
+ AccessControlModuleStandalone.sol
-
+
100.0 %
- 113 / 113
+ 8 / 8
100.0 %
- 20 / 20
+ 2 / 2
100.0 %
- 31 / 31
+ 3 / 3
diff --git a/doc/coverage/coverage/src/rules/operation/abstract/index.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index.html
similarity index 57%
rename from doc/coverage/coverage/src/rules/operation/abstract/index.html
rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index.html
index 1428f56..7bed3a1 100644
--- a/doc/coverage/coverage/src/rules/operation/abstract/index.html
+++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - src/rules/operation/abstract
-
+ LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules
+
LCOV - code coverage report
-
+
-
+
@@ -31,17 +31,17 @@
-
-
+
+
-
+
-
-
+
+
@@ -49,16 +49,16 @@
-
-
+
+
-
+
-
+
@@ -76,29 +76,29 @@
- Filename
- Line Coverage
- Functions
- Branches
+ Filename
+ Line Coverage
+ Functions
+ Branches
- RuleConditionalTransferOperator.sol
+ AccessControlModuleStandalone.sol
-
+
100.0 %
- 113 / 113
+ 8 / 8
100.0 %
- 20 / 20
+ 2 / 2
100.0 %
- 31 / 31
+ 3 / 3
diff --git a/doc/coverage/coverage/index-sort-b.html b/doc/coverage/coverage/index-sort-b.html
index 79c22e9..2c38638 100644
--- a/doc/coverage/coverage/index-sort-b.html
+++ b/doc/coverage/coverage/index-sort-b.html
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,124 +82,52 @@
Branches
- script
+ validation
-
+
- 0.0 %
- 0 / 26
- 0.0 %
- 0 / 2
- 0.0 %
- 0 / 2
+ 89.9 %
+ 151 / 168
+ 84.8 %
+ 39 / 46
+ 94.3 %
+ 50 / 53
- test/RuleConditionalTransfer/utils
+ validation/abstract/RuleAddressSet
-
+
+ 91.3 %
+ 42 / 46
+ 88.2 %
+ 15 / 17
100.0 %
- 10 / 10
- 100.0 %
- 1 / 1
- -
- 0 / 0
+ 2 / 2
- test/utils
-
-
-
- 85.7 %
- 6 / 7
- 80.0 %
- 4 / 5
- -
- 0 / 0
-
-
- src/rules/validation/abstract
+ /home/ryan/Pictures/dev/Rules/src/modules
100.0 %
- 10 / 10
- 100.0 %
- 3 / 3
- 100.0 %
- 4 / 4
-
-
- src/rules/validation/abstract/RuleAddressList
-
-
-
- 97.8 %
- 44 / 45
- 94.4 %
- 17 / 18
- 100.0 %
- 6 / 6
-
-
- src
-
-
-
- 97.4 %
- 38 / 39
- 88.9 %
- 8 / 9
- 100.0 %
8 / 8
-
-
- src/modules
-
-
-
- 100.0 %
- 81 / 81
100.0 %
- 27 / 27
+ 2 / 2
100.0 %
- 12 / 12
-
-
- src/rules/operation/abstract
-
-
-
- 100.0 %
- 113 / 113
- 100.0 %
- 20 / 20
- 100.0 %
- 31 / 31
+ 3 / 3
- src/rules/validation
+ validation/abstract
-
+
- 97.3 %
- 72 / 74
+ 93.5 %
+ 29 / 31
90.9 %
- 20 / 22
- 100.0 %
- 32 / 32
-
-
- src/rules/operation
-
-
-
- 99.1 %
- 105 / 106
- 94.4 %
- 17 / 18
+ 10 / 11
100.0 %
- 33 / 33
+ 10 / 10
diff --git a/doc/coverage/coverage/index-sort-f.html b/doc/coverage/coverage/index-sort-f.html
index 4c104bd..ddafc17 100644
--- a/doc/coverage/coverage/index-sort-f.html
+++ b/doc/coverage/coverage/index-sort-f.html
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,124 +82,52 @@
Branches
- script
+ validation
-
+
- 0.0 %
- 0 / 26
- 0.0 %
- 0 / 2
- 0.0 %
- 0 / 2
+ 89.9 %
+ 151 / 168
+ 84.8 %
+ 39 / 46
+ 94.3 %
+ 50 / 53
- test/utils
+ validation/abstract/RuleAddressSet
-
+
- 85.7 %
- 6 / 7
- 80.0 %
- 4 / 5
- -
- 0 / 0
-
-
- src
-
-
-
- 97.4 %
- 38 / 39
- 88.9 %
- 8 / 9
+ 91.3 %
+ 42 / 46
+ 88.2 %
+ 15 / 17
100.0 %
- 8 / 8
+ 2 / 2
- src/rules/validation
+ validation/abstract
-
+
- 97.3 %
- 72 / 74
+ 93.5 %
+ 29 / 31
90.9 %
- 20 / 22
- 100.0 %
- 32 / 32
-
-
- src/rules/validation/abstract/RuleAddressList
-
-
-
- 97.8 %
- 44 / 45
- 94.4 %
- 17 / 18
- 100.0 %
- 6 / 6
-
-
- src/rules/operation
-
-
-
- 99.1 %
- 105 / 106
- 94.4 %
- 17 / 18
- 100.0 %
- 33 / 33
-
-
- test/RuleConditionalTransfer/utils
-
-
-
+ 10 / 11
100.0 %
10 / 10
- 100.0 %
- 1 / 1
- -
- 0 / 0
-
-
- src/rules/validation/abstract
-
-
-
- 100.0 %
- 10 / 10
- 100.0 %
- 3 / 3
- 100.0 %
- 4 / 4
- src/rules/operation/abstract
+ /home/ryan/Pictures/dev/Rules/src/modules
100.0 %
- 113 / 113
- 100.0 %
- 20 / 20
- 100.0 %
- 31 / 31
-
-
- src/modules
-
-
-
- 100.0 %
- 81 / 81
+ 8 / 8
100.0 %
- 27 / 27
+ 2 / 2
100.0 %
- 12 / 12
+ 3 / 3
diff --git a/doc/coverage/coverage/index-sort-l.html b/doc/coverage/coverage/index-sort-l.html
index f352c82..53eb3c2 100644
--- a/doc/coverage/coverage/index-sort-l.html
+++ b/doc/coverage/coverage/index-sort-l.html
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,124 +82,52 @@
Branches
- script
+ validation
-
+
- 0.0 %
- 0 / 26
- 0.0 %
- 0 / 2
- 0.0 %
- 0 / 2
+ 89.9 %
+ 151 / 168
+ 84.8 %
+ 39 / 46
+ 94.3 %
+ 50 / 53
- test/utils
+ validation/abstract/RuleAddressSet
-
-
- 85.7 %
- 6 / 7
- 80.0 %
- 4 / 5
- -
- 0 / 0
-
-
- src/rules/validation
-
-
-
- 97.3 %
- 72 / 74
- 90.9 %
- 20 / 22
- 100.0 %
- 32 / 32
-
-
- src
-
-
-
- 97.4 %
- 38 / 39
- 88.9 %
- 8 / 9
- 100.0 %
- 8 / 8
-
-
- src/rules/validation/abstract/RuleAddressList
-
-
-
- 97.8 %
- 44 / 45
- 94.4 %
- 17 / 18
- 100.0 %
- 6 / 6
-
-
- src/rules/operation
-
-
-
- 99.1 %
- 105 / 106
- 94.4 %
- 17 / 18
- 100.0 %
- 33 / 33
-
-
- src/rules/validation/abstract
-
-
+
+ 91.3 %
+ 42 / 46
+ 88.2 %
+ 15 / 17
100.0 %
- 10 / 10
- 100.0 %
- 3 / 3
- 100.0 %
- 4 / 4
+ 2 / 2
- test/RuleConditionalTransfer/utils
+ validation/abstract
-
+
+ 93.5 %
+ 29 / 31
+ 90.9 %
+ 10 / 11
100.0 %
10 / 10
- 100.0 %
- 1 / 1
- -
- 0 / 0
- src/modules
+ /home/ryan/Pictures/dev/Rules/src/modules
100.0 %
- 81 / 81
- 100.0 %
- 27 / 27
- 100.0 %
- 12 / 12
-
-
- src/rules/operation/abstract
-
-
-
- 100.0 %
- 113 / 113
+ 8 / 8
100.0 %
- 20 / 20
+ 2 / 2
100.0 %
- 31 / 31
+ 3 / 3
diff --git a/doc/coverage/coverage/index.html b/doc/coverage/coverage/index.html
index 92f429f..d70aabb 100644
--- a/doc/coverage/coverage/index.html
+++ b/doc/coverage/coverage/index.html
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,124 +82,52 @@
Branches
- script
-
-
-
- 0.0 %
- 0 / 26
- 0.0 %
- 0 / 2
- 0.0 %
- 0 / 2
-
-
- src
-
-
-
- 97.4 %
- 38 / 39
- 88.9 %
- 8 / 9
- 100.0 %
- 8 / 8
-
-
- src/modules
+ /home/ryan/Pictures/dev/Rules/src/modules
100.0 %
- 81 / 81
- 100.0 %
- 27 / 27
+ 8 / 8
100.0 %
- 12 / 12
-
-
- src/rules/operation
-
-
-
- 99.1 %
- 105 / 106
- 94.4 %
- 17 / 18
+ 2 / 2
100.0 %
- 33 / 33
+ 3 / 3
- src/rules/operation/abstract
+ validation
-
+
- 100.0 %
- 113 / 113
- 100.0 %
- 20 / 20
- 100.0 %
- 31 / 31
+ 89.9 %
+ 151 / 168
+ 84.8 %
+ 39 / 46
+ 94.3 %
+ 50 / 53
- src/rules/validation
+ validation/abstract
-
+
- 97.3 %
- 72 / 74
+ 93.5 %
+ 29 / 31
90.9 %
- 20 / 22
- 100.0 %
- 32 / 32
-
-
- src/rules/validation/abstract
-
-
-
+ 10 / 11
100.0 %
10 / 10
- 100.0 %
- 3 / 3
- 100.0 %
- 4 / 4
- src/rules/validation/abstract/RuleAddressList
+ validation/abstract/RuleAddressSet
-
+
- 97.8 %
- 44 / 45
- 94.4 %
- 17 / 18
+ 91.3 %
+ 42 / 46
+ 88.2 %
+ 15 / 17
100.0 %
- 6 / 6
-
-
- test/RuleConditionalTransfer/utils
-
-
-
- 100.0 %
- 10 / 10
- 100.0 %
- 1 / 1
- -
- 0 / 0
-
-
- test/utils
-
-
-
- 85.7 %
- 6 / 7
- 80.0 %
- 4 / 5
- -
- 0 / 0
+ 2 / 2
diff --git a/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html b/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html
deleted file mode 100644
index 9ab57f2..0000000
--- a/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - script/CMTATWithRuleEngineScript.s.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html b/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html
deleted file mode 100644
index 6dcfe5d..0000000
--- a/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - script/CMTATWithRuleEngineScript.s.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html b/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html
deleted file mode 100644
index 0600472..0000000
--- a/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html
+++ /dev/null
@@ -1,128 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - script/CMTATWithRuleEngineScript.s.sol
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/script/RuleEngineScript.s.sol.func-sort-c.html b/doc/coverage/coverage/script/RuleEngineScript.s.sol.func-sort-c.html
deleted file mode 100644
index 347d446..0000000
--- a/doc/coverage/coverage/script/RuleEngineScript.s.sol.func-sort-c.html
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - script/RuleEngineScript.s.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/script/RuleEngineScript.s.sol.func.html b/doc/coverage/coverage/script/RuleEngineScript.s.sol.func.html
deleted file mode 100644
index 29ef250..0000000
--- a/doc/coverage/coverage/script/RuleEngineScript.s.sol.func.html
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - script/RuleEngineScript.s.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/script/RuleEngineScript.s.sol.gcov.html b/doc/coverage/coverage/script/RuleEngineScript.s.sol.gcov.html
deleted file mode 100644
index 3b01d2b..0000000
--- a/doc/coverage/coverage/script/RuleEngineScript.s.sol.gcov.html
+++ /dev/null
@@ -1,121 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - script/RuleEngineScript.s.sol
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/script/index-sort-b.html b/doc/coverage/coverage/script/index-sort-b.html
deleted file mode 100644
index 9a13b3e..0000000
--- a/doc/coverage/coverage/script/index-sort-b.html
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - script
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/script/index-sort-f.html b/doc/coverage/coverage/script/index-sort-f.html
deleted file mode 100644
index 89cfad4..0000000
--- a/doc/coverage/coverage/script/index-sort-f.html
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - script
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/script/index-sort-l.html b/doc/coverage/coverage/script/index-sort-l.html
deleted file mode 100644
index 0303269..0000000
--- a/doc/coverage/coverage/script/index-sort-l.html
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - script
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/script/index.html b/doc/coverage/coverage/script/index.html
deleted file mode 100644
index 11ddb92..0000000
--- a/doc/coverage/coverage/script/index.html
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - script
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html b/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html
deleted file mode 100644
index 260f236..0000000
--- a/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html
+++ /dev/null
@@ -1,125 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/modules/RuleEngineOperation.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func.html b/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func.html
deleted file mode 100644
index 323d585..0000000
--- a/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func.html
+++ /dev/null
@@ -1,125 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/modules/RuleEngineOperation.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.gcov.html b/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.gcov.html
deleted file mode 100644
index 75768bd..0000000
--- a/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.gcov.html
+++ /dev/null
@@ -1,255 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/modules/RuleEngineOperation.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 : : import "./RuleInternal.sol";
- 6 : : import "../interfaces/IRuleEngineOperation.sol";
- 7 : : import "../interfaces/IRuleOperation.sol";
- 8 : : import "OZ/access/AccessControl.sol";
- 9 : :
- 10 : : /**
- 11 : : * @title Implementation of a ruleEngine defined by the CMTAT
- 12 : : */
- 13 : : abstract contract RuleEngineOperation is
- 14 : : AccessControl,
- 15 : : RuleInternal,
- 16 : : IRuleEngineOperation
- 17 : : {
- 18 : : /// @dev Array of rules
- 19 : : address[] internal _rulesOperation;
- 20 : :
- 21 : : /**
- 22 : : * @notice Set all the rules, will overwrite all the previous rules. \n
- 23 : : * Revert if one rule is a zero address or if the rule is already present
- 24 : : *
- 25 : : */
- 26 : : function setRulesOperation(
- 27 : : address[] calldata rules_
- 28 : : ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
- 29 [ + ]: 11 : if (_rulesOperation.length > 0) {
- 30 : 10 : _clearRulesOperation();
- 31 : : }
- 32 : 11 : _setRules(rules_);
- 33 : 8 : _rulesOperation = rules_;
- 34 : : }
- 35 : :
- 36 : : /**
- 37 : : * @notice Clear all the rules of the array of rules
- 38 : : *
- 39 : : */
- 40 : : function clearRulesOperation() public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
- 41 : 4 : _clearRulesOperation();
- 42 : : }
- 43 : :
- 44 : : /**
- 45 : : * @notice Clear all the rules of the array of rules
- 46 : : *
- 47 : : */
- 48 : : function _clearRulesOperation() internal {
- 49 : 14 : uint256 index;
- 50 : : // we remove the last element first since it is more optimized.
- 51 : 14 : for (uint256 i = _rulesOperation.length; i > 0; --i) {
- 52 : : unchecked {
- 53 : : // don't underflow since i > 0
- 54 : 17 : index = i - 1;
- 55 : : }
- 56 : 17 : _removeRuleOperation(_rulesOperation[index], index);
- 57 : : }
- 58 : 14 : emit ClearRules(_rulesOperation);
- 59 : : }
- 60 : :
- 61 : : /**
- 62 : : * @notice Add a rule to the array of rules
- 63 : : * Revert if one rule is a zero address or if the rule is already present
- 64 : : *
- 65 : : */
- 66 : : function addRuleOperation(
- 67 : : IRuleOperation rule_
- 68 : : ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
- 69 : 85 : RuleInternal._addRule(_rulesOperation, address(rule_));
- 70 : 83 : emit AddRule(address(rule_));
- 71 : : }
- 72 : :
- 73 : : /**
- 74 : : * @notice Remove a rule from the array of rules
- 75 : : * Revert if the rule found at the specified index does not match the rule in argument
- 76 : : * @param rule_ address of the target rule
- 77 : : * @param index the position inside the array of rule
- 78 : : * @dev To reduce the array size, the last rule is moved to the location occupied
- 79 : : * by the rule to remove
- 80 : : *
- 81 : : *
- 82 : : */
- 83 : : function removeRuleOperation(
- 84 : : IRuleOperation rule_,
- 85 : : uint256 index
- 86 : : ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
- 87 : 5 : _removeRuleOperation(address(rule_), index);
- 88 : : }
- 89 : :
- 90 : : /**
- 91 : : * @notice Remove a rule from the array of rules
- 92 : : * Revert if the rule found at the specified index does not match the rule in argument
- 93 : : * @param rule_ address of the target rule
- 94 : : * @param index the position inside the array of rule
- 95 : : * @dev To reduce the array size, the last rule is moved to the location occupied
- 96 : : * by the rule to remove
- 97 : : *
- 98 : : *
- 99 : : */
- 100 : : function _removeRuleOperation(address rule_, uint256 index) internal {
- 101 : 22 : RuleInternal._removeRule(_rulesOperation, rule_, index);
- 102 : 21 : emit RemoveRule(address(rule_));
- 103 : : }
- 104 : :
- 105 : : /**
- 106 : : * @return The number of rules inside the array
- 107 : : */
- 108 : : function rulesCountOperation() external view override returns (uint256) {
- 109 : 41 : return _rulesOperation.length;
- 110 : : }
- 111 : :
- 112 : : /**
- 113 : : * @notice Get the index of a rule inside the list
- 114 : : * @return index if the rule is found, _rulesOperation.length otherwise
- 115 : : */
- 116 : : function getRuleIndexOperation(
- 117 : : IRuleOperation rule_
- 118 : : ) external view returns (uint256 index) {
- 119 : 3 : return RuleInternal._getRuleIndex(_rulesOperation, address(rule_));
- 120 : : }
- 121 : :
- 122 : : /**
- 123 : : * @notice Get the rule at the position specified by ruleId
- 124 : : * @param ruleId index of the rule
- 125 : : * @return a rule address
- 126 : : */
- 127 : : function ruleOperation(
- 128 : : uint256 ruleId
- 129 : : ) external view override returns (address) {
- 130 : 1 : return _rulesOperation[ruleId];
- 131 : : }
- 132 : :
- 133 : : /**
- 134 : : * @notice Get all the rules
- 135 : : * @return An array of rules
- 136 : : */
- 137 : : function rulesOperation()
- 138 : : external
- 139 : : view
- 140 : : override
- 141 : : returns (address[] memory)
- 142 : : {
- 143 : 5 : return _rulesOperation;
- 144 : : }
- 145 : :
- 146 : : /**
- 147 : : * @notice Go through all the rule to know if a restriction exists on the transfer
- 148 : : * @param _from the origin address
- 149 : : * @param _to the destination address
- 150 : : * @param _amount to transfer
- 151 : : **/
- 152 : : function _operateOnTransfer(
- 153 : : address _from,
- 154 : : address _to,
- 155 : : uint256 _amount
- 156 : : ) internal returns (bool isValid) {
- 157 : 58 : uint256 rulesLength = _rulesOperation.length;
- 158 : 58 : for (uint256 i = 0; i < rulesLength; ++i) {
- 159 : 50 : bool result = IRuleOperation(_rulesOperation[i]).operateOnTransfer(
- 160 : : _from,
- 161 : : _to,
- 162 : : _amount
- 163 : : );
- 164 [ + ]: 50 : if (!result) {
- 165 : 24 : return false;
- 166 : : }
- 167 : : }
- 168 : 34 : return true;
- 169 : : }
- 170 : : }
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/modules/RuleEngineValidation.sol.func-sort-c.html b/doc/coverage/coverage/src/modules/RuleEngineValidation.sol.func-sort-c.html
deleted file mode 100644
index 3f2eb78..0000000
--- a/doc/coverage/coverage/src/modules/RuleEngineValidation.sol.func-sort-c.html
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/modules/RuleEngineValidation.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/modules/RuleEngineValidation.sol.func.html b/doc/coverage/coverage/src/modules/RuleEngineValidation.sol.func.html
deleted file mode 100644
index 8e114c8..0000000
--- a/doc/coverage/coverage/src/modules/RuleEngineValidation.sol.func.html
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/modules/RuleEngineValidation.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/modules/RuleEngineValidation.sol.gcov.html b/doc/coverage/coverage/src/modules/RuleEngineValidation.sol.gcov.html
deleted file mode 100644
index 92443af..0000000
--- a/doc/coverage/coverage/src/modules/RuleEngineValidation.sol.gcov.html
+++ /dev/null
@@ -1,147 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/modules/RuleEngineValidation.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 : : import "OZ/access/AccessControl.sol";
- 6 : : import "./RuleInternal.sol";
- 7 : : import "./RuleEngineValidationCommon.sol";
- 8 : : import "../interfaces/IRuleEngineValidation.sol";
- 9 : : import "../interfaces/IRuleValidation.sol";
- 10 : : import "CMTAT/interfaces/draft-IERC1404/draft-IERC1404EnumCode.sol";
- 11 : :
- 12 : : /**
- 13 : : * @title Implementation of a ruleEngine defined by the CMTAT
- 14 : : */
- 15 : : abstract contract RuleEngineValidation is
- 16 : : AccessControl,
- 17 : : RuleInternal,
- 18 : : RuleEngineValidationCommon,
- 19 : : IRuleEngineValidation,
- 20 : : IERC1404EnumCode
- 21 : : {
- 22 : : /**
- 23 : : * @notice Go through all the rule to know if a restriction exists on the transfer
- 24 : : * @param _from the origin address
- 25 : : * @param _to the destination address
- 26 : : * @param _amount to transfer
- 27 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
- 28 : : **/
- 29 : : function detectTransferRestrictionValidation(
- 30 : : address _from,
- 31 : : address _to,
- 32 : : uint256 _amount
- 33 : : ) public view override returns (uint8) {
- 34 : 105 : uint256 rulesLength = _rulesValidation.length;
- 35 : 105 : for (uint256 i = 0; i < rulesLength; ++i) {
- 36 : 43 : uint8 restriction = IRuleValidation(_rulesValidation[i])
- 37 : : .detectTransferRestriction(_from, _to, _amount);
- 38 [ + ]: 43 : if (restriction > 0) {
- 39 : 28 : return restriction;
- 40 : : }
- 41 : : }
- 42 : :
- 43 : 77 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- 44 : : }
- 45 : :
- 46 : : /**
- 47 : : * @notice Validate a transfer
- 48 : : * @param _from the origin address
- 49 : : * @param _to the destination address
- 50 : : * @param _amount to transfer
- 51 : : * @return True if the transfer is valid, false otherwise
- 52 : : **/
- 53 : : function validateTransferValidation(
- 54 : : address _from,
- 55 : : address _to,
- 56 : : uint256 _amount
- 57 : : ) public view override returns (bool) {
- 58 : 70 : return
- 59 : 70 : detectTransferRestrictionValidation(_from, _to, _amount) ==
- 60 : : uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- 61 : : }
- 62 : : }
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.func-sort-c.html b/doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.func-sort-c.html
deleted file mode 100644
index 31de5ea..0000000
--- a/doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.func-sort-c.html
+++ /dev/null
@@ -1,121 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/modules/RuleEngineValidationCommon.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.func.html b/doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.func.html
deleted file mode 100644
index d05c663..0000000
--- a/doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.func.html
+++ /dev/null
@@ -1,121 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/modules/RuleEngineValidationCommon.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/modules/index-sort-b.html b/doc/coverage/coverage/src/modules/index-sort-b.html
deleted file mode 100644
index 1356192..0000000
--- a/doc/coverage/coverage/src/modules/index-sort-b.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/modules
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/modules/index-sort-f.html b/doc/coverage/coverage/src/modules/index-sort-f.html
deleted file mode 100644
index f0cc112..0000000
--- a/doc/coverage/coverage/src/modules/index-sort-f.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/modules
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/modules/index-sort-l.html b/doc/coverage/coverage/src/modules/index-sort-l.html
deleted file mode 100644
index 7d113ca..0000000
--- a/doc/coverage/coverage/src/modules/index-sort-l.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/modules
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/modules/index.html b/doc/coverage/coverage/src/modules/index.html
deleted file mode 100644
index 60ae93b..0000000
--- a/doc/coverage/coverage/src/modules/index.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/modules
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.func-sort-c.html
deleted file mode 100644
index 7f4ab01..0000000
--- a/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.func-sort-c.html
+++ /dev/null
@@ -1,153 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/operation/RuleConditionalTransfer.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.func.html b/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.func.html
deleted file mode 100644
index fba2e82..0000000
--- a/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.func.html
+++ /dev/null
@@ -1,153 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/operation/RuleConditionalTransfer.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.gcov.html b/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.gcov.html
deleted file mode 100644
index 476c0ca..0000000
--- a/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.gcov.html
+++ /dev/null
@@ -1,486 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/operation/RuleConditionalTransfer.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 : : import "OZ/access/AccessControl.sol";
- 6 : : import "../../interfaces/IRuleOperation.sol";
- 7 : : import "./../../modules/MetaTxModuleStandalone.sol";
- 8 : : import "./abstract/RuleConditionalTransferInvariantStorage.sol";
- 9 : : import "./abstract/RuleConditionalTransferOperator.sol";
- 10 : : import "../validation/abstract/RuleValidateTransfer.sol";
- 11 : : import "CMTAT/interfaces/engine/IRuleEngine.sol";
- 12 : :
- 13 : : /**
- 14 : : * @title RuleConditionalTransfer
- 15 : : */
- 16 : :
- 17 : : contract RuleConditionalTransfer is
- 18 : : RuleValidateTransfer,
- 19 : : IRuleOperation,
- 20 : : RuleConditionalTransferOperator,
- 21 : : MetaTxModuleStandalone
- 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(
- 28 : : address admin,
- 29 : : address forwarderIrrevocable,
- 30 : : IRuleEngine ruleEngineContract,
- 31 : : OPTION memory options_
- 32 : : ) MetaTxModuleStandalone(forwarderIrrevocable) {
- 33 [ + ]: 158 : if (admin == address(0)) {
- 34 : 1 : revert RuleConditionalTransfer_AdminWithAddressZeroNotAllowed();
- 35 : : }
- 36 : 157 : _grantRole(DEFAULT_ADMIN_ROLE, admin);
- 37 [ + ]: 157 : if (address(ruleEngineContract) != address(0x0)) {
- 38 : 153 : _grantRole(RULE_ENGINE_CONTRACT_ROLE, address(ruleEngineContract));
- 39 : : }
- 40 : 157 : options = options_;
- 41 : : }
- 42 : :
- 43 : : /*//////////////////////////////////////////////////////////////
- 44 : : PUBLIC/EXTERNAL FUNCTIONS
- 45 : : //////////////////////////////////////////////////////////////*/
- 46 : : /**
- 47 : : * @notice function called by the RuleEngine
- 48 : : * @dev Returns true if the transfer is valid, and false otherwise.
- 49 : : * Add access control with the RuleEngine
- 50 : : */
- 51 : : function operateOnTransfer(
- 52 : : address _from,
- 53 : : address _to,
- 54 : : uint256 _amount
- 55 : : )
- 56 : : public
- 57 : : override
- 58 : : onlyRole(RULE_ENGINE_CONTRACT_ROLE)
- 59 : : returns (bool isValid)
- 60 : : {
- 61 [ + + ]: 50 : if (_validateTransfer(_from, _to)) {
- 62 : 8 : return true;
- 63 : : } else {
- 64 : 42 : bytes32 key = keccak256(abi.encode(_from, _to, _amount));
- 65 [ + + ]: 42 : if (_validateApproval(key)) {
- 66 : 18 : _updateProcessedTransfer(key);
- 67 : 18 : return true;
- 68 : : } else {
- 69 : 24 : return false;
- 70 : : }
- 71 : : }
- 72 : : }
- 73 : :
- 74 : : /**
- 75 : : * @notice Create a request of transfer for yourselves
- 76 : : * @param to recipient of tokens
- 77 : : * @param value amount of tokens to transfer
- 78 : : */
- 79 : : function createTransferRequest(address to, uint256 value) public {
- 80 : : // WAIT => Will set a new delay to approve
- 81 : : // APPROVED => will overwrite previous status
- 82 : : // DENIED => reject
- 83 : 117 : address from = _msgSender();
- 84 : 117 : bytes32 key = keccak256(abi.encode(from, to, value));
- 85 [ + ]: 117 : if (transferRequests[key].status == STATUS.DENIED) {
- 86 : 1 : revert RuleConditionalTransfer_TransferDenied();
- 87 : : }
- 88 [ + + ]: 116 : if (_checkRequestStatus(key)) {
- 89 : 113 : uint256 requestIdLocal = requestId;
- 90 : 113 : TransferRequest memory newTransferApproval = TransferRequest({
- 91 : : key: key,
- 92 : : id: requestIdLocal,
- 93 : : keyElement: TransferRequestKeyElement({
- 94 : : from: from,
- 95 : : to: to,
- 96 : : value: value
- 97 : : }),
- 98 : : askTime: block.timestamp,
- 99 : : maxTime: 0,
- 100 : : status: STATUS.WAIT
- 101 : : });
- 102 : 113 : transferRequests[key] = newTransferApproval;
- 103 : 113 : IdToKey[requestIdLocal] = key;
- 104 : 113 : emit transferWaiting(key, from, to, value, requestId);
- 105 : 113 : ++requestId;
- 106 : : } else {
- 107 : : // Overwrite previous approval
- 108 : 3 : transferRequests[key].askTime = block.timestamp;
- 109 : 3 : transferRequests[key].status = STATUS.WAIT;
- 110 : 3 : emit transferWaiting(
- 111 : : key,
- 112 : : from,
- 113 : : to,
- 114 : : value,
- 115 : : transferRequests[key].id
- 116 : : );
- 117 : : }
- 118 : : }
- 119 : :
- 120 : : /**
- 121 : : * @notice Batch version of {createTransferRequest}
- 122 : : */
- 123 : : function createTransferRequestBatch(
- 124 : : address[] memory tos,
- 125 : : uint256[] memory values
- 126 : : ) public {
- 127 [ + ]: 3 : if (tos.length == 0) {
- 128 : 1 : revert RuleConditionalTransfer_EmptyArray();
- 129 : : }
- 130 [ + ]: 2 : if (tos.length != values.length) {
- 131 : 1 : revert RuleConditionalTransfer_InvalidLengthArray();
- 132 : : }
- 133 : 1 : for (uint256 i = 0; i < tos.length; ++i) {
- 134 : 3 : createTransferRequest(tos[i], values[i]);
- 135 : : }
- 136 : : }
- 137 : :
- 138 : : /**
- 139 : : * @notice allow a token holder to cancel/reset his own request
- 140 : : */
- 141 : : function cancelTransferRequest(uint256 requestId_) public {
- 142 : 6 : _cancelTransferRequest(requestId_);
- 143 : : }
- 144 : :
- 145 : : /**
- 146 : : * @notice allow a token holder to cancel/reset his own request
- 147 : : */
- 148 : : function cancelTransferRequestBatch(uint256[] memory requestIds) public {
- 149 [ + ]: 3 : if (requestIds.length == 0) {
- 150 : 1 : revert RuleConditionalTransfer_EmptyArray();
- 151 : : }
- 152 : : // Check id validity before performing actions
- 153 : 2 : for (uint256 i = 0; i < requestIds.length; ++i) {
- 154 [ + ]: 5 : if (requestIds[i] + 1 > requestId) {
- 155 : 1 : revert RuleConditionalTransfer_InvalidId();
- 156 : : }
- 157 : : }
- 158 : 1 : for (uint256 i = 0; i < requestIds.length; ++i) {
- 159 : 3 : _cancelTransferRequest(requestIds[i]);
- 160 : : }
- 161 : : }
- 162 : :
- 163 : : function getRequestTrade(
- 164 : : address from,
- 165 : : address to,
- 166 : : uint256 value
- 167 : : ) public view returns (TransferRequest memory) {
- 168 : 57 : bytes32 key = keccak256(abi.encode(from, to, value));
- 169 : 57 : return transferRequests[key];
- 170 : : }
- 171 : :
- 172 : : /**
- 173 : : * @notice get Trade by status
- 174 : : * @param _targetStatus The status of the transactions you want to retrieve
- 175 : : * @return array with corresponding transactions
- 176 : : */
- 177 : : function getRequestByStatus(
- 178 : : STATUS _targetStatus
- 179 : : ) public view returns (TransferRequest[] memory) {
- 180 : 35 : uint totalRequestCount = requestId;
- 181 : 35 : uint requestCount = 0;
- 182 : 35 : uint currentIndex = 0;
- 183 : :
- 184 : : // We count the number of requests matching the criteria
- 185 : 35 : for (uint i = 0; i < totalRequestCount; ++i) {
- 186 [ + ]: 38 : if (transferRequests[IdToKey[i]].status == _targetStatus) {
- 187 : 36 : requestCount += 1;
- 188 : : }
- 189 : : }
- 190 : :
- 191 : : // We reserve the memory to store the trade
- 192 : 35 : TransferRequest[] memory requests = new TransferRequest[](requestCount);
- 193 : :
- 194 : : // We create an array with the list of trade
- 195 : 35 : for (uint i = 0; i < totalRequestCount; ++i) {
- 196 [ + ]: 38 : if (transferRequests[IdToKey[i]].status == _targetStatus) {
- 197 : : //uint currentId = i + 1;
- 198 : 36 : TransferRequest memory currentRequest = transferRequests[
- 199 : : IdToKey[i]
- 200 : : ];
- 201 : 36 : requests[currentIndex] = currentRequest;
- 202 : 36 : currentIndex += 1;
- 203 : : }
- 204 : : }
- 205 : 35 : return requests;
- 206 : : }
- 207 : :
- 208 : : /**
- 209 : : * @notice Check if the transfer is valid
- 210 : : * @param _from the origin address
- 211 : : * @param _to the destination address
- 212 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
- 213 : : **/
- 214 : : function detectTransferRestriction(
- 215 : : address _from,
- 216 : : address _to,
- 217 : : uint256 _amount
- 218 : : ) public view override returns (uint8) {
- 219 : : // No need of approval if from and to are in the whitelist
- 220 [ + ]: 56 : if (_validateTransfer(_from, _to)) {
- 221 : 1 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- 222 : : }
- 223 : 55 : bytes32 key = keccak256(abi.encode(_from, _to, _amount));
- 224 [ + + ]: 55 : if (_validateApproval(key)) {
- 225 : 8 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- 226 : : } else {
- 227 : 47 : return CODE_TRANSFER_REQUEST_NOT_APPROVED;
- 228 : : }
- 229 : : }
- 230 : :
- 231 : : /**
- 232 : : * @notice To know if the restriction code is valid for this rule or not.
- 233 : : * @param _restrictionCode The target restriction code
- 234 : : * @return true if the restriction code is known, false otherwise
- 235 : : **/
- 236 : : function canReturnTransferRestrictionCode(
- 237 : : uint8 _restrictionCode
- 238 : : ) external pure override returns (bool) {
- 239 : 2 : return _restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED;
- 240 : : }
- 241 : :
- 242 : : /**
- 243 : : * @notice Return the corresponding message
- 244 : : * @param _restrictionCode The target restriction code
- 245 : : * @return true if the transfer is valid, false otherwise
- 246 : : **/
- 247 : : function messageForTransferRestriction(
- 248 : : uint8 _restrictionCode
- 249 : : ) external pure override returns (string memory) {
- 250 [ + + ]: 3 : if (_restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED) {
- 251 : 2 : return TEXT_TRANSFER_REQUEST_NOT_APPROVED;
- 252 : : } else {
- 253 : 1 : return TEXT_CODE_NOT_FOUND;
- 254 : : }
- 255 : : }
- 256 : :
- 257 : : /*//////////////////////////////////////////////////////////////
- 258 : : INTERNAL FUNCTIONS
- 259 : : //////////////////////////////////////////////////////////////*/
- 260 : : function _validateTransfer(
- 261 : : address _from,
- 262 : : address _to
- 263 : : ) internal view returns (bool) {
- 264 : : // No need of approval if from and to are in the whitelist
- 265 [ + ]: 106 : if (address(whitelistConditionalTransfer) != address(0)) {
- 266 : : if (
- 267 : 36 : whitelistConditionalTransfer.addressIsListed(_from) &&
- 268 : 5 : whitelistConditionalTransfer.addressIsListed(_to)
- 269 [ + ]: 3 : ) {
- 270 : 3 : return true;
- 271 : : }
- 272 : : }
- 273 : :
- 274 : : // Mint & Burn
- 275 [ + ]: 103 : if (_validateBurnMint(_from, _to)) {
- 276 : 6 : return true;
- 277 : : }
- 278 : 97 : return false;
- 279 : : }
- 280 : :
- 281 : : function _cancelTransferRequest(uint256 requestId_) internal {
- 282 [ + ]: 9 : if (requestId_ + 1 > requestId) {
- 283 : 1 : revert RuleConditionalTransfer_InvalidId();
- 284 : : }
- 285 : 8 : bytes32 key = IdToKey[requestId_];
- 286 : : // Check Sender
- 287 [ + ]: 8 : if (transferRequests[key].keyElement.from != _msgSender()) {
- 288 : 1 : revert RuleConditionalTransfer_InvalidSender();
- 289 : : }
- 290 : : // Check status
- 291 : : if (
- 292 : 7 : transferRequests[key].status != STATUS.WAIT &&
- 293 : 2 : transferRequests[key].status != STATUS.APPROVED
- 294 [ + ]: 1 : ) {
- 295 : 1 : revert RuleConditionalTransfer_Wrong_Status();
- 296 : : }
- 297 : 6 : _resetRequestStatus(key);
- 298 : : }
- 299 : :
- 300 : : /**
- 301 : : *
- 302 : : * @dev
- 303 : : * Test burn and mint condition
- 304 : : * Returns true if the transfer is valid, and false otherwise.
- 305 : : *
- 306 : : */
- 307 : : function _validateBurnMint(
- 308 : : address _from,
- 309 : : address _to
- 310 : : ) internal view returns (bool isValid) {
- 311 : : // Mint & Burn
- 312 : : if (
- 313 : 103 : (_from == address(0) &&
- 314 : : options.issuance.authorizedMintWithoutApproval) ||
- 315 : : (_to == address(0) &&
- 316 : : options.issuance.authorizedBurnWithoutApproval)
- 317 [ + ]: 6 : ) {
- 318 : 6 : return true;
- 319 : : }
- 320 : 97 : return false;
- 321 : : }
- 322 : :
- 323 : : /**
- 324 : : *
- 325 : : * @dev
- 326 : : * Test transfer approval condition
- 327 : : * Returns true if the transfer is valid, and false otherwise.
- 328 : : */
- 329 : : function _validateApproval(
- 330 : : bytes32 key
- 331 : : ) internal view returns (bool isValid) {
- 332 : : // If automatic approval is activate and time to approve the request has passed
- 333 : 97 : if(transferRequests[key].status == STATUS.NONE
- 334 : : ||
- 335 : 50 : transferRequests[key].status == STATUS.DENIED
- 336 : : ||
- 337 : 47 : transferRequests[key].status == STATUS.EXECUTED)
- 338 [ + ]: 50 : {
- 339 : 50 : return false;
- 340 : : }
- 341 : 47 : bool isTransferApproved;
- 342 : 47 : bool automaticApprovalCondition;
- 343 [ + ]: 47 : if(transferRequests[key].status ==
- 344 [ + ]: 20 : STATUS.APPROVED){
- 345 : 20 : isTransferApproved = (transferRequests[key].maxTime >= block.timestamp);
- 346 : : } else if(options
- 347 : : .automaticApproval
- 348 [ + ]: 27 : .isActivate){
- 349 : : // Warning: overflow possible if timeLimitBeforeAutomaticApproval == max(uint256)
- 350 : 27 : automaticApprovalCondition= block.timestamp >=
- 351 : : (transferRequests[key].askTime +
- 352 : : options.automaticApproval.timeLimitBeforeAutomaticApproval);
- 353 : : }
- 354 : : // If the transfer is approved and delay to perform the transfer is respected
- 355 [ + + ]: 47 : if (automaticApprovalCondition || isTransferApproved) {
- 356 : 26 : return true;
- 357 : : } else {
- 358 : 21 : return false;
- 359 : : }
- 360 : : }
- 361 : :
- 362 : : /*//////////////////////////////////////////////////////////////
- 363 : : ERC-2771
- 364 : : //////////////////////////////////////////////////////////////*/
- 365 : :
- 366 : : /**
- 367 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 368 : : */
- 369 : : function _msgSender()
- 370 : : internal
- 371 : : view
- 372 : : override(ERC2771Context, Context)
- 373 : : returns (address sender)
- 374 : : {
- 375 : 829 : return ERC2771Context._msgSender();
- 376 : : }
- 377 : :
- 378 : : /**
- 379 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 380 : : */
- 381 : : function _msgData()
- 382 : : internal
- 383 : : view
- 384 : : override(ERC2771Context, Context)
- 385 : : returns (bytes calldata)
- 386 : : {
- 387 : 0 : return ERC2771Context._msgData();
- 388 : : }
- 389 : :
- 390 : : /**
- 391 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 392 : : */
- 393 : : function _contextSuffixLength()
- 394 : : internal
- 395 : : view
- 396 : : override(ERC2771Context, Context)
- 397 : : returns (uint256)
- 398 : : {
- 399 : 829 : return ERC2771Context._contextSuffixLength();
- 400 : : }
- 401 : : }
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func-sort-c.html
deleted file mode 100644
index acebdd7..0000000
--- a/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func-sort-c.html
+++ /dev/null
@@ -1,161 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/operation/abstract/RuleConditionalTransferOperator.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func.html b/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func.html
deleted file mode 100644
index bbcca68..0000000
--- a/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func.html
+++ /dev/null
@@ -1,161 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/operation/abstract/RuleConditionalTransferOperator.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.gcov.html b/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.gcov.html
deleted file mode 100644
index 8a6d8ca..0000000
--- a/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.gcov.html
+++ /dev/null
@@ -1,558 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/operation/abstract/RuleConditionalTransferOperator.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 : : import "OZ/access/AccessControl.sol";
- 6 : : import "./RuleConditionalTransferInvariantStorage.sol";
- 7 : : import "OZ/token/ERC20/utils/SafeERC20.sol";
- 8 : :
- 9 : : /**
- 10 : : * @title Restricted functions
- 11 : : */
- 12 : : abstract contract RuleConditionalTransferOperator is
- 13 : : AccessControl,
- 14 : : RuleConditionalTransferInvariantStorage
- 15 : : {
- 16 : : // Security
- 17 : : using SafeERC20 for IERC20;
- 18 : : /* ============ State Variables ============ */
- 19 : : OPTION public options;
- 20 : : uint256 public requestId;
- 21 : : mapping(uint256 => bytes32) public IdToKey;
- 22 : : mapping(bytes32 => TransferRequest) public transferRequests;
- 23 : : RuleWhitelist public whitelistConditionalTransfer;
- 24 : :
- 25 : : /*//////////////////////////////////////////////////////////////
- 26 : : PUBLIC/EXTERNAL FUNCTIONS
- 27 : : //////////////////////////////////////////////////////////////*/
- 28 : :
- 29 : : /**
- 30 : : * @notice set a whitelist. A transfer does not need of an approved request if from and to are in the whitelist
- 31 : : */
- 32 : : function setConditionalWhitelist(
- 33 : : RuleWhitelist newWhitelistConditionalTransfer
- 34 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- 35 : 26 : whitelistConditionalTransfer = newWhitelistConditionalTransfer;
- 36 : 26 : emit WhitelistConditionalTransfer(newWhitelistConditionalTransfer);
- 37 : : }
- 38 : :
- 39 : : /**
- 40 : : * @notice set/unset the issuance options (mint & burn)
- 41 : : */
- 42 : : function setIssuanceOptions(
- 43 : : ISSUANCE calldata issuance_
- 44 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- 45 : : if (
- 46 : 6 : options.issuance.authorizedMintWithoutApproval !=
- 47 : : issuance_.authorizedMintWithoutApproval
- 48 [ + ]: 3 : ) {
- 49 : 3 : options.issuance.authorizedMintWithoutApproval = issuance_
- 50 : : .authorizedMintWithoutApproval;
- 51 : : }
- 52 : : if (
- 53 : 6 : options.issuance.authorizedBurnWithoutApproval !=
- 54 : : issuance_.authorizedBurnWithoutApproval
- 55 [ + ]: 3 : ) {
- 56 : 3 : options.issuance.authorizedBurnWithoutApproval = issuance_
- 57 : : .authorizedBurnWithoutApproval;
- 58 : : }
- 59 : : }
- 60 : :
- 61 : : /**
- 62 : : * @notice set/unset the option to perform the transfer if the request is approved by the rule operator.
- 63 : : * To perform the transfer, the token holder has to approve the rule to spend tokens on his behalf (standard ERC-20 approval).
- 64 : : * If the allowance is not sufficient, the request will be approved, but without performing the transfer.
- 65 : : */
- 66 : : function setAutomaticTransfer(
- 67 : : AUTOMATIC_TRANSFER calldata automaticTransfer_
- 68 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- 69 : : if (
- 70 : 3 : automaticTransfer_.isActivate !=
- 71 : : options.automaticTransfer.isActivate
- 72 [ + ]: 2 : ) {
- 73 : 2 : options.automaticTransfer.isActivate = automaticTransfer_
- 74 : : .isActivate;
- 75 : : }
- 76 : : // No need to put the cmtat to zero to deactivate automaticTransfer
- 77 : : if (
- 78 : 3 : address(automaticTransfer_.cmtat) !=
- 79 : : address(options.automaticTransfer.cmtat)
- 80 [ + ]: 2 : ) {
- 81 : 2 : options.automaticTransfer.cmtat = automaticTransfer_.cmtat;
- 82 : : }
- 83 : : }
- 84 : :
- 85 : : /**
- 86 : : * @notice set time limit for new requests (Approval and transfer)
- 87 : : * timeLimitToApprove: time limit for an operator to approve a request
- 88 : : * timeLimitToTransfer: once a request is approved, time limit for the token holder to perform the transfer
- 89 : : */
- 90 : : function setTimeLimit(
- 91 : : TIME_LIMIT memory timeLimit_
- 92 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- 93 : : if (
- 94 : 4 : options.timeLimit.timeLimitToApprove !=
- 95 : : timeLimit_.timeLimitToApprove
- 96 [ + ]: 4 : ) {
- 97 : 4 : options.timeLimit.timeLimitToApprove = timeLimit_
- 98 : : .timeLimitToApprove;
- 99 : : }
- 100 : : if (
- 101 : 4 : options.timeLimit.timeLimitToTransfer !=
- 102 : : timeLimit_.timeLimitToTransfer
- 103 [ + ]: 4 : ) {
- 104 : 4 : options.timeLimit.timeLimitToTransfer = timeLimit_
- 105 : : .timeLimitToTransfer;
- 106 : : }
- 107 : : }
- 108 : :
- 109 : : /**
- 110 : : * @notice If the transfer is not approved or denied within {timeLimitBeforeAutomaticApproval},
- 111 : : * the request is considered as approved during a transfer.
- 112 : : *
- 113 : : */
- 114 : : function setAutomaticApproval(
- 115 : : AUTOMATIC_APPROVAL memory automaticApproval_
- 116 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- 117 : : if (
- 118 : 9 : options.automaticApproval.isActivate !=
- 119 : : automaticApproval_.isActivate
- 120 [ + ]: 6 : ) {
- 121 : 6 : options.automaticApproval.isActivate = automaticApproval_
- 122 : : .isActivate;
- 123 : : }
- 124 : : if (
- 125 : 9 : options.automaticApproval.timeLimitBeforeAutomaticApproval !=
- 126 : : automaticApproval_.timeLimitBeforeAutomaticApproval
- 127 [ + ]: 9 : ) {
- 128 : 9 : options
- 129 : : .automaticApproval
- 130 : : .timeLimitBeforeAutomaticApproval = automaticApproval_
- 131 : : .timeLimitBeforeAutomaticApproval;
- 132 : : }
- 133 : : }
- 134 : :
- 135 : : /**
- 136 : : * @notice create a transfer request directly approved
- 137 : : */
- 138 : : function createTransferRequestWithApproval(
- 139 : : TransferRequestKeyElement calldata keyElement
- 140 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- 141 : 5 : _createTransferRequestWithApproval(keyElement);
- 142 : : }
- 143 : :
- 144 : : /**
- 145 : : * @notice approve a transferRequest
- 146 : : * @param keyElement contains from, to, value
- 147 : : * @param partialValue amount approved. Put 0 if all the amount specified by value is approved.
- 148 : : * @param isApproved approved (true) or refused (false). Put true if you use partialApproval
- 149 : : */
- 150 : : function approveTransferRequest(
- 151 : : TransferRequestKeyElement calldata keyElement,
- 152 : : uint256 partialValue,
- 153 : : bool isApproved
- 154 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- 155 : 39 : _approveTransferRequestKeyElement(keyElement, partialValue, isApproved);
- 156 : : }
- 157 : :
- 158 : : /**
- 159 : : * @notice approve a transferRequestby using its id
- 160 : : */
- 161 : : function approveTransferRequestWithId(
- 162 : : uint256 requestId_,
- 163 : : bool isApproved
- 164 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- 165 [ + ]: 4 : if (requestId_ + 1 > requestId) {
- 166 : 2 : revert RuleConditionalTransfer_InvalidId();
- 167 : : }
- 168 : 2 : TransferRequest memory transferRequest = transferRequests[
- 169 : : IdToKey[requestId_]
- 170 : : ];
- 171 : 2 : _approveRequest(transferRequest, isApproved);
- 172 : : }
- 173 : :
- 174 : : /**
- 175 : : * @notice reset to None the status of a request
- 176 : : */
- 177 : : function resetRequestStatus(
- 178 : : uint256 requestId_
- 179 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- 180 [ + ]: 2 : if (requestId_ + 1 > requestId) {
- 181 : 1 : revert RuleConditionalTransfer_InvalidId();
- 182 : : }
- 183 : 1 : bytes32 key = IdToKey[requestId_];
- 184 : 1 : _resetRequestStatus(key);
- 185 : : }
- 186 : :
- 187 : : /* ============ Batch function ============ */
- 188 : : /**
- 189 : : * @notice Batch version of {approveTransferRequestWithId}
- 190 : : */
- 191 : : function approveTransferRequestBatchWithId(
- 192 : : uint256[] calldata requestId_,
- 193 : : bool[] calldata isApproved
- 194 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- 195 [ + ]: 5 : if (requestId_.length == 0) {
- 196 : 1 : revert RuleConditionalTransfer_EmptyArray();
- 197 : : }
- 198 [ + ]: 4 : if (requestId_.length != isApproved.length) {
- 199 : 1 : revert RuleConditionalTransfer_InvalidLengthArray();
- 200 : : }
- 201 : : // Check id validity before performing actions
- 202 : 3 : for (uint256 i = 0; i < requestId_.length; ++i) {
- 203 [ + ]: 11 : if (requestId_[i] + 1 > requestId) {
- 204 : 1 : revert RuleConditionalTransfer_InvalidId();
- 205 : : }
- 206 : : }
- 207 : 2 : for (uint256 i = 0; i < requestId_.length; ++i) {
- 208 : 5 : TransferRequest memory transferRequest = transferRequests[
- 209 : : IdToKey[requestId_[i]]
- 210 : : ];
- 211 : 5 : _approveRequest(transferRequest, isApproved[i]);
- 212 : : }
- 213 : : }
- 214 : :
- 215 : : /**
- 216 : : * @notice Batch version of {approveTransferRequest}
- 217 : : */
- 218 : : function approveTransferRequestBatch(
- 219 : : TransferRequestKeyElement[] calldata keyElements,
- 220 : : uint256[] calldata partialValues,
- 221 : : bool[] calldata isApproved
- 222 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- 223 [ + ]: 6 : if (keyElements.length == 0) {
- 224 : 1 : revert RuleConditionalTransfer_EmptyArray();
- 225 : : }
- 226 : : if (
- 227 : 5 : (keyElements.length != partialValues.length) ||
- 228 : : (partialValues.length != isApproved.length)
- 229 [ + ]: 3 : ) {
- 230 : 3 : revert RuleConditionalTransfer_InvalidLengthArray();
- 231 : : }
- 232 : 2 : for (uint256 i = 0; i < keyElements.length; ++i) {
- 233 : 9 : _approveTransferRequestKeyElement(
- 234 : : keyElements[i],
- 235 : : partialValues[i],
- 236 : : isApproved[i]
- 237 : : );
- 238 : : }
- 239 : : }
- 240 : :
- 241 : : /**
- 242 : : * @notice Batch version of {createTransferRequestWithApproval}
- 243 : : */
- 244 : : function createTransferRequestWithApprovalBatch(
- 245 : : TransferRequestKeyElement[] calldata keyElements
- 246 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- 247 [ + ]: 2 : if (keyElements.length == 0) {
- 248 : 1 : revert RuleConditionalTransfer_EmptyArray();
- 249 : : }
- 250 : 1 : for (uint256 i = 0; i < keyElements.length; ++i) {
- 251 : 4 : _createTransferRequestWithApproval(keyElements[i]);
- 252 : : }
- 253 : : }
- 254 : :
- 255 : : /**
- 256 : : * @notice Batch version of {resetRequestStatus}
- 257 : : */
- 258 : : function resetRequestStatusBatch(
- 259 : : uint256[] memory requestIds
- 260 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- 261 [ + ]: 3 : if (requestIds.length == 0) {
- 262 : 1 : revert RuleConditionalTransfer_EmptyArray();
- 263 : : }
- 264 : : // Check id validity before performing actions
- 265 : 2 : for (uint256 i = 0; i < requestIds.length; ++i) {
- 266 [ + ]: 4 : if (requestIds[i] + 1 > requestId) {
- 267 : 1 : revert RuleConditionalTransfer_InvalidId();
- 268 : : }
- 269 : : }
- 270 : 1 : for (uint256 i = 0; i < requestIds.length; ++i) {
- 271 : 3 : bytes32 key = IdToKey[requestIds[i]];
- 272 : 3 : _resetRequestStatus(key);
- 273 : : }
- 274 : : }
- 275 : :
- 276 : : /* ============ ACCESS CONTROL ============ */
- 277 : : /**
- 278 : : * @dev Returns `true` if `account` has been granted `role`.
- 279 : : */
- 280 : : function hasRole(
- 281 : : bytes32 role,
- 282 : : address account
- 283 : : ) public view virtual override(AccessControl) returns (bool) {
- 284 : : // The Default Admin has all roles
- 285 [ + ]: 704 : if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
- 286 : 137 : return true;
- 287 : : }
- 288 : 567 : return AccessControl.hasRole(role, account);
- 289 : : }
- 290 : :
- 291 : : /*//////////////////////////////////////////////////////////////
- 292 : : INTERNAL FUNCTIONS
- 293 : : //////////////////////////////////////////////////////////////*/
- 294 : : function _approveTransferRequestKeyElement(
- 295 : : TransferRequestKeyElement calldata keyElement,
- 296 : : uint256 partialValue,
- 297 : : bool isApproved
- 298 : : ) internal {
- 299 [ + ]: 48 : if (partialValue > keyElement.value) {
- 300 : 1 : revert RuleConditionalTransfer_InvalidValueApproved();
- 301 : : }
- 302 : 47 : bytes32 key = keccak256(
- 303 : : abi.encode(keyElement.from, keyElement.to, keyElement.value)
- 304 : : );
- 305 : 47 : TransferRequest memory transferRequest = transferRequests[key];
- 306 [ + + ]: 47 : if (partialValue > 0) {
- 307 [ + ]: 9 : if (!isApproved) {
- 308 : 1 : revert RuleConditionalTransfer_CannotDeniedPartially();
- 309 : : }
- 310 : : // Denied the first request
- 311 : 8 : _approveRequest(transferRequest, false);
- 312 : : // Create new request
- 313 : 8 : _createTransferRequestWithApproval(
- 314 : : TransferRequestKeyElement({
- 315 : : from: keyElement.from,
- 316 : : to: keyElement.to,
- 317 : : value: partialValue
- 318 : : })
- 319 : : );
- 320 : : } else {
- 321 : 38 : _approveRequest(transferRequest, isApproved);
- 322 : : }
- 323 : : }
- 324 : :
- 325 : : function _createTransferRequestWithApproval(
- 326 : : TransferRequestKeyElement memory keyElement_
- 327 : : ) internal {
- 328 : : // WAIT => Will overwrite
- 329 : : // APPROVED => will overwrite previous status with a new delay
- 330 : : // DENIED => will overwrite
- 331 : 17 : bytes32 key = keccak256(
- 332 : : abi.encode(keyElement_.from, keyElement_.to, keyElement_.value)
- 333 : : );
- 334 [ + + ]: 17 : if (_checkRequestStatus(key)) {
- 335 : : // Only if it is a new request
- 336 : 16 : TransferRequest memory newTransferApproval = TransferRequest({
- 337 : : key: key,
- 338 : : id: requestId,
- 339 : : keyElement: keyElement_,
- 340 : : askTime: 0,
- 341 : : // Warning: overflow possible if timeLimitToTransfer == max(uint256)
- 342 : : maxTime: block.timestamp +
- 343 : : options.timeLimit.timeLimitToTransfer,
- 344 : : status: STATUS.APPROVED
- 345 : : });
- 346 : 16 : transferRequests[key] = newTransferApproval;
- 347 : 16 : IdToKey[requestId] = key;
- 348 : 16 : emit transferApproved(
- 349 : : key,
- 350 : : keyElement_.from,
- 351 : : keyElement_.to,
- 352 : : keyElement_.value,
- 353 : : requestId
- 354 : : );
- 355 : 16 : ++requestId;
- 356 : : } else {
- 357 : : // Overwrite previous approval
- 358 : : // Warning: overflow possible if timeLimitToTransfer == max(uint256)
- 359 : 1 : transferRequests[key].maxTime =
- 360 : : block.timestamp +
- 361 : : options.timeLimit.timeLimitToTransfer;
- 362 : 1 : transferRequests[key].status = STATUS.APPROVED;
- 363 : 1 : emit transferApproved(
- 364 : : key,
- 365 : : keyElement_.from,
- 366 : : keyElement_.to,
- 367 : : keyElement_.value,
- 368 : : transferRequests[key].id
- 369 : : );
- 370 : : }
- 371 : : }
- 372 : :
- 373 : : function _resetRequestStatus(bytes32 key) internal {
- 374 : 10 : transferRequests[key].status = STATUS.NONE;
- 375 : 10 : emit transferReset(
- 376 : : key,
- 377 : : transferRequests[key].keyElement.from,
- 378 : : transferRequests[key].keyElement.to,
- 379 : : transferRequests[key].keyElement.value,
- 380 : : transferRequests[key].id
- 381 : : );
- 382 : : }
- 383 : :
- 384 : : /**
- 385 : : * @dev check if it is a new request or not
- 386 : : */
- 387 : : function _checkRequestStatus(bytes32 key) internal view returns (bool) {
- 388 : : // Status NONE not enough because reset is possible
- 389 : 133 : return
- 390 : 133 : (transferRequests[key].status == STATUS.NONE) &&
- 391 : : (transferRequests[key].key == 0x0);
- 392 : : }
- 393 : :
- 394 : : function _approveRequest(
- 395 : : TransferRequest memory transferRequest,
- 396 : : bool isApproved
- 397 : : ) internal {
- 398 : : // status
- 399 [ + ]: 53 : if (transferRequest.status != STATUS.WAIT) {
- 400 : 1 : revert RuleConditionalTransfer_Wrong_Status();
- 401 : : }
- 402 [ + + ]: 32 : if (isApproved) {
- 403 : : // Time
- 404 : : if (
- 405 : 32 : block.timestamp >
- 406 : : (transferRequest.askTime + options.timeLimit.timeLimitToApprove)
- 407 [ + ]: 3 : ) {
- 408 : 3 : revert RuleConditionalTransfer_timeExceeded();
- 409 : : }
- 410 : : // Set status
- 411 : 29 : transferRequests[transferRequest.key].status = STATUS.APPROVED;
- 412 : : // Set max time
- 413 : 29 : transferRequests[transferRequest.key].maxTime =
- 414 : : block.timestamp +
- 415 : : options.timeLimit.timeLimitToTransfer;
- 416 : 29 : emit transferApproved(
- 417 : : transferRequest.key,
- 418 : : transferRequest.keyElement.from,
- 419 : : transferRequest.keyElement.to,
- 420 : : transferRequest.keyElement.value,
- 421 : : transferRequests[transferRequest.key].id
- 422 : : );
- 423 : : if (
- 424 : 29 : options.automaticTransfer.isActivate &&
- 425 : 7 : address(options.automaticTransfer.cmtat) != address(0)
- 426 [ + ]: 7 : ) {
- 427 : : // Transfer with approval
- 428 : : // External call
- 429 : : if (
- 430 : 7 : options.automaticTransfer.cmtat.allowance(
- 431 : : transferRequest.keyElement.from,
- 432 : : address(this)
- 433 : : ) >= transferRequest.keyElement.value
- 434 [ + ]: 3 : ) {
- 435 : : // Will call the ruleEngine and the rule again...
- 436 : 3 : options.automaticTransfer.cmtat.safeTransferFrom(
- 437 : : transferRequest.keyElement.from,
- 438 : : transferRequest.keyElement.to,
- 439 : : transferRequest.keyElement.value
- 440 : : );
- 441 : : }
- 442 : : }
- 443 : : } else {
- 444 : 20 : transferRequests[transferRequest.key].status = STATUS.DENIED;
- 445 : 20 : emit transferDenied(
- 446 : : transferRequest.key,
- 447 : : transferRequest.keyElement.from,
- 448 : : transferRequest.keyElement.to,
- 449 : : transferRequest.keyElement.value,
- 450 : : transferRequests[transferRequest.key].id
- 451 : : );
- 452 : : }
- 453 : : }
- 454 : :
- 455 : : /**
- 456 : : * @notice update the request during a transfer
- 457 : : */
- 458 : : function _updateProcessedTransfer(bytes32 key) internal {
- 459 : : // Reset to zero
- 460 : 18 : transferRequests[key].maxTime = 0;
- 461 : 18 : transferRequests[key].askTime = 0;
- 462 : : // Change status
- 463 : 18 : transferRequests[key].status = STATUS.EXECUTED;
- 464 : : // Emit event
- 465 : 18 : emit transferProcessed(
- 466 : : key,
- 467 : : transferRequests[key].keyElement.from,
- 468 : : transferRequests[key].keyElement.to,
- 469 : : transferRequests[key].keyElement.value,
- 470 : : transferRequests[key].id
- 471 : : );
- 472 : : }
- 473 : : }
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/operation/index-sort-b.html b/doc/coverage/coverage/src/rules/operation/index-sort-b.html
deleted file mode 100644
index d14d712..0000000
--- a/doc/coverage/coverage/src/rules/operation/index-sort-b.html
+++ /dev/null
@@ -1,107 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/operation
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleConditionalTransfer.sol
-
-
-
- 99.1 %
- 105 / 106
- 94.4 %
- 17 / 18
- 100.0 %
- 33 / 33
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/operation/index-sort-f.html b/doc/coverage/coverage/src/rules/operation/index-sort-f.html
deleted file mode 100644
index d28f603..0000000
--- a/doc/coverage/coverage/src/rules/operation/index-sort-f.html
+++ /dev/null
@@ -1,107 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/operation
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleConditionalTransfer.sol
-
-
-
- 99.1 %
- 105 / 106
- 94.4 %
- 17 / 18
- 100.0 %
- 33 / 33
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/operation/index-sort-l.html b/doc/coverage/coverage/src/rules/operation/index-sort-l.html
deleted file mode 100644
index ece5b0b..0000000
--- a/doc/coverage/coverage/src/rules/operation/index-sort-l.html
+++ /dev/null
@@ -1,107 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/operation
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleConditionalTransfer.sol
-
-
-
- 99.1 %
- 105 / 106
- 94.4 %
- 17 / 18
- 100.0 %
- 33 / 33
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/operation/index.html b/doc/coverage/coverage/src/rules/operation/index.html
deleted file mode 100644
index 260d74e..0000000
--- a/doc/coverage/coverage/src/rules/operation/index.html
+++ /dev/null
@@ -1,107 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/operation
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleConditionalTransfer.sol
-
-
-
- 99.1 %
- 105 / 106
- 94.4 %
- 17 / 18
- 100.0 %
- 33 / 33
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.func-sort-c.html
deleted file mode 100644
index a23344e..0000000
--- a/doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.func-sort-c.html
+++ /dev/null
@@ -1,97 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/RuleBlacklist.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.func.html b/doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.func.html
deleted file mode 100644
index 0168a37..0000000
--- a/doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.func.html
+++ /dev/null
@@ -1,97 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/RuleBlacklist.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.gcov.html b/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.gcov.html
deleted file mode 100644
index 299cb3a..0000000
--- a/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.gcov.html
+++ /dev/null
@@ -1,250 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/RuleSanctionList.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 : : import "OZ/access/AccessControl.sol";
- 6 : : import "../../modules/MetaTxModuleStandalone.sol";
- 7 : : import "./abstract/RuleSanctionListInvariantStorage.sol";
- 8 : : import "./abstract/RuleValidateTransfer.sol";
- 9 : :
- 10 : : interface SanctionsList {
- 11 : : function isSanctioned(address addr) external view returns (bool);
- 12 : : }
- 13 : :
- 14 : : contract RuleSanctionList is
- 15 : : AccessControl,
- 16 : : MetaTxModuleStandalone,
- 17 : : RuleValidateTransfer,
- 18 : : RuleSanctionlistInvariantStorage
- 19 : : {
- 20 : : SanctionsList public sanctionsList;
- 21 : :
- 22 : : /**
- 23 : : * @param admin Address of the contract (Access Control)
- 24 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
- 25 : : */
- 26 : : constructor(
- 27 : : address admin,
- 28 : : address forwarderIrrevocable,
- 29 : : address sanctionContractOracle_
- 30 : : ) MetaTxModuleStandalone(forwarderIrrevocable) {
- 31 [ + ]: 13 : if (admin == address(0)) {
- 32 : 1 : revert RuleSanctionList_AdminWithAddressZeroNotAllowed();
- 33 : : }
- 34 [ + ]: 12 : if (sanctionContractOracle_ != address(0)) {
- 35 : 1 : _setSanctionListOracle(sanctionContractOracle_);
- 36 : : }
- 37 : 12 : _grantRole(DEFAULT_ADMIN_ROLE, admin);
- 38 : : }
- 39 : :
- 40 : : /**
- 41 : : * @notice Set the oracle contract
- 42 : : * @param sanctionContractOracle_ address of your oracle contract
- 43 : : * @dev zero address is authorized to authorize all transfers
- 44 : : */
- 45 : : function setSanctionListOracle(
- 46 : : address sanctionContractOracle_
- 47 : : ) public onlyRole(SANCTIONLIST_ROLE) {
- 48 : 10 : _setSanctionListOracle(sanctionContractOracle_);
- 49 : : }
- 50 : :
- 51 : : /**
- 52 : : * @notice Check if an addres is in the whitelist or not
- 53 : : * @param _from the origin address
- 54 : : * @param _to the destination address
- 55 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
- 56 : : **/
- 57 : : function detectTransferRestriction(
- 58 : : address _from,
- 59 : : address _to,
- 60 : : uint256 /*_amount */
- 61 : : ) public view override returns (uint8) {
- 62 [ + ]: 7 : if (address(sanctionsList) != address(0)) {
- 63 [ + + ]: 7 : if (sanctionsList.isSanctioned(_from)) {
- 64 : 2 : return CODE_ADDRESS_FROM_IS_SANCTIONED;
- 65 [ + ]: 5 : } else if (sanctionsList.isSanctioned(_to)) {
- 66 : 2 : return CODE_ADDRESS_TO_IS_SANCTIONED;
- 67 : : }
- 68 : : }
- 69 : 3 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- 70 : : }
- 71 : :
- 72 : : /**
- 73 : : * @notice To know if the restriction code is valid for this rule or not.
- 74 : : * @param _restrictionCode The target restriction code
- 75 : : * @return true if the restriction code is known, false otherwise
- 76 : : **/
- 77 : : function canReturnTransferRestrictionCode(
- 78 : : uint8 _restrictionCode
- 79 : : ) external pure override returns (bool) {
- 80 : 3 : return
- 81 : 3 : _restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED ||
- 82 : 2 : _restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED;
- 83 : : }
- 84 : :
- 85 : : /**
- 86 : : * @notice Return the corresponding message
- 87 : : * @param _restrictionCode The target restriction code
- 88 : : * @return true if the transfer is valid, false otherwise
- 89 : : **/
- 90 : : function messageForTransferRestriction(
- 91 : : uint8 _restrictionCode
- 92 : : ) external pure override returns (string memory) {
- 93 [ + + ]: 3 : if (_restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED) {
- 94 : 1 : return TEXT_ADDRESS_FROM_IS_SANCTIONED;
- 95 [ + + ]: 2 : } else if (_restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED) {
- 96 : 1 : return TEXT_ADDRESS_TO_IS_SANCTIONED;
- 97 : : } else {
- 98 : 1 : return TEXT_CODE_NOT_FOUND;
- 99 : : }
- 100 : : }
- 101 : :
- 102 : : /* ============ ACCESS CONTROL ============ */
- 103 : : /**
- 104 : : * @dev Returns `true` if `account` has been granted `role`.
- 105 : : */
- 106 : : function hasRole(
- 107 : : bytes32 role,
- 108 : : address account
- 109 : : ) public view virtual override(AccessControl) returns (bool) {
- 110 : : // The Default Admin has all roles
- 111 [ + ]: 24 : if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
- 112 : 11 : return true;
- 113 : : }
- 114 : 13 : return AccessControl.hasRole(role, account);
- 115 : : }
- 116 : :
- 117 : : /*//////////////////////////////////////////////////////////////
- 118 : : INTERNAL FUNCTIONS
- 119 : : //////////////////////////////////////////////////////////////*/
- 120 : :
- 121 : : function _setSanctionListOracle(address sanctionContractOracle_) internal {
- 122 : 11 : sanctionsList = SanctionsList(sanctionContractOracle_);
- 123 : 11 : emit SetSanctionListOracle(address(sanctionContractOracle_));
- 124 : : }
- 125 : :
- 126 : : /*//////////////////////////////////////////////////////////////
- 127 : : ERC-2771
- 128 : : //////////////////////////////////////////////////////////////*/
- 129 : :
- 130 : : /**
- 131 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 132 : : */
- 133 : : function _msgSender()
- 134 : : internal
- 135 : : view
- 136 : : override(ERC2771Context, Context)
- 137 : : returns (address sender)
- 138 : : {
- 139 : 23 : return ERC2771Context._msgSender();
- 140 : : }
- 141 : :
- 142 : : /**
- 143 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 144 : : */
- 145 : : function _msgData()
- 146 : : internal
- 147 : : view
- 148 : : override(ERC2771Context, Context)
- 149 : : returns (bytes calldata)
- 150 : : {
- 151 : 0 : return ERC2771Context._msgData();
- 152 : : }
- 153 : :
- 154 : : /**
- 155 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 156 : : */
- 157 : : function _contextSuffixLength()
- 158 : : internal
- 159 : : view
- 160 : : override(ERC2771Context, Context)
- 161 : : returns (uint256)
- 162 : : {
- 163 : 23 : return ERC2771Context._contextSuffixLength();
- 164 : : }
- 165 : : }
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/RuleWhitelist.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/validation/RuleWhitelist.sol.func-sort-c.html
deleted file mode 100644
index 3983775..0000000
--- a/doc/coverage/coverage/src/rules/validation/RuleWhitelist.sol.func-sort-c.html
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/RuleWhitelist.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/RuleWhitelist.sol.func.html b/doc/coverage/coverage/src/rules/validation/RuleWhitelist.sol.func.html
deleted file mode 100644
index 855b26a..0000000
--- a/doc/coverage/coverage/src/rules/validation/RuleWhitelist.sol.func.html
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/RuleWhitelist.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/RuleWhitelist.sol.gcov.html b/doc/coverage/coverage/src/rules/validation/RuleWhitelist.sol.gcov.html
deleted file mode 100644
index 729cd39..0000000
--- a/doc/coverage/coverage/src/rules/validation/RuleWhitelist.sol.gcov.html
+++ /dev/null
@@ -1,125 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/RuleWhitelist.sol
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func-sort-c.html
deleted file mode 100644
index 50d42d4..0000000
--- a/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func-sort-c.html
+++ /dev/null
@@ -1,105 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/RuleWhitelistWrapper.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func.html b/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func.html
deleted file mode 100644
index 87ddb39..0000000
--- a/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func.html
+++ /dev/null
@@ -1,105 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/RuleWhitelistWrapper.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func-sort-c.html
deleted file mode 100644
index 98ee305..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func-sort-c.html
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func.html
deleted file mode 100644
index ed5ebcb..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func.html
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func-sort-c.html
deleted file mode 100644
index 5b3956f..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func-sort-c.html
+++ /dev/null
@@ -1,105 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func.html
deleted file mode 100644
index d5e1465..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func.html
+++ /dev/null
@@ -1,105 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.gcov.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.gcov.html
deleted file mode 100644
index f91cf24..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.gcov.html
+++ /dev/null
@@ -1,186 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-b.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-b.html
deleted file mode 100644
index 5f6b1ad..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-b.html
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleAddressList.sol
-
-
-
- 95.7 %
- 22 / 23
- 91.7 %
- 11 / 12
- 100.0 %
- 2 / 2
-
-
- RuleAddressListInternal.sol
-
-
-
- 100.0 %
- 22 / 22
- 100.0 %
- 6 / 6
- 100.0 %
- 4 / 4
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-f.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-f.html
deleted file mode 100644
index d55918c..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-f.html
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleAddressList.sol
-
-
-
- 95.7 %
- 22 / 23
- 91.7 %
- 11 / 12
- 100.0 %
- 2 / 2
-
-
- RuleAddressListInternal.sol
-
-
-
- 100.0 %
- 22 / 22
- 100.0 %
- 6 / 6
- 100.0 %
- 4 / 4
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-l.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-l.html
deleted file mode 100644
index 94dea7d..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-l.html
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleAddressList.sol
-
-
-
- 95.7 %
- 22 / 23
- 91.7 %
- 11 / 12
- 100.0 %
- 2 / 2
-
-
- RuleAddressListInternal.sol
-
-
-
- 100.0 %
- 22 / 22
- 100.0 %
- 6 / 6
- 100.0 %
- 4 / 4
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index.html
deleted file mode 100644
index b24b451..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index.html
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleAddressList.sol
-
-
-
- 95.7 %
- 22 / 23
- 91.7 %
- 11 / 12
- 100.0 %
- 2 / 2
-
-
- RuleAddressListInternal.sol
-
-
-
- 100.0 %
- 22 / 22
- 100.0 %
- 6 / 6
- 100.0 %
- 4 / 4
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html
deleted file mode 100644
index 9025b1d..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract/RuleValidateTransfer.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func.html
deleted file mode 100644
index cef3f12..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func.html
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract/RuleValidateTransfer.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.gcov.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.gcov.html
deleted file mode 100644
index c350c3b..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.gcov.html
+++ /dev/null
@@ -1,110 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract/RuleValidateTransfer.sol
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/index-sort-b.html b/doc/coverage/coverage/src/rules/validation/abstract/index-sort-b.html
deleted file mode 100644
index 32f7fc4..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/index-sort-b.html
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleValidateTransfer.sol
-
-
-
- 100.0 %
- 2 / 2
- 100.0 %
- 1 / 1
- -
- 0 / 0
-
-
- RuleWhitelistCommon.sol
-
-
-
- 100.0 %
- 8 / 8
- 100.0 %
- 2 / 2
- 100.0 %
- 4 / 4
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/index-sort-f.html b/doc/coverage/coverage/src/rules/validation/abstract/index-sort-f.html
deleted file mode 100644
index 37e913e..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/index-sort-f.html
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleValidateTransfer.sol
-
-
-
- 100.0 %
- 2 / 2
- 100.0 %
- 1 / 1
- -
- 0 / 0
-
-
- RuleWhitelistCommon.sol
-
-
-
- 100.0 %
- 8 / 8
- 100.0 %
- 2 / 2
- 100.0 %
- 4 / 4
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/index-sort-l.html b/doc/coverage/coverage/src/rules/validation/abstract/index-sort-l.html
deleted file mode 100644
index 51f2975..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/index-sort-l.html
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleValidateTransfer.sol
-
-
-
- 100.0 %
- 2 / 2
- 100.0 %
- 1 / 1
- -
- 0 / 0
-
-
- RuleWhitelistCommon.sol
-
-
-
- 100.0 %
- 8 / 8
- 100.0 %
- 2 / 2
- 100.0 %
- 4 / 4
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/index.html b/doc/coverage/coverage/src/rules/validation/abstract/index.html
deleted file mode 100644
index 74cd455..0000000
--- a/doc/coverage/coverage/src/rules/validation/abstract/index.html
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation/abstract
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleValidateTransfer.sol
-
-
-
- 100.0 %
- 2 / 2
- 100.0 %
- 1 / 1
- -
- 0 / 0
-
-
- RuleWhitelistCommon.sol
-
-
-
- 100.0 %
- 8 / 8
- 100.0 %
- 2 / 2
- 100.0 %
- 4 / 4
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/index-sort-b.html b/doc/coverage/coverage/src/rules/validation/index-sort-b.html
deleted file mode 100644
index d627eb6..0000000
--- a/doc/coverage/coverage/src/rules/validation/index-sort-b.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleWhitelist.sol
-
-
-
- 100.0 %
- 5 / 5
- 100.0 %
- 2 / 2
- 100.0 %
- 4 / 4
-
-
- RuleBlacklist.sol
-
-
-
- 100.0 %
- 13 / 13
- 100.0 %
- 4 / 4
- 100.0 %
- 8 / 8
-
-
- RuleWhitelistWrapper.sol
-
-
-
- 96.4 %
- 27 / 28
- 83.3 %
- 5 / 6
- 100.0 %
- 9 / 9
-
-
- RuleSanctionList.sol
-
-
-
- 96.4 %
- 27 / 28
- 90.0 %
- 9 / 10
- 100.0 %
- 11 / 11
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/index-sort-f.html b/doc/coverage/coverage/src/rules/validation/index-sort-f.html
deleted file mode 100644
index 7939279..0000000
--- a/doc/coverage/coverage/src/rules/validation/index-sort-f.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleWhitelistWrapper.sol
-
-
-
- 96.4 %
- 27 / 28
- 83.3 %
- 5 / 6
- 100.0 %
- 9 / 9
-
-
- RuleSanctionList.sol
-
-
-
- 96.4 %
- 27 / 28
- 90.0 %
- 9 / 10
- 100.0 %
- 11 / 11
-
-
- RuleWhitelist.sol
-
-
-
- 100.0 %
- 5 / 5
- 100.0 %
- 2 / 2
- 100.0 %
- 4 / 4
-
-
- RuleBlacklist.sol
-
-
-
- 100.0 %
- 13 / 13
- 100.0 %
- 4 / 4
- 100.0 %
- 8 / 8
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/index-sort-l.html b/doc/coverage/coverage/src/rules/validation/index-sort-l.html
deleted file mode 100644
index e147ebd..0000000
--- a/doc/coverage/coverage/src/rules/validation/index-sort-l.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleSanctionList.sol
-
-
-
- 96.4 %
- 27 / 28
- 90.0 %
- 9 / 10
- 100.0 %
- 11 / 11
-
-
- RuleWhitelistWrapper.sol
-
-
-
- 96.4 %
- 27 / 28
- 83.3 %
- 5 / 6
- 100.0 %
- 9 / 9
-
-
- RuleWhitelist.sol
-
-
-
- 100.0 %
- 5 / 5
- 100.0 %
- 2 / 2
- 100.0 %
- 4 / 4
-
-
- RuleBlacklist.sol
-
-
-
- 100.0 %
- 13 / 13
- 100.0 %
- 4 / 4
- 100.0 %
- 8 / 8
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/src/rules/validation/index.html b/doc/coverage/coverage/src/rules/validation/index.html
deleted file mode 100644
index 3d1ec09..0000000
--- a/doc/coverage/coverage/src/rules/validation/index.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - src/rules/validation
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Filename
- Line Coverage
- Functions
- Branches
-
-
- RuleBlacklist.sol
-
-
-
- 100.0 %
- 13 / 13
- 100.0 %
- 4 / 4
- 100.0 %
- 8 / 8
-
-
- RuleSanctionList.sol
-
-
-
- 96.4 %
- 27 / 28
- 90.0 %
- 9 / 10
- 100.0 %
- 11 / 11
-
-
- RuleWhitelist.sol
-
-
-
- 100.0 %
- 5 / 5
- 100.0 %
- 2 / 2
- 100.0 %
- 4 / 4
-
-
- RuleWhitelistWrapper.sol
-
-
-
- 96.4 %
- 27 / 28
- 83.3 %
- 5 / 6
- 100.0 %
- 9 / 9
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.gcov.html b/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.gcov.html
deleted file mode 100644
index 471014d..0000000
--- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.gcov.html
+++ /dev/null
@@ -1,142 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - test/RuleConditionalTransfer/utils/RuleCTDeployment.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 "forge-std/Test.sol";
- 5 : : import "../../HelperContract.sol";
- 6 : : import "src/RuleEngine.sol";
- 7 : :
- 8 : : /**
- 9 : : * @title Tests on the Access Control
- 10 : : */
- 11 : : contract RuleCTDeployment is Test, HelperContract {
- 12 : : // Arrange
- 13 : : constructor() {
- 14 : 13 : TIME_LIMIT memory timeLimit_ = TIME_LIMIT({
- 15 : : timeLimitToApprove: 7 days,
- 16 : : timeLimitToTransfer: 30 days
- 17 : : });
- 18 : :
- 19 : 13 : AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
- 20 : : isActivate: false,
- 21 : : timeLimitBeforeAutomaticApproval: 0
- 22 : : });
- 23 : :
- 24 : 13 : ISSUANCE memory issuanceOption_ = ISSUANCE({
- 25 : : authorizedMintWithoutApproval: false,
- 26 : : authorizedBurnWithoutApproval: false
- 27 : : });
- 28 : 13 : AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({
- 29 : : isActivate: false,
- 30 : : cmtat: IERC20(address(0))
- 31 : : });
- 32 : :
- 33 : 13 : OPTION memory options = OPTION({
- 34 : : issuance: issuanceOption_,
- 35 : : timeLimit: timeLimit_,
- 36 : : automaticApproval: automaticApproval_,
- 37 : : automaticTransfer: automaticTransfer_
- 38 : : });
- 39 : 13 : ruleEngineMock = new RuleEngine(
- 40 : : RULE_ENGINE_OPERATOR_ADDRESS,
- 41 : : ZERO_ADDRESS,
- 42 : : ZERO_ADDRESS
- 43 : : );
- 44 : 13 : vm.prank(DEFAULT_ADMIN_ADDRESS);
- 45 : 13 : ruleConditionalTransfer = new RuleConditionalTransfer(
- 46 : : DEFAULT_ADMIN_ADDRESS,
- 47 : : ZERO_ADDRESS,
- 48 : : ruleEngineMock,
- 49 : : options
- 50 : : );
- 51 : 13 : vm.prank(DEFAULT_ADMIN_ADDRESS);
- 52 : 13 : ruleConditionalTransfer.grantRole(
- 53 : : RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE,
- 54 : : CONDITIONAL_TRANSFER_OPERATOR_ADDRESS
- 55 : : );
- 56 : : }
- 57 : : }
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func-sort-c.html b/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func-sort-c.html
deleted file mode 100644
index a8ae820..0000000
--- a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func-sort-c.html
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - test/utils/CMTATDeployment.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func.html b/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func.html
deleted file mode 100644
index a912669..0000000
--- a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func.html
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - test/utils/CMTATDeployment.sol - functions
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.gcov.html b/doc/coverage/coverage/test/utils/CMTATDeployment.sol.gcov.html
deleted file mode 100644
index a0b1546..0000000
--- a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.gcov.html
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - test/utils/CMTATDeployment.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 "forge-std/Test.sol";
- 5 : : import "OZ/access/AccessControl.sol";
- 6 : : import "CMTAT/CMTAT_STANDALONE.sol";
- 7 : :
- 8 : : contract CMTATDeployment {
- 9 : : // Share with helper contract
- 10 : : address constant ZERO_ADDRESS = address(0);
- 11 : : address constant DEFAULT_ADMIN_ADDRESS = address(1);
- 12 : :
- 13 : : CMTAT_STANDALONE public cmtat;
- 14 : :
- 15 : : constructor() {
- 16 : : // CMTAT
- 17 : 86 : ICMTATConstructor.ERC20Attributes
- 18 : : memory erc20Attributes = ICMTATConstructor.ERC20Attributes(
- 19 : : "CMTA Token",
- 20 : : "CMTAT",
- 21 : : 0
- 22 : : );
- 23 : 86 : ICMTATConstructor.BaseModuleAttributes
- 24 : : memory baseModuleAttributes = ICMTATConstructor
- 25 : : .BaseModuleAttributes(
- 26 : : "CMTAT_ISIN",
- 27 : : "https://cmta.ch",
- 28 : : "CMTAT_info"
- 29 : : );
- 30 : 86 : ICMTATConstructor.Engine memory engines = ICMTATConstructor.Engine(
- 31 : : IRuleEngine(ZERO_ADDRESS),
- 32 : : IDebtEngine(ZERO_ADDRESS),
- 33 : : IAuthorizationEngine(ZERO_ADDRESS),
- 34 : : IERC1643(ZERO_ADDRESS)
- 35 : : );
- 36 : 86 : cmtat = new CMTAT_STANDALONE(
- 37 : : ZERO_ADDRESS,
- 38 : : DEFAULT_ADMIN_ADDRESS,
- 39 : : erc20Attributes,
- 40 : : baseModuleAttributes,
- 41 : : engines
- 42 : : );
- 43 : : }
- 44 : : }
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.gcov.html b/doc/coverage/coverage/test/utils/SanctionListOracle.sol.gcov.html
deleted file mode 100644
index 6a45b5a..0000000
--- a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.gcov.html
+++ /dev/null
@@ -1,109 +0,0 @@
-
-
-
-
-
-
- LCOV - lcov.info - test/utils/SanctionListOracle.sol
-
-
-
-
-
-
- LCOV - code coverage report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html b/doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html
new file mode 100644
index 0000000..09bb6da
--- /dev/null
+++ b/doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+ LCOV - lcov.info - validation/RuleBlacklist.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/validation/RuleBlacklist.sol.func.html b/doc/coverage/coverage/validation/RuleBlacklist.sol.func.html
new file mode 100644
index 0000000..7644183
--- /dev/null
+++ b/doc/coverage/coverage/validation/RuleBlacklist.sol.func.html
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+ LCOV - lcov.info - validation/RuleBlacklist.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html b/doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html
new file mode 100644
index 0000000..9ee3de4
--- /dev/null
+++ b/doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html
@@ -0,0 +1,272 @@
+
+
+
+
+
+
+ LCOV - lcov.info - validation/RuleBlacklist.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 : : 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)
+ 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 : : }
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html b/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html
new file mode 100644
index 0000000..3e4edde
--- /dev/null
+++ b/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+ 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
new file mode 100644
index 0000000..03d8771
--- /dev/null
+++ b/doc/coverage/coverage/validation/RuleSanctionsList.sol.func.html
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+ LCOV - lcov.info - validation/RuleSanctionsList.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html b/doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html
new file mode 100644
index 0000000..1d03613
--- /dev/null
+++ b/doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html
@@ -0,0 +1,349 @@
+
+
+
+
+
+
+ LCOV - lcov.info - validation/RuleSanctionsList.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 : : 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";
+ 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 : : }
+ 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 : : }
+ 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 : : }
+ 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 : : }
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/src/RuleEngine.sol.func-sort-c.html b/doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html
similarity index 54%
rename from doc/coverage/coverage/src/RuleEngine.sol.func-sort-c.html
rename to doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html
index eabf2d9..f9af8e7 100644
--- a/doc/coverage/coverage/src/RuleEngine.sol.func-sort-c.html
+++ b/doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - src/RuleEngine.sol - functions
+ LCOV - lcov.info - validation/RuleWhitelist.sol - functions
@@ -19,7 +19,7 @@
-
+
@@ -31,26 +31,26 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
+
+
@@ -65,44 +65,36 @@
diff --git a/doc/coverage/coverage/src/RuleEngine.sol.func.html b/doc/coverage/coverage/validation/RuleWhitelist.sol.func.html
similarity index 55%
rename from doc/coverage/coverage/src/RuleEngine.sol.func.html
rename to doc/coverage/coverage/validation/RuleWhitelist.sol.func.html
index f12d35b..e3f8fe0 100644
--- a/doc/coverage/coverage/src/RuleEngine.sol.func.html
+++ b/doc/coverage/coverage/validation/RuleWhitelist.sol.func.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - src/RuleEngine.sol - functions
+ LCOV - lcov.info - validation/RuleWhitelist.sol - functions
@@ -19,7 +19,7 @@
diff --git a/doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.gcov.html b/doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html
similarity index 54%
rename from doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.gcov.html
rename to doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html
index 1c29fc2..09c1d37 100644
--- a/doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.gcov.html
+++ b/doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - src/modules/RuleEngineValidationCommon.sol
-
+ LCOV - lcov.info - validation/RuleWhitelist.sol
+
LCOV - code coverage report
-
+
-
+
@@ -31,34 +31,34 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
+
+
-
+
-
+
@@ -70,157 +70,151 @@
Branch data Line data Source code
1 : : // SPDX-License-Identifier: MPL-2.0
- 2 : :
- 3 : : pragma solidity ^0.8.20;
- 4 : :
- 5 : : import "OZ/access/AccessControl.sol";
- 6 : : import "./RuleInternal.sol";
- 7 : : import "../interfaces/IRuleEngineValidation.sol";
- 8 : : import "../interfaces/IRuleValidation.sol";
- 9 : :
- 10 : : /**
- 11 : : * @title Implementation of a ruleEngine defined by the CMTAT
- 12 : : */
- 13 : : abstract contract RuleEngineValidationCommon is
- 14 : : AccessControl,
- 15 : : RuleInternal,
- 16 : : IRuleEngineValidationCommon
- 17 : : {
- 18 : : /// @dev Array of rules
- 19 : : address[] internal _rulesValidation;
- 20 : :
- 21 : : /*//////////////////////////////////////////////////////////////
- 22 : : PUBLIC/EXTERNAL FUNCTIONS
- 23 : : //////////////////////////////////////////////////////////////*/
- 24 : : /**
- 25 : : * @notice Set all the rules, will overwrite all the previous rules. \n
- 26 : : * Revert if one rule is a zero address or if the rule is already present
- 27 : : * @dev take address[] instead of IRuleEngineValidation[] since it is not possible to cast IRuleEngineValidation[] -> address[]
- 28 : : *
- 29 : : */
- 30 : : function setRulesValidation(
- 31 : : address[] calldata rules_
- 32 : : ) public override onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
- 33 [ + ]: 21 : if (_rulesValidation.length > 0) {
- 34 : 20 : _clearRulesValidation();
- 35 : : }
- 36 : 21 : _setRules(rules_);
- 37 : 18 : _rulesValidation = rules_;
- 38 : : }
- 39 : :
- 40 : : /**
- 41 : : * @notice Clear all the rules of the array of rules
- 42 : : *
- 43 : : */
- 44 : : function clearRulesValidation() public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
- 45 : 5 : _clearRulesValidation();
- 46 : : }
- 47 : :
- 48 : : /**
- 49 : : * @notice Add a rule to the array of rules
- 50 : : * Revert if one rule is a zero address or if the rule is already present
- 51 : : *
- 52 : : */
- 53 : : function addRuleValidation(
- 54 : : IRuleValidation rule_
- 55 : : ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
- 56 : 118 : RuleInternal._addRule(_rulesValidation, address(rule_));
- 57 : 116 : emit AddRule(address(rule_));
- 58 : : }
- 59 : :
- 60 : : /**
- 61 : : * @notice Remove a rule from the array of rules
- 62 : : * Revert if the rule found at the specified index does not match the rule in argument
- 63 : : * @param rule_ address of the target rule
- 64 : : * @param index the position inside the array of rule
- 65 : : * @dev To reduce the array size, the last rule is moved to the location occupied
- 66 : : * by the rule to remove
- 67 : : *
- 68 : : *
- 69 : : */
- 70 : : function removeRuleValidation(
- 71 : : IRuleValidation rule_,
- 72 : : uint256 index
- 73 : : ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
- 74 : 5 : _removeRuleValidation(address(rule_), index);
- 75 : : }
- 76 : :
- 77 : : /**
- 78 : : * @return The number of rules inside the array
- 79 : : */
- 80 : : function rulesCountValidation() external view override returns (uint256) {
- 81 : 69 : return _rulesValidation.length;
- 82 : : }
- 83 : :
- 84 : : /**
- 85 : : * @notice Get the index of a rule inside the list
- 86 : : * @return index if the rule is found, _rulesValidation.length otherwise
- 87 : : */
- 88 : : function getRuleIndexValidation(
- 89 : : IRuleValidation rule_
- 90 : : ) external view returns (uint256 index) {
- 91 : 3 : return RuleInternal._getRuleIndex(_rulesValidation, address(rule_));
- 92 : : }
- 93 : :
- 94 : : /**
- 95 : : * @notice Get the rule at the position specified by ruleId
- 96 : : * @param ruleId index of the rule
- 97 : : * @return a rule address
- 98 : : */
- 99 : : function ruleValidation(
- 100 : : uint256 ruleId
- 101 : : ) external view override returns (address) {
- 102 : 1 : return _rulesValidation[ruleId];
- 103 : : }
- 104 : :
- 105 : : /**
- 106 : : * @notice Get all the rules
- 107 : : * @return An array of rules
- 108 : : */
- 109 : : function rulesValidation()
- 110 : : external
- 111 : : view
- 112 : : override
- 113 : : returns (address[] memory)
- 114 : : {
- 115 : 5 : return _rulesValidation;
- 116 : : }
- 117 : :
- 118 : : /*//////////////////////////////////////////////////////////////
- 119 : : INTERNAL FUNCTIONS
- 120 : : //////////////////////////////////////////////////////////////*/
- 121 : : /**
- 122 : : * @notice Clear all the rules of the array of rules
- 123 : : *
- 124 : : */
- 125 : : function _clearRulesValidation() internal {
- 126 : 25 : uint256 index;
- 127 : : // we remove the last element first since it is more optimized.
- 128 : 25 : for (uint256 i = _rulesValidation.length; i > 0; --i) {
- 129 : : unchecked {
- 130 : : // don't underflow since i > 0
- 131 : 28 : index = i - 1;
- 132 : : }
- 133 : 28 : _removeRuleValidation(_rulesValidation[index], index);
- 134 : : }
- 135 : 25 : emit ClearRules(_rulesValidation);
- 136 : : }
- 137 : :
- 138 : : /**
- 139 : : * @notice Remove a rule from the array of rules
- 140 : : * Revert if the rule found at the specified index does not match the rule in argument
- 141 : : * @param rule_ address of the target rule
- 142 : : * @param index the position inside the array of rule
- 143 : : * @dev To reduce the array size, the last rule is moved to the location occupied
- 144 : : * by the rule to remove
- 145 : : *
- 146 : : *
- 147 : : */
- 148 : : function _removeRuleValidation(address rule_, uint256 index) internal {
- 149 : 33 : RuleInternal._removeRule(_rulesValidation, rule_, index);
- 150 : 32 : emit RemoveRule(address(rule_));
- 151 : : }
- 152 : : }
+ 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
+ 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 : : }
@@ -228,7 +222,7 @@
diff --git a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html
new file mode 100644
index 0000000..19a2bf6
--- /dev/null
+++ b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+ LCOV - lcov.info - validation/RuleWhitelistWrapper.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html
new file mode 100644
index 0000000..4994cad
--- /dev/null
+++ b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+ LCOV - lcov.info - validation/RuleWhitelistWrapper.sol - functions
+
+
+
+
+
+
+ LCOV - code coverage report
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/coverage/coverage/src/RuleEngine.sol.gcov.html b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html
similarity index 55%
rename from doc/coverage/coverage/src/RuleEngine.sol.gcov.html
rename to doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html
index b32d492..325f5a0 100644
--- a/doc/coverage/coverage/src/RuleEngine.sol.gcov.html
+++ b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - src/RuleEngine.sol
+ LCOV - lcov.info - validation/RuleWhitelistWrapper.sol
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
+
+
-
-
-
+
+
+
@@ -73,204 +73,202 @@
2 : :
3 : : pragma solidity ^0.8.20;
4 : :
- 5 : : import "CMTAT/interfaces/engine/IRuleEngine.sol";
- 6 : : import "./modules/MetaTxModuleStandalone.sol";
- 7 : : import "./modules/RuleEngineOperation.sol";
- 8 : : import "./modules/RuleEngineValidation.sol";
- 9 : :
- 10 : : /**
- 11 : : * @title Implementation of a ruleEngine as defined by the CMTAT
- 12 : : */
- 13 : : contract RuleEngine is
- 14 : : IRuleEngine,
- 15 : : RuleEngineOperation,
- 16 : : RuleEngineValidation,
- 17 : : MetaTxModuleStandalone
- 18 : : {
- 19 : : /**
- 20 : : * @notice
- 21 : : * Get the current version of the smart contract
- 22 : : */
- 23 : : string public constant VERSION = "2.0.4";
- 24 : :
- 25 : : /**
- 26 : : * @param admin Address of the contract (Access Control)
- 27 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
- 28 : : */
- 29 : : constructor(
- 30 : : address admin,
- 31 : : address forwarderIrrevocable,
- 32 : : address tokenContract
- 33 : : ) MetaTxModuleStandalone(forwarderIrrevocable) {
- 34 [ + ]: 205 : if (admin == address(0)) {
- 35 : 1 : revert RuleEngine_AdminWithAddressZeroNotAllowed();
- 36 : : }
- 37 [ + ]: 204 : if (tokenContract != address(0)) {
- 38 : 86 : _grantRole(TOKEN_CONTRACT_ROLE, tokenContract);
- 39 : : }
- 40 : 204 : _grantRole(DEFAULT_ADMIN_ROLE, admin);
- 41 : : }
- 42 : :
- 43 : : /**
- 44 : : * @notice Go through all the rule to know if a restriction exists on the transfer
- 45 : : * @param _from the origin address
- 46 : : * @param _to the destination address
- 47 : : * @param _amount to transfer
- 48 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
- 49 : : **/
- 50 : : function detectTransferRestriction(
- 51 : : address _from,
- 52 : : address _to,
- 53 : : uint256 _amount
- 54 : : ) public view override returns (uint8) {
- 55 : : // Validation
- 56 : 32 : uint8 code = RuleEngineValidation.detectTransferRestrictionValidation(
- 57 : : _from,
- 58 : : _to,
- 59 : : _amount
- 60 : : );
- 61 [ + ]: 32 : if (code != uint8(REJECTED_CODE_BASE.TRANSFER_OK)) {
- 62 : 15 : return code;
- 63 : : }
- 64 : :
- 65 : : // Operation
- 66 : 17 : uint256 rulesLength = _rulesOperation.length;
- 67 : 17 : for (uint256 i = 0; i < rulesLength; ++i) {
- 68 : 12 : uint8 restriction = IRuleValidation(_rulesOperation[i])
- 69 : : .detectTransferRestriction(_from, _to, _amount);
- 70 [ + ]: 12 : if (restriction > 0) {
- 71 : 11 : return restriction;
- 72 : : }
- 73 : : }
- 74 : :
- 75 : 6 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- 76 : : }
- 77 : :
- 78 : : /**
- 79 : : * @notice Validate a transfer
- 80 : : * @param _from the origin address
- 81 : : * @param _to the destination address
- 82 : : * @param _amount to transfer
- 83 : : * @return True if the transfer is valid, false otherwise
- 84 : : **/
- 85 : : function validateTransfer(
- 86 : : address _from,
- 87 : : address _to,
- 88 : : uint256 _amount
- 89 : : ) public view override returns (bool) {
- 90 : 12 : return
- 91 : 12 : detectTransferRestriction(_from, _to, _amount) ==
- 92 : : uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- 93 : : }
+ 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 : : /**
- 96 : : * @notice Return the message corresponding to the code
- 97 : : * @param _restrictionCode The target restriction code
- 98 : : * @return True if the transfer is valid, false otherwise
- 99 : : **/
- 100 : : function messageForTransferRestriction(
- 101 : : uint8 _restrictionCode
- 102 : : ) external view override returns (string memory) {
- 103 : : // Validation
- 104 : 18 : uint256 rulesLength = _rulesValidation.length;
- 105 : 18 : for (uint256 i = 0; i < rulesLength; ++i) {
- 106 : : if (
- 107 : 13 : IRuleValidation(_rulesValidation[i])
- 108 : : .canReturnTransferRestrictionCode(_restrictionCode)
- 109 [ + ]: 10 : ) {
- 110 : 10 : return
- 111 : 10 : IRuleValidation(_rulesValidation[i])
- 112 : : .messageForTransferRestriction(_restrictionCode);
- 113 : : }
- 114 : : }
- 115 : : // operation
- 116 : 8 : rulesLength = _rulesOperation.length;
- 117 : 8 : for (uint256 i = 0; i < rulesLength; ++i) {
- 118 : : if (
- 119 : 2 : IRuleValidation(_rulesOperation[i])
- 120 : : .canReturnTransferRestrictionCode(_restrictionCode)
- 121 [ + ]: 1 : ) {
- 122 : 1 : return
- 123 : 1 : IRuleValidation(_rulesOperation[i])
- 124 : : .messageForTransferRestriction(_restrictionCode);
- 125 : : }
- 126 : : }
- 127 : 7 : return "Unknown restriction code";
- 128 : : }
- 129 : :
- 130 : : /*
- 131 : : * @notice function protected by access control
- 132 : : */
- 133 : : function operateOnTransfer(
- 134 : : address from,
- 135 : : address to,
- 136 : : uint256 amount
- 137 : : ) external override onlyRole(TOKEN_CONTRACT_ROLE) returns (bool isValid) {
- 138 : : // Validate the transfer
- 139 : : if (
- 140 : 68 : !RuleEngineValidation.validateTransferValidation(from, to, amount)
- 141 [ + ]: 10 : ) {
- 142 : 10 : return false;
- 143 : : }
- 144 : : // Apply operation on RuleEngine
- 145 : 58 : return RuleEngineOperation._operateOnTransfer(from, to, amount);
- 146 : : }
- 147 : :
- 148 : : /* ============ ACCESS CONTROL ============ */
- 149 : : /**
- 150 : : * @dev Returns `true` if `account` has been granted `role`.
- 151 : : */
- 152 : : function hasRole(
- 153 : : bytes32 role,
- 154 : : address account
- 155 : : ) public view virtual override(AccessControl) returns (bool) {
- 156 : : // The Default Admin has all roles
- 157 [ + ]: 597 : if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
- 158 : 220 : return true;
- 159 : : }
- 160 : 377 : return AccessControl.hasRole(role, account);
- 161 : : }
- 162 : :
- 163 : : /*//////////////////////////////////////////////////////////////
- 164 : : ERC-2771
- 165 : : //////////////////////////////////////////////////////////////*/
- 166 : :
- 167 : : /**
- 168 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 169 : : */
- 170 : : function _msgSender()
- 171 : : internal
- 172 : : view
- 173 : : override(ERC2771Context, Context)
- 174 : : returns (address sender)
- 175 : : {
- 176 : 588 : return ERC2771Context._msgSender();
- 177 : : }
- 178 : :
- 179 : : /**
- 180 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 181 : : */
- 182 : : function _msgData()
- 183 : : internal
- 184 : : view
- 185 : : override(ERC2771Context, Context)
- 186 : : returns (bytes calldata)
- 187 : : {
- 188 : 0 : return ERC2771Context._msgData();
- 189 : : }
- 190 : :
- 191 : : /**
- 192 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 193 : : */
- 194 : : function _contextSuffixLength()
- 195 : : internal
- 196 : : view
- 197 : : override(ERC2771Context, Context)
- 198 : : returns (uint256)
- 199 : : {
- 200 : 588 : return ERC2771Context._contextSuffixLength();
- 201 : : }
- 202 : : }
+ 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/src/rules/validation/RuleSanctionList.sol.func-sort-c.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html
similarity index 54%
rename from doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html
rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html
index 76ad884..6808037 100644
--- a/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html
+++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - src/rules/validation/RuleSanctionList.sol - functions
+ LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSet.sol - functions
@@ -19,7 +19,7 @@
-
+
@@ -31,26 +31,26 @@
-
-
+
+
-
+
-
-
+
+
-
-
+
+
@@ -65,48 +65,52 @@
diff --git a/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html
similarity index 54%
rename from doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func.html
rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html
index f3eefa0..3ebf795 100644
--- a/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func.html
+++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - src/rules/validation/RuleSanctionList.sol - functions
+ LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSet.sol - functions
@@ -19,7 +19,7 @@
diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html
similarity index 58%
rename from doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html
rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html
index 2cd242c..cded5ef 100644
--- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html
+++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol
-
+ LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSet.sol
+
LCOV - code coverage report
-
+
-
+
@@ -31,18 +31,18 @@
-
-
-
+
+
+
-
+
+
-
-
+
@@ -53,12 +53,12 @@
-
+
-
+
@@ -70,181 +70,170 @@
Branch data Line data Source code
1 : : // SPDX-License-Identifier: MPL-2.0
- 2 : :
- 3 : : pragma solidity ^0.8.20;
- 4 : :
- 5 : : import "OZ/access/AccessControl.sol";
- 6 : : import "./../../../../modules/MetaTxModuleStandalone.sol";
- 7 : : import "./RuleAddressListInternal.sol";
- 8 : : import "./invariantStorage/RuleAddressListInvariantStorage.sol";
- 9 : :
- 10 : : /**
- 11 : : @title an addresses list manager
- 12 : : */
- 13 : :
- 14 : : abstract contract RuleAddressList is
- 15 : : AccessControl,
- 16 : : MetaTxModuleStandalone,
- 17 : : RuleAddressListInternal,
- 18 : : RuleAddressListInvariantStorage
- 19 : : {
- 20 : : // Number of addresses in the list at the moment
- 21 : : uint256 private numAddressesWhitelisted;
- 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(
- 28 : : address admin,
- 29 : : address forwarderIrrevocable
- 30 : : ) MetaTxModuleStandalone(forwarderIrrevocable) {
- 31 [ + ]: 185 : if (admin == address(0)) {
- 32 : 1 : revert RuleAddressList_AdminWithAddressZeroNotAllowed();
- 33 : : }
- 34 : 184 : _grantRole(DEFAULT_ADMIN_ROLE, admin);
- 35 : : }
- 36 : :
- 37 : : /**
- 38 : : * @notice Add addresses to the list
- 39 : : * If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert).
- 40 : : * @param listTargetAddresses an array with the addresses to list
- 41 : : */
- 42 : : function addAddressesToTheList(
- 43 : : address[] calldata listTargetAddresses
- 44 : : ) public onlyRole(ADDRESS_LIST_ADD_ROLE) {
- 45 : 16 : _addAddressesToThelist(listTargetAddresses);
- 46 : 16 : emit AddAddressesToTheList(listTargetAddresses);
- 47 : : }
- 48 : :
- 49 : : /**
- 50 : : * @notice Remove addresses from the list
- 51 : : * If the address does not exist in the list, there is no change for this address.
- 52 : : * The transaction remains valid (no revert).
- 53 : : * @param listTargetAddresses an array with the addresses to remove
- 54 : : */
- 55 : : function removeAddressesFromTheList(
- 56 : : address[] calldata listTargetAddresses
- 57 : : ) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) {
- 58 : 3 : _removeAddressesFromThelist(listTargetAddresses);
- 59 : 3 : emit RemoveAddressesFromTheList(listTargetAddresses);
- 60 : : }
- 61 : :
- 62 : : /**
- 63 : : * @notice Add one address to the list
- 64 : : * If the address already exists, the transaction is reverted to save gas.
- 65 : : * @param targetAddress The address to list
- 66 : : */
- 67 : : function addAddressToTheList(
- 68 : : address targetAddress
- 69 : : ) public onlyRole(ADDRESS_LIST_ADD_ROLE) {
- 70 : 51 : _addAddressToThelist(targetAddress);
- 71 : 50 : emit AddAddressToTheList(targetAddress);
- 72 : : }
- 73 : :
- 74 : : /**
- 75 : : * @notice Remove one address from the list
- 76 : : * If the address does not exist in the list, the transaction is reverted to save gas.
- 77 : : * @param targetAddress The address to remove
- 78 : : *
- 79 : : */
- 80 : : function removeAddressFromTheList(
- 81 : : address targetAddress
- 82 : : ) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) {
- 83 : 2 : _removeAddressFromThelist(targetAddress);
- 84 : 1 : emit RemoveAddressFromTheList(targetAddress);
- 85 : : }
- 86 : :
- 87 : : /**
- 88 : : * @notice Get the number of listed addresses
- 89 : : * @return Number of listed addresses
- 90 : : *
- 91 : : */
- 92 : : function numberListedAddress() public view returns (uint256) {
- 93 : 24 : return _numberListedAddress();
- 94 : : }
- 95 : :
- 96 : : /**
- 97 : : * @notice Know if an address is listed or not
- 98 : : * @param _targetAddress The concerned address
- 99 : : * @return True if the address is listed, false otherwise
- 100 : : *
+ 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 : : //////////////////////////////////////////////////////////////*/
+ 55 : :
+ 56 : : /**
+ 57 : : * @notice Adds multiple addresses to 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.
+ 62 : : */
+ 63 : 17 : function addAddresses(address[] calldata targetAddresses) public onlyRole(ADDRESS_LIST_ADD_ROLE) {
+ 64 : 16 : _addAddresses(targetAddresses);
+ 65 : 16 : emit AddAddresses(targetAddresses);
+ 66 : : }
+ 67 : :
+ 68 : : /**
+ 69 : : * @notice Removes multiple addresses from 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.
+ 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 : : function addressIsListed(
- 103 : : address _targetAddress
- 104 : : ) public view returns (bool) {
- 105 : 159 : return _addressIsListed(_targetAddress);
- 106 : : }
- 107 : :
- 108 : : /**
- 109 : : * @notice batch version of {addressIsListed}
- 110 : : *
- 111 : : */
- 112 : : function addressIsListedBatch(
- 113 : : address[] memory _targetAddresses
- 114 : : ) public view returns (bool[] memory) {
- 115 : 28 : bool[] memory isListed = new bool[](_targetAddresses.length);
- 116 : 28 : for (uint256 i = 0; i < _targetAddresses.length; ++i) {
- 117 : 55 : isListed[i] = _addressIsListed(_targetAddresses[i]);
- 118 : : }
- 119 : 28 : return isListed;
- 120 : : }
- 121 : :
- 122 : : /* ============ ACCESS CONTROL ============ */
- 123 : : /**
- 124 : : * @dev Returns `true` if `account` has been granted `role`.
- 125 : : */
- 126 : : function hasRole(
- 127 : : bytes32 role,
- 128 : : address account
- 129 : : ) public view virtual override(AccessControl) returns (bool) {
- 130 : : // The Default Admin has all roles
- 131 [ + ]: 280 : if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
- 132 : 78 : return true;
- 133 : : }
- 134 : 202 : return AccessControl.hasRole(role, account);
- 135 : : }
- 136 : :
- 137 : : /*//////////////////////////////////////////////////////////////
- 138 : : ERC-2771
- 139 : : //////////////////////////////////////////////////////////////*/
- 140 : :
- 141 : : /**
- 142 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 143 : : */
- 144 : : function _msgSender()
- 145 : : internal
- 146 : : view
- 147 : : override(ERC2771Context, Context)
- 148 : : returns (address sender)
- 149 : : {
- 150 : 270 : return ERC2771Context._msgSender();
- 151 : : }
- 152 : :
- 153 : : /**
- 154 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 155 : : */
- 156 : : function _msgData()
- 157 : : internal
- 158 : : view
- 159 : : override(ERC2771Context, Context)
- 160 : : returns (bytes calldata)
- 161 : : {
- 162 : 0 : return ERC2771Context._msgData();
- 163 : : }
- 164 : :
- 165 : : /**
- 166 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 167 : : */
- 168 : : function _contextSuffixLength()
- 169 : : internal
- 170 : : view
- 171 : : override(ERC2771Context, Context)
- 172 : : returns (uint256)
- 173 : : {
- 174 : 270 : return ERC2771Context._contextSuffixLength();
- 175 : : }
- 176 : : }
+ 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 : : }
+ 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 : : }
@@ -252,7 +241,7 @@
diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func-sort-c.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html
similarity index 57%
rename from doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func-sort-c.html
rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html
index 88c2a09..715669b 100644
--- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func-sort-c.html
+++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - test/RuleConditionalTransfer/utils/RuleCTDeployment.sol - functions
+ LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol - functions
@@ -19,7 +19,7 @@
-
+
@@ -31,17 +31,17 @@
-
-
+
+
-
+
-
-
+
+
@@ -65,12 +65,32 @@
diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html
similarity index 57%
rename from doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func.html
rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html
index ead2a6c..bfbd673 100644
--- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func.html
+++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - test/RuleConditionalTransfer/utils/RuleCTDeployment.sol - functions
+ LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol - functions
@@ -19,7 +19,7 @@
diff --git a/doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html
similarity index 54%
rename from doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html
rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html
index bea5e34..c60105a 100644
--- a/doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html
+++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - src/rules/validation/RuleBlacklist.sol
+ LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol
@@ -19,7 +19,7 @@
-
+
@@ -31,17 +31,17 @@
-
-
+
+
-
+
-
-
+
+
@@ -49,9 +49,9 @@
-
-
-
+
+
+
@@ -70,81 +70,92 @@
Branch data Line data Source code
1 : : // SPDX-License-Identifier: MPL-2.0
- 2 : :
- 3 : : pragma solidity ^0.8.20;
- 4 : :
- 5 : : import "./abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol";
- 6 : : import "./abstract/RuleAddressList/RuleAddressList.sol";
- 7 : : import "./abstract/RuleValidateTransfer.sol";
- 8 : :
- 9 : : /**
- 10 : : * @title a blacklist manager
- 11 : : */
- 12 : :
- 13 : : contract RuleBlacklist is
- 14 : : RuleValidateTransfer,
- 15 : : RuleAddressList,
- 16 : : RuleBlacklistInvariantStorage
- 17 : : {
- 18 : : /**
- 19 : : * @param admin Address of the contract (Access Control)
- 20 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
- 21 : : */
- 22 : : constructor(
- 23 : : address admin,
- 24 : : address forwarderIrrevocable
- 25 : : ) RuleAddressList(admin, forwarderIrrevocable) {}
- 26 : :
- 27 : : /**
- 28 : : * @notice Check if an addres is in the whitelist or not
- 29 : : * @param _from the origin address
- 30 : : * @param _to the destination address
- 31 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
- 32 : : **/
- 33 : : function detectTransferRestriction(
- 34 : : address _from,
- 35 : : address _to,
- 36 : : uint256 /*_amount */
- 37 : : ) public view override returns (uint8) {
- 38 [ + + ]: 10 : if (addressIsListed(_from)) {
- 39 : 5 : return CODE_ADDRESS_FROM_IS_BLACKLISTED;
- 40 [ + + ]: 5 : } else if (addressIsListed(_to)) {
- 41 : 2 : return CODE_ADDRESS_TO_IS_BLACKLISTED;
- 42 : : } else {
- 43 : 3 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- 44 : : }
- 45 : : }
- 46 : :
- 47 : : /**
- 48 : : * @notice To know if the restriction code is valid for this rule or not.
- 49 : : * @param _restrictionCode The target restriction code
- 50 : : * @return true if the restriction code is known, false otherwise
- 51 : : **/
- 52 : : function canReturnTransferRestrictionCode(
- 53 : : uint8 _restrictionCode
- 54 : : ) external pure override returns (bool) {
- 55 : 4 : return
- 56 : 4 : _restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED ||
- 57 : 2 : _restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED;
- 58 : : }
- 59 : :
- 60 : : /**
- 61 : : * @notice Return the corresponding message
- 62 : : * @param _restrictionCode The target restriction code
- 63 : : * @return true if the transfer is valid, false otherwise
- 64 : : **/
- 65 : : function messageForTransferRestriction(
- 66 : : uint8 _restrictionCode
- 67 : : ) external pure override returns (string memory) {
- 68 [ + + ]: 4 : if (_restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED) {
- 69 : 2 : return TEXT_ADDRESS_FROM_IS_BLACKLISTED;
- 70 [ + + ]: 2 : } else if (_restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED) {
- 71 : 1 : return TEXT_ADDRESS_TO_IS_BLACKLISTED;
- 72 : : } else {
- 73 : 1 : return TEXT_CODE_NOT_FOUND;
- 74 : : }
- 75 : : }
- 76 : : }
+ 2 : : pragma solidity ^0.8.20;
+ 3 : :
+ 4 : : /* ==== OpenZeppelin === */
+ 5 : : import {EnumerableSet} from "OZ/utils/structs/EnumerableSet.sol";
+ 6 : :
+ 7 : : /**
+ 8 : : * @title Rule Address Set (Internal)
+ 9 : : * @notice Internal utility for managing a set of rule-related addresses.
+ 10 : : * @dev
+ 11 : : * - Uses OpenZeppelin's EnumerableSet for efficient enumeration.
+ 12 : : * - Designed for internal inheritance and logic composition.
+ 13 : : * - Batch operations do not revert when individual entries are invalid.
+ 14 : : */
+ 15 : : abstract contract RuleAddressSetInternal {
+ 16 : : using EnumerableSet for EnumerableSet.AddressSet;
+ 17 : :
+ 18 : : /*//////////////////////////////////////////////////////////////
+ 19 : : STATE VARIABLES
+ 20 : : //////////////////////////////////////////////////////////////*/
+ 21 : :
+ 22 : : /// @dev Storage for all listed addresses.
+ 23 : : EnumerableSet.AddressSet private _listedAddresses;
+ 24 : :
+ 25 : : /*//////////////////////////////////////////////////////////////
+ 26 : : INTERNAL
+ 27 : : //////////////////////////////////////////////////////////////*/
+ 28 : :
+ 29 : : /**
+ 30 : : * @notice Adds multiple addresses to the set.
+ 31 : : * @dev
+ 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 : : }
diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-b.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html
similarity index 71%
rename from doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-b.html
rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html
index 273564b..fe9d655 100644
--- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-b.html
+++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - test/RuleConditionalTransfer/utils
+ LCOV - lcov.info - validation/abstract/RuleAddressSet
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,17 +82,29 @@
Branches
- RuleCTDeployment.sol
+ RuleAddressSetInternal.sol
100.0 %
- 10 / 10
+ 14 / 14
100.0 %
- 1 / 1
+ 6 / 6
-
0 / 0
+
+ RuleAddressSet.sol
+
+
+
+ 87.5 %
+ 28 / 32
+ 81.8 %
+ 9 / 11
+ 100.0 %
+ 2 / 2
+
diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-f.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html
similarity index 71%
rename from doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-f.html
rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html
index cfa53fa..b79046b 100644
--- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-f.html
+++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - test/RuleConditionalTransfer/utils
+ LCOV - lcov.info - validation/abstract/RuleAddressSet
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,14 +82,26 @@
Branches
- RuleCTDeployment.sol
+ RuleAddressSet.sol
+
+
+
+ 87.5 %
+ 28 / 32
+ 81.8 %
+ 9 / 11
+ 100.0 %
+ 2 / 2
+
+
+ RuleAddressSetInternal.sol
100.0 %
- 10 / 10
+ 14 / 14
100.0 %
- 1 / 1
+ 6 / 6
-
0 / 0
diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-l.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html
similarity index 71%
rename from doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-l.html
rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html
index 8cfb2ca..7506cec 100644
--- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-l.html
+++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - test/RuleConditionalTransfer/utils
+ LCOV - lcov.info - validation/abstract/RuleAddressSet
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,14 +82,26 @@
Branches
- RuleCTDeployment.sol
+ RuleAddressSet.sol
+
+
+
+ 87.5 %
+ 28 / 32
+ 81.8 %
+ 9 / 11
+ 100.0 %
+ 2 / 2
+
+
+ RuleAddressSetInternal.sol
100.0 %
- 10 / 10
+ 14 / 14
100.0 %
- 1 / 1
+ 6 / 6
-
0 / 0
diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html
similarity index 71%
rename from doc/coverage/coverage/test/RuleConditionalTransfer/utils/index.html
rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html
index 0fb4392..4c0f604 100644
--- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index.html
+++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - test/RuleConditionalTransfer/utils
+ LCOV - lcov.info - validation/abstract/RuleAddressSet
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,14 +82,26 @@
Branches
- RuleCTDeployment.sol
+ RuleAddressSet.sol
+
+
+
+ 87.5 %
+ 28 / 32
+ 81.8 %
+ 9 / 11
+ 100.0 %
+ 2 / 2
+
+
+ RuleAddressSetInternal.sol
100.0 %
- 10 / 10
+ 14 / 14
100.0 %
- 1 / 1
+ 6 / 6
-
0 / 0
diff --git a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html
similarity index 63%
rename from doc/coverage/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html
rename to doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html
index 32ca64b..93f72fb 100644
--- a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html
+++ b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - test/utils/SanctionListOracle.sol - functions
+ LCOV - lcov.info - validation/abstract/RuleValidateTransfer.sol - functions
@@ -19,7 +19,7 @@
-
+
@@ -31,18 +31,18 @@
-
-
-
+
+
+
-
+
-
-
+
+
@@ -65,24 +65,28 @@
diff --git a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.func.html b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html
similarity index 63%
rename from doc/coverage/coverage/test/utils/SanctionListOracle.sol.func.html
rename to doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html
index 12d4508..f811a3f 100644
--- a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.func.html
+++ b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - test/utils/SanctionListOracle.sol - functions
+ LCOV - lcov.info - validation/abstract/RuleValidateTransfer.sol - functions
@@ -19,7 +19,7 @@
diff --git a/doc/coverage/coverage/src/modules/RuleInternal.sol.gcov.html b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html
similarity index 50%
rename from doc/coverage/coverage/src/modules/RuleInternal.sol.gcov.html
rename to doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html
index cd50bce..174dc57 100644
--- a/doc/coverage/coverage/src/modules/RuleInternal.sol.gcov.html
+++ b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - src/modules/RuleInternal.sol
+ LCOV - lcov.info - validation/abstract/RuleValidateTransfer.sol
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
+
+
-
-
-
+
+
+
@@ -72,102 +72,88 @@
1 : : // SPDX-License-Identifier: MPL-2.0
2 : :
3 : : pragma solidity ^0.8.20;
- 4 : : import "./RuleEngineInvariantStorage.sol";
- 5 : :
- 6 : : /**
- 7 : : * @title Implementation of a ruleEngine defined by the CMTAT
- 8 : : */
- 9 : : abstract contract RuleInternal is RuleEngineInvariantStorage {
- 10 : : /// @dev Indicate if a rule already exists
- 11 : : // Can be shared betwen RuleOperation and RuleValidation since it is a mapping
- 12 : : mapping(address => bool) _ruleIsPresent;
- 13 : :
- 14 : : /**
- 15 : : * @notice Set all the rules, will overwrite all the previous rules. \n
- 16 : : * Revert if one rule is a zero address or if the rule is already present
- 17 : : *
- 18 : : */
- 19 : : function _setRules(address[] calldata rules_) internal {
- 20 [ + ]: 32 : if (rules_.length == 0) {
- 21 : 2 : revert RuleEngine_ArrayIsEmpty();
- 22 : : }
- 23 : 30 : for (uint256 i = 0; i < rules_.length; ) {
- 24 [ + ]: 48 : if (address(rules_[i]) == address(0x0)) {
- 25 : 2 : revert RuleEngine_RuleAddressZeroNotAllowed();
- 26 : : }
- 27 [ + ]: 2 : if (_ruleIsPresent[rules_[i]]) {
- 28 : 2 : revert RuleEngine_RuleAlreadyExists();
- 29 : : }
- 30 : 44 : _ruleIsPresent[rules_[i]] = true;
- 31 : 44 : emit AddRule(rules_[i]);
- 32 : : unchecked {
- 33 : 44 : ++i;
- 34 : : }
- 35 : : }
- 36 : : }
- 37 : :
- 38 : : /**
- 39 : : * @notice Add a rule to the array of rules
- 40 : : * Revert if one rule is a zero address or if the rule is already present
- 41 : : *
- 42 : : */
- 43 : : function _addRule(address[] storage _rules, address rule_) internal {
- 44 [ + ]: 203 : if (address(rule_) == address(0x0)) {
- 45 : 2 : revert RuleEngine_RuleAddressZeroNotAllowed();
- 46 : : }
- 47 [ + ]: 2 : if (_ruleIsPresent[rule_]) {
- 48 : 2 : revert RuleEngine_RuleAlreadyExists();
- 49 : : }
- 50 : 199 : _rules.push(rule_);
- 51 : 199 : _ruleIsPresent[rule_] = true;
- 52 : : }
- 53 : :
- 54 : : /**
- 55 : : * @notice Remove a rule from the array of rules
- 56 : : * Revert if the rule found at the specified index does not match the rule in argument
- 57 : : * @param rule_ address of the target rule
- 58 : : * @param index the position inside the array of rule
- 59 : : * @dev To reduce the array size, the last rule is moved to the location occupied
- 60 : : * by the rule to remove
- 61 : : *
- 62 : : *
- 63 : : */
- 64 : : function _removeRule(
- 65 : : address[] storage _rules,
- 66 : : address rule_,
- 67 : : uint256 index
- 68 : : ) internal {
- 69 [ + ]: 55 : if (_rules[index] != rule_) {
- 70 : 2 : revert RuleEngine_RuleDoNotMatch();
- 71 : : }
- 72 [ + ]: 53 : if (index != _rules.length - 1) {
- 73 : 4 : _rules[index] = _rules[_rules.length - 1];
- 74 : : }
- 75 : 53 : _rules.pop();
- 76 : 53 : _ruleIsPresent[rule_] = false;
- 77 : 53 : emit RemoveRule(rule_);
- 78 : : }
- 79 : :
- 80 : : /**
- 81 : : * @notice Get the index of a rule inside the list
- 82 : : * @return index if the rule is found, _rules.length otherwise
- 83 : : */
- 84 : : function _getRuleIndex(
- 85 : : address[] storage _rules,
- 86 : : address rule_
- 87 : : ) internal view returns (uint256 index) {
- 88 : 6 : uint256 rulesLength = _rules.length;
- 89 : 6 : for (index = 0; index < rulesLength; ) {
- 90 [ + ]: 10 : if (_rules[index] == rule_) {
- 91 : 4 : return index;
- 92 : : }
- 93 : : unchecked {
- 94 : 6 : ++index;
- 95 : : }
- 96 : : }
- 97 : 2 : return _rules.length;
- 98 : : }
- 99 : : }
+ 4 : :
+ 5 : : /* ==== CMTAT === */
+ 6 : : import {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);
+ 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;
+ 84 : : }
+ 85 : : }
diff --git a/doc/coverage/coverage/src/modules/RuleInternal.sol.func-sort-c.html b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html
similarity index 57%
rename from doc/coverage/coverage/src/modules/RuleInternal.sol.func-sort-c.html
rename to doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html
index 7456c15..bf6dc6f 100644
--- a/doc/coverage/coverage/src/modules/RuleInternal.sol.func-sort-c.html
+++ b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - src/modules/RuleInternal.sol - functions
+ LCOV - lcov.info - validation/abstract/RuleWhitelistCommon.sol - functions
@@ -19,7 +19,7 @@
-
+
@@ -31,17 +31,17 @@
-
-
+
+
-
+
-
-
+
+
@@ -49,8 +49,8 @@
-
-
+
+
@@ -65,24 +65,32 @@
diff --git a/doc/coverage/coverage/src/modules/RuleInternal.sol.func.html b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html
similarity index 58%
rename from doc/coverage/coverage/src/modules/RuleInternal.sol.func.html
rename to doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html
index 239df15..2fda202 100644
--- a/doc/coverage/coverage/src/modules/RuleInternal.sol.func.html
+++ b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - src/modules/RuleInternal.sol - functions
+ LCOV - lcov.info - validation/abstract/RuleWhitelistCommon.sol - functions
@@ -19,7 +19,7 @@
diff --git a/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.gcov.html b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html
similarity index 50%
rename from doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.gcov.html
rename to doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html
index 497bf06..746edeb 100644
--- a/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.gcov.html
+++ b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html
@@ -4,22 +4,22 @@
- LCOV - lcov.info - src/rules/validation/RuleWhitelistWrapper.sol
-
+ LCOV - lcov.info - validation/abstract/RuleWhitelistCommon.sol
+
LCOV - code coverage report
-
+
-
+
@@ -31,34 +31,34 @@
-
-
-
+
+
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
@@ -70,135 +70,128 @@
Branch data Line data Source code
1 : : // SPDX-License-Identifier: MPL-2.0
- 2 : :
- 3 : : pragma solidity ^0.8.20;
- 4 : :
- 5 : : import "OZ/access/AccessControl.sol";
- 6 : : import "../../modules/RuleEngineValidationCommon.sol";
- 7 : : import "../../modules/MetaTxModuleStandalone.sol";
- 8 : : import "./abstract/RuleAddressList/RuleAddressList.sol";
- 9 : : import "./abstract/RuleWhitelistCommon.sol";
- 10 : :
- 11 : : /**
- 12 : : * @title Wrapper to call several different whitelist rules
- 13 : : */
- 14 : : contract RuleWhitelistWrapper is
- 15 : : RuleEngineValidationCommon,
- 16 : : MetaTxModuleStandalone,
- 17 : : RuleWhitelistCommon
- 18 : : {
- 19 : : /**
- 20 : : * @param admin Address of the contract (Access Control)
- 21 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
- 22 : : */
- 23 : : constructor(
- 24 : : address admin,
- 25 : : address forwarderIrrevocable
- 26 : : ) MetaTxModuleStandalone(forwarderIrrevocable) {
- 27 [ + ]: 14 : if (admin == address(0)) {
- 28 : 1 : revert RuleEngine_AdminWithAddressZeroNotAllowed();
- 29 : : }
- 30 : 13 : _grantRole(DEFAULT_ADMIN_ROLE, admin);
- 31 : : }
- 32 : :
- 33 : : /**
- 34 : : * @notice Go through all the whitelist rules to know if a restriction exists on the transfer
- 35 : : * @param _from the origin address
- 36 : : * @param _to the destination address
- 37 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
- 38 : : **/
- 39 : : function detectTransferRestriction(
- 40 : : address _from,
- 41 : : address _to,
- 42 : : uint256 /*_amount*/
- 43 : : ) public view override returns (uint8) {
- 44 : 11 : address[] memory targetAddress = new address[](2);
- 45 : 11 : bool[] memory isListed = new bool[](2);
- 46 : 11 : bool[] memory result = new bool[](2);
- 47 : 11 : targetAddress[0] = _from;
- 48 : 11 : targetAddress[1] = _to;
- 49 : 11 : uint256 rulesLength = _rulesValidation.length;
- 50 : : // For each whitelist rule, we ask if from or to are in the whitelist
- 51 : 11 : for (uint256 i = 0; i < rulesLength; ++i) {
- 52 : : // External call
- 53 : 25 : isListed = RuleAddressList(_rulesValidation[i])
- 54 : : .addressIsListedBatch(targetAddress);
- 55 [ + ]: 25 : if (isListed[0] && !result[0]) {
- 56 : : // Update if from is in the list
- 57 : 7 : result[0] = true;
- 58 : : }
- 59 [ + ]: 25 : if (isListed[1] && !result[1]) {
- 60 : : // Update if to is in the list
- 61 : 7 : result[1] = true;
- 62 : : }
- 63 [ + ]: 25 : if (result[0] && result[1]) {
- 64 : 25 : break;
- 65 : : }
- 66 : : }
- 67 [ + + ]: 11 : if (!result[0]) {
- 68 : 4 : return CODE_ADDRESS_FROM_NOT_WHITELISTED;
- 69 [ + + ]: 7 : } else if (!result[1]) {
- 70 : 2 : return CODE_ADDRESS_TO_NOT_WHITELISTED;
- 71 : : } else {
- 72 : 5 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- 73 : : }
- 74 : : }
- 75 : :
- 76 : : /* ============ ACCESS CONTROL ============ */
- 77 : : /**
- 78 : : * @dev Returns `true` if `account` has been granted `role`.
- 79 : : */
- 80 : : function hasRole(
- 81 : : bytes32 role,
- 82 : : address account
- 83 : : ) public view virtual override(AccessControl) returns (bool) {
- 84 : : // The Default Admin has all roles
- 85 [ + ]: 52 : if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
- 86 : 39 : return true;
- 87 : : }
- 88 : 13 : return AccessControl.hasRole(role, account);
- 89 : : }
- 90 : :
- 91 : : /*//////////////////////////////////////////////////////////////
- 92 : : ERC-2771
- 93 : : //////////////////////////////////////////////////////////////*/
- 94 : :
- 95 : : /**
- 96 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 97 : : */
- 98 : : function _msgSender()
- 99 : : internal
- 100 : : view
- 101 : : override(ERC2771Context, Context)
- 102 : : returns (address sender)
- 103 : : {
- 104 : 52 : return ERC2771Context._msgSender();
- 105 : : }
- 106 : :
- 107 : : /**
- 108 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 109 : : */
- 110 : : function _msgData()
- 111 : : internal
- 112 : : view
- 113 : : override(ERC2771Context, Context)
- 114 : : returns (bytes calldata)
- 115 : : {
- 116 : 0 : return ERC2771Context._msgData();
- 117 : : }
- 118 : :
- 119 : : /**
- 120 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 121 : : */
- 122 : : function _contextSuffixLength()
- 123 : : internal
- 124 : : view
- 125 : : override(ERC2771Context, Context)
- 126 : : returns (uint256)
- 127 : : {
- 128 : 52 : return ERC2771Context._contextSuffixLength();
- 129 : : }
- 130 : : }
+ 2 : : pragma solidity ^0.8.20;
+ 3 : :
+ 4 : : /* ==== CMTAT === */
+ 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);
+ 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 : : }
@@ -206,7 +199,7 @@
diff --git a/doc/coverage/coverage/test/utils/index-sort-b.html b/doc/coverage/coverage/validation/abstract/index-sort-b.html
similarity index 73%
rename from doc/coverage/coverage/test/utils/index-sort-b.html
rename to doc/coverage/coverage/validation/abstract/index-sort-b.html
index 500c424..5fe0919 100644
--- a/doc/coverage/coverage/test/utils/index-sort-b.html
+++ b/doc/coverage/coverage/validation/abstract/index-sort-b.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - test/utils
+ LCOV - lcov.info - validation/abstract
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,28 +82,28 @@
Branches
- CMTATDeployment.sol
+ RuleValidateTransfer.sol
-
+
- 100.0 %
- 4 / 4
- 100.0 %
- 1 / 1
+ 80.0 %
+ 8 / 10
+ 80.0 %
+ 4 / 5
-
0 / 0
- SanctionListOracle.sol
+ RuleWhitelistCommon.sol
-
+
- 66.7 %
- 2 / 3
- 75.0 %
- 3 / 4
- -
- 0 / 0
+ 100.0 %
+ 21 / 21
+ 100.0 %
+ 6 / 6
+ 100.0 %
+ 10 / 10
diff --git a/doc/coverage/coverage/test/utils/index-sort-f.html b/doc/coverage/coverage/validation/abstract/index-sort-f.html
similarity index 73%
rename from doc/coverage/coverage/test/utils/index-sort-f.html
rename to doc/coverage/coverage/validation/abstract/index-sort-f.html
index ff0b711..b7e1816 100644
--- a/doc/coverage/coverage/test/utils/index-sort-f.html
+++ b/doc/coverage/coverage/validation/abstract/index-sort-f.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - test/utils
+ LCOV - lcov.info - validation/abstract
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,28 +82,28 @@
Branches
- SanctionListOracle.sol
+ RuleValidateTransfer.sol
-
+
- 66.7 %
- 2 / 3
- 75.0 %
- 3 / 4
+ 80.0 %
+ 8 / 10
+ 80.0 %
+ 4 / 5
-
0 / 0
- CMTATDeployment.sol
+ RuleWhitelistCommon.sol
100.0 %
- 4 / 4
+ 21 / 21
100.0 %
- 1 / 1
- -
- 0 / 0
+ 6 / 6
+ 100.0 %
+ 10 / 10
diff --git a/doc/coverage/coverage/test/utils/index-sort-l.html b/doc/coverage/coverage/validation/abstract/index-sort-l.html
similarity index 73%
rename from doc/coverage/coverage/test/utils/index-sort-l.html
rename to doc/coverage/coverage/validation/abstract/index-sort-l.html
index b1f3e52..f752721 100644
--- a/doc/coverage/coverage/test/utils/index-sort-l.html
+++ b/doc/coverage/coverage/validation/abstract/index-sort-l.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - test/utils
+ LCOV - lcov.info - validation/abstract
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,28 +82,28 @@
Branches
- SanctionListOracle.sol
+ RuleValidateTransfer.sol
-
+
- 66.7 %
- 2 / 3
- 75.0 %
- 3 / 4
+ 80.0 %
+ 8 / 10
+ 80.0 %
+ 4 / 5
-
0 / 0
- CMTATDeployment.sol
+ RuleWhitelistCommon.sol
100.0 %
- 4 / 4
+ 21 / 21
100.0 %
- 1 / 1
- -
- 0 / 0
+ 6 / 6
+ 100.0 %
+ 10 / 10
diff --git a/doc/coverage/coverage/test/utils/index.html b/doc/coverage/coverage/validation/abstract/index.html
similarity index 73%
rename from doc/coverage/coverage/test/utils/index.html
rename to doc/coverage/coverage/validation/abstract/index.html
index 0cb6aec..34817f4 100644
--- a/doc/coverage/coverage/test/utils/index.html
+++ b/doc/coverage/coverage/validation/abstract/index.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - test/utils
+ LCOV - lcov.info - validation/abstract
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,28 +82,28 @@
Branches
- CMTATDeployment.sol
+ RuleValidateTransfer.sol
-
+
- 100.0 %
- 4 / 4
- 100.0 %
- 1 / 1
+ 80.0 %
+ 8 / 10
+ 80.0 %
+ 4 / 5
-
0 / 0
- SanctionListOracle.sol
+ RuleWhitelistCommon.sol
-
+
- 66.7 %
- 2 / 3
- 75.0 %
- 3 / 4
- -
- 0 / 0
+ 100.0 %
+ 21 / 21
+ 100.0 %
+ 6 / 6
+ 100.0 %
+ 10 / 10
diff --git a/doc/coverage/coverage/src/index-sort-b.html b/doc/coverage/coverage/validation/index-sort-b.html
similarity index 53%
rename from doc/coverage/coverage/src/index-sort-b.html
rename to doc/coverage/coverage/validation/index-sort-b.html
index 576ca6d..944c1e9 100644
--- a/doc/coverage/coverage/src/index-sort-b.html
+++ b/doc/coverage/coverage/validation/index-sort-b.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - src
+ LCOV - lcov.info - validation
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,16 +82,52 @@
Branches
- RuleEngine.sol
+ 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
-
+
- 97.4 %
- 38 / 39
- 88.9 %
- 8 / 9
+ 92.6 %
+ 50 / 54
+ 88.2 %
+ 15 / 17
100.0 %
- 8 / 8
+ 18 / 18
diff --git a/doc/coverage/coverage/src/index-sort-f.html b/doc/coverage/coverage/validation/index-sort-f.html
similarity index 53%
rename from doc/coverage/coverage/src/index-sort-f.html
rename to doc/coverage/coverage/validation/index-sort-f.html
index 8962246..803ea1c 100644
--- a/doc/coverage/coverage/src/index-sort-f.html
+++ b/doc/coverage/coverage/validation/index-sort-f.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - src
+ LCOV - lcov.info - validation
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,16 +82,52 @@
Branches
- RuleEngine.sol
+ 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
-
+
- 97.4 %
- 38 / 39
- 88.9 %
- 8 / 9
+ 94.6 %
+ 35 / 37
+ 90.9 %
+ 10 / 11
100.0 %
- 8 / 8
+ 16 / 16
diff --git a/doc/coverage/coverage/src/index-sort-l.html b/doc/coverage/coverage/validation/index-sort-l.html
similarity index 53%
rename from doc/coverage/coverage/src/index-sort-l.html
rename to doc/coverage/coverage/validation/index-sort-l.html
index f6e4883..b4d9395 100644
--- a/doc/coverage/coverage/src/index-sort-l.html
+++ b/doc/coverage/coverage/validation/index-sort-l.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - src
+ LCOV - lcov.info - validation
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,16 +82,52 @@
Branches
- RuleEngine.sol
+ 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
-
+
- 97.4 %
- 38 / 39
- 88.9 %
- 8 / 9
+ 94.6 %
+ 35 / 37
+ 90.9 %
+ 10 / 11
100.0 %
- 8 / 8
+ 16 / 16
diff --git a/doc/coverage/coverage/src/index.html b/doc/coverage/coverage/validation/index.html
similarity index 53%
rename from doc/coverage/coverage/src/index.html
rename to doc/coverage/coverage/validation/index.html
index 0762168..bffbd19 100644
--- a/doc/coverage/coverage/src/index.html
+++ b/doc/coverage/coverage/validation/index.html
@@ -4,7 +4,7 @@
- LCOV - lcov.info - src
+ LCOV - lcov.info - validation
@@ -19,7 +19,7 @@
-
+
@@ -31,27 +31,27 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -82,16 +82,52 @@
Branches
- RuleEngine.sol
+ 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
-
+
- 97.4 %
- 38 / 39
- 88.9 %
- 8 / 9
+ 80.0 %
+ 16 / 20
+ 71.4 %
+ 5 / 7
100.0 %
- 8 / 8
+ 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 a4e6aaf..3c88298 100644
--- a/doc/coverage/lcov.info
+++ b/doc/coverage/lcov.info
@@ -1,1091 +1,554 @@
TN:
-SF:script/CMTATWithRuleEngineScript.s.sol
-FN:15,CMTATWithRuleEngineScript.run
-FNDA:0,CMTATWithRuleEngineScript.run
-DA:17,0
-DA:18,0
-DA:19,0
-DA:20,0
-DA:22,0
-DA:23,0
-DA:24,0
-DA:26,0
-DA:30,0
-DA:32,0
-DA:37,0
-DA:38,0
-DA:39,0
-DA:41,0
-FNF:1
-FNH:0
-LF:14
-LH:0
-BRF:0
-BRH:0
-end_of_record
-TN:
-SF:script/RuleEngineScript.s.sol
-FN:16,RuleEngineScript.run
-FNDA:0,RuleEngineScript.run
-DA:18,0
-DA:19,0
-DA:20,0
-DA:21,0
-DA:23,0
-DA:24,0
-DA:26,0
-DA:27,0
-DA:28,0
-DA:30,0
-DA:33,0
-BRDA:33,0,0,-
-BRDA:33,0,1,-
-DA:34,0
-FNF:1
-FNH:0
-LF:12
-LH:0
-BRF:2
-BRH:0
-end_of_record
-TN:
-SF:src/RuleEngine.sol
-FN:29,RuleEngine.
-FNDA:205,RuleEngine.
-DA:34,205
-BRDA:34,0,0,1
-DA:35,1
-DA:37,204
-BRDA:37,1,0,86
-DA:38,86
-DA:40,204
-FN:50,RuleEngine.detectTransferRestriction
-FNDA:20,RuleEngine.detectTransferRestriction
-DA:56,32
-DA:61,32
-BRDA:61,2,0,15
-DA:62,15
-DA:66,17
-DA:67,17
-DA:68,12
-DA:70,12
-BRDA:70,3,0,11
-DA:71,11
-DA:75,6
-FN:85,RuleEngine.validateTransfer
-FNDA:12,RuleEngine.validateTransfer
-DA:90,12
-DA:91,12
-FN:100,RuleEngine.messageForTransferRestriction
-FNDA:18,RuleEngine.messageForTransferRestriction
-DA:104,18
-DA:105,18
-DA:107,13
-DA:109,10
-BRDA:109,4,0,10
-DA:110,10
-DA:111,10
-DA:116,8
-DA:117,8
-DA:119,2
-DA:121,1
-BRDA:121,5,0,1
-DA:122,1
-DA:123,1
-DA:127,7
-FN:133,RuleEngine.operateOnTransfer
-FNDA:69,RuleEngine.operateOnTransfer
-DA:140,68
-DA:141,10
-BRDA:141,6,0,10
-DA:142,10
-DA:145,58
-FN:152,RuleEngine.hasRole
-FNDA:299,RuleEngine.hasRole
-DA:157,597
-BRDA:157,7,0,220
-DA:158,220
-DA:160,377
-FN:170,RuleEngine._msgSender
-FNDA:588,RuleEngine._msgSender
-DA:176,588
-FN:182,RuleEngine._msgData
-FNDA:0,RuleEngine._msgData
-DA:188,0
-FN:194,RuleEngine._contextSuffixLength
-FNDA:588,RuleEngine._contextSuffixLength
-DA:200,588
-FNF:9
-FNH:8
-LF:39
-LH:38
-BRF:8
-BRH:8
-end_of_record
-TN:
-SF:src/modules/MetaTxModuleStandalone.sol
-FN:11,MetaTxModuleStandalone.
-FNDA:575,MetaTxModuleStandalone.
-FNF:1
-FNH:1
-LF:0
-LH:0
-BRF:0
-BRH:0
-end_of_record
-TN:
-SF:src/modules/RuleEngineOperation.sol
-FN:26,RuleEngineOperation.setRulesOperation
-FNDA:11,RuleEngineOperation.setRulesOperation
-DA:29,11
-BRDA:29,0,0,10
-DA:30,10
-DA:32,11
-DA:33,8
-FN:40,RuleEngineOperation.clearRulesOperation
-FNDA:4,RuleEngineOperation.clearRulesOperation
-DA:41,4
-FN:48,RuleEngineOperation._clearRulesOperation
-FNDA:14,RuleEngineOperation._clearRulesOperation
-DA:49,14
-DA:51,14
-DA:54,17
-DA:56,17
-DA:58,14
-FN:66,RuleEngineOperation.addRuleOperation
-FNDA:85,RuleEngineOperation.addRuleOperation
-DA:69,85
-DA:70,83
-FN:83,RuleEngineOperation.removeRuleOperation
-FNDA:5,RuleEngineOperation.removeRuleOperation
-DA:87,5
-FN:100,RuleEngineOperation._removeRuleOperation
-FNDA:22,RuleEngineOperation._removeRuleOperation
-DA:101,22
-DA:102,21
-FN:108,RuleEngineOperation.rulesCountOperation
-FNDA:41,RuleEngineOperation.rulesCountOperation
-DA:109,41
-FN:116,RuleEngineOperation.getRuleIndexOperation
-FNDA:3,RuleEngineOperation.getRuleIndexOperation
-DA:119,3
-FN:127,RuleEngineOperation.ruleOperation
-FNDA:1,RuleEngineOperation.ruleOperation
-DA:130,1
-FN:137,RuleEngineOperation.rulesOperation
-FNDA:5,RuleEngineOperation.rulesOperation
-DA:143,5
-FN:152,RuleEngineOperation._operateOnTransfer
-FNDA:58,RuleEngineOperation._operateOnTransfer
-DA:157,58
-DA:158,58
-DA:159,50
-DA:164,50
-BRDA:164,1,0,24
-DA:165,24
-DA:168,34
-FNF:11
-FNH:11
-LF:25
-LH:25
-BRF:2
-BRH:2
-end_of_record
-TN:
-SF:src/modules/RuleEngineValidation.sol
-FN:29,RuleEngineValidation.detectTransferRestrictionValidation
-FNDA:3,RuleEngineValidation.detectTransferRestrictionValidation
-DA:34,105
-DA:35,105
-DA:36,43
-DA:38,43
-BRDA:38,0,0,28
-DA:39,28
-DA:43,77
-FN:53,RuleEngineValidation.validateTransferValidation
-FNDA:2,RuleEngineValidation.validateTransferValidation
-DA:58,70
-DA:59,70
+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
+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
FNF:2
FNH:2
LF:8
LH:8
-BRF:1
-BRH:1
+BRF:3
+BRH:3
end_of_record
TN:
-SF:src/modules/RuleEngineValidationCommon.sol
-FN:30,RuleEngineValidationCommon.setRulesValidation
-FNDA:22,RuleEngineValidationCommon.setRulesValidation
-DA:33,21
-BRDA:33,0,0,20
-DA:34,20
-DA:36,21
-DA:37,18
-FN:44,RuleEngineValidationCommon.clearRulesValidation
-FNDA:6,RuleEngineValidationCommon.clearRulesValidation
-DA:45,5
-FN:53,RuleEngineValidationCommon.addRuleValidation
-FNDA:119,RuleEngineValidationCommon.addRuleValidation
-DA:56,118
-DA:57,116
-FN:70,RuleEngineValidationCommon.removeRuleValidation
-FNDA:6,RuleEngineValidationCommon.removeRuleValidation
-DA:74,5
-FN:80,RuleEngineValidationCommon.rulesCountValidation
-FNDA:69,RuleEngineValidationCommon.rulesCountValidation
-DA:81,69
-FN:88,RuleEngineValidationCommon.getRuleIndexValidation
-FNDA:3,RuleEngineValidationCommon.getRuleIndexValidation
-DA:91,3
-FN:99,RuleEngineValidationCommon.ruleValidation
-FNDA:1,RuleEngineValidationCommon.ruleValidation
-DA:102,1
-FN:109,RuleEngineValidationCommon.rulesValidation
-FNDA:5,RuleEngineValidationCommon.rulesValidation
-DA:115,5
-FN:125,RuleEngineValidationCommon._clearRulesValidation
-FNDA:25,RuleEngineValidationCommon._clearRulesValidation
-DA:126,25
-DA:128,25
-DA:131,28
-DA:133,28
-DA:135,25
-FN:148,RuleEngineValidationCommon._removeRuleValidation
-FNDA:33,RuleEngineValidationCommon._removeRuleValidation
-DA:149,33
-DA:150,32
-FNF:10
-FNH:10
-LF:19
-LH:19
-BRF:1
-BRH:1
-end_of_record
-TN:
-SF:src/modules/RuleInternal.sol
-FN:19,RuleInternal._setRules
-FNDA:32,RuleInternal._setRules
-DA:20,32
-BRDA:20,0,0,2
-DA:21,2
-DA:23,30
-DA:24,48
-BRDA:24,1,0,2
-DA:25,2
-DA:27,2
-BRDA:27,2,0,2
-DA:28,2
-DA:30,44
-DA:31,44
-DA:33,44
-FN:43,RuleInternal._addRule
-FNDA:203,RuleInternal._addRule
-DA:44,203
-BRDA:44,3,0,2
-DA:45,2
-DA:47,2
-BRDA:47,4,0,2
-DA:48,2
-DA:50,199
-DA:51,199
-FN:64,RuleInternal._removeRule
-FNDA:55,RuleInternal._removeRule
-DA:69,55
-BRDA:69,5,0,2
-DA:70,2
-DA:72,53
-BRDA:72,6,0,4
-DA:73,4
-DA:75,53
-DA:76,53
-DA:77,53
-FN:84,RuleInternal._getRuleIndex
-FNDA:6,RuleInternal._getRuleIndex
-DA:88,6
-DA:89,6
-DA:90,10
-BRDA:90,7,0,4
-DA:91,4
-DA:94,6
-DA:97,2
-FNF:4
-FNH:4
-LF:29
-LH:29
-BRF:8
-BRH:8
-end_of_record
-TN:
-SF:src/rules/operation/RuleConditionalTransfer.sol
-FN:27,RuleConditionalTransfer.
-FNDA:158,RuleConditionalTransfer.
-DA:33,158
-BRDA:33,0,0,1
-DA:34,1
-DA:36,157
-DA:37,157
-BRDA:37,1,0,153
-DA:38,153
-DA:40,157
-FN:51,RuleConditionalTransfer.operateOnTransfer
-FNDA:50,RuleConditionalTransfer.operateOnTransfer
-DA:61,50
-BRDA:61,2,0,8
-BRDA:61,2,1,24
-DA:62,8
-DA:64,42
-DA:65,42
-BRDA:65,3,0,18
-BRDA:65,3,1,24
-DA:66,18
-DA:67,18
-DA:69,24
-FN:79,RuleConditionalTransfer.createTransferRequest
-FNDA:114,RuleConditionalTransfer.createTransferRequest
-DA:83,117
-DA:84,117
-DA:85,117
-BRDA:85,4,0,1
-DA:86,1
-DA:88,116
-BRDA:88,5,0,113
-BRDA:88,5,1,3
-DA:89,113
-DA:90,113
-DA:102,113
-DA:103,113
-DA:104,113
-DA:105,113
-DA:108,3
-DA:109,3
-DA:110,3
-FN:123,RuleConditionalTransfer.createTransferRequestBatch
-FNDA:3,RuleConditionalTransfer.createTransferRequestBatch
-DA:127,3
-BRDA:127,6,0,1
-DA:128,1
-DA:130,2
-BRDA:130,7,0,1
-DA:131,1
-DA:133,1
-DA:134,3
-FN:141,RuleConditionalTransfer.cancelTransferRequest
-FNDA:6,RuleConditionalTransfer.cancelTransferRequest
-DA:142,6
-FN:148,RuleConditionalTransfer.cancelTransferRequestBatch
-FNDA:3,RuleConditionalTransfer.cancelTransferRequestBatch
-DA:149,3
-BRDA:149,8,0,1
-DA:150,1
-DA:153,2
-DA:154,5
-BRDA:154,9,0,1
-DA:155,1
-DA:158,1
-DA:159,3
-FN:163,RuleConditionalTransfer.getRequestTrade
-FNDA:57,RuleConditionalTransfer.getRequestTrade
-DA:168,57
-DA:169,57
-FN:177,RuleConditionalTransfer.getRequestByStatus
-FNDA:35,RuleConditionalTransfer.getRequestByStatus
-DA:180,35
-DA:181,35
-DA:182,35
-DA:185,35
-DA:186,38
-BRDA:186,10,0,36
-DA:187,36
-DA:192,35
-DA:195,35
-DA:196,38
-BRDA:196,11,0,36
-DA:198,36
-DA:201,36
-DA:202,36
-DA:205,35
-FN:214,RuleConditionalTransfer.detectTransferRestriction
-FNDA:56,RuleConditionalTransfer.detectTransferRestriction
-DA:220,56
-BRDA:220,12,0,1
-DA:221,1
-DA:223,55
-DA:224,55
-BRDA:224,13,0,8
-BRDA:224,13,1,8
-DA:225,8
-DA:227,47
-FN:236,RuleConditionalTransfer.canReturnTransferRestrictionCode
-FNDA:2,RuleConditionalTransfer.canReturnTransferRestrictionCode
-DA:239,2
-FN:247,RuleConditionalTransfer.messageForTransferRestriction
-FNDA:3,RuleConditionalTransfer.messageForTransferRestriction
-DA:250,3
-BRDA:250,14,0,2
-BRDA:250,14,1,1
-DA:251,2
-DA:253,1
-FN:260,RuleConditionalTransfer._validateTransfer
-FNDA:106,RuleConditionalTransfer._validateTransfer
-DA:265,106
-BRDA:265,15,0,36
-DA:267,36
-DA:268,5
-DA:269,3
-BRDA:269,16,0,3
-DA:270,3
-DA:275,103
-BRDA:275,17,0,6
-DA:276,6
-DA:278,97
-FN:281,RuleConditionalTransfer._cancelTransferRequest
-FNDA:9,RuleConditionalTransfer._cancelTransferRequest
-DA:282,9
-BRDA:282,18,0,1
-DA:283,1
-DA:285,8
-DA:287,8
-BRDA:287,19,0,1
-DA:288,1
-DA:292,7
-DA:293,2
-DA:294,1
-BRDA:294,20,0,1
-DA:295,1
-DA:297,6
-FN:307,RuleConditionalTransfer._validateBurnMint
-FNDA:103,RuleConditionalTransfer._validateBurnMint
-DA:313,103
-DA:317,6
-BRDA:317,21,0,6
-DA:318,6
-DA:320,97
-FN:329,RuleConditionalTransfer._validateApproval
-FNDA:97,RuleConditionalTransfer._validateApproval
-DA:333,97
-DA:335,50
-DA:337,47
-DA:338,50
-BRDA:338,22,0,50
-DA:339,50
-DA:341,47
-DA:342,47
-DA:343,47
-DA:344,20
-BRDA:344,23,0,20
-BRDA:343,23,1,27
-DA:345,20
-DA:348,27
-BRDA:348,24,0,27
-DA:350,27
-DA:355,47
-BRDA:355,25,0,26
-BRDA:355,25,1,21
-DA:356,26
-DA:358,21
-FN:369,RuleConditionalTransfer._msgSender
-FNDA:829,RuleConditionalTransfer._msgSender
-DA:375,829
-FN:381,RuleConditionalTransfer._msgData
-FNDA:0,RuleConditionalTransfer._msgData
-DA:387,0
-FN:393,RuleConditionalTransfer._contextSuffixLength
-FNDA:829,RuleConditionalTransfer._contextSuffixLength
-DA:399,829
-FNF:18
-FNH:17
-LF:106
-LH:105
-BRF:33
-BRH:33
-end_of_record
-TN:
-SF:src/rules/operation/abstract/RuleConditionalTransferOperator.sol
-FN:32,RuleConditionalTransferOperator.setConditionalWhitelist
-FNDA:26,RuleConditionalTransferOperator.setConditionalWhitelist
-DA:35,26
-DA:36,26
-FN:42,RuleConditionalTransferOperator.setIssuanceOptions
-FNDA:7,RuleConditionalTransferOperator.setIssuanceOptions
-DA:46,6
-DA:48,3
-BRDA:48,0,0,3
-DA:49,3
-DA:53,6
-DA:55,3
-BRDA:55,1,0,3
-DA:56,3
-FN:66,RuleConditionalTransferOperator.setAutomaticTransfer
-FNDA:4,RuleConditionalTransferOperator.setAutomaticTransfer
-DA:70,3
-DA:72,2
-BRDA:72,2,0,2
-DA:73,2
-DA:78,3
-DA:80,2
-BRDA:80,3,0,2
-DA:81,2
-FN:90,RuleConditionalTransferOperator.setTimeLimit
-FNDA:5,RuleConditionalTransferOperator.setTimeLimit
+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:96,4
-BRDA:96,4,0,4
-DA:97,4
-DA:101,4
DA:103,4
-BRDA:103,5,0,4
-DA:104,4
-FN:114,RuleConditionalTransferOperator.setAutomaticApproval
-FNDA:10,RuleConditionalTransferOperator.setAutomaticApproval
-DA:118,9
-DA:120,6
-BRDA:120,6,0,6
-DA:121,6
-DA:125,9
-DA:127,9
-BRDA:127,7,0,9
-DA:128,9
-FN:138,RuleConditionalTransferOperator.createTransferRequestWithApproval
-FNDA:6,RuleConditionalTransferOperator.createTransferRequestWithApproval
-DA:141,5
-FN:150,RuleConditionalTransferOperator.approveTransferRequest
-FNDA:40,RuleConditionalTransferOperator.approveTransferRequest
-DA:155,39
-FN:161,RuleConditionalTransferOperator.approveTransferRequestWithId
-FNDA:5,RuleConditionalTransferOperator.approveTransferRequestWithId
-DA:165,4
-BRDA:165,8,0,2
-DA:166,2
-DA:168,2
-DA:171,2
-FN:177,RuleConditionalTransferOperator.resetRequestStatus
-FNDA:3,RuleConditionalTransferOperator.resetRequestStatus
-DA:180,2
-BRDA:180,9,0,1
-DA:181,1
-DA:183,1
-DA:184,1
-FN:191,RuleConditionalTransferOperator.approveTransferRequestBatchWithId
-FNDA:7,RuleConditionalTransferOperator.approveTransferRequestBatchWithId
-DA:195,5
-BRDA:195,10,0,1
-DA:196,1
-DA:198,4
-BRDA:198,11,0,1
-DA:199,1
-DA:202,3
-DA:203,11
-BRDA:203,12,0,1
-DA:204,1
-DA:207,2
-DA:208,5
-DA:211,5
-FN:218,RuleConditionalTransferOperator.approveTransferRequestBatch
-FNDA:7,RuleConditionalTransferOperator.approveTransferRequestBatch
-DA:223,6
-BRDA:223,13,0,1
-DA:224,1
-DA:227,5
-DA:229,3
-BRDA:229,14,0,3
-DA:230,3
-DA:232,2
-DA:233,9
-FN:244,RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch
-FNDA:3,RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch
-DA:247,2
-BRDA:247,15,0,1
-DA:248,1
-DA:250,1
-DA:251,4
-FN:258,RuleConditionalTransferOperator.resetRequestStatusBatch
-FNDA:3,RuleConditionalTransferOperator.resetRequestStatusBatch
-DA:261,3
-BRDA:261,16,0,1
-DA:262,1
-DA:265,2
-DA:266,4
-BRDA:266,17,0,1
-DA:267,1
-DA:270,1
-DA:271,3
-DA:272,3
-FN:280,RuleConditionalTransferOperator.hasRole
-FNDA:310,RuleConditionalTransferOperator.hasRole
-DA:285,704
-BRDA:285,18,0,137
-DA:286,137
-DA:288,567
-FN:294,RuleConditionalTransferOperator._approveTransferRequestKeyElement
-FNDA:48,RuleConditionalTransferOperator._approveTransferRequestKeyElement
-DA:299,48
-BRDA:299,19,0,1
-DA:300,1
-DA:302,47
-DA:305,47
-DA:306,47
-BRDA:306,20,0,9
-BRDA:306,20,1,8
-DA:307,9
-BRDA:307,21,0,1
-DA:308,1
-DA:311,8
-DA:313,8
-DA:321,38
-FN:325,RuleConditionalTransferOperator._createTransferRequestWithApproval
-FNDA:17,RuleConditionalTransferOperator._createTransferRequestWithApproval
-DA:331,17
-DA:334,17
-BRDA:334,22,0,16
-BRDA:334,22,1,1
-DA:336,16
-DA:346,16
-DA:347,16
-DA:348,16
-DA:355,16
-DA:359,1
-DA:362,1
-DA:363,1
-FN:373,RuleConditionalTransferOperator._resetRequestStatus
-FNDA:10,RuleConditionalTransferOperator._resetRequestStatus
-DA:374,10
-DA:375,10
-FN:387,RuleConditionalTransferOperator._checkRequestStatus
-FNDA:133,RuleConditionalTransferOperator._checkRequestStatus
-DA:389,133
-DA:390,133
-FN:394,RuleConditionalTransferOperator._approveRequest
-FNDA:53,RuleConditionalTransferOperator._approveRequest
-DA:399,53
-BRDA:399,23,0,1
-DA:400,1
-DA:402,32
-BRDA:402,24,0,32
-BRDA:402,24,1,20
-DA:405,32
-DA:407,3
-BRDA:407,25,0,3
-DA:408,3
-DA:411,29
-DA:413,29
-DA:416,29
-DA:424,29
-DA:425,7
-DA:426,7
-BRDA:426,26,0,7
-DA:430,7
-DA:434,3
-BRDA:434,27,0,3
-DA:436,3
-DA:444,20
-DA:445,20
-FN:458,RuleConditionalTransferOperator._updateProcessedTransfer
-FNDA:18,RuleConditionalTransferOperator._updateProcessedTransfer
-DA:460,18
-DA:461,18
-DA:463,18
-DA:465,18
-FNF:20
-FNH:20
-LF:113
-LH:113
-BRF:31
-BRH:31
-end_of_record
-TN:
-SF:src/rules/validation/RuleBlacklist.sol
-FN:22,RuleBlacklist.
-FNDA:12,RuleBlacklist.
-FN:33,RuleBlacklist.detectTransferRestriction
-FNDA:10,RuleBlacklist.detectTransferRestriction
-DA:38,10
-BRDA:38,0,0,5
-BRDA:38,0,1,3
-DA:39,5
-DA:40,5
-BRDA:40,1,0,2
-BRDA:40,1,1,3
-DA:41,2
-DA:43,3
-FN:52,RuleBlacklist.canReturnTransferRestrictionCode
+FN:103,RuleBlacklist.canReturnTransferRestrictionCode
FNDA:4,RuleBlacklist.canReturnTransferRestrictionCode
-DA:55,4
-DA:56,4
-DA:57,2
-FN:65,RuleBlacklist.messageForTransferRestriction
-FNDA:4,RuleBlacklist.messageForTransferRestriction
-DA:68,4
-BRDA:68,2,0,2
-BRDA:68,2,1,1
-DA:69,2
-DA:70,2
-BRDA:70,3,0,1
-BRDA:70,3,1,1
-DA:71,1
-DA:73,1
-FNF:4
-FNH:4
-LF:13
-LH:13
-BRF:8
-BRH:8
+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
+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/RuleSanctionList.sol
-FN:26,RuleSanctionList.
-FNDA:13,RuleSanctionList.
-DA:31,13
-BRDA:31,0,0,1
-DA:32,1
-DA:34,12
-BRDA:34,1,0,1
-DA:35,1
-DA:37,12
-FN:45,RuleSanctionList.setSanctionListOracle
-FNDA:11,RuleSanctionList.setSanctionListOracle
-DA:48,10
-FN:57,RuleSanctionList.detectTransferRestriction
-FNDA:7,RuleSanctionList.detectTransferRestriction
-DA:62,7
-BRDA:62,2,0,7
-DA:63,7
-BRDA:63,3,0,2
-BRDA:63,3,1,3
-DA:64,2
-DA:65,5
-BRDA:65,4,0,2
-DA:66,2
-DA:69,3
-FN:77,RuleSanctionList.canReturnTransferRestrictionCode
-FNDA:3,RuleSanctionList.canReturnTransferRestrictionCode
-DA:80,3
-DA:81,3
-DA:82,2
-FN:90,RuleSanctionList.messageForTransferRestriction
-FNDA:3,RuleSanctionList.messageForTransferRestriction
-DA:93,3
-BRDA:93,5,0,1
-BRDA:93,5,1,1
-DA:94,1
-DA:95,2
-BRDA:95,6,0,1
-BRDA:95,6,1,1
-DA:96,1
-DA:98,1
-FN:106,RuleSanctionList.hasRole
-FNDA:13,RuleSanctionList.hasRole
-DA:111,24
-BRDA:111,7,0,11
-DA:112,11
-DA:114,13
-FN:121,RuleSanctionList._setSanctionListOracle
-FNDA:11,RuleSanctionList._setSanctionListOracle
-DA:122,11
-DA:123,11
-FN:133,RuleSanctionList._msgSender
-FNDA:23,RuleSanctionList._msgSender
-DA:139,23
-FN:145,RuleSanctionList._msgData
-FNDA:0,RuleSanctionList._msgData
-DA:151,0
-FN:157,RuleSanctionList._contextSuffixLength
-FNDA:23,RuleSanctionList._contextSuffixLength
-DA:163,23
-FNF:10
-FNH:9
-LF:28
-LH:27
-BRF:11
-BRH:11
+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
end_of_record
TN:
SF:src/rules/validation/RuleWhitelist.sol
-FN:16,RuleWhitelist.
-FNDA:173,RuleWhitelist.
-FN:27,RuleWhitelist.detectTransferRestriction
-FNDA:28,RuleWhitelist.detectTransferRestriction
-DA:32,28
-BRDA:32,0,0,13
-BRDA:32,0,1,10
-DA:33,13
-DA:34,15
-BRDA:34,1,0,5
-BRDA:34,1,1,10
-DA:35,5
-DA:37,10
-FNF:2
-FNH:2
-LF:5
-LH:5
-BRF:4
-BRH:4
+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
+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
-FN:23,RuleWhitelistWrapper.
-FNDA:14,RuleWhitelistWrapper.
-DA:27,14
-BRDA:27,0,0,1
-DA:28,1
-DA:30,13
-FN:39,RuleWhitelistWrapper.detectTransferRestriction
-FNDA:11,RuleWhitelistWrapper.detectTransferRestriction
-DA:44,11
-DA:45,11
-DA:46,11
-DA:47,11
-DA:48,11
-DA:49,11
-DA:51,11
-DA:53,25
-DA:55,25
-BRDA:55,1,0,7
-DA:57,7
-DA:59,25
-BRDA:59,2,0,7
-DA:61,7
-DA:63,25
-BRDA:63,3,0,25
+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:67,11
-BRDA:67,4,0,4
-BRDA:67,4,1,5
-DA:68,4
-DA:69,7
-BRDA:69,5,0,2
-BRDA:69,5,1,5
-DA:70,2
-DA:72,5
-FN:80,RuleWhitelistWrapper.hasRole
-FNDA:13,RuleWhitelistWrapper.hasRole
-DA:85,52
-BRDA:85,6,0,39
-DA:86,39
-DA:88,13
-FN:98,RuleWhitelistWrapper._msgSender
-FNDA:52,RuleWhitelistWrapper._msgSender
-DA:104,52
-FN:110,RuleWhitelistWrapper._msgData
+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:116,0
-FN:122,RuleWhitelistWrapper._contextSuffixLength
-FNDA:52,RuleWhitelistWrapper._contextSuffixLength
-DA:128,52
-FNF:6
-FNH:5
-LF:28
-LH:27
-BRF:9
-BRH:9
+DA:191,0
+DA:197,80
+FN:197,RuleWhitelistWrapper._contextSuffixLength
+FNDA:80,RuleWhitelistWrapper._contextSuffixLength
+DA:198,80
+FNF:11
+FNH:9
+LF:57
+LH:50
+BRF:14
+BRH:11
end_of_record
TN:
-SF:src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol
-FN:27,RuleAddressList.
-FNDA:185,RuleAddressList.
-DA:31,185
-BRDA:31,0,0,1
-DA:32,1
-DA:34,184
-FN:42,RuleAddressList.addAddressesToTheList
-FNDA:17,RuleAddressList.addAddressesToTheList
-DA:45,16
-DA:46,16
-FN:55,RuleAddressList.removeAddressesFromTheList
-FNDA:4,RuleAddressList.removeAddressesFromTheList
-DA:58,3
-DA:59,3
-FN:67,RuleAddressList.addAddressToTheList
-FNDA:52,RuleAddressList.addAddressToTheList
-DA:70,51
-DA:71,50
-FN:80,RuleAddressList.removeAddressFromTheList
-FNDA:3,RuleAddressList.removeAddressFromTheList
-DA:83,2
-DA:84,1
-FN:92,RuleAddressList.numberListedAddress
-FNDA:24,RuleAddressList.numberListedAddress
-DA:93,24
-FN:102,RuleAddressList.addressIsListed
-FNDA:101,RuleAddressList.addressIsListed
-DA:105,159
-FN:112,RuleAddressList.addressIsListedBatch
-FNDA:28,RuleAddressList.addressIsListedBatch
-DA:115,28
-DA:116,28
-DA:117,55
-DA:119,28
-FN:126,RuleAddressList.hasRole
-FNDA:194,RuleAddressList.hasRole
-DA:131,280
-BRDA:131,1,0,78
-DA:132,78
-DA:134,202
-FN:144,RuleAddressList._msgSender
-FNDA:270,RuleAddressList._msgSender
-DA:150,270
-FN:156,RuleAddressList._msgData
-FNDA:0,RuleAddressList._msgData
-DA:162,0
-FN:168,RuleAddressList._contextSuffixLength
-FNDA:270,RuleAddressList._contextSuffixLength
-DA:174,270
-FNF:12
-FNH:11
-LF:23
-LH:22
+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
+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:103,2
+BRDA:103,1,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
end_of_record
TN:
-SF:src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol
-FN:22,RuleAddressListInternal._addAddressesToThelist
-FNDA:16,RuleAddressListInternal._addAddressesToThelist
-DA:25,16
-DA:26,16
-DA:27,34
-BRDA:27,0,0,32
-DA:28,32
-DA:29,32
-DA:32,16
-FN:41,RuleAddressListInternal._removeAddressesFromThelist
-FNDA:3,RuleAddressListInternal._removeAddressesFromThelist
-DA:44,3
-DA:45,3
-DA:46,6
-BRDA:46,1,0,6
-DA:47,6
-DA:48,6
-DA:51,3
-FN:59,RuleAddressListInternal._addAddressToThelist
-FNDA:51,RuleAddressListInternal._addAddressToThelist
-DA:60,1
-BRDA:60,2,0,1
-DA:61,1
-DA:63,50
-DA:64,50
-FN:73,RuleAddressListInternal._removeAddressFromThelist
-FNDA:2,RuleAddressListInternal._removeAddressFromThelist
-DA:74,2
-BRDA:74,3,0,1
-DA:75,1
-DA:77,1
-DA:78,1
-FN:86,RuleAddressListInternal._numberListedAddress
-FNDA:24,RuleAddressListInternal._numberListedAddress
-DA:87,24
-FN:96,RuleAddressListInternal._addressIsListed
-FNDA:214,RuleAddressListInternal._addressIsListed
-DA:99,214
+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:22
-LH:22
-BRF:4
-BRH:4
-end_of_record
-TN:
-SF:src/rules/validation/abstract/RuleValidateTransfer.sol
-FN:15,RuleValidateTransfer.validateTransfer
-FNDA:40,RuleValidateTransfer.validateTransfer
-DA:21,40
-DA:22,40
-FNF:1
-FNH:1
-LF:2
-LH:2
-BRF:0
-BRH:0
-end_of_record
-TN:
-SF:src/rules/validation/abstract/RuleWhitelistCommon.sol
-FN:17,RuleWhitelistCommon.canReturnTransferRestrictionCode
-FNDA:12,RuleWhitelistCommon.canReturnTransferRestrictionCode
-DA:20,12
-DA:21,12
-DA:22,6
-FN:30,RuleWhitelistCommon.messageForTransferRestriction
-FNDA:10,RuleWhitelistCommon.messageForTransferRestriction
-DA:33,10
-BRDA:33,0,0,6
-BRDA:33,0,1,1
-DA:34,6
-DA:35,4
-BRDA:35,1,0,3
-BRDA:35,1,1,1
-DA:36,3
-DA:38,1
-FNF:2
-FNH:2
-LF:8
-LH:8
-BRF:4
-BRH:4
-end_of_record
-TN:
-SF:test/HelperContract.sol
-FN:95,HelperContract.
-FNDA:0,HelperContract.
-FNF:1
-FNH:0
-LF:0
-LH:0
+LF:14
+LH:14
BRF:0
BRH:0
end_of_record
TN:
-SF:test/RuleConditionalTransfer/utils/RuleCTDeployment.sol
-FN:13,RuleCTDeployment.
-FNDA:13,RuleCTDeployment.
-DA:14,13
-DA:19,13
-DA:24,13
-DA:28,13
-DA:33,13
-DA:39,13
-DA:44,13
-DA:45,13
-DA:51,13
-DA:52,13
-FNF:1
-FNH:1
+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
+FNF:5
+FNH:4
LF:10
-LH:10
-BRF:0
-BRH:0
-end_of_record
-TN:
-SF:test/utils/CMTATDeployment.sol
-FN:15,CMTATDeployment.
-FNDA:86,CMTATDeployment.
-DA:17,86
-DA:23,86
-DA:30,86
-DA:36,86
-FNF:1
-FNH:1
-LF:4
-LH:4
+LH:8
BRF:0
BRH:0
end_of_record
TN:
-SF:test/utils/SanctionListOracle.sol
-FN:9,SanctionListOracle.
-FNDA:11,SanctionListOracle.
-FN:13,SanctionListOracle.addToSanctionsList
-FNDA:10,SanctionListOracle.addToSanctionsList
-DA:14,10
-FN:17,SanctionListOracle.removeFromSanctionsList
-FNDA:0,SanctionListOracle.removeFromSanctionsList
-DA:18,0
-FN:21,SanctionListOracle.isSanctioned
-FNDA:12,SanctionListOracle.isSanctioned
-DA:22,12
-FNF:4
-FNH:3
-LF:3
-LH:2
-BRF:0
-BRH:0
+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
+FNF:6
+FNH:6
+LF:21
+LH:21
+BRF:10
+BRH:10
end_of_record
diff --git a/doc/security/audits/tools/aderyn-report.md b/doc/security/audits/tools/aderyn-report.md
new file mode 100644
index 0000000..c215e0d
--- /dev/null
+++ b/doc/security/audits/tools/aderyn-report.md
@@ -0,0 +1,454 @@
+# Aderyn Analysis Report
+
+This report was generated by [Aderyn](https://github.com/Cyfrin/aderyn), a static analysis tool built by [Cyfrin](https://cyfrin.io), a blockchain security company. This report is not a substitute for manual audit or security review. It should not be relied upon for any purpose other than to assist in the identification of potential security vulnerabilities.
+# Table of Contents
+
+- [Summary](#summary)
+ - [Files Summary](#files-summary)
+ - [Files Details](#files-details)
+ - [Issue Summary](#issue-summary)
+- [Low Issues](#low-issues)
+ - [L-1: Centralization Risk](#l-1-centralization-risk)
+ - [L-2: Unspecific Solidity Pragma](#l-2-unspecific-solidity-pragma)
+ - [L-3: Address State Variable Set Without Checks](#l-3-address-state-variable-set-without-checks)
+ - [L-4: PUSH0 Opcode](#l-4-push0-opcode)
+ - [L-5: Costly operations inside loop](#l-5-costly-operations-inside-loop)
+ - [L-6: Unchecked Return](#l-6-unchecked-return)
+
+
+# Summary
+
+## Files Summary
+
+| Key | Value |
+| --- | --- |
+| .sol Files | 19 |
+| Total nSLOC | 839 |
+
+
+## Files Details
+
+| Filepath | nSLOC |
+| --- | --- |
+| src/modules/AccessControlModuleStandalone.sol | 18 |
+| src/modules/MetaTxModuleStandalone.sol | 6 |
+| src/rules/interfaces/IAddressList.sol | 15 |
+| src/rules/interfaces/IERC7943NonFungibleCompliance.sol | 22 |
+| src/rules/interfaces/IIdentityRegistry.sol | 7 |
+| src/rules/interfaces/ISanctionsList.sol | 4 |
+| src/rules/validation/RuleBlacklist.sol | 127 |
+| src/rules/validation/RuleSanctionsList.sol | 157 |
+| src/rules/validation/RuleWhitelist.sol | 84 |
+| src/rules/validation/RuleWhitelistWrapper.sol | 141 |
+| src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol | 67 |
+| src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol | 28 |
+| src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol | 7 |
+| src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol | 12 |
+| src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol | 13 |
+| src/rules/validation/abstract/RuleCommonInvariantStorage.sol | 4 |
+| src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol | 15 |
+| src/rules/validation/abstract/RuleValidateTransfer.sol | 50 |
+| src/rules/validation/abstract/RuleWhitelistCommon.sol | 62 |
+| **Total** | **839** |
+
+
+## Issue Summary
+
+| Category | No. of Issues |
+| --- | --- |
+| High | 0 |
+| Low | 6 |
+
+
+# Low Issues
+
+## L-1: Centralization Risk
+
+Contracts have owners with privileged rights to perform admin tasks and need to be trusted to not perform malicious updates or drain funds.
+
+8 Found Instances
+
+
+- Found in src/modules/AccessControlModuleStandalone.sol [Line: 8](src/modules/AccessControlModuleStandalone.sol#L8)
+
+ ```solidity
+ abstract contract AccessControlModuleStandalone is AccessControl {
+ ```
+
+- Found in src/rules/validation/RuleSanctionsList.sol [Line: 177](src/rules/validation/RuleSanctionsList.sol#L177)
+
+ ```solidity
+ function setSanctionListOracle(ISanctionsList sanctionContractOracle_) public virtual onlyRole(SANCTIONLIST_ROLE) {
+ ```
+
+- Found in src/rules/validation/RuleWhitelist.sol [Line: 157](src/rules/validation/RuleWhitelist.sol#L157)
+
+ ```solidity
+ onlyRole(DEFAULT_ADMIN_ROLE) // or a dedicated role if you prefer
+ ```
+
+- Found in src/rules/validation/RuleWhitelistWrapper.sol [Line: 155](src/rules/validation/RuleWhitelistWrapper.sol#L155)
+
+ ```solidity
+ onlyRole(DEFAULT_ADMIN_ROLE) // or a dedicated role if you prefer
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol [Line: 63](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L63)
+
+ ```solidity
+ function addAddresses(address[] calldata targetAddresses) public onlyRole(ADDRESS_LIST_ADD_ROLE) {
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol [Line: 75](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L75)
+
+ ```solidity
+ function removeAddresses(address[] calldata targetAddresses) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) {
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol [Line: 87](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L87)
+
+ ```solidity
+ function addAddress(address targetAddress) public onlyRole(ADDRESS_LIST_ADD_ROLE) {
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol [Line: 102](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L102)
+
+ ```solidity
+ function removeAddress(address targetAddress) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) {
+ ```
+
+
+
+
+
+## L-2: Unspecific Solidity Pragma
+
+Consider using a specific version of Solidity in your contracts instead of a wide version. For example, instead of `pragma solidity ^0.8.0;`, use `pragma solidity 0.8.0;`
+
+19 Found Instances
+
+
+- Found in src/modules/AccessControlModuleStandalone.sol [Line: 3](src/modules/AccessControlModuleStandalone.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/modules/MetaTxModuleStandalone.sol [Line: 3](src/modules/MetaTxModuleStandalone.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/interfaces/IAddressList.sol [Line: 2](src/rules/interfaces/IAddressList.sol#L2)
+
+ ```solidity
+ pragma solidity ^0.8.0;
+ ```
+
+- Found in src/rules/interfaces/IERC7943NonFungibleCompliance.sol [Line: 3](src/rules/interfaces/IERC7943NonFungibleCompliance.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/interfaces/IIdentityRegistry.sol [Line: 3](src/rules/interfaces/IIdentityRegistry.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/interfaces/ISanctionsList.sol [Line: 3](src/rules/interfaces/ISanctionsList.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/RuleBlacklist.sol [Line: 3](src/rules/validation/RuleBlacklist.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/RuleSanctionsList.sol [Line: 3](src/rules/validation/RuleSanctionsList.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/RuleWhitelist.sol [Line: 2](src/rules/validation/RuleWhitelist.sol#L2)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/RuleWhitelistWrapper.sol [Line: 3](src/rules/validation/RuleWhitelistWrapper.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol [Line: 2](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L2)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 2](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L2)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleCommonInvariantStorage.sol [Line: 2](src/rules/validation/abstract/RuleCommonInvariantStorage.sol#L2)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleValidateTransfer.sol [Line: 3](src/rules/validation/abstract/RuleValidateTransfer.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleWhitelistCommon.sol [Line: 2](src/rules/validation/abstract/RuleWhitelistCommon.sol#L2)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+
+
+
+
+## L-3: Address State Variable Set Without Checks
+
+Check for `address(0)` when assigning values to address state variables.
+
+1 Found Instances
+
+
+- Found in src/rules/validation/RuleSanctionsList.sol [Line: 236](src/rules/validation/RuleSanctionsList.sol#L236)
+
+ ```solidity
+ sanctionsList = sanctionContractOracle_;
+ ```
+
+
+
+
+
+## L-4: PUSH0 Opcode
+
+Solc compiler version 0.8.20 switches the default target EVM version to Shanghai, which means that the generated bytecode will include PUSH0 opcodes. Be sure to select the appropriate EVM version in case you intend to deploy on a chain other than mainnet like L2 chains that may not support PUSH0, otherwise deployment of your contracts will fail.
+
+19 Found Instances
+
+
+- Found in src/modules/AccessControlModuleStandalone.sol [Line: 3](src/modules/AccessControlModuleStandalone.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/modules/MetaTxModuleStandalone.sol [Line: 3](src/modules/MetaTxModuleStandalone.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/interfaces/IAddressList.sol [Line: 2](src/rules/interfaces/IAddressList.sol#L2)
+
+ ```solidity
+ pragma solidity ^0.8.0;
+ ```
+
+- Found in src/rules/interfaces/IERC7943NonFungibleCompliance.sol [Line: 3](src/rules/interfaces/IERC7943NonFungibleCompliance.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/interfaces/IIdentityRegistry.sol [Line: 3](src/rules/interfaces/IIdentityRegistry.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/interfaces/ISanctionsList.sol [Line: 3](src/rules/interfaces/ISanctionsList.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/RuleBlacklist.sol [Line: 3](src/rules/validation/RuleBlacklist.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/RuleSanctionsList.sol [Line: 3](src/rules/validation/RuleSanctionsList.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/RuleWhitelist.sol [Line: 2](src/rules/validation/RuleWhitelist.sol#L2)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/RuleWhitelistWrapper.sol [Line: 3](src/rules/validation/RuleWhitelistWrapper.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol [Line: 2](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L2)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 2](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L2)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleCommonInvariantStorage.sol [Line: 2](src/rules/validation/abstract/RuleCommonInvariantStorage.sol#L2)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleValidateTransfer.sol [Line: 3](src/rules/validation/abstract/RuleValidateTransfer.sol#L3)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+- Found in src/rules/validation/abstract/RuleWhitelistCommon.sol [Line: 2](src/rules/validation/abstract/RuleWhitelistCommon.sol#L2)
+
+ ```solidity
+ pragma solidity ^0.8.20;
+ ```
+
+
+
+
+
+## L-5: Costly operations inside loop
+
+Invoking `SSTORE` operations in loops may waste gas. Use a local variable to hold the loop computation result.
+
+2 Found Instances
+
+
+- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 37](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L37)
+
+ ```solidity
+ for (uint256 i = 0; i < addressesToAdd.length; ++i) {
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 50](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L50)
+
+ ```solidity
+ for (uint256 i = 0; i < addressesToRemove.length; ++i) {
+ ```
+
+
+
+
+
+## L-6: Unchecked Return
+
+Function returns a value but it is ignored. Consider checking the return value.
+
+5 Found Instances
+
+
+- Found in src/modules/AccessControlModuleStandalone.sol [Line: 29](src/modules/AccessControlModuleStandalone.sol#L29)
+
+ ```solidity
+ _grantRole(DEFAULT_ADMIN_ROLE, admin);
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 38](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L38)
+
+ ```solidity
+ _listedAddresses.add(addressesToAdd[i]);
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 51](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L51)
+
+ ```solidity
+ _listedAddresses.remove(addressesToRemove[i]);
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 60](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L60)
+
+ ```solidity
+ _listedAddresses.add(targetAddress);
+ ```
+
+- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 68](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L68)
+
+ ```solidity
+ _listedAddresses.remove(targetAddress);
+ ```
+
+
+
+
+
diff --git a/doc/security/audits/tools/slither-report.md b/doc/security/audits/tools/slither-report.md
index fb021eb..19aabf7 100644
--- a/doc/security/audits/tools/slither-report.md
+++ b/doc/security/audits/tools/slither-report.md
@@ -1,643 +1,157 @@
**THIS CHECKLIST IS NOT COMPLETE**. Use `--show-ignored-findings` to show all the results.
Summary
- - [incorrect-equality](#incorrect-equality) (4 results) (Medium)
- - [calls-loop](#calls-loop) (8 results) (Low)
- - [timestamp](#timestamp) (5 results) (Low)
- - [costly-loop](#costly-loop) (2 results) (Informational)
- - [dead-code](#dead-code) (5 results) (Informational)
+ - [unused-return](#unused-return) (4 results) (Medium)
+ - [dead-code](#dead-code) (3 results) (Informational)
- [solc-version](#solc-version) (1 results) (Informational)
- - [naming-convention](#naming-convention) (50 results) (Informational)
- - [similar-names](#similar-names) (7 results) (Informational)
- - [unused-import](#unused-import) (1 results) (Informational)
- - [var-read-using-this](#var-read-using-this) (1 results) (Optimization)
-## incorrect-equality
-
-> Strict equality is required to check the request status
-
+ - [naming-convention](#naming-convention) (2 results) (Informational)
+ - [constable-states](#constable-states) (1 results) (Optimization)
+ - [var-read-using-this](#var-read-using-this) (9 results) (Optimization)
+## unused-return
Impact: Medium
-Confidence: High
+Confidence: Medium
- [ ] ID-0
- [RuleConditionalTransfer.getRequestByStatus(RuleConditionalTransferInvariantStorage.STATUS)](src/rules/operation/RuleConditionalTransfer.sol#L177-L206) uses a dangerous strict equality:
- - [transferRequests[IdToKey[i_scope_0]].status == _targetStatus](src/rules/operation/RuleConditionalTransfer.sol#L196)
+[RuleAddressSetInternal._addAddresses(address[])](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L36-L40) ignores return value by [_listedAddresses.add(addressesToAdd[i])](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L38)
-src/rules/operation/RuleConditionalTransfer.sol#L177-L206
+src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L36-L40
- [ ] ID-1
- [RuleConditionalTransfer._validateApproval(bytes32)](src/rules/operation/RuleConditionalTransfer.sol#L329-L349) uses a dangerous strict equality:
- - [isTransferApproved = (transferRequests[key].status == STATUS.APPROVED) && (transferRequests[key].maxTime >= block.timestamp)](src/rules/operation/RuleConditionalTransfer.sol#L341-L343)
+[RuleAddressSetInternal._addAddress(address)](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L59-L61) ignores return value by [_listedAddresses.add(targetAddress)](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L60)
-src/rules/operation/RuleConditionalTransfer.sol#L329-L349
+src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L59-L61
- [ ] ID-2
- [RuleConditionalTransferOperator._checkRequestStatus(bytes32)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L383-L388) uses a dangerous strict equality:
- - [(transferRequests[key].status == STATUS.NONE) && (transferRequests[key].key == 0x0)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L385-L387)
+[RuleAddressSetInternal._removeAddresses(address[])](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L49-L53) ignores return value by [_listedAddresses.remove(addressesToRemove[i])](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L51)
-src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L383-L388
+src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L49-L53
- [ ] ID-3
- [RuleConditionalTransfer.getRequestByStatus(RuleConditionalTransferInvariantStorage.STATUS)](src/rules/operation/RuleConditionalTransfer.sol#L177-L206) uses a dangerous strict equality:
- - [transferRequests[IdToKey[i]].status == _targetStatus](src/rules/operation/RuleConditionalTransfer.sol#L186)
+[RuleAddressSetInternal._removeAddress(address)](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L67-L69) ignores return value by [_listedAddresses.remove(targetAddress)](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L68)
-src/rules/operation/RuleConditionalTransfer.sol#L177-L206
+src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L67-L69
-## calls-loop
-> Acknowledge
-
-Impact: Low
+## dead-code
+Impact: Informational
Confidence: Medium
- [ ] ID-4
-[RuleWhitelistWrapper.detectTransferRestriction(address,address,uint256)](src/rules/validation/RuleWhitelistWrapper.sol#L39-L74) has external calls inside a loop: [isListed = RuleAddressList(_rulesValidation[i]).addressIsListedBatch(targetAddress)](src/rules/validation/RuleWhitelistWrapper.sol#L53-L54)
+[RuleAddressSet._msgData()](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L157-L159) is never used and should be removed
-src/rules/validation/RuleWhitelistWrapper.sol#L39-L74
+src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L157-L159
- [ ] ID-5
-[RuleEngineValidation.detectTransferRestrictionValidation(address,address,uint256)](src/modules/RuleEngineValidation.sol#L29-L44) has external calls inside a loop: [restriction = IRuleValidation(_rulesValidation[i]).detectTransferRestriction(_from,_to,_amount)](src/modules/RuleEngineValidation.sol#L36-L37)
+[RuleSanctionsList._msgData()](src/rules/validation/RuleSanctionsList.sol#L254-L256) is never used and should be removed
-src/modules/RuleEngineValidation.sol#L29-L44
+src/rules/validation/RuleSanctionsList.sol#L254-L256
- [ ] ID-6
-[RuleEngine.messageForTransferRestriction(uint8)](src/RuleEngine.sol#L100-L128) has external calls inside a loop: [IRuleValidation(_rulesOperation[i_scope_0]).messageForTransferRestriction(_restrictionCode)](src/RuleEngine.sol#L122-L124)
+[RuleWhitelistWrapper._msgData()](src/rules/validation/RuleWhitelistWrapper.sol#L215-L217) is never used and should be removed
-src/RuleEngine.sol#L100-L128
+src/rules/validation/RuleWhitelistWrapper.sol#L215-L217
+## solc-version
+Impact: Informational
+Confidence: High
- [ ] ID-7
-[RuleEngine.messageForTransferRestriction(uint8)](src/RuleEngine.sol#L100-L128) has external calls inside a loop: [IRuleValidation(_rulesValidation[i]).canReturnTransferRestrictionCode(_restrictionCode)](src/RuleEngine.sol#L107-L108)
+Version constraint ^0.8.0 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)
+ - FullInlinerNonExpressionSplitArgumentEvaluationOrder
+ - MissingSideEffectsOnSelectorAccess
+ - AbiReencodingHeadOverflowWithStaticArrayCleanup
+ - DirtyBytesArrayToStorage
+ - DataLocationChangeInInternalOverride
+ - NestedCalldataArrayAbiReencodingSizeValidation
+ - SignedImmutables
+ - ABIDecodeTwoDimensionalArrayMemory
+ - KeccakCaching.
+It is used by:
+ - [^0.8.0](src/rules/interfaces/IAddressList.sol#L2)
-src/RuleEngine.sol#L100-L128
+src/rules/interfaces/IAddressList.sol#L2
+## naming-convention
+Impact: Informational
+Confidence: High
- [ ] ID-8
-[RuleEngine.messageForTransferRestriction(uint8)](src/RuleEngine.sol#L100-L128) has external calls inside a loop: [IRuleValidation(_rulesValidation[i]).messageForTransferRestriction(_restrictionCode)](src/RuleEngine.sol#L110-L112)
+Parameter [RuleBlacklist.canReturnTransferRestrictionCode(uint8)._restrictionCode](src/rules/validation/RuleBlacklist.sol#L103) is not in mixedCase
-src/RuleEngine.sol#L100-L128
+src/rules/validation/RuleBlacklist.sol#L103
- [ ] ID-9
-[RuleConditionalTransferOperator._approveRequest(RuleConditionalTransferInvariantStorage.TransferRequest,bool)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L390-L449) has external calls inside a loop: [options.automaticTransfer.cmtat.allowance(transferRequest.keyElement.from,address(this)) >= transferRequest.keyElement.value](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L426-L429)
+Parameter [RuleBlacklist.messageForTransferRestriction(uint8)._restrictionCode](src/rules/validation/RuleBlacklist.sol#L120) is not in mixedCase
-src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L390-L449
+src/rules/validation/RuleBlacklist.sol#L120
+## constable-states
+Impact: Optimization
+Confidence: High
- [ ] ID-10
-[RuleEngine.messageForTransferRestriction(uint8)](src/RuleEngine.sol#L100-L128) has external calls inside a loop: [IRuleValidation(_rulesOperation[i_scope_0]).canReturnTransferRestrictionCode(_restrictionCode)](src/RuleEngine.sol#L119-L120)
+[RuleAddressSet._listedAddressCountCache](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L33) should be constant
-src/RuleEngine.sol#L100-L128
+src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L33
+## var-read-using-this
+Impact: Optimization
+Confidence: High
- [ ] ID-11
-[RuleEngine.detectTransferRestriction(address,address,uint256)](src/RuleEngine.sol#L50-L76) has external calls inside a loop: [restriction = IRuleValidation(_rulesOperation[i]).detectTransferRestriction(_from,_to,_amount)](src/RuleEngine.sol#L68-L69)
+The function [RuleSanctionsList.transferred(address,address,address,uint256)](src/rules/validation/RuleSanctionsList.sol#L201-L212) reads [code = this.detectTransferRestrictionFrom(spender,from,to,value)](src/rules/validation/RuleSanctionsList.sol#L207) with `this` which adds an extra STATICCALL.
-src/RuleEngine.sol#L50-L76
+src/rules/validation/RuleSanctionsList.sol#L201-L212
-## timestamp
-
-> With the Proof of Work, it was possible for a miner to modify the timestamp in a range of about 15 seconds
->
-> With the Proof Of Stake, a new block is created every 12 seconds
->
-> In all cases, we are not looking for such precision
->
-> btw, ID-13 and ID-15 don't use timestamp in their comparison
-
-Impact: Low
-Confidence: Medium
- [ ] ID-12
- [RuleConditionalTransfer._validateApproval(bytes32)](src/rules/operation/RuleConditionalTransfer.sol#L329-L349) uses timestamp for comparisons
- Dangerous comparisons:
- - [automaticApprovalCondition = options.automaticApproval.isActivate && block.timestamp >= (transferRequests[key].askTime + options.automaticApproval.timeLimitBeforeAutomaticApproval)](src/rules/operation/RuleConditionalTransfer.sol#L334-L339)
- - [isTransferApproved = (transferRequests[key].status == STATUS.APPROVED) && (transferRequests[key].maxTime >= block.timestamp)](src/rules/operation/RuleConditionalTransfer.sol#L341-L343)
- - [automaticApprovalCondition || isTransferApproved](src/rules/operation/RuleConditionalTransfer.sol#L344)
+The function [RuleWhitelistCommon.transferred(address,address,address,uint256)](src/rules/validation/abstract/RuleWhitelistCommon.sol#L97-L103) reads [code = this.detectTransferRestrictionFrom(spender,from,to,value)](src/rules/validation/abstract/RuleWhitelistCommon.sol#L98) with `this` which adds an extra STATICCALL.
-src/rules/operation/RuleConditionalTransfer.sol#L329-L349
+src/rules/validation/abstract/RuleWhitelistCommon.sol#L97-L103
- [ ] ID-13
- [RuleConditionalTransferOperator._checkRequestStatus(bytes32)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L383-L388) uses timestamp for comparisons
- Dangerous comparisons:
- - [(transferRequests[key].status == STATUS.NONE) && (transferRequests[key].key == 0x0)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L385-L387)
+The function [RuleBlacklist.transferred(address,address,uint256)](src/rules/validation/RuleBlacklist.sol#L144-L155) reads [code = this.detectTransferRestriction(from,to,value)](src/rules/validation/RuleBlacklist.sol#L150) with `this` which adds an extra STATICCALL.
-src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L383-L388
+src/rules/validation/RuleBlacklist.sol#L144-L155
- [ ] ID-14
- [RuleConditionalTransfer.getRequestByStatus(RuleConditionalTransferInvariantStorage.STATUS)](src/rules/operation/RuleConditionalTransfer.sol#L177-L206) uses timestamp for comparisons
- Dangerous comparisons:
- - [transferRequests[IdToKey[i]].status == _targetStatus](src/rules/operation/RuleConditionalTransfer.sol#L186)
- - [transferRequests[IdToKey[i_scope_0]].status == _targetStatus](src/rules/operation/RuleConditionalTransfer.sol#L196)
+The function [RuleBlacklist.transferred(address,address,address,uint256)](src/rules/validation/RuleBlacklist.sol#L157-L168) reads [code = this.detectTransferRestrictionFrom(spender,from,to,value)](src/rules/validation/RuleBlacklist.sol#L163) with `this` which adds an extra STATICCALL.
-src/rules/operation/RuleConditionalTransfer.sol#L177-L206
+src/rules/validation/RuleBlacklist.sol#L157-L168
- [ ] ID-15
- [RuleConditionalTransfer._cancelTransferRequest(uint256)](src/rules/operation/RuleConditionalTransfer.sol#L281-L298) uses timestamp for comparisons
- Dangerous comparisons:
- - [transferRequests[key].keyElement.from != _msgSender()](src/rules/operation/RuleConditionalTransfer.sol#L287)
+The function [RuleWhitelistCommon.transferred(address,address,uint256)](src/rules/validation/abstract/RuleWhitelistCommon.sol#L79-L85) reads [code = this.detectTransferRestriction(from,to,value)](src/rules/validation/abstract/RuleWhitelistCommon.sol#L80) with `this` which adds an extra STATICCALL.
-src/rules/operation/RuleConditionalTransfer.sol#L281-L298
+src/rules/validation/abstract/RuleWhitelistCommon.sol#L79-L85
- [ ] ID-16
- [RuleConditionalTransferOperator._approveRequest(RuleConditionalTransferInvariantStorage.TransferRequest,bool)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L390-L449) uses timestamp for comparisons
- Dangerous comparisons:
- - [transferRequest.status != STATUS.WAIT](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L395)
- - [block.timestamp > (transferRequest.askTime + options.timeLimit.timeLimitToApprove)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L401-L402)
- - [options.automaticTransfer.cmtat.allowance(transferRequest.keyElement.from,address(this)) >= transferRequest.keyElement.value](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L426-L429)
-
-src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L390-L449
+The function [RuleValidateTransfer.canTransfer(address,address,uint256)](src/rules/validation/abstract/RuleValidateTransfer.sol#L45-L53) reads [this.detectTransferRestriction(from,to,amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK)](src/rules/validation/abstract/RuleValidateTransfer.sol#L52) with `this` which adds an extra STATICCALL.
-## costly-loop
+src/rules/validation/abstract/RuleValidateTransfer.sol#L45-L53
-> Acknowledge
-Impact: Informational
-Confidence: Medium
- [ ] ID-17
- [RuleConditionalTransfer.createTransferRequest(address,uint256)](src/rules/operation/RuleConditionalTransfer.sol#L79-L118) has costly operations inside a loop:
- - [++ requestId](src/rules/operation/RuleConditionalTransfer.sol#L105)
+The function [RuleValidateTransfer.canTransferFrom(address,address,address,uint256)](src/rules/validation/abstract/RuleValidateTransfer.sol#L58-L67) reads [this.detectTransferRestrictionFrom(spender,from,to,value) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK)](src/rules/validation/abstract/RuleValidateTransfer.sol#L65-L66) with `this` which adds an extra STATICCALL.
-src/rules/operation/RuleConditionalTransfer.sol#L79-L118
+src/rules/validation/abstract/RuleValidateTransfer.sol#L58-L67
- [ ] ID-18
- [RuleConditionalTransferOperator._createTransferRequestWithApproval(RuleConditionalTransferInvariantStorage.TransferRequestKeyElement)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L325-L370) has costly operations inside a loop:
- - [++ requestId](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L354)
+The function [RuleSanctionsList.transferred(address,address,uint256)](src/rules/validation/RuleSanctionsList.sol#L184-L195) reads [code = this.detectTransferRestriction(from,to,value)](src/rules/validation/RuleSanctionsList.sol#L190) with `this` which adds an extra STATICCALL.
-src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L325-L370
-
-## dead-code
+src/rules/validation/RuleSanctionsList.sol#L184-L195
-> - Implemented to be gasless compatible (see MetaTxModule)
->
-> - If we remove this function, we will have the following error:
->
-> "Derived contract must override function "_msgData". Two or more base classes define function with same name and parameter types."
-
-Impact: Informational
-Confidence: Medium
- [ ] ID-19
-[RuleSanctionList._msgData()](src/rules/validation/RuleSanctionList.sol#L145-L152) is never used and should be removed
-
-src/rules/validation/RuleSanctionList.sol#L145-L152
-
-
- - [ ] ID-20
-[RuleAddressList._msgData()](src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol#L156-L163) is never used and should be removed
-
-src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol#L156-L163
-
-
- - [ ] ID-21
-[RuleWhitelistWrapper._msgData()](src/rules/validation/RuleWhitelistWrapper.sol#L110-L117) is never used and should be removed
-
-src/rules/validation/RuleWhitelistWrapper.sol#L110-L117
-
-
- - [ ] ID-22
-[RuleConditionalTransfer._msgData()](src/rules/operation/RuleConditionalTransfer.sol#L370-L377) is never used and should be removed
-
-src/rules/operation/RuleConditionalTransfer.sol#L370-L377
-
-
- - [ ] ID-23
-[RuleEngine._msgData()](src/RuleEngine.sol#L182-L189) is never used and should be removed
-
-src/RuleEngine.sol#L182-L189
-
-## solc-version
-
-> The version set in the config file is 0.8.27
-
-Impact: Informational
-Confidence: High
-
- - [ ] ID-24
- Version constraint ^0.8.20 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)
- - VerbatimInvalidDeduplication
- - FullInlinerNonExpressionSplitArgumentEvaluationOrder
- - MissingSideEffectsOnSelectorAccess.
- It is used by:
- - lib/CMTAT/contracts/interfaces/draft-IERC1404/draft-IERC1404.sol#3
- - lib/CMTAT/contracts/interfaces/draft-IERC1404/draft-IERC1404EnumCode.sol#3
- - lib/CMTAT/contracts/interfaces/draft-IERC1404/draft-IERC1404Wrapper.sol#3
- - lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol#3
- - lib/openzeppelin-contracts/contracts/access/AccessControl.sol#4
- - lib/openzeppelin-contracts/contracts/access/IAccessControl.sol#4
- - lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol#4
- - lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol#4
- - lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol#4
- - lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol#4
- - lib/openzeppelin-contracts/contracts/utils/Address.sol#4
- - lib/openzeppelin-contracts/contracts/utils/Context.sol#4
- - lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol#4
- - lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol#4
- - src/RuleEngine.sol#3
- - src/interfaces/IRuleEngineOperation.sol#3
- - src/interfaces/IRuleEngineValidation.sol#3
- - src/interfaces/IRuleOperation.sol#3
- - src/interfaces/IRuleValidation.sol#3
- - src/modules/MetaTxModuleStandalone.sol#3
- - src/modules/RuleEngineInvariantStorage.sol#3
- - src/modules/RuleEngineOperation.sol#3
- - src/modules/RuleEngineValidation.sol#3
- - src/modules/RuleEngineValidationCommon.sol#3
- - src/modules/RuleInternal.sol#3
- - src/rules/operation/RuleConditionalTransfer.sol#3
- - src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#3
- - src/rules/operation/abstract/RuleConditionalTransferOperator.sol#3
- - src/rules/validation/RuleBlacklist.sol#3
- - src/rules/validation/RuleSanctionList.sol#3
- - src/rules/validation/RuleWhitelist.sol#3
- - src/rules/validation/RuleWhitelistWrapper.sol#3
- - src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol#3
- - src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol#3
- - src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol#3
- - src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol#3
- - src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol#3
- - src/rules/validation/abstract/RuleCommonInvariantStorage.sol#2
- - src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol#3
- - src/rules/validation/abstract/RuleValidateTransfer.sol#3
- - src/rules/validation/abstract/RuleWhitelistCommon.sol#3
-
-## naming-convention
-
-> Acknowledge
-
-Impact: Informational
-Confidence: High
-
- - [ ] ID-25
-Event [RuleConditionalTransferInvariantStorage.transferDenied(bytes32,address,address,uint256,uint256)](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L124-L130) is not in CapWords
-
-src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L124-L130
-
-
- - [ ] ID-26
-Parameter [RuleConditionalTransfer.operateOnTransfer(address,address,uint256)._amount](src/rules/operation/RuleConditionalTransfer.sol#L54) is not in mixedCase
-
-src/rules/operation/RuleConditionalTransfer.sol#L54
-
-
- - [ ] ID-27
-Parameter [RuleWhitelistCommon.canReturnTransferRestrictionCode(uint8)._restrictionCode](src/rules/validation/abstract/RuleWhitelistCommon.sol#L18) is not in mixedCase
-
-src/rules/validation/abstract/RuleWhitelistCommon.sol#L18
-
-
- - [ ] ID-28
-Parameter [RuleValidateTransfer.validateTransfer(address,address,uint256)._from](src/rules/validation/abstract/RuleValidateTransfer.sol#L16) is not in mixedCase
-
-src/rules/validation/abstract/RuleValidateTransfer.sol#L16
-
-
- - [ ] ID-29
-Parameter [RuleEngine.detectTransferRestriction(address,address,uint256)._amount](src/RuleEngine.sol#L53) is not in mixedCase
-
-src/RuleEngine.sol#L53
-
-
- - [ ] ID-30
-Event [RuleConditionalTransferInvariantStorage.transferReset(bytes32,address,address,uint256,uint256)](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L131-L137) is not in CapWords
-
-src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L131-L137
-
-
- - [ ] ID-31
-Parameter [RuleEngineValidation.detectTransferRestrictionValidation(address,address,uint256)._amount](src/modules/RuleEngineValidation.sol#L32) is not in mixedCase
-
-src/modules/RuleEngineValidation.sol#L32
-
-
- - [ ] ID-32
-Parameter [RuleBlacklist.canReturnTransferRestrictionCode(uint8)._restrictionCode](src/rules/validation/RuleBlacklist.sol#L53) is not in mixedCase
-
-src/rules/validation/RuleBlacklist.sol#L53
-
-
- - [ ] ID-33
-Parameter [RuleWhitelistCommon.messageForTransferRestriction(uint8)._restrictionCode](src/rules/validation/abstract/RuleWhitelistCommon.sol#L31) is not in mixedCase
-
-src/rules/validation/abstract/RuleWhitelistCommon.sol#L31
-
-
- - [ ] ID-34
-Variable [RuleConditionalTransferOperator.IdToKey](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L21) is not in mixedCase
-
-src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L21
-
-
- - [ ] ID-35
-Parameter [RuleSanctionList.detectTransferRestriction(address,address,uint256)._to](src/rules/validation/RuleSanctionList.sol#L59) is not in mixedCase
-
-src/rules/validation/RuleSanctionList.sol#L59
-
-
- - [ ] ID-36
-Parameter [RuleBlacklist.detectTransferRestriction(address,address,uint256)._to](src/rules/validation/RuleBlacklist.sol#L35) is not in mixedCase
-
-src/rules/validation/RuleBlacklist.sol#L35
-
-
- - [ ] ID-37
-Parameter [RuleEngine.detectTransferRestriction(address,address,uint256)._to](src/RuleEngine.sol#L52) is not in mixedCase
-
-src/RuleEngine.sol#L52
-
-
- - [ ] ID-38
-Parameter [RuleConditionalTransfer.detectTransferRestriction(address,address,uint256)._amount](src/rules/operation/RuleConditionalTransfer.sol#L217) is not in mixedCase
-
-src/rules/operation/RuleConditionalTransfer.sol#L217
-
-
- - [ ] ID-39
-Parameter [RuleConditionalTransfer.getRequestByStatus(RuleConditionalTransferInvariantStorage.STATUS)._targetStatus](src/rules/operation/RuleConditionalTransfer.sol#L178) is not in mixedCase
-
-src/rules/operation/RuleConditionalTransfer.sol#L178
-
-
- - [ ] ID-40
-Parameter [RuleEngine.detectTransferRestriction(address,address,uint256)._from](src/RuleEngine.sol#L51) is not in mixedCase
-
-src/RuleEngine.sol#L51
-
-
- - [ ] ID-41
-Parameter [RuleWhitelistWrapper.detectTransferRestriction(address,address,uint256)._to](src/rules/validation/RuleWhitelistWrapper.sol#L41) is not in mixedCase
-
-src/rules/validation/RuleWhitelistWrapper.sol#L41
-
-
- - [ ] ID-42
-Parameter [RuleConditionalTransfer.operateOnTransfer(address,address,uint256)._from](src/rules/operation/RuleConditionalTransfer.sol#L52) is not in mixedCase
-
-src/rules/operation/RuleConditionalTransfer.sol#L52
-
-
- - [ ] ID-43
-Parameter [RuleBlacklist.messageForTransferRestriction(uint8)._restrictionCode](src/rules/validation/RuleBlacklist.sol#L66) is not in mixedCase
-
-src/rules/validation/RuleBlacklist.sol#L66
-
-
- - [ ] ID-44
-Parameter [RuleEngine.messageForTransferRestriction(uint8)._restrictionCode](src/RuleEngine.sol#L101) is not in mixedCase
-
-src/RuleEngine.sol#L101
-
-
- - [ ] ID-45
-Parameter [RuleSanctionList.canReturnTransferRestrictionCode(uint8)._restrictionCode](src/rules/validation/RuleSanctionList.sol#L78) is not in mixedCase
-
-src/rules/validation/RuleSanctionList.sol#L78
-
+The function [RuleValidateTransfer.canTransfer(address,address,uint256,uint256)](src/rules/validation/abstract/RuleValidateTransfer.sol#L26-L35) reads [this.detectTransferRestriction(from,to,tokenId,amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK)](src/rules/validation/abstract/RuleValidateTransfer.sol#L33-L34) with `this` which adds an extra STATICCALL.
- - [ ] ID-46
-Parameter [RuleAddressList.addressIsListed(address)._targetAddress](src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol#L103) is not in mixedCase
-
-src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol#L103
-
-
- - [ ] ID-47
-Parameter [RuleEngineValidation.validateTransferValidation(address,address,uint256)._to](src/modules/RuleEngineValidation.sol#L55) is not in mixedCase
-
-src/modules/RuleEngineValidation.sol#L55
-
-
- - [ ] ID-48
-Event [RuleConditionalTransferInvariantStorage.transferWaiting(bytes32,address,address,uint256,uint256)](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L110-L116) is not in CapWords
-
-src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L110-L116
-
-
- - [ ] ID-49
-Struct [RuleConditionalTransferInvariantStorage.TIME_LIMIT](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L30-L35) is not in CapWords
-
-src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L30-L35
-
-
- - [ ] ID-50
-Parameter [RuleConditionalTransfer.canReturnTransferRestrictionCode(uint8)._restrictionCode](src/rules/operation/RuleConditionalTransfer.sol#L237) is not in mixedCase
-
-src/rules/operation/RuleConditionalTransfer.sol#L237
-
-
- - [ ] ID-51
-Parameter [RuleEngine.validateTransfer(address,address,uint256)._amount](src/RuleEngine.sol#L88) is not in mixedCase
-
-src/RuleEngine.sol#L88
-
-
- - [ ] ID-52
-Struct [RuleConditionalTransferInvariantStorage.AUTOMATIC_APPROVAL](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L37-L44) is not in CapWords
-
-src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L37-L44
-
-
- - [ ] ID-53
-Parameter [RuleEngineValidation.validateTransferValidation(address,address,uint256)._from](src/modules/RuleEngineValidation.sol#L54) is not in mixedCase
-
-src/modules/RuleEngineValidation.sol#L54
-
-
- - [ ] ID-54
-Parameter [RuleSanctionList.detectTransferRestriction(address,address,uint256)._from](src/rules/validation/RuleSanctionList.sol#L58) is not in mixedCase
-
-src/rules/validation/RuleSanctionList.sol#L58
-
-
- - [ ] ID-55
-Parameter [RuleConditionalTransfer.detectTransferRestriction(address,address,uint256)._to](src/rules/operation/RuleConditionalTransfer.sol#L216) is not in mixedCase
-
-src/rules/operation/RuleConditionalTransfer.sol#L216
-
-
- - [ ] ID-56
-Parameter [RuleEngineValidation.detectTransferRestrictionValidation(address,address,uint256)._from](src/modules/RuleEngineValidation.sol#L30) is not in mixedCase
-
-src/modules/RuleEngineValidation.sol#L30
-
-
- - [ ] ID-57
-Parameter [RuleEngineValidation.validateTransferValidation(address,address,uint256)._amount](src/modules/RuleEngineValidation.sol#L56) is not in mixedCase
-
-src/modules/RuleEngineValidation.sol#L56
-
-
- - [ ] ID-58
-Parameter [RuleWhitelistWrapper.detectTransferRestriction(address,address,uint256)._from](src/rules/validation/RuleWhitelistWrapper.sol#L40) is not in mixedCase
-
-src/rules/validation/RuleWhitelistWrapper.sol#L40
-
-
- - [ ] ID-59
-Parameter [RuleWhitelist.detectTransferRestriction(address,address,uint256)._to](src/rules/validation/RuleWhitelist.sol#L29) is not in mixedCase
-
-src/rules/validation/RuleWhitelist.sol#L29
-
-
- - [ ] ID-60
-Struct [RuleConditionalTransferInvariantStorage.AUTOMATIC_TRANSFER](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L18-L21) is not in CapWords
-
-src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L18-L21
-
-
- - [ ] ID-61
-Parameter [RuleValidateTransfer.validateTransfer(address,address,uint256)._to](src/rules/validation/abstract/RuleValidateTransfer.sol#L17) is not in mixedCase
-
-src/rules/validation/abstract/RuleValidateTransfer.sol#L17
-
-
- - [ ] ID-62
-Event [RuleConditionalTransferInvariantStorage.transferProcessed(bytes32,address,address,uint256,uint256)](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L103-L109) is not in CapWords
-
-src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L103-L109
-
-
- - [ ] ID-63
-Parameter [RuleWhitelist.detectTransferRestriction(address,address,uint256)._from](src/rules/validation/RuleWhitelist.sol#L28) is not in mixedCase
-
-src/rules/validation/RuleWhitelist.sol#L28
-
-
- - [ ] ID-64
-Parameter [RuleValidateTransfer.validateTransfer(address,address,uint256)._amount](src/rules/validation/abstract/RuleValidateTransfer.sol#L18) is not in mixedCase
-
-src/rules/validation/abstract/RuleValidateTransfer.sol#L18
-
-
- - [ ] ID-65
-Parameter [RuleEngine.validateTransfer(address,address,uint256)._from](src/RuleEngine.sol#L86) is not in mixedCase
-
-src/RuleEngine.sol#L86
-
-
- - [ ] ID-66
-Parameter [RuleConditionalTransfer.operateOnTransfer(address,address,uint256)._to](src/rules/operation/RuleConditionalTransfer.sol#L53) is not in mixedCase
-
-src/rules/operation/RuleConditionalTransfer.sol#L53
-
-
- - [ ] ID-67
-Parameter [RuleConditionalTransfer.detectTransferRestriction(address,address,uint256)._from](src/rules/operation/RuleConditionalTransfer.sol#L215) is not in mixedCase
-
-src/rules/operation/RuleConditionalTransfer.sol#L215
-
-
- - [ ] ID-68
-Parameter [RuleEngineValidation.detectTransferRestrictionValidation(address,address,uint256)._to](src/modules/RuleEngineValidation.sol#L31) is not in mixedCase
-
-src/modules/RuleEngineValidation.sol#L31
-
-
- - [ ] ID-69
-Parameter [RuleBlacklist.detectTransferRestriction(address,address,uint256)._from](src/rules/validation/RuleBlacklist.sol#L34) is not in mixedCase
-
-src/rules/validation/RuleBlacklist.sol#L34
-
-
- - [ ] ID-70
-Parameter [RuleConditionalTransfer.messageForTransferRestriction(uint8)._restrictionCode](src/rules/operation/RuleConditionalTransfer.sol#L248) is not in mixedCase
-
-src/rules/operation/RuleConditionalTransfer.sol#L248
-
-
- - [ ] ID-71
-Parameter [RuleSanctionList.messageForTransferRestriction(uint8)._restrictionCode](src/rules/validation/RuleSanctionList.sol#L91) is not in mixedCase
-
-src/rules/validation/RuleSanctionList.sol#L91
-
-
- - [ ] ID-72
-Parameter [RuleAddressList.addressIsListedBatch(address[])._targetAddresses](src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol#L113) is not in mixedCase
-
-src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol#L113
-
-
- - [ ] ID-73
-Parameter [RuleEngine.validateTransfer(address,address,uint256)._to](src/RuleEngine.sol#L87) is not in mixedCase
-
-src/RuleEngine.sol#L87
-
-
- - [ ] ID-74
-Event [RuleConditionalTransferInvariantStorage.transferApproved(bytes32,address,address,uint256,uint256)](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L117-L123) is not in CapWords
-
-src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L117-L123
-
-## similar-names
-
-> Acknowlege
-
-Impact: Informational
-Confidence: Medium
- - [ ] ID-75
-Variable [RuleSanctionlistInvariantStorage.CODE_ADDRESS_FROM_IS_SANCTIONED](src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol#L27) is too similar to [RuleSanctionlistInvariantStorage.TEXT_ADDRESS_FROM_IS_SANCTIONED](src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol#L20-L21)
-
-src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol#L27
-
-
- - [ ] ID-76
-Variable [RuleConditionalTransferOperator._createTransferRequestWithApproval(RuleConditionalTransferInvariantStorage.TransferRequestKeyElement).keyElement_](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L326) is too similar to [RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch(RuleConditionalTransferInvariantStorage.TransferRequestKeyElement[]).keyElements](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L245)
-
-src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L326
-
-
- - [ ] ID-77
-Variable [RuleConditionalTransferOperator._createTransferRequestWithApproval(RuleConditionalTransferInvariantStorage.TransferRequestKeyElement).keyElement_](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L326) is too similar to [RuleConditionalTransferOperator.approveTransferRequestBatch(RuleConditionalTransferInvariantStorage.TransferRequestKeyElement[],uint256[],bool[]).keyElements](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L219)
-
-src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L326
-
-
- - [ ] ID-78
-Variable [RuleConditionalTransferInvariantStorage.CODE_TRANSFER_REQUEST_NOT_APPROVED](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L87) is too similar to [RuleConditionalTransferInvariantStorage.TEXT_TRANSFER_REQUEST_NOT_APPROVED](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L83-L84)
-
-src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L87
-
-
- - [ ] ID-79
-Variable [RuleBlacklistInvariantStorage.CODE_ADDRESS_FROM_IS_BLACKLISTED](src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol#L16) is too similar to [RuleBlacklistInvariantStorage.TEXT_ADDRESS_FROM_IS_BLACKLISTED](src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol#L9-L10)
-
-src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol#L16
-
-
- - [ ] ID-80
-Variable [RuleWhitelistInvariantStorage.CODE_ADDRESS_TO_NOT_WHITELISTED](src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol#L17) is too similar to [RuleWhitelistInvariantStorage.TEXT_ADDRESS_TO_NOT_WHITELISTED](src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol#L11-L12)
-
-src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol#L17
-
-
- - [ ] ID-81
-Variable [RuleWhitelistInvariantStorage.CODE_ADDRESS_FROM_NOT_WHITELISTED](src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol#L16) is too similar to [RuleWhitelistInvariantStorage.TEXT_ADDRESS_FROM_NOT_WHITELISTED](src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol#L9-L10)
-
-src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol#L16
-
-## unused-import
-
-> Concerns OpenZeppelin library
-
-Impact: Informational
-Confidence: High
- - [ ] ID-82
- The following unused import(s) in lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol should be removed:
- -import {IERC20Permit} from "../extensions/IERC20Permit.sol"; (lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol#7)
-
-## var-read-using-this
-
-> Don't manage to find a better solution
-
-Impact: Optimization
-Confidence: High
- - [ ] ID-83
-The function [RuleValidateTransfer.validateTransfer(address,address,uint256)](src/rules/validation/abstract/RuleValidateTransfer.sol#L15-L24) reads [this.detectTransferRestriction(_from,_to,_amount) == uint8(REJECTED_CODE_BASE.TRANSFER_OK)](src/rules/validation/abstract/RuleValidateTransfer.sol#L21-L23) with `this` which adds an extra STATICCALL.
+src/rules/validation/abstract/RuleValidateTransfer.sol#L26-L35
-src/rules/validation/abstract/RuleValidateTransfer.sol#L15-L24
diff --git a/doc/technical/RuleBlacklist.md b/doc/technical/RuleBlacklist.md
index 59ebb3c..1186217 100644
--- a/doc/technical/RuleBlacklist.md
+++ b/doc/technical/RuleBlacklist.md
@@ -15,35 +15,3 @@ A part of the code is shared with Rule Whitelist

-## Access Control
-
-### Admin
-
-The default admin is the address put in argument(`admin`) inside the constructor. It is set in the constructor when the contract is deployed.
-
-### Schema
-
-Here a schema of the Access Control.
-
-
-
-
-
-
-## Methods
-
-### Null address
-It is possible to add the null address (0x0) to the blacklist. If it is the case, it will not be possible to mint and burn tokens.
-
-### Duplicate address
-
-**addAddress**
-If the address already exists, the transaction is reverted to save gas.
-**addAddresses**
-If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert).
-
-### NonExistent Address
-**removeAddress**
-If the address does not exist in the whitelist, the transaction is reverted to save gas.
-**removeAddresses**
-If the address does not exist in the whitelist, there is no change for this address. The transaction remains valid (no revert).
diff --git a/doc/technical/RuleEngine.md b/doc/technical/RuleEngine.md
deleted file mode 100644
index 159cf07..0000000
--- a/doc/technical/RuleEngine.md
+++ /dev/null
@@ -1,58 +0,0 @@
-# RuleEngine
-
-[TOC]
-
-The RuleEngine is an external contract used to apply transfer restriction to the CMTAT.
-
-This contract acts as a controller and can call different contract rule to apply rule on each transfer.
-
-A possible rule is a whitelist rule where only the address inside the whitelist can perform a transfer
-
-## Schema
-
-
-
-### Graph
-
-
-
-
-
-
-
-## Access Control
-
-### Admin
-
-The default admin is the address put in argument(`admin`) inside the constructor. It is set in the constructor when the contract is deployed.
-
-### Schema
-
-Here a schema of the Access Control.
-
-
-By default, the `DEFAULT_ADMIN_ROLE` has the role `RULE_ENGINE_ROLE`.
-
-
-
-## Methods
-
-### Duplicate rules
-
-**setRules**
-
-If one rule is already present, the function is reverted
-
-**addRule**
-
-If one rule is already present, the function is reverted
-
-### Null address
-
-**setRules**
-
-The function is reverted if one rule is the zero address
-
-**addRule**
-
-The function is reverted if one rule is the zero address
diff --git a/doc/technical/RuleSanctionList.md b/doc/technical/RuleSanctionList.md
index 3ce697e..f9bf55a 100644
--- a/doc/technical/RuleSanctionList.md
+++ b/doc/technical/RuleSanctionList.md
@@ -20,7 +20,7 @@ The documentation and the contracts addresses are available here: [Chainalysis o
### Inheritance
-
+
## Access Control
@@ -32,7 +32,3 @@ The default admin is the address put in argument(`admin`) inside the constructor
Here a schema of the Access Control.
-**RuleSanctionList**
-
-
-
diff --git a/doc/technical/RuleWhitelist.md b/doc/technical/RuleWhitelist.md
index d74b8aa..d72c098 100644
--- a/doc/technical/RuleWhitelist.md
+++ b/doc/technical/RuleWhitelist.md
@@ -12,7 +12,7 @@ This rule can be used to restrict transfers from/to only addresses inside a whit
### Inheritance
-
+
## Access Control
diff --git a/doc/technical/RuleWhitelistWrapper.md b/doc/technical/RuleWhitelistWrapper.md
index 4895bf1..e8a0047 100644
--- a/doc/technical/RuleWhitelistWrapper.md
+++ b/doc/technical/RuleWhitelistWrapper.md
@@ -19,13 +19,13 @@ If this is the case, the rule return 0 (transfer valid) or an error otherwise.
### Inheritance
-
+
## Details
### Architecture
-This rule inherits from `RuleEngineValidationCommon`. Thus the whitelist rules are managed with the same architecture and code than for the ruleEngine. For example, rules are added with the functions `setRulesValidation` or `addRuleValidation`.
+
### Admin
diff --git a/foundry.toml b/foundry.toml
index 25b918f..388d129 100644
--- a/foundry.toml
+++ b/foundry.toml
@@ -1,6 +1,10 @@
[profile.default]
-src = "src"
-out = "out"
-libs = ["lib"]
+solc = "0.8.30"
+src = 'src'
+out = 'out'
+libs = ['lib']
+optimizer = true
+optimizer_runs = 200
+evm_version = 'prague'
# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
diff --git a/hardhat.config.js b/hardhat.config.js
index 83d9e54..8ebcba7 100644
--- a/hardhat.config.js
+++ b/hardhat.config.js
@@ -1,13 +1,12 @@
/** @type import('hardhat/config').HardhatUserConfig */
require("@nomicfoundation/hardhat-foundry");
-require('solidity-docgen');
module.exports = {
- solidity: "0.8.27",
+ solidity: "0.8.30",
settings: {
optimizer: {
enabled: true,
runs: 200
},
- evmVersion:"cancun"
+ evmVersion:"prague"
}
};
diff --git a/lib/CMTAT b/lib/CMTAT
index 305351b..69eecc9 160000
--- a/lib/CMTAT
+++ b/lib/CMTAT
@@ -1 +1 @@
-Subproject commit 305351bb1cff10cd87ff4bda6e263628c34b9543
+Subproject commit 69eecc9735ce8ada84fd35801888b05747658939
diff --git a/lib/RuleEngine b/lib/RuleEngine
index 461d32f..f3283c3 160000
--- a/lib/RuleEngine
+++ b/lib/RuleEngine
@@ -1 +1 @@
-Subproject commit 461d32fca6cf501d6c15f3aed5f18855b2a6581c
+Subproject commit f3283c3b8a99089c3c6f674150831003a6bd2927
diff --git a/lib/forge-std b/lib/forge-std
index c7be2a3..7117c90 160000
--- a/lib/forge-std
+++ b/lib/forge-std
@@ -1 +1 @@
-Subproject commit c7be2a3481f9e51230880bb0949072c7e3a4da82
+Subproject commit 7117c90c8cf6c68e5acce4f09a6b24715cea4de6
diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts
index c64a1ed..fcbae53 160000
--- a/lib/openzeppelin-contracts
+++ b/lib/openzeppelin-contracts
@@ -1 +1 @@
-Subproject commit c64a1edb67b6e3f4a15cca8909c9482ad33a02b0
+Subproject commit fcbae5394ae8ad52d8e580a3477db99814b9d565
diff --git a/package-lock.json b/package-lock.json
index 755c254..27c66e9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,5 +1,5 @@
{
- "name": "RuleEngine",
+ "name": "Rules",
"lockfileVersion": 2,
"requires": true,
"packages": {
@@ -9,7 +9,6 @@
"ethlint": "^1.2.5",
"prettier-plugin-solidity": "^1.0.0-rc.1",
"sol2uml": "^2.5.20",
- "solidity-docgen": "^0.6.0-beta.35",
"surya": "^0.4.6"
}
},
@@ -3969,45 +3968,6 @@
"node": ">=4.x"
}
},
- "node_modules/handlebars": {
- "version": "4.7.7",
- "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
- "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
- "dev": true,
- "dependencies": {
- "minimist": "^1.2.5",
- "neo-async": "^2.6.0",
- "source-map": "^0.6.1",
- "wordwrap": "^1.0.0"
- },
- "bin": {
- "handlebars": "bin/handlebars"
- },
- "engines": {
- "node": ">=0.4.7"
- },
- "optionalDependencies": {
- "uglify-js": "^3.1.4"
- }
- },
- "node_modules/handlebars/node_modules/minimist": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/handlebars/node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/hardhat": {
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.14.0.tgz",
@@ -6184,12 +6144,6 @@
"dev": true,
"peer": true
},
- "node_modules/neo-async": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
- "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
- "dev": true
- },
"node_modules/next-tick": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
@@ -8010,31 +7964,12 @@
"node": ">=0.6.0"
}
},
- "node_modules/solidity-ast": {
- "version": "0.4.49",
- "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.49.tgz",
- "integrity": "sha512-Pr5sCAj1SFqzwFZw1HPKSq0PehlQNdM8GwKyAVYh2DOn7/cCK8LUKD1HeHnKtTgBW7hi9h4nnnan7hpAg5RhWQ==",
- "dev": true
- },
"node_modules/solidity-comments-extractor": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz",
"integrity": "sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==",
"dev": true
},
- "node_modules/solidity-docgen": {
- "version": "0.6.0-beta.35",
- "resolved": "https://registry.npmjs.org/solidity-docgen/-/solidity-docgen-0.6.0-beta.35.tgz",
- "integrity": "sha512-9QdwK1THk/MWIdq1PEW/6dvtND0pUqpFTsbKwwU9YQIMYuRhH1lek9SsgnsGGYtdJ0VTrXXcVT30q20a8Y610A==",
- "dev": true,
- "dependencies": {
- "handlebars": "^4.7.7",
- "solidity-ast": "^0.4.38"
- },
- "peerDependencies": {
- "hardhat": "^2.8.0"
- }
- },
"node_modules/solium": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/solium/-/solium-1.2.5.tgz",
@@ -8779,19 +8714,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/uglify-js": {
- "version": "3.17.4",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
- "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
- "dev": true,
- "optional": true,
- "bin": {
- "uglifyjs": "bin/uglifyjs"
- },
- "engines": {
- "node": ">=0.8.0"
- }
- },
"node_modules/unbzip2-stream": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
@@ -8973,12 +8895,6 @@
"integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==",
"dev": true
},
- "node_modules/wordwrap": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
- "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
- "dev": true
- },
"node_modules/workerpool": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
@@ -12271,33 +12187,6 @@
"integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==",
"dev": true
},
- "handlebars": {
- "version": "4.7.7",
- "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
- "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
- "dev": true,
- "requires": {
- "minimist": "^1.2.5",
- "neo-async": "^2.6.0",
- "source-map": "^0.6.1",
- "uglify-js": "^3.1.4",
- "wordwrap": "^1.0.0"
- },
- "dependencies": {
- "minimist": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "dev": true
- },
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- }
- }
- },
"hardhat": {
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.14.0.tgz",
@@ -13965,12 +13854,6 @@
"dev": true,
"peer": true
},
- "neo-async": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
- "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
- "dev": true
- },
"next-tick": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
@@ -15401,28 +15284,12 @@
}
}
},
- "solidity-ast": {
- "version": "0.4.49",
- "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.49.tgz",
- "integrity": "sha512-Pr5sCAj1SFqzwFZw1HPKSq0PehlQNdM8GwKyAVYh2DOn7/cCK8LUKD1HeHnKtTgBW7hi9h4nnnan7hpAg5RhWQ==",
- "dev": true
- },
"solidity-comments-extractor": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz",
"integrity": "sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==",
"dev": true
},
- "solidity-docgen": {
- "version": "0.6.0-beta.35",
- "resolved": "https://registry.npmjs.org/solidity-docgen/-/solidity-docgen-0.6.0-beta.35.tgz",
- "integrity": "sha512-9QdwK1THk/MWIdq1PEW/6dvtND0pUqpFTsbKwwU9YQIMYuRhH1lek9SsgnsGGYtdJ0VTrXXcVT30q20a8Y610A==",
- "dev": true,
- "requires": {
- "handlebars": "^4.7.7",
- "solidity-ast": "^0.4.38"
- }
- },
"solium": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/solium/-/solium-1.2.5.tgz",
@@ -16026,13 +15893,6 @@
"dev": true,
"peer": true
},
- "uglify-js": {
- "version": "3.17.4",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
- "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
- "dev": true,
- "optional": true
- },
"unbzip2-stream": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
@@ -16181,12 +16041,6 @@
"integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==",
"dev": true
},
- "wordwrap": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
- "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
- "dev": true
- },
"workerpool": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
diff --git a/package.json b/package.json
index b76074f..6239783 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,6 @@
"ethlint": "^1.2.5",
"prettier-plugin-solidity": "^1.0.0-rc.1",
"sol2uml": "^2.5.20",
- "solidity-docgen": "^0.6.0-beta.35",
"surya": "^0.4.6"
}
}
diff --git a/src/modules/AccessControlModuleStandalone.sol b/src/modules/AccessControlModuleStandalone.sol
new file mode 100644
index 0000000..58d72b0
--- /dev/null
+++ b/src/modules/AccessControlModuleStandalone.sol
@@ -0,0 +1,46 @@
+//SPDX-License-Identifier: MPL-2.0
+
+pragma solidity ^0.8.20;
+
+/* ==== OpenZeppelin === */
+import {AccessControl} from "OZ/access/AccessControl.sol";
+
+abstract contract AccessControlModuleStandalone is AccessControl {
+ error AccessControlModuleStandalone_AddressZeroNotAllowed();
+ /* ============ Constructor ============ */
+ /**
+ * @notice Assigns the provided address as the default admin.
+ * @dev
+ * - Reverts if `admin` is the zero address.
+ * - Grants `DEFAULT_ADMIN_ROLE` to `admin`.
+ * The return value of `_grantRole` is intentionally ignored, as it returns `false`
+ * only when the role was already granted.
+ *
+ * @param admin The address that will receive the `DEFAULT_ADMIN_ROLE`.
+ */
+
+ constructor(address admin) {
+ if (admin == address(0)) {
+ revert AccessControlModuleStandalone_AddressZeroNotAllowed();
+ }
+ // we don't check the return value
+ // _grantRole attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
+ // return false only if the admin has already the role
+ _grantRole(DEFAULT_ADMIN_ROLE, admin);
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ PUBLIC/EXTERNAL FUNCTIONS
+ //////////////////////////////////////////////////////////////*/
+ /**
+ * @dev Returns `true` if `account` has been granted `role`.
+ */
+ function hasRole(bytes32 role, address account) public view virtual override(AccessControl) returns (bool) {
+ // The Default Admin has all roles
+ if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
+ return true;
+ } else {
+ return AccessControl.hasRole(role, account);
+ }
+ }
+}
diff --git a/src/rules/interfaces/IAddressList.sol b/src/rules/interfaces/IAddressList.sol
new file mode 100644
index 0000000..7b2176f
--- /dev/null
+++ b/src/rules/interfaces/IAddressList.sol
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import {IIdentityRegistryContains} from "./IIdentityRegistry.sol";
+
+interface IAddressList is IIdentityRegistryContains {
+ /* ============ Events ============ */
+ /// @notice Emitted when multiple addresses are added.
+ /// @param targetAddresses The array of added addresses.
+ event AddAddresses(address[] targetAddresses);
+
+ /// @notice Emitted when multiple addresses are removed.
+ /// @param targetAddresses The array of removed addresses.
+ event RemoveAddresses(address[] targetAddresses);
+
+ /// @notice Emitted when a single address is added.
+ /// @param targetAddress The added address.
+ event AddAddress(address targetAddress);
+
+ /// @notice Emitted when a single address is removed.
+ /// @param targetAddress The removed address.
+ event RemoveAddress(address targetAddress);
+
+ /* ============ Write ============ */
+ /**
+ * @notice Adds multiple addresses to the set.
+ * @dev Does not revert if some addresses are already listed.
+ * @param targetAddresses The addresses to add.
+ */
+ function addAddresses(address[] calldata targetAddresses) external;
+
+ /**
+ * @notice Removes multiple addresses from the set.
+ * @dev Does not revert if some addresses are not listed.
+ * @param targetAddresses The addresses to remove.
+ */
+ function removeAddresses(address[] calldata targetAddresses) external;
+
+ /**
+ * @notice Adds a single address to the set.
+ * @dev Reverts if the address is already listed.
+ * @param targetAddress The address to add.
+ */
+ function addAddress(address targetAddress) external;
+
+ /**
+ * @notice Removes a single address from the set.
+ * @dev Reverts if the address is not listed.
+ * @param targetAddress The address to remove.
+ */
+ function removeAddress(address targetAddress) external;
+
+ /* ============ Read ============ */
+
+ /**
+ * @notice Returns the number of currently listed addresses.
+ * @return count The number of listed addresses.
+ */
+ function listedAddressCount() external view returns (uint256 count);
+
+ /**
+ * @notice Checks whether the provided address is listed.
+ * @param targetAddress The address to check.
+ * @return isListed True if listed, otherwise false.
+ */
+ function isAddressListed(address targetAddress) external view returns (bool isListed);
+
+ /**
+ * @notice Checks multiple addresses for listing status.
+ * @param targetAddresses Array of addresses to check.
+ * @return results Boolean array aligned by index with listing results.
+ */
+ function areAddressesListed(address[] memory targetAddresses) external view returns (bool[] memory results);
+}
diff --git a/src/rules/interfaces/IERC7943NonFungibleCompliance.sol b/src/rules/interfaces/IERC7943NonFungibleCompliance.sol
new file mode 100644
index 0000000..5807cb7
--- /dev/null
+++ b/src/rules/interfaces/IERC7943NonFungibleCompliance.sol
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: MPL-2.0
+
+pragma solidity ^0.8.20;
+
+/**
+ * @title IERC7943NonFungibleCompliance
+ * @notice Compliance interface for ERC-721/1155–style non-fungible assets.
+ * @dev
+ * - For ERC-721 tokens, `amount` MUST be set to `1`.
+ * - This interface defines a read-only compliance check used to determine
+ * whether a transfer is permitted according to rule-based restrictions.
+ */
+interface IERC7943NonFungibleCompliance {
+ /**
+ * @notice Verifies whether a transfer is permitted according to the token’s compliance rules.
+ * @dev
+ * This function must not modify state.
+ * It may enforce checks such as:
+ * - Allowlist / blocklist membership
+ * - Freezing rules
+ * - Transfer limitations
+ * - Jurisdictional, regulatory, or policy-driven restrictions
+ * If the transfer is not allowed, this function MUST return `false`.
+ *
+ * @param from The address currently holding the token.
+ * @param to The address intended to receive the token.
+ * @param tokenId The ERC-721/1155 token ID being transferred.
+ * @param amount The amount being transferred (always `1` for ERC-721).
+ * @return allowed `true` if the transfer is permitted, otherwise `false`.
+ */
+ function canTransfer(address from, address to, uint256 tokenId, uint256 amount)
+ external
+ view
+ returns (bool allowed);
+}
+
+/**
+ * @title IERC7943NonFungibleComplianceExtend
+ * @notice Extended compliance interface for ERC-721/1155–style non-fungible assets.
+ * @dev
+ * Adds functionality for:
+ * - Returning standardized transfer-restriction codes
+ * - Compliance checks involving a spender (e.g., approvals and operators)
+ * - Writing compliance-related state upon successful transfers
+ * For ERC-721, `amount/value` MUST be set to `1`.
+ */
+interface IERC7943NonFungibleComplianceExtend is IERC7943NonFungibleCompliance {
+ /**
+ * @notice Returns a transfer-restriction code describing why a transfer is blocked.
+ * @dev
+ * - MUST NOT modify state.
+ * - MUST return `0` when the transfer is allowed.
+ * - Non-zero codes SHOULD follow the ERC-1404 or RuleEngine restriction-code conventions.
+ *
+ * @param from The address currently holding the token.
+ * @param to The address intended to receive the token.
+ * @param tokenId The ERC-721/1155 token ID being checked.
+ * @param amount The amount being transferred (always `1` for ERC-721).
+ * @return code A restriction code: `0` for success, otherwise an implementation-defined error code.
+ */
+ function detectTransferRestriction(address from, address to, uint256 tokenId, uint256 amount)
+ external
+ view
+ returns (uint8 code);
+
+ /**
+ * @notice Returns a transfer-restriction code for transfers triggered by a spender.
+ * @dev
+ * Similar to `detectTransferRestriction`, but includes the spender performing the transfer.
+ * - MUST NOT modify state.
+ * - MUST return `0` when transfer is allowed.
+ *
+ * @param spender The caller executing the transfer (owner, operator, or approved address).
+ * @param from The current owner of the token.
+ * @param to The intended recipient.
+ * @param tokenId The token ID being checked.
+ * @param value The amount being transferred (always `1` for ERC-721).
+ * @return code A restriction code: `0` for allowed, otherwise a non-zero restriction identifier.
+ */
+ function detectTransferRestrictionFrom(address spender, address from, address to, uint256 tokenId, uint256 value)
+ external
+ view
+ returns (uint8 code);
+
+ /**
+ * @notice Determines whether a spender-initiated transfer is allowed.
+ * @dev
+ * - MUST NOT modify state.
+ * - Implementations SHOULD use `detectTransferRestrictionFrom` internally.
+ *
+ * @param spender The address performing the transfer (owner/operator).
+ * @param from The current token owner.
+ * @param to The recipient address.
+ * @param tokenId The token ID being transferred.
+ * @param value The transfer amount (always `1` for ERC-721).
+ * @return allowed `true` if the transfer is permitted, otherwise `false`.
+ */
+ function canTransferFrom(address spender, address from, address to, uint256 tokenId, uint256 value)
+ external
+ returns (bool allowed);
+
+ /**
+ * @notice Notifies the rule engine or compliance module that a transfer has been executed.
+ * @dev
+ * - MAY modify compliance-related state (e.g., consumption of approvals, updating limits).
+ * - MUST be called by the token contract after a successful transfer.
+ * - MUST revert if called by unauthorized contracts.
+ *
+ * @param from The previous owner of the token.
+ * @param to The new owner of the token.
+ * @param tokenId The token ID that was transferred.
+ * @param value The transfer amount (always `1` for ERC-721).
+ */
+ function transferred(address from, address to, uint256 tokenId, uint256 value) external;
+
+ /**
+ * @notice Notifies the rule engine or compliance module that a transfer has been executed.
+ * @dev
+ * - MAY modify compliance-related state (e.g., consumption of approvals, updating limits).
+ * - MUST be called by the token contract after a successful transfer.
+ * - MUST revert if called by unauthorized contracts.
+ *
+ * @param spender The address executing the transfer.
+ * @param from The previous owner of the token.
+ * @param to The new owner of the token.
+ * @param tokenId The token ID that was transferred.
+ * @param value The transfer amount (always `1` for ERC-721).
+ */
+ function transferred(address spender, address from, address to, uint256 tokenId, uint256 value) external;
+}
diff --git a/src/rules/interfaces/IIdentityRegistry.sol b/src/rules/interfaces/IIdentityRegistry.sol
new file mode 100644
index 0000000..86d11d3
--- /dev/null
+++ b/src/rules/interfaces/IIdentityRegistry.sol
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: MPL-2.0
+
+pragma solidity ^0.8.20;
+
+interface IIdentityRegistryVerified {
+ // registry consultation
+ function isVerified(address _userAddress) external view returns (bool);
+}
+
+interface IIdentityRegistryContains {
+ // registry consultation
+ function contains(address _userAddress) external view returns (bool);
+}
diff --git a/src/rules/interfaces/ISanctionsList.sol b/src/rules/interfaces/ISanctionsList.sol
new file mode 100644
index 0000000..8a5775f
--- /dev/null
+++ b/src/rules/interfaces/ISanctionsList.sol
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: MPL-2.0
+
+pragma solidity ^0.8.20;
+
+interface ISanctionsList {
+ function isSanctioned(address addr) external view returns (bool);
+}
diff --git a/src/rules/operation/RuleConditionalTransfer.sol b/src/rules/operation/RuleConditionalTransferOld
similarity index 100%
rename from src/rules/operation/RuleConditionalTransfer.sol
rename to src/rules/operation/RuleConditionalTransferOld
diff --git a/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol b/src/rules/operation/abstract/RuleConditionalTransferInvariantStorageOld
similarity index 100%
rename from src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol
rename to src/rules/operation/abstract/RuleConditionalTransferInvariantStorageOld
diff --git a/src/rules/operation/abstract/RuleConditionalTransferOperator.sol b/src/rules/operation/abstract/RuleConditionalTransferOperatorOld
similarity index 100%
rename from src/rules/operation/abstract/RuleConditionalTransferOperator.sol
rename to src/rules/operation/abstract/RuleConditionalTransferOperatorOld
diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol
index e057a22..3c31225 100644
--- a/src/rules/validation/RuleBlacklist.sol
+++ b/src/rules/validation/RuleBlacklist.sol
@@ -2,93 +2,186 @@
pragma solidity ^0.8.20;
-import "./abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol";
-import "./abstract/RuleAddressList/RuleAddressList.sol";
-import "./abstract/RuleValidateTransfer.sol";
+import {AccessControl} from "OZ/access/AccessControl.sol";
+/* ==== Abtract contracts === */
+import {RuleBlacklistInvariantStorage} from
+ "./abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol";
+import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol";
+import {RuleValidateTransfer, RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol";
+/* ==== Interfaces === */
+import {IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol";
+/* ==== CMTAT === */
+import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+/* ==== IRuleEngine === */
+import {IRule} from "RuleEngine/interfaces/IRule.sol";
/**
* @title a blacklist manager
*/
-
-contract RuleBlacklist is
- RuleValidateTransfer,
- RuleAddressList,
- RuleBlacklistInvariantStorage
-{
+contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInvariantStorage {
+ /*//////////////////////////////////////////////////////////////
+ CONSTRUCTOR
+ //////////////////////////////////////////////////////////////*/
/**
* @param admin Address of the contract (Access Control)
* @param forwarderIrrevocable Address of the forwarder, required for the gasless support
*/
- constructor(
- address admin,
- address forwarderIrrevocable
- ) RuleAddressList(admin, forwarderIrrevocable) {}
+ constructor(address admin, address forwarderIrrevocable) RuleAddressSet(admin, forwarderIrrevocable) {}
+ /* ============ View Functions ============ */
/**
* @notice Check if an addres is in the whitelist or not
* @param from the origin address
* @param to the destination address
* @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
- **/
- function detectTransferRestriction(
- address from,
- address to,
- uint256 /* value */
- ) public view override returns (uint8) {
- if (addressIsListed(from)) {
+ *
+ */
+ function detectTransferRestriction(address from, address to, uint256 /* value */ )
+ public
+ view
+ override(IERC1404)
+ returns (uint8)
+ {
+ if (isAddressListed(from)) {
return CODE_ADDRESS_FROM_IS_BLACKLISTED;
- } else if (addressIsListed(to)) {
+ } else if (isAddressListed(to)) {
return CODE_ADDRESS_TO_IS_BLACKLISTED;
} else {
- return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+ return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ }
+ }
+
+ /*
+ * @inheritdoc IERC7943NonFungibleComplianceExtend
+ */
+ function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value)
+ public
+ view
+ override(IERC7943NonFungibleComplianceExtend)
+ returns (uint8)
+ {
+ return detectTransferRestriction(from, to, value);
+ }
+
+ /*
+ * @inheritdoc IERC1404Extend
+ */
+ function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+ public
+ view
+ override(IERC1404Extend)
+ returns (uint8)
+ {
+ if (isAddressListed(spender)) {
+ return CODE_ADDRESS_SPENDER_IS_BLACKLISTED;
+ } else {
+ return detectTransferRestriction(from, to, value);
}
}
+ /**
+ * @inheritdoc IERC7943NonFungibleComplianceExtend
+ */
function detectTransferRestrictionFrom(
address spender,
address from,
address to,
+ uint256, /* tokenId */
uint256 value
- ) public view override returns (uint8) {
- if(addressIsListed(spender)){
- return CODE_ADDRESS_SPENDER_IS_BLACKLISTED;
- } else {
- return detectTransferRestriction(from, to, value);
- }
+ ) public view override(IERC7943NonFungibleComplianceExtend) returns (uint8) {
+ return detectTransferRestrictionFrom(spender, from, to, value);
}
-
/**
* @notice To know if the restriction code is valid for this rule or not.
* @param _restrictionCode The target restriction code
* @return true if the restriction code is known, false otherwise
- **/
- function canReturnTransferRestrictionCode(
- uint8 _restrictionCode
- ) external pure override returns (bool) {
- return
- _restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED ||
- _restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED
- || _restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED;
+ *
+ */
+ function canReturnTransferRestrictionCode(uint8 _restrictionCode)
+ public
+ pure
+ virtual
+ override(IRule)
+ returns (bool)
+ {
+ return _restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED
+ || _restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED || _restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED;
}
/**
* @notice Return the corresponding message
* @param _restrictionCode The target restriction code
* @return true if the transfer is valid, false otherwise
- **/
- function messageForTransferRestriction(
- uint8 _restrictionCode
- ) external pure override returns (string memory) {
+ *
+ */
+ function messageForTransferRestriction(uint8 _restrictionCode)
+ public
+ pure
+ virtual
+ override(IERC1404)
+ returns (string memory)
+ {
if (_restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED) {
return TEXT_ADDRESS_FROM_IS_BLACKLISTED;
} else if (_restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED) {
return TEXT_ADDRESS_TO_IS_BLACKLISTED;
} else if (_restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED) {
return TEXT_ADDRESS_SPENDER_IS_BLACKLISTED;
- }
- else {
+ } else {
return TEXT_CODE_NOT_FOUND;
}
}
+
+ function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) {
+ return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId);
+ }
+
+ /* ============ State Functions ============ */
+
+ function transferred(address from, address to, uint256 value)
+ public
+ view
+ virtual
+ override(IERC3643IComplianceContract)
+ {
+ uint8 code = this.detectTransferRestriction(from, to, value);
+ require(
+ code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+ RuleBlacklist_InvalidTransfer(address(this), from, to, value, code)
+ );
+ }
+
+ function transferred(address spender, address from, address to, uint256 value)
+ public
+ view
+ virtual
+ override(IRuleEngine)
+ {
+ uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value);
+ require(
+ code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+ RuleBlacklist_InvalidTransferFrom(address(this), spender, from, to, value, code)
+ );
+ }
+
+ function transferred(address spender, address from, address to, uint256 /* tokenId */,uint256 value)
+ public
+ view
+ virtual
+ override(IERC7943NonFungibleComplianceExtend)
+ {
+ transferred(spender, from, to, value);
+ }
+
+ function transferred(address from, address to, uint256 /* tokenId */,uint256 value)
+ public
+ view
+ virtual
+ override(IERC7943NonFungibleComplianceExtend)
+ {
+ transferred(from, to, value);
+ }
}
diff --git a/src/rules/validation/RuleSanctionList.sol b/src/rules/validation/RuleSanctionList.sol
deleted file mode 100644
index 66a7e1a..0000000
--- a/src/rules/validation/RuleSanctionList.sol
+++ /dev/null
@@ -1,185 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-
-pragma solidity ^0.8.20;
-
-import "OZ/access/AccessControl.sol";
-import "../../modules/MetaTxModuleStandalone.sol";
-import "./abstract/RuleSanctionListInvariantStorage.sol";
-import "./abstract/RuleValidateTransfer.sol";
-
-interface SanctionsList {
- function isSanctioned(address addr) external view returns (bool);
-}
-
-contract RuleSanctionList is
- AccessControl,
- MetaTxModuleStandalone,
- RuleValidateTransfer,
- RuleSanctionlistInvariantStorage
-{
- SanctionsList public sanctionsList;
-
- /**
- * @param admin Address of the contract (Access Control)
- * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
- */
- constructor(
- address admin,
- address forwarderIrrevocable,
- address sanctionContractOracle_
- ) MetaTxModuleStandalone(forwarderIrrevocable) {
- if (admin == address(0)) {
- revert RuleSanctionList_AdminWithAddressZeroNotAllowed();
- }
- if (sanctionContractOracle_ != address(0)) {
- _setSanctionListOracle(sanctionContractOracle_);
- }
- _grantRole(DEFAULT_ADMIN_ROLE, admin);
- }
-
- /**
- * @notice Set the oracle contract
- * @param sanctionContractOracle_ address of your oracle contract
- * @dev zero address is authorized to authorize all transfers
- */
- function setSanctionListOracle(
- address sanctionContractOracle_
- ) public onlyRole(SANCTIONLIST_ROLE) {
- _setSanctionListOracle(sanctionContractOracle_);
- }
-
- /**
- * @notice Check if an addres is in the whitelist or not
- * @param from the origin address
- * @param to the destination address
- * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
- **/
- function detectTransferRestriction(
- address from,
- address to,
- uint256 /*value */
- ) public view override returns (uint8) {
- if (address(sanctionsList) != address(0)) {
- if (sanctionsList.isSanctioned(from)) {
- return CODE_ADDRESS_FROM_IS_SANCTIONED;
- } else if (sanctionsList.isSanctioned(to)) {
- return CODE_ADDRESS_TO_IS_SANCTIONED;
- }
- }
- return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- }
-
-
- function detectTransferRestrictionFrom(
- address spender,
- address from,
- address to,
- uint256 value
- ) public view override returns (uint8) {
- if(address(sanctionsList) != address(0)){
- if (sanctionsList.isSanctioned(spender)) {
- return CODE_ADDRESS_SPENDER_IS_SANCTIONED;
- } else {
- return detectTransferRestriction(from,to,value);
- }
- }
- return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- }
-
- /**
- * @notice To know if the restriction code is valid for this rule or not.
- * @param _restrictionCode The target restriction code
- * @return true if the restriction code is known, false otherwise
- **/
- function canReturnTransferRestrictionCode(
- uint8 _restrictionCode
- ) external pure override returns (bool) {
- return
- _restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED ||
- _restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED||
- _restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED;
- }
-
- /**
- * @notice Return the corresponding message
- * @param _restrictionCode The target restriction code
- * @return true if the transfer is valid, false otherwise
- **/
- function messageForTransferRestriction(
- uint8 _restrictionCode
- ) external pure override returns (string memory) {
- if (_restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED) {
- return TEXT_ADDRESS_FROM_IS_SANCTIONED;
- } else if (_restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED) {
- return TEXT_ADDRESS_TO_IS_SANCTIONED;
- } else if (_restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED) {
- return TEXT_ADDRESS_SPENDER_IS_SANCTIONED;
- } else {
- return TEXT_CODE_NOT_FOUND;
- }
- }
-
- /* ============ ACCESS CONTROL ============ */
- /**
- * @dev Returns `true` if `account` has been granted `role`.
- */
- function hasRole(
- bytes32 role,
- address account
- ) public view virtual override(AccessControl) returns (bool) {
- // The Default Admin has all roles
- if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
- return true;
- }
- return AccessControl.hasRole(role, account);
- }
-
- /*//////////////////////////////////////////////////////////////
- INTERNAL FUNCTIONS
- //////////////////////////////////////////////////////////////*/
-
- function _setSanctionListOracle(address sanctionContractOracle_) internal {
- sanctionsList = SanctionsList(sanctionContractOracle_);
- emit SetSanctionListOracle(address(sanctionContractOracle_));
- }
-
- /*//////////////////////////////////////////////////////////////
- ERC-2771
- //////////////////////////////////////////////////////////////*/
-
- /**
- * @dev This surcharge is not necessary if you do not use the MetaTxModule
- */
- function _msgSender()
- internal
- view
- override(ERC2771Context, Context)
- returns (address sender)
- {
- return ERC2771Context._msgSender();
- }
-
- /**
- * @dev This surcharge is not necessary if you do not use the MetaTxModule
- */
- function _msgData()
- internal
- view
- override(ERC2771Context, Context)
- returns (bytes calldata)
- {
- return ERC2771Context._msgData();
- }
-
- /**
- * @dev This surcharge is not necessary if you do not use the MetaTxModule
- */
- function _contextSuffixLength()
- internal
- view
- override(ERC2771Context, Context)
- returns (uint256)
- {
- return ERC2771Context._contextSuffixLength();
- }
-}
diff --git a/src/rules/validation/RuleSanctionsList.sol b/src/rules/validation/RuleSanctionsList.sol
new file mode 100644
index 0000000..81a1fb5
--- /dev/null
+++ b/src/rules/validation/RuleSanctionsList.sol
@@ -0,0 +1,264 @@
+// SPDX-License-Identifier: MPL-2.0
+
+pragma solidity ^0.8.20;
+
+import {AccessControl} from "OZ/access/AccessControl.sol";
+/* ==== Abtract contracts === */
+import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../modules/MetaTxModuleStandalone.sol";
+import {AccessControlModuleStandalone} from "../../modules/AccessControlModuleStandalone.sol";
+import {RuleSanctionsListInvariantStorage} from "./abstract/RuleSanctionsListInvariantStorage.sol";
+import {RuleValidateTransfer, RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol";
+/* ==== Interfaces === */
+import {ISanctionsList} from "../interfaces/ISanctionsList.sol";
+import {IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol";
+/* ==== CMTAT === */
+import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+/* ==== IRuleEngine === */
+import {IRule} from "RuleEngine/interfaces/IRule.sol";
+
+
+/**
+ * @title RuleSanctionsList
+ * @notice Compliance rule enforcing sanctions-screening for token transfers.
+ * @dev
+ * This rule integrates a sanctions-oracle (e.g., Chainalysis) and blocks
+ * transfers when:
+ * - the sender is sanctioned,
+ * - the recipient is sanctioned,
+ * - or the spender/operator is sanctioned.
+ *
+ * Features:
+ * - Supports ERC-1404, ERC-3643 (transferred) and ERC-7943 non-fungible compliance flows.
+ * - Oracle address can be updated by accounts holding `SANCTIONLIST_ROLE`.
+ * - Zero oracle address disables sanctions checks (all transfers allowed).
+ *
+ * The rule is designed for RuleEngine or for direct integration with
+ * CMTAT / ERC-3643 compliant tokens.
+ */
+contract RuleSanctionsList is
+ AccessControlModuleStandalone,
+ MetaTxModuleStandalone,
+ RuleValidateTransfer,
+ RuleSanctionsListInvariantStorage
+{
+ ISanctionsList public sanctionsList;
+
+ /*//////////////////////////////////////////////////////////////
+ CONSTRUCTOR
+ //////////////////////////////////////////////////////////////*/
+ /**
+ * @param admin Address of the contract (Access Control)
+ * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
+ */
+ constructor(address admin, address forwarderIrrevocable, ISanctionsList sanctionContractOracle_)
+ MetaTxModuleStandalone(forwarderIrrevocable)
+ AccessControlModuleStandalone(admin)
+ {
+ if (address(sanctionContractOracle_) != address(0)) {
+ _setSanctionListOracle(sanctionContractOracle_);
+ }
+ }
+
+ /* ============ View Functions ============ */
+
+ /**
+ * @notice Check if an addres is in the SanctionsList or not
+ * @param from the origin address
+ * @param to the destination address
+ * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
+ *
+ */
+ function detectTransferRestriction(address from, address to, uint256 /*value */ )
+ public
+ view
+ override(IERC1404)
+ returns (uint8)
+ {
+ if (address(sanctionsList) != address(0)) {
+ if (sanctionsList.isSanctioned(from)) {
+ return CODE_ADDRESS_FROM_IS_SANCTIONED;
+ } else if (sanctionsList.isSanctioned(to)) {
+ return CODE_ADDRESS_TO_IS_SANCTIONED;
+ }
+ }
+ return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+ }
+
+ /**
+ * @inheritdoc IERC7943NonFungibleComplianceExtend
+ */
+ function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value)
+ public
+ view
+ virtual
+ override(IERC7943NonFungibleComplianceExtend)
+ returns (uint8)
+ {
+ return detectTransferRestriction(from, to, value);
+ }
+
+ /**
+ * @inheritdoc IERC1404Extend
+ */
+ function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+ public
+ view
+ virtual
+ override(IERC1404Extend)
+ returns (uint8)
+ {
+ if (address(sanctionsList) != address(0)) {
+ if (sanctionsList.isSanctioned(spender)) {
+ return CODE_ADDRESS_SPENDER_IS_SANCTIONED;
+ } else {
+ return detectTransferRestriction(from, to, value);
+ }
+ }
+ return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+ }
+
+ function detectTransferRestrictionFrom(
+ address spender,
+ address from,
+ address to,
+ uint256, /* tokenId */
+ uint256 value
+ ) public view virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) {
+ return detectTransferRestrictionFrom(spender, from, to, value);
+ }
+
+ /**
+ * @notice To know if the restriction code is valid for this rule or not.
+ * @param restrictionCode The target restriction code
+ * @return true if the restriction code is known, false otherwise
+ *
+ */
+ function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override(IRule) returns (bool) {
+ return restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED || restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED
+ || restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED;
+ }
+
+ /**
+ * @notice Return the corresponding message
+ * @param restrictionCode The target restriction code
+ * @return true if the transfer is valid, false otherwise
+ *
+ */
+ function messageForTransferRestriction(uint8 restrictionCode)
+ public
+ pure
+ virtual
+ override(IERC1404)
+ returns (string memory)
+ {
+ if (restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED) {
+ return TEXT_ADDRESS_FROM_IS_SANCTIONED;
+ } else if (restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED) {
+ return TEXT_ADDRESS_TO_IS_SANCTIONED;
+ } else if (restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED) {
+ return TEXT_ADDRESS_SPENDER_IS_SANCTIONED;
+ } else {
+ return TEXT_CODE_NOT_FOUND;
+ }
+ }
+
+ function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) {
+ return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId);
+ }
+
+ /* ============ State Functions ============ */
+ /**
+ * @notice Set the oracle contract
+ * @param sanctionContractOracle_ address of your oracle contract
+ * @dev zero address is authorized to authorize all transfers
+ */
+ function setSanctionListOracle(ISanctionsList sanctionContractOracle_) public virtual onlyRole(SANCTIONLIST_ROLE) {
+ _setSanctionListOracle(sanctionContractOracle_);
+ }
+
+ /**
+ * @inheritdoc IERC3643IComplianceContract
+ */
+ function transferred(address from, address to, uint256 value)
+ public
+ view
+ virtual
+ override(IERC3643IComplianceContract)
+ {
+ uint8 code = this.detectTransferRestriction(from, to, value);
+ require(
+ code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+ RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code)
+ );
+ }
+
+
+ /**
+ * @inheritdoc IRuleEngine
+ */
+ function transferred(address spender, address from, address to, uint256 value)
+ public
+ view
+ virtual
+ override(IRuleEngine)
+ {
+ uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value);
+ require(
+ code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+ RuleSanctionsList_InvalidTransferFrom(address(this), spender, from, to, value, code)
+ );
+ }
+
+ function transferred(address spender, address from, address to, uint256 /* tokenId */,uint256 value)
+ public
+ view
+ virtual
+ override(IERC7943NonFungibleComplianceExtend)
+ {
+ transferred(spender, from, to, value);
+ }
+
+ function transferred(address from, address to, uint256 /* tokenId */,uint256 value)
+ public
+ view
+ virtual
+ override(IERC7943NonFungibleComplianceExtend)
+ {
+ transferred(from, to, value);
+ }
+ /*//////////////////////////////////////////////////////////////
+ INTERNAL FUNCTIONS
+ //////////////////////////////////////////////////////////////*/
+
+ function _setSanctionListOracle(ISanctionsList sanctionContractOracle_) internal {
+ sanctionsList = sanctionContractOracle_;
+ emit SetSanctionListOracle(sanctionContractOracle_);
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ ERC-2771
+ //////////////////////////////////////////////////////////////*/
+
+ /**
+ * @dev This surcharge is not necessary if you do not use the MetaTxModule
+ */
+ function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
+ return ERC2771Context._msgSender();
+ }
+
+ /**
+ * @dev This surcharge is not necessary if you do not use the MetaTxModule
+ */
+ function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) {
+ return ERC2771Context._msgData();
+ }
+
+ /**
+ * @dev This surcharge is not necessary if you do not use the MetaTxModule
+ */
+ function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
+ return ERC2771Context._contextSuffixLength();
+ }
+}
diff --git a/src/rules/validation/RuleWhitelist.sol b/src/rules/validation/RuleWhitelist.sol
index 5b658cb..adf2c20 100644
--- a/src/rules/validation/RuleWhitelist.sol
+++ b/src/rules/validation/RuleWhitelist.sol
@@ -1,53 +1,169 @@
// SPDX-License-Identifier: MPL-2.0
-
pragma solidity ^0.8.20;
-import "./abstract/RuleAddressList/RuleAddressList.sol";
-import "./abstract/RuleWhitelistCommon.sol";
+import {AccessControl} from "OZ/access/AccessControl.sol";
+/* ==== Abtract contracts === */
+import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol";
+import {RuleWhitelistCommon, RuleValidateTransfer} from "./abstract/RuleWhitelistCommon.sol";
+/* ==== CMTAT === */
+import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+/* ==== Interfaces === */
+import {IIdentityRegistryVerified} from "../interfaces/IIdentityRegistry.sol";
+import {
+ IERC7943NonFungibleCompliance,
+ IERC7943NonFungibleComplianceExtend
+} from "../interfaces/IERC7943NonFungibleCompliance.sol";
/**
- * @title a whitelist manager
+ * @title Rule Whitelist
+ * @notice Manages a whitelist of authorized addresses and enforces whitelist-based transfer restrictions.
+ * @dev
+ * - Inherits core address management logic from {RuleAddressSet}.
+ * - Integrates restriction code logic from {RuleWhitelistCommon}.
+ * - Implements {IERC1404} to return specific restriction codes for non-whitelisted transfers.
*/
-contract RuleWhitelist is RuleAddressList, RuleWhitelistCommon {
+contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistryVerified {
+ /*//////////////////////////////////////////////////////////////
+ CONSTRUCTOR
+ //////////////////////////////////////////////////////////////*/
/**
* @param admin Address of the contract (Access Control)
* @param forwarderIrrevocable Address of the forwarder, required for the gasless support
*/
- constructor(
- address admin,
- address forwarderIrrevocable
- ) RuleAddressList(admin, forwarderIrrevocable) {}
+ constructor(address admin, address forwarderIrrevocable, bool checkSpender_)
+ RuleAddressSet(admin, forwarderIrrevocable)
+ {
+ checkSpender = checkSpender_;
+ }
+
+ /* ============ View Functions ============ */
/**
- * @notice Check if an addres is in the whitelist or not
- * @param from the origin address
- * @param to the destination address
- * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
- **/
- function detectTransferRestriction(
- address from,
- address to,
- uint256 /*value */
- ) public view override returns (uint8) {
- if (!addressIsListed(from)) {
+ * @notice Detects whether a transfer between two addresses is allowed under the whitelist rule.
+ * @dev
+ * - Returns a restriction code indicating why a transfer is blocked.
+ * - Implements the `IERC1404.detectTransferRestriction` interface.
+ * @param from The address sending tokens.
+ * @param to The address receiving tokens.
+ * @return code Restriction code (e.g., `TRANSFER_OK` or specific whitelist rejection).
+ *
+ * | Condition | Returned Code |
+ * |------------|---------------|
+ * | `from` not whitelisted | `CODE_ADDRESS_FROM_NOT_WHITELISTED` |
+ * | `to` not whitelisted | `CODE_ADDRESS_TO_NOT_WHITELISTED` |
+ * | Both whitelisted | `TRANSFER_OK` |
+ */
+ function detectTransferRestriction(address from, address to, uint256 /* value */ )
+ public
+ view
+ virtual
+ override(IERC1404)
+ returns (uint8 code)
+ {
+ if (!isAddressListed(from)) {
return CODE_ADDRESS_FROM_NOT_WHITELISTED;
- } else if (!addressIsListed(to)) {
+ } else if (!isAddressListed(to)) {
return CODE_ADDRESS_TO_NOT_WHITELISTED;
} else {
return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
}
}
+ /**
+ * @inheritdoc IERC7943NonFungibleComplianceExtend
+ */
+ function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value)
+ public
+ view
+ virtual
+ override(IERC7943NonFungibleComplianceExtend)
+ returns (uint8)
+ {
+ return detectTransferRestriction(from, to, value);
+ }
+
+ /**
+ * @notice Detects transfer restriction for delegated transfers (`transferFrom`).
+ * @dev
+ * - Checks the `spender`, `from`, and `to` addresses for whitelist compliance.
+ * - Implements `IERC1404Extend.detectTransferRestrictionFrom`.
+ * @param spender The address initiating the transfer on behalf of another.
+ * @param from The address from which tokens are transferred.
+ * @param to The address receiving the tokens.
+ * @param value The amount being transferred (unused in this check).
+ * @return code Restriction code, or `TRANSFER_OK` if all parties are whitelisted.
+ *
+ * | Condition | Returned Code |
+ * |------------|---------------|
+ * | `spender` not whitelisted | `CODE_ADDRESS_SPENDER_NOT_WHITELISTED` |
+ * | `from` or `to` not whitelisted | respective restriction code from `detectTransferRestriction` |
+ * | All whitelisted | `TRANSFER_OK` |
+ */
+ function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+ public
+ view
+ virtual
+ override(IERC1404Extend)
+ returns (uint8 code)
+ {
+ if (checkSpender && !isAddressListed(spender)) {
+ return CODE_ADDRESS_SPENDER_NOT_WHITELISTED;
+ }
+ return detectTransferRestriction(from, to, value);
+ }
+
+ /**
+ * @inheritdoc IERC7943NonFungibleComplianceExtend
+ */
function detectTransferRestrictionFrom(
address spender,
address from,
address to,
+ uint256, /* tokenId */
uint256 value
- ) public view override returns (uint8) {
- if (addressIsListed(spender)) {
- return CODE_ADDRESS_SPENDER_NOT_WHITELISTED;
- } else {
- return detectTransferRestriction(from,to,value);
- }
+ ) public view override(IERC7943NonFungibleComplianceExtend) returns (uint8) {
+ return detectTransferRestrictionFrom(spender, from, to, value);
+ }
+
+ /**
+ * @notice Checks whether a specific address is currently listed.
+ * @param targetAddress The address to check.
+ * @return isListed True if listed, false otherwise.
+ */
+ function isVerified(address targetAddress)
+ public
+ view
+ virtual
+ override(IIdentityRegistryVerified)
+ returns (bool isListed)
+ {
+ isListed = _isAddressListed(targetAddress);
+ }
+
+ function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) {
+ return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId);
+ }
+
+ /**
+ * @notice Sets whether the rule should enforce spender-based checks.
+ * @dev
+ * - Restricted to holders of the `DEFAULT_ADMIN_ROLE`.
+ * - Updates the internal `checkSpender` flag.
+ * - Emits a {CheckSpenderUpdated} event.
+ * @param value The new state of the `checkSpender` flag.
+ */
+ function setCheckSpender(bool value)
+ public virtual
+ onlyRole(DEFAULT_ADMIN_ROLE) // or a dedicated role if you prefer
+ {
+ _setCheckSpender(value);
+ emit CheckSpenderUpdated(value);
+ }
+
+ /**
+ * @dev Internal helper to update the `checkSpender` flag.
+ */
+ function _setCheckSpender(bool value) internal {
+ checkSpender = value;
}
}
diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol
index 21f3e7f..6309c5c 100644
--- a/src/rules/validation/RuleWhitelistWrapper.sol
+++ b/src/rules/validation/RuleWhitelistWrapper.sol
@@ -2,68 +2,66 @@
pragma solidity ^0.8.20;
-import "OZ/access/AccessControl.sol";
-import "RuleEngine/modules/RuleEngineValidationCommon.sol";
-import "../../modules/MetaTxModuleStandalone.sol";
-import "./abstract/RuleAddressList/RuleAddressList.sol";
-import "./abstract/RuleWhitelistCommon.sol";
+/* ==== OpenZeppelin === */
+import {AccessControl} from "OZ/access/AccessControl.sol";
+/* ==== Abtract contracts === */
+import {AccessControlModuleStandalone} from "../../modules/AccessControlModuleStandalone.sol";
+import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../modules/MetaTxModuleStandalone.sol";
+import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol";
+import {RuleWhitelistCommon, RuleValidateTransfer} from "./abstract/RuleWhitelistCommon.sol";
+/* ==== RuleEngine === */
+import {RulesManagementModule} from "RuleEngine/modules/RulesManagementModule.sol";
+/* ==== CMTAT === */
+import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+/* ==== Interfaces === */
+import {
+ IERC7943NonFungibleCompliance,
+ IERC7943NonFungibleComplianceExtend
+} from "../interfaces/IERC7943NonFungibleCompliance.sol";
/**
* @title Wrapper to call several different whitelist rules
*/
contract RuleWhitelistWrapper is
- RuleEngineValidationCommon,
+ RulesManagementModule,
+ AccessControlModuleStandalone,
MetaTxModuleStandalone,
RuleWhitelistCommon
{
+ /*//////////////////////////////////////////////////////////////
+ CONSTRUCTOR
+ //////////////////////////////////////////////////////////////*/
/**
* @param admin Address of the contract (Access Control)
* @param forwarderIrrevocable Address of the forwarder, required for the gasless support
*/
- constructor(
- address admin,
- address forwarderIrrevocable
- ) MetaTxModuleStandalone(forwarderIrrevocable) {
- if (admin == address(0)) {
- revert RuleEngine_AdminWithAddressZeroNotAllowed();
- }
- _grantRole(DEFAULT_ADMIN_ROLE, admin);
+ constructor(address admin, address forwarderIrrevocable, bool checkSpender_)
+ MetaTxModuleStandalone(forwarderIrrevocable)
+ AccessControlModuleStandalone(admin)
+ {
+ checkSpender = checkSpender_;
}
+ /* ============ View Functions ============ */
/**
* @notice Go through all the whitelist rules to know if a restriction exists on the transfer
* @param from the origin address
* @param to the destination address
* @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
- **/
- function detectTransferRestriction(
- address from,
- address to,
- uint256 /*value*/
- ) public view override returns (uint8) {
+ *
+ */
+ function detectTransferRestriction(address from, address to, uint256 /*value*/ )
+ public
+ view
+ virtual
+ override(IERC1404)
+ returns (uint8)
+ {
address[] memory targetAddress = new address[](2);
- bool[] memory isListed = new bool[](2);
- bool[] memory result = new bool[](2);
targetAddress[0] = from;
targetAddress[1] = to;
- uint256 rulesLength = _rulesValidation.length;
- // For each whitelist rule, we ask if from or to are in the whitelist
- for (uint256 i = 0; i < rulesLength; ++i) {
- // External call
- isListed = RuleAddressList(_rulesValidation[i])
- .addressIsListedBatch(targetAddress);
- if (isListed[0] && !result[0]) {
- // Update if from is in the list
- result[0] = true;
- }
- if (isListed[1] && !result[1]) {
- // Update if to is in the list
- result[1] = true;
- }
- if (result[0] && result[1]) {
- break;
- }
- }
+
+ bool[] memory result = _detectTransferRestriction(targetAddress);
if (!result[0]) {
return CODE_ADDRESS_FROM_NOT_WHITELISTED;
} else if (!result[1]) {
@@ -73,40 +71,34 @@ contract RuleWhitelistWrapper is
}
}
- function detectTransferRestrictionFrom(
- address spender,
- address from,
- address to,
- uint256 /*value*/
- ) public view override returns (uint8) {
+ function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value)
+ public
+ view
+ virtual
+ override(IERC7943NonFungibleComplianceExtend)
+ returns (uint8)
+ {
+ return detectTransferRestriction(from, to, value);
+ }
+
+ function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+ public
+ view
+ virtual
+ override(IERC1404Extend)
+ returns (uint8)
+ {
+ if (!checkSpender) {
+ return detectTransferRestriction(from, to, value);
+ }
+
address[] memory targetAddress = new address[](3);
- bool[] memory isListed = new bool[](3);
- bool[] memory result = new bool[](3);
targetAddress[0] = from;
targetAddress[1] = to;
targetAddress[2] = spender;
- uint256 rulesLength = _rulesValidation.length;
- // For each whitelist rule, we ask if from or to are in the whitelist
- for (uint256 i = 0; i < rulesLength; ++i) {
- // External call
- isListed = RuleAddressList(_rulesValidation[i])
- .addressIsListedBatch(targetAddress);
- if (isListed[0] && !result[0]) {
- // Update if from is in the list
- result[0] = true;
- }
- if (isListed[1] && !result[1]) {
- // Update if to is in the list
- result[1] = true;
- }
- if (isListed[2] && !result[2]) {
- // Update if spender is in the list
- result[2] = true;
- }
- if (result[0] && result[1] && result[2]) {
- break;
- }
- }
+
+ bool[] memory result = _detectTransferRestriction(targetAddress);
+
if (!result[0]) {
return CODE_ADDRESS_FROM_NOT_WHITELISTED;
} else if (!result[1]) {
@@ -118,19 +110,92 @@ contract RuleWhitelistWrapper is
}
}
- /* ============ ACCESS CONTROL ============ */
+ /**
+ * @inheritdoc IERC7943NonFungibleComplianceExtend
+ */
+ function detectTransferRestrictionFrom(
+ address spender,
+ address from,
+ address to,
+ uint256, /* tokenId */
+ uint256 value
+ ) public view virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) {
+ return detectTransferRestrictionFrom(spender, from, to, value);
+ }
+
+ function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) {
+ return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId);
+ }
+
+ /* ============ Access control ============ */
+
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
- function hasRole(
- bytes32 role,
- address account
- ) public view virtual override(AccessControl) returns (bool) {
- // The Default Admin has all roles
- if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
- return true;
+ function hasRole(bytes32 role, address account)
+ public
+ view
+ virtual
+ override(AccessControl, AccessControlModuleStandalone)
+ returns (bool)
+ {
+ return AccessControlModuleStandalone.hasRole(role, account);
+ }
+
+ /**
+ * @notice Sets whether the rule should enforce spender-based checks.
+ * @dev
+ * - Restricted to holders of the `DEFAULT_ADMIN_ROLE`.
+ * - Updates the internal `checkSpender` flag.
+ * - Emits a {CheckSpenderUpdated} event.
+ * @param value The new state of the `checkSpender` flag.
+ */
+ function setCheckSpender(bool value)
+ public virtual
+ onlyRole(DEFAULT_ADMIN_ROLE) // or a dedicated role if you prefer
+ {
+ _setCheckSpender(value);
+ emit CheckSpenderUpdated(value);
+ }
+
+
+ /*//////////////////////////////////////////////////////////////
+ INTERNAL/PRIVATE FUNCTIONS
+ //////////////////////////////////////////////////////////////*/
+
+ function _detectTransferRestriction(address[] memory targetAddress) internal view returns (bool[] memory) {
+ uint256 rulesLength = rulesCount();
+ bool[] memory result = new bool[](targetAddress.length);
+ for (uint256 i = 0; i < rulesLength; ++i) {
+ // Call the whitelist rules
+ bool[] memory isListed = RuleAddressSet(rule(i)).areAddressesListed(targetAddress);
+ for (uint256 j = 0; j < targetAddress.length; ++j) {
+ if (isListed[j]) {
+ result[j] = true;
+ }
+ }
+
+ // Break early if all listed
+ bool allListed = true;
+ for (uint256 k = 0; k < result.length; ++k) {
+ if (!result[k]) {
+ allListed = false;
+ break;
+ }
+ }
+ if (allListed) {
+ break;
+ }
}
- return AccessControl.hasRole(role, account);
+ return result;
+ }
+
+
+ /**
+ * @dev Internal helper to update the `checkSpender` flag.
+ */
+ function _setCheckSpender(bool value) internal {
+ checkSpender = value;
}
/*//////////////////////////////////////////////////////////////
@@ -140,36 +205,21 @@ contract RuleWhitelistWrapper is
/**
* @dev This surcharge is not necessary if you do not use the MetaTxModule
*/
- function _msgSender()
- internal
- view
- override(ERC2771Context, Context)
- returns (address sender)
- {
+ function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
return ERC2771Context._msgSender();
}
/**
* @dev This surcharge is not necessary if you do not use the MetaTxModule
*/
- function _msgData()
- internal
- view
- override(ERC2771Context, Context)
- returns (bytes calldata)
- {
+ function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) {
return ERC2771Context._msgData();
}
/**
* @dev This surcharge is not necessary if you do not use the MetaTxModule
*/
- function _contextSuffixLength()
- internal
- view
- override(ERC2771Context, Context)
- returns (uint256)
- {
+ function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
return ERC2771Context._contextSuffixLength();
}
}
diff --git a/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol b/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol
deleted file mode 100644
index ddcdb54..0000000
--- a/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol
+++ /dev/null
@@ -1,176 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-
-pragma solidity ^0.8.20;
-
-import "OZ/access/AccessControl.sol";
-import "./../../../../modules/MetaTxModuleStandalone.sol";
-import "./RuleAddressListInternal.sol";
-import "./invariantStorage/RuleAddressListInvariantStorage.sol";
-
-/**
-@title an addresses list manager
-*/
-
-abstract contract RuleAddressList is
- AccessControl,
- MetaTxModuleStandalone,
- RuleAddressListInternal,
- RuleAddressListInvariantStorage
-{
- // Number of addresses in the list at the moment
- uint256 private numAddressesWhitelisted;
-
- /**
- * @param admin Address of the contract (Access Control)
- * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
- */
- constructor(
- address admin,
- address forwarderIrrevocable
- ) MetaTxModuleStandalone(forwarderIrrevocable) {
- if (admin == address(0)) {
- revert RuleAddressList_AdminWithAddressZeroNotAllowed();
- }
- _grantRole(DEFAULT_ADMIN_ROLE, admin);
- }
-
- /**
- * @notice Add addresses to the list
- * If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert).
- * @param listTargetAddresses an array with the addresses to list
- */
- function addAddressesToTheList(
- address[] calldata listTargetAddresses
- ) public onlyRole(ADDRESS_LIST_ADD_ROLE) {
- _addAddressesToThelist(listTargetAddresses);
- emit AddAddressesToTheList(listTargetAddresses);
- }
-
- /**
- * @notice Remove addresses from the list
- * If the address does not exist in the list, there is no change for this address.
- * The transaction remains valid (no revert).
- * @param listTargetAddresses an array with the addresses to remove
- */
- function removeAddressesFromTheList(
- address[] calldata listTargetAddresses
- ) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) {
- _removeAddressesFromThelist(listTargetAddresses);
- emit RemoveAddressesFromTheList(listTargetAddresses);
- }
-
- /**
- * @notice Add one address to the list
- * If the address already exists, the transaction is reverted to save gas.
- * @param targetAddress The address to list
- */
- function addAddressToTheList(
- address targetAddress
- ) public onlyRole(ADDRESS_LIST_ADD_ROLE) {
- _addAddressToThelist(targetAddress);
- emit AddAddressToTheList(targetAddress);
- }
-
- /**
- * @notice Remove one address from the list
- * If the address does not exist in the list, the transaction is reverted to save gas.
- * @param targetAddress The address to remove
- *
- */
- function removeAddressFromTheList(
- address targetAddress
- ) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) {
- _removeAddressFromThelist(targetAddress);
- emit RemoveAddressFromTheList(targetAddress);
- }
-
- /**
- * @notice Get the number of listed addresses
- * @return Number of listed addresses
- *
- */
- function numberListedAddress() public view returns (uint256) {
- return _numberListedAddress();
- }
-
- /**
- * @notice Know if an address is listed or not
- * @param _targetAddress The concerned address
- * @return True if the address is listed, false otherwise
- *
- */
- function addressIsListed(
- address _targetAddress
- ) public view returns (bool) {
- return _addressIsListed(_targetAddress);
- }
-
- /**
- * @notice batch version of {addressIsListed}
- *
- */
- function addressIsListedBatch(
- address[] memory _targetAddresses
- ) public view returns (bool[] memory) {
- bool[] memory isListed = new bool[](_targetAddresses.length);
- for (uint256 i = 0; i < _targetAddresses.length; ++i) {
- isListed[i] = _addressIsListed(_targetAddresses[i]);
- }
- return isListed;
- }
-
- /* ============ ACCESS CONTROL ============ */
- /**
- * @dev Returns `true` if `account` has been granted `role`.
- */
- function hasRole(
- bytes32 role,
- address account
- ) public view virtual override(AccessControl) returns (bool) {
- // The Default Admin has all roles
- if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
- return true;
- }
- return AccessControl.hasRole(role, account);
- }
-
- /*//////////////////////////////////////////////////////////////
- ERC-2771
- //////////////////////////////////////////////////////////////*/
-
- /**
- * @dev This surcharge is not necessary if you do not use the MetaTxModule
- */
- function _msgSender()
- internal
- view
- override(ERC2771Context, Context)
- returns (address sender)
- {
- return ERC2771Context._msgSender();
- }
-
- /**
- * @dev This surcharge is not necessary if you do not use the MetaTxModule
- */
- function _msgData()
- internal
- view
- override(ERC2771Context, Context)
- returns (bytes calldata)
- {
- return ERC2771Context._msgData();
- }
-
- /**
- * @dev This surcharge is not necessary if you do not use the MetaTxModule
- */
- function _contextSuffixLength()
- internal
- view
- override(ERC2771Context, Context)
- returns (uint256)
- {
- return ERC2771Context._contextSuffixLength();
- }
-}
diff --git a/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol b/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol
deleted file mode 100644
index 02cbd38..0000000
--- a/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol
+++ /dev/null
@@ -1,101 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-
-pragma solidity ^0.8.20;
-
-/**
- * @title a list manager
- */
-
-abstract contract RuleAddressListInternal {
- error Rulelist_AddressAlreadylisted();
- error Rulelist_AddressNotPresent();
-
- mapping(address => bool) private list;
- // Number of addresses in the list at the moment
- uint256 private numAddressesList;
-
- /**
- * @notice Add addresses to the list
- * If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert).
- * @param listTargetAddresses an array with the addresses to list
- */
- function _addAddressesToThelist(
- address[] calldata listTargetAddresses
- ) internal {
- uint256 numAddressesListLocal = numAddressesList;
- for (uint256 i = 0; i < listTargetAddresses.length; ++i) {
- if (!list[listTargetAddresses[i]]) {
- list[listTargetAddresses[i]] = true;
- ++numAddressesListLocal;
- }
- }
- numAddressesList = numAddressesListLocal;
- }
-
- /**
- * @notice Remove addresses from the list
- * If the address does not exist in the list, there is no change for this address.
- * The transaction remains valid (no revert).
- * @param listTargetAddresses an array with the addresses to remove
- */
- function _removeAddressesFromThelist(
- address[] calldata listTargetAddresses
- ) internal {
- uint256 numAddressesListLocal = numAddressesList;
- for (uint256 i = 0; i < listTargetAddresses.length; ++i) {
- if (list[listTargetAddresses[i]]) {
- list[listTargetAddresses[i]] = false;
- --numAddressesListLocal;
- }
- }
- numAddressesList = numAddressesListLocal;
- }
-
- /**
- * @notice Add one address to the list
- * If the address already exists, the transaction is reverted to save gas.
- * @param targetAddress The address to list
- */
- function _addAddressToThelist(address targetAddress) internal {
- if (list[targetAddress]) {
- revert Rulelist_AddressAlreadylisted();
- }
- list[targetAddress] = true;
- ++numAddressesList;
- }
-
- /**
- * @notice Remove one address from the list
- * If the address does not exist in the list, the transaction is reverted to save gas.
- * @param targetAddress The address to remove
- *
- */
- function _removeAddressFromThelist(address targetAddress) internal {
- if (!list[targetAddress]) {
- revert Rulelist_AddressNotPresent();
- }
- list[targetAddress] = false;
- --numAddressesList;
- }
-
- /**
- * @notice Get the number of listed addresses
- * @return Number of listed addresses
- *
- */
- function _numberListedAddress() internal view returns (uint256) {
- return numAddressesList;
- }
-
- /**
- * @notice Know if an address is listed or not
- * @param _targetAddress The concerned address
- * @return True if the address is listed, false otherwise
- *
- */
- function _addressIsListed(
- address _targetAddress
- ) internal view returns (bool) {
- return list[_targetAddress];
- }
-}
diff --git a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol
deleted file mode 100644
index 75f5c3c..0000000
--- a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol
+++ /dev/null
@@ -1,20 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-
-pragma solidity ^0.8.20;
-
-abstract contract RuleAddressListInvariantStorage {
- /* ============ Events ============ */
- event AddAddressesToTheList(address[] listTargetAddresses);
- event RemoveAddressesFromTheList(address[] listTargetAddresses);
- event AddAddressToTheList(address targetAddress);
- event RemoveAddressFromTheList(address targetAddress);
-
- /* ============ Custom errors ============ */
- error RuleAddressList_AdminWithAddressZeroNotAllowed();
-
- /* ============ Role ============ */
- bytes32 public constant ADDRESS_LIST_REMOVE_ROLE =
- keccak256("ADDRESS_LIST_REMOVE_ROLE");
- bytes32 public constant ADDRESS_LIST_ADD_ROLE =
- keccak256("ADDRESS_LIST_ADD_ROLE");
-}
diff --git a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol
deleted file mode 100644
index f5d8d04..0000000
--- a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol
+++ /dev/null
@@ -1,21 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-
-pragma solidity ^0.8.20;
-
-import "../../RuleCommonInvariantStorage.sol";
-
-abstract contract RuleBlacklistInvariantStorage is RuleCommonInvariantStorage {
- /* ============ String message ============ */
- string constant TEXT_ADDRESS_FROM_IS_BLACKLISTED =
- "The sender is blacklisted";
- string constant TEXT_ADDRESS_TO_IS_BLACKLISTED =
- "The recipient is blacklisted";
- string constant TEXT_ADDRESS_SPENDER_IS_BLACKLISTED =
- "The spender is blacklisted";
-
- /* ============ Code ============ */
- // It is very important that each rule uses an unique code
- uint8 public constant CODE_ADDRESS_FROM_IS_BLACKLISTED = 41;
- uint8 public constant CODE_ADDRESS_TO_IS_BLACKLISTED = 42;
- uint8 public constant CODE_ADDRESS_SPENDER_IS_BLACKLISTED = 43;
-}
diff --git a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol
deleted file mode 100644
index e2bcdbc..0000000
--- a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol
+++ /dev/null
@@ -1,21 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-
-pragma solidity ^0.8.20;
-
-import "../../RuleCommonInvariantStorage.sol";
-
-abstract contract RuleWhitelistInvariantStorage is RuleCommonInvariantStorage {
- /* ============ String message ============ */
- string constant TEXT_ADDRESS_FROM_NOT_WHITELISTED =
- "The sender is not in the whitelist";
- string constant TEXT_ADDRESS_TO_NOT_WHITELISTED =
- "The recipient is not in the whitelist";
- string constant TEXT_ADDRESS_SPENDER_NOT_WHITELISTED =
- "The spender is not in the whitelist";
-
- /* ============ Code ============ */
- // It is very important that each rule uses an unique code
- uint8 public constant CODE_ADDRESS_FROM_NOT_WHITELISTED = 21;
- uint8 public constant CODE_ADDRESS_TO_NOT_WHITELISTED = 22;
- uint8 public constant CODE_ADDRESS_SPENDER_NOT_WHITELISTED = 23;
-}
diff --git a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol
new file mode 100644
index 0000000..8907f1c
--- /dev/null
+++ b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: MPL-2.0
+pragma solidity ^0.8.20;
+
+import {AccessControlModuleStandalone} from "../../../../modules/AccessControlModuleStandalone.sol";
+import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../../../modules/MetaTxModuleStandalone.sol";
+import {RuleAddressSetInternal} from "./RuleAddressSetInternal.sol";
+import {RuleAddressSetInvariantStorage} from "./invariantStorage/RuleAddressSetInvariantStorage.sol";
+/* ==== Interfaces === */
+import {IIdentityRegistryContains} from "../../../interfaces/IIdentityRegistry.sol";
+import {IAddressList} from "../../../interfaces/IAddressList.sol";
+/**
+ * @title Rule Address Set
+ * @notice Manages a permissioned set of addresses related to rule logic.
+ * @dev
+ * - Provides controlled functions for adding and removing addresses.
+ * - Integrates `AccessControl` for role-based access.
+ * - Supports gasless transactions via ERC-2771 meta-transactions.
+ * - Extends internal logic defined in {RuleAddressSetInternal}.
+ */
+
+abstract contract RuleAddressSet is
+ AccessControlModuleStandalone,
+ MetaTxModuleStandalone,
+ RuleAddressSetInternal,
+ RuleAddressSetInvariantStorage,
+ IAddressList
+{
+ /*//////////////////////////////////////////////////////////////
+ STATE
+ //////////////////////////////////////////////////////////////*/
+
+ /// @notice Cached number of currently listed addresses.
+ uint256 private _listedAddressCountCache;
+
+ /*//////////////////////////////////////////////////////////////
+ CONSTRUCTOR
+ //////////////////////////////////////////////////////////////*/
+
+ /**
+ * @notice Initializes the RuleAddressSet contract.
+ * @param admin The address granted the default admin role.
+ * @param forwarderIrrevocable Address of the ERC2771 forwarder (for meta-transactions).
+ * @dev Reverts if the admin address is the zero address.
+ */
+ constructor(address admin, address forwarderIrrevocable)
+ MetaTxModuleStandalone(forwarderIrrevocable)
+ AccessControlModuleStandalone(admin)
+ {
+ // nothing to do
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ CORE LOGIC
+ //////////////////////////////////////////////////////////////*/
+
+ /**
+ * @notice Adds multiple addresses to the set.
+ * @dev
+ * - Does not revert if an address is already listed.
+ * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`.
+ * @param targetAddresses Array of addresses to be added.
+ */
+ function addAddresses(address[] calldata targetAddresses) public onlyRole(ADDRESS_LIST_ADD_ROLE) {
+ _addAddresses(targetAddresses);
+ emit AddAddresses(targetAddresses);
+ }
+
+ /**
+ * @notice Removes multiple addresses from the set.
+ * @dev
+ * - Does not revert if an address is not listed.
+ * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`.
+ * @param targetAddresses Array of addresses to remove.
+ */
+ function removeAddresses(address[] calldata targetAddresses) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) {
+ _removeAddresses(targetAddresses);
+ emit RemoveAddresses(targetAddresses);
+ }
+
+ /**
+ * @notice Adds a single address to the set.
+ * @dev
+ * - Reverts if the address is already listed.
+ * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`.
+ * @param targetAddress The address to be added.
+ */
+ function addAddress(address targetAddress) public onlyRole(ADDRESS_LIST_ADD_ROLE) {
+ if (_isAddressListed(targetAddress)) {
+ revert RuleAddressSet_AddressAlreadyListed();
+ }
+ _addAddress(targetAddress);
+ emit AddAddress(targetAddress);
+ }
+
+ /**
+ * @notice Removes a single address from the set.
+ * @dev
+ * - Reverts if the address is not listed.
+ * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`.
+ * @param targetAddress The address to be removed.
+ */
+ function removeAddress(address targetAddress) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) {
+ if (!_isAddressListed(targetAddress)) {
+ revert RuleAddressSet_AddressNotFound();
+ }
+ _removeAddress(targetAddress);
+ emit RemoveAddress(targetAddress);
+ }
+
+ /**
+ * @notice Returns the total number of currently listed addresses.
+ * @return count The number of listed addresses.
+ */
+ function listedAddressCount() public view returns (uint256 count) {
+ count = _listedAddressCount();
+ }
+
+ /**
+ * @notice Checks whether a specific address is currently listed.
+ * @param targetAddress The address to check.
+ * @return isListed True if listed, false otherwise.
+ */
+ function contains(address targetAddress) public view override(IIdentityRegistryContains) returns (bool isListed) {
+ isListed = _isAddressListed(targetAddress);
+ }
+
+ /**
+ * @notice Checks whether a specific address is currently listed.
+ * @param targetAddress The address to check.
+ * @return isListed True if listed, false otherwise.
+ */
+ function isAddressListed(address targetAddress) public view returns (bool isListed) {
+ isListed = _isAddressListed(targetAddress);
+ }
+
+ /**
+ * @notice Checks multiple addresses in a single call.
+ * @param targetAddresses Array of addresses to check.
+ * @return results Array of booleans corresponding to listing status.
+ */
+ function areAddressesListed(address[] memory targetAddresses) public view returns (bool[] memory results) {
+ results = new bool[](targetAddresses.length);
+ for (uint256 i = 0; i < targetAddresses.length; ++i) {
+ results[i] = _isAddressListed(targetAddresses[i]);
+ }
+ }
+ /*//////////////////////////////////////////////////////////////
+ ERC-2771 META TX
+ //////////////////////////////////////////////////////////////*/
+
+ /// @inheritdoc ERC2771Context
+ function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
+ return ERC2771Context._msgSender();
+ }
+
+ /// @inheritdoc ERC2771Context
+ function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) {
+ return ERC2771Context._msgData();
+ }
+
+ /// @inheritdoc ERC2771Context
+ function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
+ return ERC2771Context._contextSuffixLength();
+ }
+}
diff --git a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol
new file mode 100644
index 0000000..270c4b6
--- /dev/null
+++ b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: MPL-2.0
+pragma solidity ^0.8.20;
+
+/* ==== OpenZeppelin === */
+import {EnumerableSet} from "OZ/utils/structs/EnumerableSet.sol";
+
+/**
+ * @title Rule Address Set (Internal)
+ * @notice Internal utility for managing a set of rule-related addresses.
+ * @dev
+ * - Uses OpenZeppelin's EnumerableSet for efficient enumeration.
+ * - Designed for internal inheritance and logic composition.
+ * - Batch operations do not revert when individual entries are invalid.
+ */
+abstract contract RuleAddressSetInternal {
+ using EnumerableSet for EnumerableSet.AddressSet;
+
+ /*//////////////////////////////////////////////////////////////
+ STATE VARIABLES
+ //////////////////////////////////////////////////////////////*/
+
+ /// @dev Storage for all listed addresses.
+ EnumerableSet.AddressSet private _listedAddresses;
+
+ /*//////////////////////////////////////////////////////////////
+ INTERNAL
+ //////////////////////////////////////////////////////////////*/
+
+ /**
+ * @notice Adds multiple addresses to the set.
+ * @dev
+ * - Does not revert if an address is already listed.
+ * - Skips existing entries silently.
+ * @param addressesToAdd The array of addresses to add.
+ */
+ function _addAddresses(address[] calldata addressesToAdd) internal {
+ for (uint256 i = 0; i < addressesToAdd.length; ++i) {
+ _listedAddresses.add(addressesToAdd[i]);
+ }
+ }
+
+ /**
+ * @notice Removes multiple addresses from the set.
+ * @dev
+ * - Does not revert if an address is not found.
+ * - Skips non-existing entries silently.
+ * @param addressesToRemove The array of addresses to remove.
+ */
+ function _removeAddresses(address[] calldata addressesToRemove) internal {
+ for (uint256 i = 0; i < addressesToRemove.length; ++i) {
+ _listedAddresses.remove(addressesToRemove[i]);
+ }
+ }
+
+ /**
+ * @notice Adds a single address to the set.
+ * @param targetAddress The address to add.
+ */
+ function _addAddress(address targetAddress) internal {
+ _listedAddresses.add(targetAddress);
+ }
+
+ /**
+ * @notice Removes a single address from the set.
+ * @param targetAddress The address to remove.
+ */
+ function _removeAddress(address targetAddress) internal {
+ _listedAddresses.remove(targetAddress);
+ }
+
+ /**
+ * @notice Returns the total number of listed addresses.
+ * @return count The number of listed addresses.
+ */
+ function _listedAddressCount() internal view returns (uint256 count) {
+ count = _listedAddresses.length();
+ }
+
+ /**
+ * @notice Checks if an address is listed.
+ * @param targetAddress The address to check.
+ * @return isListed True if the address is listed, false otherwise.
+ */
+ function _isAddressListed(address targetAddress) internal view returns (bool isListed) {
+ isListed = _listedAddresses.contains(targetAddress);
+ }
+}
diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol
new file mode 100644
index 0000000..5d1a8a9
--- /dev/null
+++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: MPL-2.0
+
+pragma solidity ^0.8.20;
+
+abstract contract RuleAddressSetInvariantStorage {
+ /* ============ Custom errors ============ */
+ /// @notice Thrown when trying to add an address that is already listed.
+ error RuleAddressSet_AddressAlreadyListed();
+
+ /// @notice Thrown when trying to remove an address that is not listed.
+ error RuleAddressSet_AddressNotFound();
+
+ /* ============ Role ============ */
+ bytes32 public constant ADDRESS_LIST_REMOVE_ROLE = keccak256("ADDRESS_LIST_REMOVE_ROLE");
+ bytes32 public constant ADDRESS_LIST_ADD_ROLE = keccak256("ADDRESS_LIST_ADD_ROLE");
+}
diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol
new file mode 100644
index 0000000..261f3d8
--- /dev/null
+++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: MPL-2.0
+
+pragma solidity ^0.8.20;
+
+import {RuleCommonInvariantStorage} from "../../RuleCommonInvariantStorage.sol";
+
+abstract contract RuleBlacklistInvariantStorage is RuleCommonInvariantStorage {
+ error RuleBlacklist_InvalidTransfer(address rule, address from, address to, uint256 value, uint8 code);
+ error RuleBlacklist_InvalidTransferFrom(address rule, address spender, address from, address to, uint256 value, uint8 code);
+ /* ============ String message ============ */
+
+ string constant TEXT_ADDRESS_FROM_IS_BLACKLISTED = "The sender is blacklisted";
+ string constant TEXT_ADDRESS_TO_IS_BLACKLISTED = "The recipient is blacklisted";
+ string constant TEXT_ADDRESS_SPENDER_IS_BLACKLISTED = "The spender is blacklisted";
+
+ /* ============ Code ============ */
+ // It is very important that each rule uses an unique code
+ uint8 public constant CODE_ADDRESS_FROM_IS_BLACKLISTED = 36;
+ uint8 public constant CODE_ADDRESS_TO_IS_BLACKLISTED = 37;
+ uint8 public constant CODE_ADDRESS_SPENDER_IS_BLACKLISTED = 38;
+}
diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol
new file mode 100644
index 0000000..4a3561b
--- /dev/null
+++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: MPL-2.0
+
+pragma solidity ^0.8.20;
+
+import {RuleCommonInvariantStorage} from "../../RuleCommonInvariantStorage.sol";
+
+abstract contract RuleWhitelistInvariantStorage is RuleCommonInvariantStorage {
+ error RuleWhitelist_InvalidTransfer(address rule, address from, address to, uint256 value, uint8 code);
+ error RuleWhitelist_InvalidTransferFrom(address rule, address spender, address from, address to, uint256 value, uint8 code);
+ /* ============ String message ============ */
+
+ string constant TEXT_ADDRESS_FROM_NOT_WHITELISTED = "The sender is not in the whitelist";
+ string constant TEXT_ADDRESS_TO_NOT_WHITELISTED = "The recipient is not in the whitelist";
+ string constant TEXT_ADDRESS_SPENDER_NOT_WHITELISTED = "The spender is not in the whitelist";
+
+ /* ============ Code ============ */
+ // It is very important that each rule uses an unique code
+ uint8 public constant CODE_ADDRESS_FROM_NOT_WHITELISTED = 21;
+ uint8 public constant CODE_ADDRESS_TO_NOT_WHITELISTED = 22;
+ uint8 public constant CODE_ADDRESS_SPENDER_NOT_WHITELISTED = 23;
+
+
+ /* ============ Events ============ */
+ /// @dev Emitted when the `checkSpender` flag is updated.
+ event CheckSpenderUpdated(bool newValue);
+
+}
diff --git a/src/rules/validation/abstract/RuleCommonInvariantStorage.sol b/src/rules/validation/abstract/RuleCommonInvariantStorage.sol
index 855e72f..e4cd505 100644
--- a/src/rules/validation/abstract/RuleCommonInvariantStorage.sol
+++ b/src/rules/validation/abstract/RuleCommonInvariantStorage.sol
@@ -2,6 +2,6 @@
pragma solidity ^0.8.20;
abstract contract RuleCommonInvariantStorage {
- // Text
+ /* ============ String message ============ */
string constant TEXT_CODE_NOT_FOUND = "Unknown restriction code";
}
diff --git a/src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol b/src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol
deleted file mode 100644
index e8798c4..0000000
--- a/src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-
-pragma solidity ^0.8.20;
-
-import "./RuleCommonInvariantStorage.sol";
-
-abstract contract RuleSanctionlistInvariantStorage is
- RuleCommonInvariantStorage
-{
- /* ============ Event ============ */
- event SetSanctionListOracle(address newOracle);
- /* ============ Custom errors ============ */
- error RuleSanctionList_AdminWithAddressZeroNotAllowed();
- error RuleSanctionList_AddressAlreadyWhitelisted();
-
- /* ============ Role ============ */
- bytes32 public constant SANCTIONLIST_ROLE = keccak256("SANCTIONLIST_ROLE");
-
- /* ============ String message ============ */
- string constant TEXT_ADDRESS_FROM_IS_SANCTIONED =
- "The sender is sanctioned";
- string constant TEXT_ADDRESS_TO_IS_SANCTIONED =
- "The recipient is sanctioned";
- string constant TEXT_ADDRESS_SPENDER_IS_SANCTIONED =
- "The spender is sanctioned";
-
- /* ============ Code ============ */
- // It is very important that each rule uses an unique code
- uint8 public constant CODE_ADDRESS_FROM_IS_SANCTIONED = 31;
- uint8 public constant CODE_ADDRESS_TO_IS_SANCTIONED = 32;
- uint8 public constant CODE_ADDRESS_SPENDER_IS_SANCTIONED = 33;
-}
diff --git a/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol
new file mode 100644
index 0000000..318d5d2
--- /dev/null
+++ b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: MPL-2.0
+
+pragma solidity ^0.8.20;
+
+import {RuleCommonInvariantStorage} from "./RuleCommonInvariantStorage.sol";
+import {ISanctionsList} from "../../interfaces/ISanctionsList.sol";
+
+abstract contract RuleSanctionsListInvariantStorage is RuleCommonInvariantStorage {
+ /* ============ Event ============ */
+ event SetSanctionListOracle(ISanctionsList newOracle);
+ /* ============ Custom errors ============ */
+ error RuleSanctionsList_InvalidTransfer(address rule, address from, address to, uint256 value, uint8 code);
+ error RuleSanctionsList_InvalidTransferFrom(address rule, address spender, address from, address to, uint256 value, uint8 code);
+ /* ============ Role ============ */
+ bytes32 public constant SANCTIONLIST_ROLE = keccak256("SANCTIONLIST_ROLE");
+
+ /* ============ String message ============ */
+ string constant TEXT_ADDRESS_FROM_IS_SANCTIONED = "The sender is sanctioned";
+ string constant TEXT_ADDRESS_TO_IS_SANCTIONED = "The recipient is sanctioned";
+ string constant TEXT_ADDRESS_SPENDER_IS_SANCTIONED = "The spender is sanctioned";
+
+ /* ============ Code ============ */
+ // It is very important that each rule uses an unique code
+ uint8 public constant CODE_ADDRESS_FROM_IS_SANCTIONED = 30;
+ uint8 public constant CODE_ADDRESS_TO_IS_SANCTIONED = 31;
+ uint8 public constant CODE_ADDRESS_SPENDER_IS_SANCTIONED = 32;
+}
diff --git a/src/rules/validation/abstract/RuleValidateTransfer.sol b/src/rules/validation/abstract/RuleValidateTransfer.sol
index 2df3a33..f9c3d31 100644
--- a/src/rules/validation/abstract/RuleValidateTransfer.sol
+++ b/src/rules/validation/abstract/RuleValidateTransfer.sol
@@ -2,34 +2,84 @@
pragma solidity ^0.8.20;
-import {IRuleValidation} from "RuleEngine/interfaces/IRuleValidation.sol";
-import {IERC1404} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
-abstract contract RuleValidateTransfer is IRuleValidation {
+/* ==== CMTAT === */
+import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+import {IERC3643ComplianceRead} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol";
+/* ==== RuleEngine === */
+import {IRule} from "RuleEngine/interfaces/IRule.sol";
+import {
+ IERC7943NonFungibleCompliance,
+ IERC7943NonFungibleComplianceExtend
+} from "../../interfaces/IERC7943NonFungibleCompliance.sol";
+
+abstract contract RuleValidateTransfer is IERC7943NonFungibleComplianceExtend, IRule {
+ /**
+ * @notice Validate a transfer
+ * @param from the origin address
+ * @param to the destination address
+ * @param tokenId ERC-721 or ERC-1155 token Id
+ * @param amount to transfer, 1 for NFT
+ * @return isValid => true if the transfer is valid, false otherwise
+ *
+ */
+ function canTransfer(address from, address to, uint256 tokenId, uint256 amount)
+ public
+ view
+ override(IERC7943NonFungibleCompliance)
+ returns (bool isValid)
+ {
+ // does not work without `this` keyword => "Undeclared identifier"
+ return this.detectTransferRestriction(from, to, tokenId, amount)
+ == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ }
+
/**
* @notice Validate a transfer
- * @param _from the origin address
- * @param _to the destination address
- * @param _amount to transfer
+ * @param from the origin address
+ * @param to the destination address
+ * @param amount to transfer
* @return isValid => true if the transfer is valid, false otherwise
- **/
- function canTransfer(
- address _from,
- address _to,
- uint256 _amount
- ) public view override returns (bool isValid) {
+ *
+ */
+ function canTransfer(address from, address to, uint256 amount)
+ public
+ view
+ override(IERC3643ComplianceRead)
+ returns (bool isValid)
+ {
// does not work without `this` keyword => "Undeclared identifier"
- return
- this.detectTransferRestriction(_from, _to, _amount) ==
- uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+ return this.detectTransferRestriction(from, to, amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ }
+
+ /**
+ * @inheritdoc IERC7551Compliance
+ */
+ function canTransferFrom(address spender, address from, address to, uint256 value)
+ public
+ view
+ virtual
+ override(IERC7551Compliance)
+ returns (bool)
+ {
+ return this.detectTransferRestrictionFrom(spender, from, to, value)
+ == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+ }
+
+ /**
+ * @inheritdoc IERC7943NonFungibleComplianceExtend
+ */
+ function canTransferFrom(address spender, address from, address to, uint256 tokenId, uint256 value)
+ public
+ view
+ virtual
+ override(IERC7943NonFungibleComplianceExtend)
+ returns (bool)
+ {
+ return canTransferFrom(spender, from, to, value);
}
- function canTransferFrom(
- address spender,
- address from,
- address to,
- uint256 value
- ) public view virtual override returns (bool) {
- return this.detectTransferRestrictionFrom(spender, from, to, value) ==
- uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
+ return interfaceId == type(IRule).interfaceId;
}
}
diff --git a/src/rules/validation/abstract/RuleWhitelistCommon.sol b/src/rules/validation/abstract/RuleWhitelistCommon.sol
index dedd371..5d72ac5 100644
--- a/src/rules/validation/abstract/RuleWhitelistCommon.sol
+++ b/src/rules/validation/abstract/RuleWhitelistCommon.sol
@@ -1,44 +1,123 @@
// SPDX-License-Identifier: MPL-2.0
-
pragma solidity ^0.8.20;
-import "./RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol";
-import "./RuleValidateTransfer.sol";
+/* ==== CMTAT === */
+import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+/* ==== Abstract contracts === */
+import {RuleWhitelistInvariantStorage} from "./RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol";
+import {RuleValidateTransfer} from "./RuleValidateTransfer.sol";
+/* ==== Interface === */
+import {
+ IERC7943NonFungibleCompliance,
+ IERC7943NonFungibleComplianceExtend
+} from "../../interfaces/IERC7943NonFungibleCompliance.sol";
+
+/**
+ * @title Rule Whitelist Common
+ * @notice Provides common logic for validating whitelist-based transfer restrictions.
+ * @dev
+ * - Implements ERC-3643–compatible `transferred` hooks to enforce whitelist checks.
+ * - Defines utility functions for restriction code validation and message mapping.
+ * - Inherits restriction code constants and messages from {RuleWhitelistInvariantStorage}.
+ */
+abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInvariantStorage {
+ /**
+ * Indicate if the spender is verified or not
+ */
+ bool public checkSpender;
-abstract contract RuleWhitelistCommon is
- RuleValidateTransfer,
- RuleWhitelistInvariantStorage
-{
+ /* ============ View Functions ============ */
/**
- * @notice To know if the restriction code is valid for this rule or not
- * @param _restrictionCode The target restriction code
- * @return true if the restriction code is known, false otherwise
- **/
- function canReturnTransferRestrictionCode(
- uint8 _restrictionCode
- ) external pure override returns (bool) {
- return
- _restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED ||
- _restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED ||
- _restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED;
+ * @notice Checks whether a restriction code is recognized by this rule.
+ * @dev
+ * Used to verify if a returned restriction code belongs to the whitelist rule.
+ * @param restrictionCode The restriction code to validate.
+ * @return isKnown True if the restriction code is recognized by this rule, false otherwise.
+ */
+ function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override returns (bool isKnown) {
+ return restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED
+ || restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED || restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED;
}
/**
- * @notice Return the corresponding message
- * @param _restrictionCode The target restriction code
- * @return true if the transfer is valid, false otherwise
- **/
- function messageForTransferRestriction(
- uint8 _restrictionCode
- ) external pure override returns (string memory) {
- if (_restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) {
+ * @notice Returns the human-readable message corresponding to a restriction code.
+ * @dev
+ * Returns a descriptive text that explains why a transfer was restricted.
+ * @param restrictionCode The restriction code to decode.
+ * @return message A human-readable explanation of the restriction.
+ */
+ function messageForTransferRestriction(uint8 restrictionCode)
+ external
+ pure
+ override
+ returns (string memory message)
+ {
+ if (restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) {
return TEXT_ADDRESS_FROM_NOT_WHITELISTED;
- } else if (_restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) {
+ } else if (restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) {
return TEXT_ADDRESS_TO_NOT_WHITELISTED;
- } else if (_restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED) {
+ } else if (restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED) {
return TEXT_ADDRESS_SPENDER_NOT_WHITELISTED;
} else {
return TEXT_CODE_NOT_FOUND;
}
}
+
+ /* ============ State Functions ============ */
+
+ /**
+ * @notice ERC-3643 hook called when a transfer occurs.
+ * @dev
+ * - Validates that both `from` and `to` addresses are whitelisted.
+ * - Reverts if any restriction code other than `TRANSFER_OK` is returned.
+ * - Should be called during token transfer logic to enforce whitelist compliance.
+ * @param from The address sending tokens.
+ * @param to The address receiving tokens.
+ * @param value The token amount being transferred.
+ */
+ function transferred(address from, address to, uint256 value) public view override(IERC3643IComplianceContract) {
+ uint8 code = this.detectTransferRestriction(from, to, value);
+ require(
+ code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+ RuleWhitelist_InvalidTransfer(address(this), from, to, value, code)
+ );
+ }
+
+ /**
+ * @notice hook called when a delegated transfer occurs (`transferFrom`).
+ * @dev
+ * - Validates that `spender`, `from`, and `to` are all whitelisted.
+ * - Reverts if any restriction code other than `TRANSFER_OK` is returned.
+ * @param spender The address performing the transfer on behalf of another.
+ * @param from The address from which tokens are transferred.
+ * @param to The recipient address.
+ * @param value The token amount being transferred.
+ */
+ function transferred(address spender, address from, address to, uint256 value) public view override(IRuleEngine) {
+ uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value);
+ require(
+ code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+ RuleWhitelist_InvalidTransferFrom(address(this), spender, from, to, value, code)
+ );
+ }
+
+
+ function transferred(address spender, address from, address to, uint256 /* tokenId */,uint256 value)
+ public
+ view
+ virtual
+ override(IERC7943NonFungibleComplianceExtend)
+ {
+ transferred(spender, from, to, value);
+ }
+
+ function transferred(address from, address to, uint256 /* tokenId */,uint256 value)
+ public
+ view
+ virtual
+ override(IERC7943NonFungibleComplianceExtend)
+ {
+ transferred(from, to, value);
+ }
}
diff --git a/test/HelperContract.sol b/test/HelperContract.sol
index c6f487e..f2b5340 100644
--- a/test/HelperContract.sol
+++ b/test/HelperContract.sol
@@ -6,29 +6,29 @@ import "CMTAT/deployment/CMTATStandalone.sol";
import "CMTAT/libraries/Errors.sol";
// RuleEngine
-import {RuleEngineInvariantStorage} from "RuleEngine/modules/RuleEngineInvariantStorage.sol";
+import {RuleEngineInvariantStorage} from "RuleEngine/modules/library/RuleEngineInvariantStorage.sol";
import {RuleEngine} from "RuleEngine/RuleEngine.sol";
-// RuleConditionalTransfer
-import {RuleConditionalTransferInvariantStorage} from "src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol";
-import {RuleConditionalTransfer} from "src/rules/operation/RuleConditionalTransfer.sol";
+
// RuleSanctionList
-import {RuleSanctionList} from "src/rules/validation/RuleSanctionList.sol";
+import {RuleSanctionsList} from "src/rules/validation/RuleSanctionsList.sol";
// RUleBlackList
import {RuleBlacklist} from "src/rules/validation/RuleBlacklist.sol";
-import {RuleBlacklistInvariantStorage} from "src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol";
+import {RuleBlacklistInvariantStorage} from
+ "src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol";
// RuleWhitelist
import {RuleWhitelist} from "src/rules/validation/RuleWhitelist.sol";
import {RuleWhitelistWrapper} from "src/rules/validation/RuleWhitelistWrapper.sol";
-import {RuleWhitelistInvariantStorage} from "src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol";
-import {RuleAddressListInvariantStorage} from "src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol";
+import {RuleWhitelistInvariantStorage} from
+ "src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol";
+import {RuleAddressSetInvariantStorage} from
+ "src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol";
-import {RuleSanctionlistInvariantStorage}from "src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol";
+import {RuleSanctionsListInvariantStorage} from "src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol";
// Rule interface
-import {IRuleValidation} from "RuleEngine/interfaces/IRuleValidation.sol";
-import {IRuleOperation} from "RuleEngine/interfaces/IRuleOperation.sol";
+import {IAddressList} from "src/rules/interfaces/IAddressList.sol";
// utils
-import "./utils/CMTATDeployment.sol";
+import "RuleEngine/../test/utils/CMTATDeployment.sol";
/**
* @title Constants used by the tests
@@ -36,10 +36,9 @@ import "./utils/CMTATDeployment.sol";
abstract contract HelperContract is
RuleWhitelistInvariantStorage,
RuleBlacklistInvariantStorage,
- RuleAddressListInvariantStorage,
- RuleSanctionlistInvariantStorage,
- RuleEngineInvariantStorage,
- RuleConditionalTransferInvariantStorage
+ RuleAddressSetInvariantStorage,
+ RuleSanctionsListInvariantStorage,
+ RuleEngineInvariantStorage
{
// Test result
uint256 internal resUint256;
@@ -59,19 +58,15 @@ abstract contract HelperContract is
address constant ADDRESS2 = address(6);
address constant ADDRESS3 = address(7);
// role string
- string constant RULE_ENGINE_ROLE_HASH =
- "0x774b3c5f4a8b37a7da21d72b7f2429e4a6d49c4de0ac5f2b831a1a539d0f0fd2";
- string constant WHITELIST_ROLE_HASH =
- "0xdc72ed553f2544c34465af23b847953efeb813428162d767f9ba5f4013be6760";
- string constant DEFAULT_ADMIN_ROLE_HASH =
- "0x0000000000000000000000000000000000000000000000000000000000000000";
+ string constant RULE_ENGINE_ROLE_HASH = "0x774b3c5f4a8b37a7da21d72b7f2429e4a6d49c4de0ac5f2b831a1a539d0f0fd2";
+ string constant WHITELIST_ROLE_HASH = "0xdc72ed553f2544c34465af23b847953efeb813428162d767f9ba5f4013be6760";
+ string constant DEFAULT_ADMIN_ROLE_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000";
uint256 DEFAULT_TIME_LIMIT_TO_APPROVE = 7 days;
uint256 DEFAULT_TIME_LIMIT_TO_TRANSFER = 7 days;
// contract
RuleBlacklist public ruleBlacklist;
RuleWhitelist public ruleWhitelist;
- RuleConditionalTransfer public ruleConditionalTransfer;
// CMTAT
CMTATDeployment cmtatDeployment;
diff --git a/test/RuleBlacklist/CMTATIntegration.t.sol b/test/RuleBlacklist/CMTATIntegration.t.sol
index 6314514..171f08b 100644
--- a/test/RuleBlacklist/CMTATIntegration.t.sol
+++ b/test/RuleBlacklist/CMTATIntegration.t.sol
@@ -13,9 +13,6 @@ contract CMTATIntegration is Test, HelperContract {
uint256 ADDRESS1_BALANCE_INIT = 31;
uint256 ADDRESS2_BALANCE_INIT = 32;
uint256 ADDRESS3_BALANCE_INIT = 33;
-
- uint256 FLAG = 5;
-
// Arrange
function setUp() public {
// CMTAT
@@ -27,13 +24,9 @@ contract CMTATIntegration is Test, HelperContract {
// specific arrange
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleEngineMock = new RuleEngine(
- DEFAULT_ADMIN_ADDRESS,
- ZERO_ADDRESS,
- address(CMTAT_CONTRACT)
- );
+ ruleEngineMock = new RuleEngine(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, address(CMTAT_CONTRACT));
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleEngineMock.addRuleValidation(ruleBlacklist);
+ ruleEngineMock.addRule(ruleBlacklist);
vm.prank(DEFAULT_ADMIN_ADDRESS);
CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT);
vm.prank(DEFAULT_ADMIN_ADDRESS);
@@ -45,12 +38,10 @@ contract CMTATIntegration is Test, HelperContract {
CMTAT_CONTRACT.setRuleEngine(ruleEngineMock);
}
- /******* Transfer *******/
+ /**
+ * Transfer ******
+ */
function testCanTransferIfAddressNotBlacklisted() public {
- // Arrange
- /*vm.prank(ADDRESS1);
- vm.expectRevert(
- abi.encodeWithSelector(RuleEngine_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21)); */
// Act
vm.prank(ADDRESS1);
CMTAT_CONTRACT.transfer(ADDRESS2, 21);
@@ -60,15 +51,17 @@ contract CMTATIntegration is Test, HelperContract {
// Arrange
uint256 amount = 21;
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleBlacklist.addAddressToTheList(ADDRESS2);
+ ruleBlacklist.addAddress(ADDRESS2);
vm.prank(ADDRESS1);
vm.expectRevert(
abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
+ RuleBlacklist_InvalidTransfer.selector,
+ address(ruleBlacklist),
ADDRESS1,
ADDRESS2,
- amount
+ amount,
+ CODE_ADDRESS_TO_IS_BLACKLISTED
)
);
// Act
@@ -79,15 +72,17 @@ contract CMTATIntegration is Test, HelperContract {
// Arrange
uint256 amount = 21;
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleBlacklist.addAddressToTheList(ADDRESS1);
+ ruleBlacklist.addAddress(ADDRESS1);
vm.prank(ADDRESS1);
vm.expectRevert(
abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
+ RuleBlacklist_InvalidTransfer.selector,
+ address(ruleBlacklist),
ADDRESS1,
ADDRESS2,
- amount
+ amount,
+ CODE_ADDRESS_FROM_IS_BLACKLISTED
)
);
// Act
@@ -101,44 +96,37 @@ contract CMTATIntegration is Test, HelperContract {
blacklist[0] = ADDRESS1;
blacklist[1] = ADDRESS2;
vm.prank(DEFAULT_ADMIN_ADDRESS);
- (bool success, ) = address(ruleBlacklist).call(
- abi.encodeWithSignature(
- "addAddressesToTheList(address[])",
- blacklist
- )
- );
+ (bool success,) = address(ruleBlacklist).call(abi.encodeWithSignature("addAddresses(address[])", blacklist));
require(success);
// Act
vm.prank(ADDRESS1);
vm.expectRevert(
abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
+ RuleBlacklist_InvalidTransfer.selector,
+ address(ruleBlacklist),
ADDRESS1,
ADDRESS2,
- amount
+ amount,
+ CODE_ADDRESS_FROM_IS_BLACKLISTED
)
);
CMTAT_CONTRACT.transfer(ADDRESS2, amount);
}
- /******* detectTransferRestriction & messageForTransferRestriction *******/
+ /**
+ * detectTransferRestriction & messageForTransferRestriction ******
+ */
function testDetectAndMessageWithToBlacklisted() public {
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleBlacklist.addAddressToTheList(ADDRESS2);
- resBool = ruleBlacklist.addressIsListed(ADDRESS2);
+ ruleBlacklist.addAddress(ADDRESS2);
+ resBool = ruleBlacklist.isAddressListed(ADDRESS2);
// Assert
assertEq(resBool, true);
- uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 11
- );
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
// Assert
assertEq(res1, CODE_ADDRESS_TO_IS_BLACKLISTED);
- string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(
- res1
- );
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
// Assert
assertEq(message1, TEXT_ADDRESS_TO_IS_BLACKLISTED);
}
@@ -147,40 +135,28 @@ contract CMTATIntegration is Test, HelperContract {
// Arrange
// We add the sender to the whitelist
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleBlacklist.addAddressToTheList(ADDRESS1);
+ ruleBlacklist.addAddress(ADDRESS1);
// Arrange - Assert
- resBool = ruleBlacklist.addressIsListed(ADDRESS1);
+ resBool = ruleBlacklist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
// Act
- uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 11
- );
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
// Assert
assertEq(res1, CODE_ADDRESS_FROM_IS_BLACKLISTED);
// Act
- string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(
- res1
- );
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
// Assert
assertEq(message1, TEXT_ADDRESS_FROM_IS_BLACKLISTED);
}
function testDetectAndMessageWithFromAndToNotBlacklisted() public view {
// Act
- uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 11
- );
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
// Assert
assertEq(res1, TRANSFER_OK);
// Act
- string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(
- res1
- );
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
// Assert
assertEq(message1, TEXT_TRANSFER_OK);
}
@@ -192,25 +168,14 @@ contract CMTATIntegration is Test, HelperContract {
blacklist[0] = ADDRESS1;
blacklist[1] = ADDRESS2;
vm.prank(DEFAULT_ADMIN_ADDRESS);
- (bool success, ) = address(ruleBlacklist).call(
- abi.encodeWithSignature(
- "addAddressesToTheList(address[])",
- blacklist
- )
- );
+ (bool success,) = address(ruleBlacklist).call(abi.encodeWithSignature("addAddresses(address[])", blacklist));
require(success);
// Act
- uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 11
- );
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
// Assert
assertEq(res1, CODE_ADDRESS_FROM_IS_BLACKLISTED);
// Act
- string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(
- res1
- );
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
// Assert
assertEq(message1, TEXT_ADDRESS_FROM_IS_BLACKLISTED);
}
@@ -228,22 +193,21 @@ contract CMTATIntegration is Test, HelperContract {
function testCannotMintIfAddressIsInTheBlacklist() public {
uint256 amount = 11;
// Arrange
- // Add address zero to the blacklist
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleBlacklist.addAddressToTheList(ZERO_ADDRESS);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleBlacklist.addAddressToTheList(ADDRESS1);
+ ruleBlacklist.addAddress(ADDRESS1);
// Arrange - Assert
- resBool = ruleBlacklist.addressIsListed(ZERO_ADDRESS);
+ resBool = ruleBlacklist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
// Act
vm.expectRevert(
abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
+ RuleBlacklist_InvalidTransfer.selector,
+ address(ruleBlacklist),
ZERO_ADDRESS,
ADDRESS1,
- amount
+ amount,
+ CODE_ADDRESS_TO_IS_BLACKLISTED
)
);
vm.prank(DEFAULT_ADMIN_ADDRESS);
@@ -252,9 +216,7 @@ contract CMTATIntegration is Test, HelperContract {
function testCanReturnMessageNotFoundWithUnknownCodeId() public view {
// Act
- string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(
- 255
- );
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(255);
// Assert
assertEq(message1, TEXT_CODE_NOT_FOUND);
diff --git a/test/RuleBlacklist/CMTATIntegrationDirect.t.sol b/test/RuleBlacklist/CMTATIntegrationDirect.t.sol
new file mode 100644
index 0000000..2ce8e1f
--- /dev/null
+++ b/test/RuleBlacklist/CMTATIntegrationDirect.t.sol
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: MPL-2.0
+pragma solidity ^0.8.20;
+
+import "forge-std/Test.sol";
+import "CMTAT/deployment/CMTATStandalone.sol";
+import "../HelperContract.sol";
+
+
+/**
+ * @title Integration test with the CMTAT using direct RuleBlacklist
+ */
+contract CMTATIntegrationDirectBlacklist is Test, HelperContract {
+ uint256 ADDRESS1_BALANCE_INIT = 31;
+ uint256 ADDRESS2_BALANCE_INIT = 32;
+ uint256 ADDRESS3_BALANCE_INIT = 33;
+
+ function setUp() public {
+ // Deploy CMTAT
+ cmtatDeployment = new CMTATDeployment();
+ CMTAT_CONTRACT = cmtatDeployment.cmtat();
+
+ // Deploy RuleBlacklist directly
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleBlacklist = new RuleBlacklist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS);
+
+ // Mint initial balances
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ CMTAT_CONTRACT.mint(ADDRESS2, ADDRESS2_BALANCE_INIT);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ CMTAT_CONTRACT.mint(ADDRESS3, ADDRESS3_BALANCE_INIT);
+
+ // Directly plug the blacklist into CMTAT
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ CMTAT_CONTRACT.setRuleEngine(IRuleEngine(address(ruleBlacklist)));
+ }
+
+ /* ---------------- Transfer Tests ---------------- */
+
+ function testCanTransferIfAddressNotBlacklisted() public {
+ vm.prank(ADDRESS1);
+ CMTAT_CONTRACT.transfer(ADDRESS2, 21);
+ }
+
+ function testCannotTransferIfAddressToIsBlacklisted() public {
+ uint256 amount = 21;
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleBlacklist.addAddress(ADDRESS2);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleBlacklist_InvalidTransfer.selector,
+ address(ruleBlacklist),
+ ADDRESS1,
+ ADDRESS2,
+ amount,
+ CODE_ADDRESS_TO_IS_BLACKLISTED
+ )
+ );
+ CMTAT_CONTRACT.transfer(ADDRESS2, amount);
+ }
+
+ function testCannotTransferIfAddressFromIsBlacklisted() public {
+ uint256 amount = 21;
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleBlacklist.addAddress(ADDRESS1);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleBlacklist_InvalidTransfer.selector,
+ address(ruleBlacklist),
+ ADDRESS1,
+ ADDRESS2,
+ amount,
+ CODE_ADDRESS_FROM_IS_BLACKLISTED
+ )
+ );
+ CMTAT_CONTRACT.transfer(ADDRESS2, amount);
+ }
+
+ function testCannotTransferIfBothAddressesAreBlacklisted() public {
+ uint256 amount = 21;
+ address[] memory blacklist = new address[](2);
+ blacklist[0] = ADDRESS1;
+ blacklist[1] = ADDRESS2;
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ (bool success,) = address(ruleBlacklist).call(abi.encodeWithSignature("addAddresses(address[])", blacklist));
+ require(success);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleBlacklist_InvalidTransfer.selector,
+ address(ruleBlacklist),
+ ADDRESS1,
+ ADDRESS2,
+ amount,
+ CODE_ADDRESS_FROM_IS_BLACKLISTED
+ )
+ );
+ CMTAT_CONTRACT.transfer(ADDRESS2, amount);
+ }
+
+ /* ---------------- Detect & Message Tests ---------------- */
+
+ function testDetectAndMessageWithToBlacklisted() public {
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleBlacklist.addAddress(ADDRESS2);
+ bool resBool = ruleBlacklist.isAddressListed(ADDRESS2);
+ assertEq(resBool, true);
+
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
+ assertEq(res1, CODE_ADDRESS_TO_IS_BLACKLISTED);
+
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
+ assertEq(message1, TEXT_ADDRESS_TO_IS_BLACKLISTED);
+ }
+
+ function testDetectAndMessageWithFromBlacklisted() public {
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleBlacklist.addAddress(ADDRESS1);
+ bool resBool = ruleBlacklist.isAddressListed(ADDRESS1);
+ assertEq(resBool, true);
+
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
+ assertEq(res1, CODE_ADDRESS_FROM_IS_BLACKLISTED);
+
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
+ assertEq(message1, TEXT_ADDRESS_FROM_IS_BLACKLISTED);
+ }
+
+ function testDetectAndMessageWithFromAndToNotBlacklisted() public view {
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
+ assertEq(res1, TRANSFER_OK);
+
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
+ assertEq(message1, TEXT_TRANSFER_OK);
+ }
+
+ function testDetectAndMessageWithFromAndToBlacklisted() public {
+ address[] memory blacklist = new address[](2);
+ blacklist[0] = ADDRESS1;
+ blacklist[1] = ADDRESS2;
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ (bool success,) = address(ruleBlacklist).call(abi.encodeWithSignature("addAddresses(address[])", blacklist));
+ require(success);
+
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
+ assertEq(res1, CODE_ADDRESS_FROM_IS_BLACKLISTED);
+
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
+ assertEq(message1, TEXT_ADDRESS_FROM_IS_BLACKLISTED);
+ }
+
+ /* ---------------- Mint Tests ---------------- */
+
+ function testCanMintIfAddressNotInTheBlacklist() public {
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ CMTAT_CONTRACT.mint(ADDRESS1, 11);
+
+ uint256 resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1);
+ assertEq(resUint256, ADDRESS1_BALANCE_INIT + 11);
+ }
+
+ function testCannotMintIfAddressIsInTheBlacklist() public {
+ uint256 amount = 11;
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleBlacklist.addAddress(ADDRESS1);
+ bool resBool = ruleBlacklist.isAddressListed(ADDRESS1);
+ assertEq(resBool, true);
+
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleBlacklist_InvalidTransfer.selector,
+ address(ruleBlacklist),
+ ZERO_ADDRESS,
+ ADDRESS1,
+ amount,
+ CODE_ADDRESS_TO_IS_BLACKLISTED
+ )
+ );
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ CMTAT_CONTRACT.mint(ADDRESS1, amount);
+ }
+
+ function testCanReturnMessageNotFoundWithUnknownCodeId() public view {
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(255);
+ assertEq(message1, TEXT_CODE_NOT_FOUND);
+ }
+}
\ No newline at end of file
diff --git a/test/RuleBlacklist/RuleBlacklist.t.sol b/test/RuleBlacklist/RuleBlacklist.t.sol
index 9ad87aa..f35fa71 100644
--- a/test/RuleBlacklist/RuleBlacklist.t.sol
+++ b/test/RuleBlacklist/RuleBlacklist.t.sol
@@ -15,16 +15,294 @@ contract RuleBlacklistTest is Test, HelperContract {
ruleBlacklist = new RuleBlacklist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS);
}
- function testCanRuleBlacklistReturnMessageNotFoundWithUnknownCodeId()
- public
- view
- {
+ function testReturnTheRightMessageForAGivenCode() public {
+ // Assert
+ resString = ruleBlacklist.messageForTransferRestriction(CODE_ADDRESS_FROM_IS_BLACKLISTED);
+ // Assert
+ assertEq(resString, TEXT_ADDRESS_FROM_IS_BLACKLISTED);
+
// Act
- string memory message1 = ruleBlacklist.messageForTransferRestriction(
- 255
- );
+ resString = ruleBlacklist.messageForTransferRestriction(CODE_ADDRESS_TO_IS_BLACKLISTED);
+ // Assert
+ assertEq(resString, TEXT_ADDRESS_TO_IS_BLACKLISTED);
+
+ // Act
+ resString = ruleBlacklist.messageForTransferRestriction(CODE_ADDRESS_SPENDER_IS_BLACKLISTED);
+ // Assert
+ assertEq(resString, TEXT_ADDRESS_SPENDER_IS_BLACKLISTED);
+
+ // Act
+ resString = ruleBlacklist.messageForTransferRestriction(CODE_NONEXISTENT);
+ // Assert
+ assertEq(resString, TEXT_CODE_NOT_FOUND);
+ }
+
+ function testCanRuleBlacklistReturnMessageNotFoundWithUnknownCodeId() public view {
+ // Act
+ string memory message1 = ruleBlacklist.messageForTransferRestriction(255);
// Assert
assertEq(message1, TEXT_CODE_NOT_FOUND);
}
+
+ function testDetectTransferRestrictionOk() public {
+ // Act
+ resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+
+ // With tokenId
+ resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+
+ // With tokenId
+ resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+
+ // Act
+ resBool = ruleBlacklist.canTransfer(ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resBool, true);
+ // Act
+ resBool = ruleBlacklist.canTransfer(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resBool, true);
+
+ // No revert
+ // Act
+ ruleBlacklist.transferred(ADDRESS1, ADDRESS2, 20);
+ ruleBlacklist.transferred(ADDRESS1, ADDRESS2, 0, 20);
+ }
+
+ function testDetectTransferRestrictionFRom() public {
+ // Arrange
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleBlacklist.addAddress(ADDRESS1);
+ // Act
+ resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_FROM_IS_BLACKLISTED);
+
+ // With tokenId
+ resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_FROM_IS_BLACKLISTED);
+
+ // Act
+ resBool = ruleBlacklist.canTransfer(ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertFalse(resBool);
+
+ // Act
+ resBool = ruleBlacklist.canTransfer(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertFalse(resBool);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleBlacklist_InvalidTransfer.selector,
+ address(ruleBlacklist),
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_FROM_IS_BLACKLISTED
+ )
+ );
+ // Act
+ ruleBlacklist.transferred(ADDRESS1, ADDRESS2, 20);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleBlacklist_InvalidTransfer.selector,
+ address(ruleBlacklist),
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_FROM_IS_BLACKLISTED
+ )
+ );
+ ruleBlacklist.transferred(ADDRESS1, ADDRESS2, 0, 20);
+ }
+
+ function testDetectTransferRestrictionTO() public {
+ // Arrange
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleBlacklist.addAddress(ADDRESS2);
+ // Act
+ resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20);
+ assertEq(resUint8, CODE_ADDRESS_TO_IS_BLACKLISTED);
+
+ // With tokenId
+ resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_TO_IS_BLACKLISTED);
+
+ // Act
+ resBool = ruleBlacklist.canTransfer(ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertFalse(resBool);
+
+ // Act
+ resBool = ruleBlacklist.canTransfer(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertFalse(resBool);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleBlacklist_InvalidTransfer.selector,
+ address(ruleBlacklist),
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_TO_IS_BLACKLISTED
+ )
+ );
+ // Act
+ ruleBlacklist.transferred(ADDRESS1, ADDRESS2, 20);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleBlacklist_InvalidTransfer.selector,
+ address(ruleBlacklist),
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_TO_IS_BLACKLISTED
+ )
+ );
+ ruleBlacklist.transferred(ADDRESS1, ADDRESS2, 0, 20);
+ }
+
+ function testDetectTransferRestrictionSpender() public {
+ // Arrange
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleBlacklist.addAddress(ADDRESS3);
+ // Act
+ resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ assertEq(resUint8, CODE_ADDRESS_SPENDER_IS_BLACKLISTED);
+
+ // With tokenId
+ resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_SPENDER_IS_BLACKLISTED);
+
+ // Act
+ resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertFalse(resBool);
+
+ // Act
+ resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertFalse(resBool);
+
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleBlacklist_InvalidTransferFrom.selector,
+ address(ruleBlacklist),
+ ADDRESS3,
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_SPENDER_IS_BLACKLISTED
+ )
+ );
+ // Act
+ ruleBlacklist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleBlacklist_InvalidTransferFrom.selector,
+ address(ruleBlacklist),
+ ADDRESS3,
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_SPENDER_IS_BLACKLISTED
+ )
+ );
+ ruleBlacklist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ }
+
+ function testDetectTransferRestrictionSpenderTo() public {
+ // Arrange
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleBlacklist.addAddress(ADDRESS2);
+ // Act
+ resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+
+ // With tokenId
+ resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_TO_IS_BLACKLISTED);
+
+ // Act
+ resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertFalse(resBool);
+
+ // Act
+ resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertFalse(resBool);
+ }
+
+ function testDetectTransferRestrictionSpenderFrom() public {
+ // Arrange
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleBlacklist.addAddress(ADDRESS1);
+ // Act
+ resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ assertEq(resUint8, CODE_ADDRESS_FROM_IS_BLACKLISTED);
+ // With tokenId
+ resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_FROM_IS_BLACKLISTED);
+
+ // Act
+ resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertFalse(resBool);
+
+ // Act
+ resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertFalse(resBool);
+ }
+
+ function testDetectTransferRestrictionSpenderOk() public {
+ // Act
+ resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ assertEq(resUint8, NO_ERROR);
+
+ // With tokenId
+ resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+
+ // Act
+ resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resBool, true);
+
+ // Act
+ resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resBool, true);
+
+ // No revert
+ // Act
+ ruleBlacklist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ ruleBlacklist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ }
+
}
diff --git a/test/RuleConditionalTransfer/CMTATIntegration.t.sol b/test/RuleConditionalTransfer/CMTATIntegration.t.sol
deleted file mode 100644
index 3768ef3..0000000
--- a/test/RuleConditionalTransfer/CMTATIntegration.t.sol
+++ /dev/null
@@ -1,160 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "CMTAT/deployment/CMTATStandalone.sol";
-import "../HelperContract.sol";
-import "./utils/CMTATIntegrationShare.sol";
-
-/**
- * @title Integration test with the CMTAT
- */
-contract CMTATIntegrationConditionalTransfer is Test, HelperContract, CMTATIntegrationShare {
- // Arrange
- function setUp() public {
- TIME_LIMIT memory timeLimit_ = TIME_LIMIT({
- timeLimitToApprove: 7 days,
- timeLimitToTransfer: 30 days
- });
- ISSUANCE memory issuanceOption_ = ISSUANCE({
- authorizedMintWithoutApproval: true,
- authorizedBurnWithoutApproval: true
- });
-
- AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
- isActivate: false,
- timeLimitBeforeAutomaticApproval: 0
- });
-
- AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({
- isActivate: false,
- cmtat: IERC20(address(0))
- });
- OPTION memory options = OPTION({
- issuance: issuanceOption_,
- timeLimit: timeLimit_,
- automaticApproval: automaticApproval_,
- automaticTransfer: automaticTransfer_
- });
-
- // global arrange
- cmtatDeployment = new CMTATDeployment();
- CMTAT_CONTRACT = cmtatDeployment.cmtat();
-
- // RuleEngine
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleEngineMock = new RuleEngine(
- DEFAULT_ADMIN_ADDRESS,
- ZERO_ADDRESS,
- address(CMTAT_CONTRACT)
- );
-
- // RuleConditionalTransfer
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleConditionalTransfer = new RuleConditionalTransfer(
- DEFAULT_ADMIN_ADDRESS,
- ZERO_ADDRESS,
- ruleEngineMock,
- options
- );
- // specific arrange
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleConditionalTransfer.grantRole(
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE,
- CONDITIONAL_TRANSFER_OPERATOR_ADDRESS
- );
-
- // RuleEngine
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleEngineMock.addRuleOperation(ruleConditionalTransfer);
-
- // Mint
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- CMTAT_CONTRACT.mint(ADDRESS2, ADDRESS2_BALANCE_INIT);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- CMTAT_CONTRACT.mint(ADDRESS3, ADDRESS3_BALANCE_INIT);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
-
- // We set the Rule Engine
- CMTAT_CONTRACT.setRuleEngine(ruleEngineMock);
- }
-
- function _createTransferRequest() internal {
- vm.prank(ADDRESS1);
- // Act
- vm.expectEmit(true, true, true, true);
- emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue);
- }
-
- /******* Transfer *******/
- function testCannotTransferWithoutApproval() public {
- CMTATIntegrationShare.testShareCannotTransferWithoutApproval();
- }
-
- function testCanMakeATransferIfApproved() public {
- CMTATIntegrationShare.testShareCanMakeATransferIfApproved();
- }
-
- function testCanMakeAPartialTransferIfPartiallyApproved() public {
- CMTATIntegrationShare.testShareCanMakeAPartialTransferIfPartiallyApproved();
- }
-
- function testCannotMakeAWholeTransferIfPartiallyApproved() public {
- CMTATIntegrationShare.testShareCannotMakeAWholeTransferIfPartiallyApproved();
- }
- function testCannotMakeATransferIfDelayExceeded() public {
- // // +30 days and one second
- CMTATIntegrationShare.testShareCannotMakeATransferIfDelayExceeded(2592001);
- }
-
- function testCannotMakeATransferIfDelayJustInTime() public {
- // 30 days
- CMTATIntegrationShare.testShareCannotMakeATransferIfDelayJustInTime(2592000);
- }
-
- function testCanSetTimeLimitWithTransferExceeded() public {
- // Assert
- // Timeout
- // >1 days
- CMTATIntegrationShare.testShareCanSetTimeLimitWithTransferExceeded(1 days + 1 seconds);
- }
-
- function testCanMintWithoutApproval() public {
- CMTATIntegrationShare.testShareCanMintWithoutApproval();
- }
-
- function testCanBurnWithoutApproval() public {
- CMTATIntegrationShare.testShareCanBurnWithoutApproval();
- }
-
- function testCannotMintWithoutApproval() public {
- CMTATIntegrationShare.testShareCannotMintWithoutApproval();
- }
-
- function testCannotBurnWithoutApproval() public {
- CMTATIntegrationShare.testShareCannotBurnWithoutApproval();
- }
-
- function testAutomaticTransferIfOptionsSet() public {
- CMTATIntegrationShare.testShareAutomaticTransferIfOptionsSet();
- }
-
- function testCanTransferIfAutomaticApprovalSetAndTimeExceedsJustInTime()
- public
- {
- CMTATIntegrationShare.testShareCanTransferIfAutomaticApprovalSetAndTimeExceedsJustInTime();
- }
-
- function testCanTransferIfAutomaticApprovalSetAndTimeExceeds() public {
- CMTATIntegrationShare.testShareCanTransferIfAutomaticApprovalSetAndTimeExceeds();
- }
-
- function testCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds()
- public
- {
- CMTATIntegrationShare.testShareCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds();
- }
-}
diff --git a/test/RuleConditionalTransfer/CMTATIntegrationConditionalTransfer.t.sol b/test/RuleConditionalTransfer/CMTATIntegrationConditionalTransfer.t.sol
deleted file mode 100644
index d1a289a..0000000
--- a/test/RuleConditionalTransfer/CMTATIntegrationConditionalTransfer.t.sol
+++ /dev/null
@@ -1,321 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "CMTAT/deployment/CMTATStandalone.sol";
-import "../HelperContract.sol";
-import "./utils/CMTATIntegrationShare.sol";
-
-/**
- * @title Integration test with the CMTAT
- */
-contract CMTATIntegrationConditionalTransfer is Test, HelperContract, CMTATIntegrationShare {
-
- // Arrange
- function setUp() public {
- TIME_LIMIT memory timeLimit_ = TIME_LIMIT({
- timeLimitToApprove: 7 days,
- timeLimitToTransfer: 30 days
- });
- ISSUANCE memory issuanceOption_ = ISSUANCE({
- authorizedMintWithoutApproval: true,
- authorizedBurnWithoutApproval: true
- });
-
- AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
- isActivate: false,
- timeLimitBeforeAutomaticApproval: 0
- });
-
- AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({
- isActivate: false,
- cmtat: IERC20(address(0))
- });
- OPTION memory options = OPTION({
- issuance: issuanceOption_,
- timeLimit: timeLimit_,
- automaticApproval: automaticApproval_,
- automaticTransfer: automaticTransfer_
- });
-
- // global arrange
- cmtatDeployment = new CMTATDeployment();
- CMTAT_CONTRACT = cmtatDeployment.cmtat();
-
- // Whitelist
- ruleWhitelist = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS);
-
- // RuleEngine
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleEngineMock = new RuleEngine(
- DEFAULT_ADMIN_ADDRESS,
- ZERO_ADDRESS,
- address(CMTAT_CONTRACT)
- );
-
- // RuleConditionalTransfer
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleConditionalTransfer = new RuleConditionalTransfer(
- DEFAULT_ADMIN_ADDRESS,
- ZERO_ADDRESS,
- ruleEngineMock,
- options
- );
- // Add whitelist
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleConditionalTransfer.setConditionalWhitelist(ruleWhitelist);
- // specific arrange
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleConditionalTransfer.grantRole(
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE,
- CONDITIONAL_TRANSFER_OPERATOR_ADDRESS
- );
-
- // RuleEngine
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleEngineMock.addRuleOperation(ruleConditionalTransfer);
-
- // Mint
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- CMTAT_CONTRACT.mint(ADDRESS2, ADDRESS2_BALANCE_INIT);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- CMTAT_CONTRACT.mint(ADDRESS3, ADDRESS3_BALANCE_INIT);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
-
- // We set the Rule Engine
- CMTAT_CONTRACT.setRuleEngine(ruleEngineMock);
- }
-
- function _createTransferRequest() internal {
- vm.prank(ADDRESS1);
- // Act
- vm.expectEmit(true, true, true, true);
- emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue);
- }
-
- /******* Transfer *******/
- function testCanMakeATransferWithoutApprovalIfFromAndToAreInTheWhitelist()
- public
- {
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS2);
- // Arrange
- // Act
- vm.prank(ADDRESS1);
- CMTAT_CONTRACT.transfer(ADDRESS2, 21);
- }
-
- function testCannotMakeATransferWithoutApprovalIfOnlyFromIsInTheWhitelist()
- public
- {
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
- // Arrange
- // Act
- vm.expectRevert(
- abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
- ADDRESS1,
- ADDRESS2,
- 21
- )
- );
- vm.prank(ADDRESS1);
- CMTAT_CONTRACT.transfer(ADDRESS2, 21);
- }
-
- function testCannotMakeATransferWithoutApprovalIfOnlyToIsInTheWhitelist()
- public
- {
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS2);
- // Arrange
- // Act
- vm.expectRevert(
- abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
- ADDRESS1,
- ADDRESS2,
- 21
- )
- );
- vm.prank(ADDRESS1);
- CMTAT_CONTRACT.transfer(ADDRESS2, 21);
- }
-
- function testCanSetANewWhitelist() public {
- RuleWhitelist ruleWhitelist2 = new RuleWhitelist(
- DEFAULT_ADMIN_ADDRESS,
- ZERO_ADDRESS
- );
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- vm.expectEmit(true, false, false, false);
- emit WhitelistConditionalTransfer(ruleWhitelist2);
- ruleConditionalTransfer.setConditionalWhitelist(ruleWhitelist2);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist2.addAddressToTheList(ADDRESS1);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist2.addAddressToTheList(ADDRESS2);
-
- // Arrange
- // Act
- vm.prank(ADDRESS1);
- CMTAT_CONTRACT.transfer(ADDRESS2, 21);
- }
-
- function testCanUnSetWhitelist() public {
- // Arrange
- RuleWhitelist ruleWhitelist2 = new RuleWhitelist(
- DEFAULT_ADMIN_ADDRESS,
- ZERO_ADDRESS
- );
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- vm.expectEmit(true, false, false, false);
- emit WhitelistConditionalTransfer(ruleWhitelist2);
- ruleConditionalTransfer.setConditionalWhitelist(ruleWhitelist2);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist2.addAddressToTheList(ADDRESS1);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist2.addAddressToTheList(ADDRESS2);
-
- // Act
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleConditionalTransfer.setConditionalWhitelist(
- RuleWhitelist(ZERO_ADDRESS)
- );
-
- // Assert
- vm.prank(ADDRESS1);
- vm.expectRevert(
- abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
- ADDRESS1,
- ADDRESS2,
- 21
- )
- );
- CMTAT_CONTRACT.transfer(ADDRESS2, 21);
- }
-
- function testCanDetectTransferRestrictionOKWithWhitelist() public {
- // Arrange
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS2);
-
- // Act
- uint8 resUint8 = ruleConditionalTransfer.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
-
- // Assert
- assertEq(resUint8, 0);
- }
-
- function testCanDetectTransferRestrictionWithOnlyFromInTheWhitelist()
- public
- {
- // Arrange
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
-
- // Act
- uint8 resUint8 = ruleConditionalTransfer.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
-
- // Assert
- assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED);
- }
-
- function testCanDetectTransferRestrictionWithOnlyToInTheWhitelist() public {
- // Arrange
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS2);
-
- // Act
- uint8 resUint8 = ruleConditionalTransfer.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
-
- // Assert
- assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED);
- }
-
- /***** Test from CMTAT integration */
-
- function testCannotTransferWithoutApproval() public {
- CMTATIntegrationShare.testShareCannotTransferWithoutApproval();
- }
-
- function testCanMakeATransferIfApproved() public {
- CMTATIntegrationShare.testShareCanMakeATransferIfApproved();
- }
- function testCanMakeAPartialTransferIfPartiallyApproved() public {
- CMTATIntegrationShare.testShareCanMakeAPartialTransferIfPartiallyApproved();
- }
-
- function testCannotMakeAWholeTransferIfPartiallyApproved() public {
- CMTATIntegrationShare.testShareCannotMakeAWholeTransferIfPartiallyApproved();
- }
-
- function testCannotMakeATransferIfDelayExceeded() public {
- CMTATIntegrationShare.testShareCannotMakeATransferIfDelayExceeded(2592001);
- }
-
- function testCannotMakeATransferIfDelayJustInTime() public {
- // 30 days
- CMTATIntegrationShare.testShareCannotMakeATransferIfDelayJustInTime(2592000);
- }
-
- function testCanSetTimeLimitWithTransferExceeded() public {
- CMTATIntegrationShare.testShareCanSetTimeLimitWithTransferExceeded(1 days + 1 seconds);
- }
-
- function testCanMintWithoutApproval() public {
- CMTATIntegrationShare.testShareCanMintWithoutApproval();
- }
-
- function testCanBurnWithoutApproval() public {
- CMTATIntegrationShare.testShareCanBurnWithoutApproval();
- }
-
- function testCannotMintWithoutApproval() public {
- CMTATIntegrationShare.testShareCannotMintWithoutApproval();
- }
-
- function testCannotBurnWithoutApproval() public {
- CMTATIntegrationShare.testShareCannotBurnWithoutApproval();
- }
- function testAutomaticTransferIfOptionsSet() public {
- CMTATIntegrationShare.testShareAutomaticTransferIfOptionsSet();
- }
-
- function testCanTransferIfAutomaticApprovalSetAndTimeExceedsJustInTime()
- public
- {
- CMTATIntegrationShare.testShareCanTransferIfAutomaticApprovalSetAndTimeExceedsJustInTime();
- }
-
- function testCanTransferIfAutomaticApprovalSetAndTimeExceeds() public {
- CMTATIntegrationShare.testShareCanTransferIfAutomaticApprovalSetAndTimeExceeds();
- }
-
- function testCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds()
- public
- {
- CMTATIntegrationShare.testShareCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds();
- }
-}
diff --git a/test/RuleConditionalTransfer/CMTATIntegrationTest2.t.sol b/test/RuleConditionalTransfer/CMTATIntegrationTest2.t.sol
deleted file mode 100644
index 12cddb3..0000000
--- a/test/RuleConditionalTransfer/CMTATIntegrationTest2.t.sol
+++ /dev/null
@@ -1,182 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "CMTAT/deployment/CMTATStandalone.sol";
-import "../HelperContract.sol";
-import "RuleEngine/RuleEngine.sol";
-import "./utils/CMTATIntegrationShare.sol";
-
-/**
- * @title Integration test with the CMTAT
- * @dev set blocktimestamp to a value different from 0
- */
-contract CMTATIntegrationConditionalTransferWithTimeStampSet is Test, HelperContract, CMTATIntegrationShare {
- uint256 TIME_LIMIT_AUTO_APPROVAL = 259200; //3 days;
- uint256 TIME_LIMIT_TO_APPROVE = 432000; //5 days;
- uint256 TIME_LIMIT_TO_TRANSFER = 259200; //3 days
- // Arrange
- function setUp() public {
- // global arrange
- cmtatDeployment = new CMTATDeployment();
- CMTAT_CONTRACT = cmtatDeployment.cmtat();
-
- TIME_LIMIT memory timeLimit_ = TIME_LIMIT({
- timeLimitToApprove: TIME_LIMIT_TO_APPROVE, // 5days
- timeLimitToTransfer: TIME_LIMIT_TO_TRANSFER
- });
- ISSUANCE memory issuanceOption_ = ISSUANCE({
- authorizedMintWithoutApproval: true,
- authorizedBurnWithoutApproval: true
- });
-
- AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
- isActivate: true,
- timeLimitBeforeAutomaticApproval: TIME_LIMIT_AUTO_APPROVAL
- });
-
- AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({
- isActivate: true,
- cmtat: IERC20(address(CMTAT_CONTRACT))
- });
- OPTION memory options = OPTION({
- issuance: issuanceOption_,
- timeLimit: timeLimit_,
- automaticApproval: automaticApproval_,
- automaticTransfer: automaticTransfer_
- });
-
-
-
- // RuleEngine
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleEngineMock = new RuleEngine(
- DEFAULT_ADMIN_ADDRESS,
- ZERO_ADDRESS,
- address(CMTAT_CONTRACT)
- );
-
- // RuleConditionalTransfer
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleConditionalTransfer = new RuleConditionalTransfer(
- DEFAULT_ADMIN_ADDRESS,
- ZERO_ADDRESS,
- ruleEngineMock,
- options
- );
- // specific arrange
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleConditionalTransfer.grantRole(
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE,
- CONDITIONAL_TRANSFER_OPERATOR_ADDRESS
- );
-
- // RuleEngine
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleEngineMock.addRuleOperation(ruleConditionalTransfer);
-
- // Mint
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- CMTAT_CONTRACT.mint(ADDRESS2, ADDRESS2_BALANCE_INIT);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- CMTAT_CONTRACT.mint(ADDRESS3, ADDRESS3_BALANCE_INIT);
- vm.prank(DEFAULT_ADMIN_ADDRESS);
-
- // We set the Rule Engine
- CMTAT_CONTRACT.setRuleEngine(ruleEngineMock);
-
- vm.warp(1734531338);
- }
-
- function _createTransferRequest() internal {
- vm.prank(ADDRESS1);
- // Act
- vm.expectEmit(true, true, true, true);
- emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue);
- }
-
- /******* Transfer *******/
- function testCannotTransferWithoutApproval() public {
- // Arrange - Assert
- // ConditionalTransfer
- resUint8 = ruleConditionalTransfer.detectTransferRestriction(
- address(0xD65Fb7036518F4B34482E0a1905Dc6e3Fc379FF0),
- address(0xD65Fb7036518F4B34482E0a1905Dc6e3Fc379FF0),
- defaultValue
- );
- assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED);
- resUint8 = ruleConditionalTransfer.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 5
- );
- assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED);
- // Assert
- // Arrange
- CMTATIntegrationShare.testShareCannotTransferWithoutApproval();
- }
-
- function testCanMakeATransferIfApproved() public {
- CMTATIntegrationShare.testShareCanMakeATransferIfApproved();
- }
-
- function testCanMakeAPartialTransferIfPartiallyApproved() public {
- CMTATIntegrationShare.testShareCanMakeAPartialTransferIfPartiallyApproved();
- }
-
- function testCannotMakeAWholeTransferIfPartiallyApproved() public {
- CMTATIntegrationShare.testShareCannotMakeAWholeTransferIfPartiallyApproved();
-
- }
-
- function testCannotMakeATransferIfDelayExceeded() public {
- CMTATIntegrationShare.testShareCannotMakeATransferIfDelayExceeded(TIME_LIMIT_TO_TRANSFER + 1 seconds);
- }
-
- function testCanMakeATransferIfDelayJustInTime() public {
- CMTATIntegrationShare.testShareCannotMakeATransferIfDelayJustInTime(TIME_LIMIT_TO_TRANSFER);
- }
-
- function testCanSetTimeLimitWithTransferExceeded() public {
- CMTATIntegrationShare.testShareCanSetTimeLimitWithTransferExceeded(1 days + 1 seconds);
- }
-
- function testCanMintWithoutApproval() public {
- CMTATIntegrationShare.testShareCanMintWithoutApproval();
- }
-
- function testCanBurnWithoutApproval() public {
- CMTATIntegrationShare.testShareCanBurnWithoutApproval();
- }
-
- function testCannotMintWithoutApproval() public {
- CMTATIntegrationShare.testShareCannotMintWithoutApproval();
- }
-
- function testCannotBurnWithoutApproval() public {
- CMTATIntegrationShare.testShareCannotBurnWithoutApproval();
- }
-
- function testAutomaticTransferIfOptionsSet() public {
- CMTATIntegrationShare.testShareAutomaticTransferIfOptionsSet();
- }
-
- function testCanTransferIfAutomaticApprovalSetAndTimeExceedsJustInTime()
- public
- {
- CMTATIntegrationShare.testShareCanTransferIfAutomaticApprovalSetAndTimeExceedsJustInTime();
- }
-
- function testCanTransferIfAutomaticApprovalSetAndTimeExceeds() public {
- CMTATIntegrationShare.testShareCanTransferIfAutomaticApprovalSetAndTimeExceeds();
- }
-
- function testCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds()
- public
- {
- CMTATIntegrationShare.testShareCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds();
- }
-}
diff --git a/test/RuleConditionalTransfer/RuleConditionalTransfer.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransfer.t.sol
deleted file mode 100644
index 01047df..0000000
--- a/test/RuleConditionalTransfer/RuleConditionalTransfer.t.sol
+++ /dev/null
@@ -1,979 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "../HelperContract.sol";
-import "OZ/token/ERC20/IERC20.sol";
-/**
- * @title General functions of the RuleWhitelist
- */
-contract RuleConditionalTransferTest is Test, HelperContract {
- uint256 defaultValue = 10;
- bytes32 defaultKey =
- keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue));
-
- // Batch test
- uint256 value2 = 1;
- uint256 value3 = 2;
- uint256 value4 = 1000;
- uint256 value5 = 2000;
- bytes32 key2 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value2));
- bytes32 key3 = keccak256(abi.encode(ADDRESS2, ADDRESS1, value3));
- bytes32 key4 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value4));
- bytes32 key5 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value5));
-
- TransferRequestKeyElement transferRequestInput2 =
- TransferRequestKeyElement({
- from: ADDRESS1,
- to: ADDRESS2,
- value: value2
- });
-
- TransferRequestKeyElement transferRequestInput3 =
- TransferRequestKeyElement({
- from: ADDRESS2,
- to: ADDRESS1,
- value: value3
- });
-
- TransferRequestKeyElement transferRequestInput4 =
- TransferRequestKeyElement({
- from: ADDRESS1,
- to: ADDRESS2,
- value: value4
- });
- TransferRequestKeyElement transferRequestInput5 =
- TransferRequestKeyElement({
- from: ADDRESS1,
- to: ADDRESS2,
- value: value5
- });
- TransferRequestKeyElement transferRequestInput =
- TransferRequestKeyElement({
- from: ADDRESS1,
- to: ADDRESS2,
- value: defaultValue
- });
-
- // Arrange
- function setUp() public {
- TIME_LIMIT memory timeLimit_ = TIME_LIMIT({
- timeLimitToApprove: 3 days,
- timeLimitToTransfer: 30 days
- });
-
- AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
- isActivate: false,
- timeLimitBeforeAutomaticApproval: 0
- });
-
- ISSUANCE memory issuanceOption_ = ISSUANCE({
- authorizedMintWithoutApproval: false,
- authorizedBurnWithoutApproval: false
- });
- AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({
- isActivate: false,
- cmtat: IERC20(address(0))
- });
-
- OPTION memory options = OPTION({
- issuance: issuanceOption_,
- timeLimit: timeLimit_,
- automaticApproval: automaticApproval_,
- automaticTransfer: automaticTransfer_
- });
- ruleEngineMock = new RuleEngine(
- RULE_ENGINE_OPERATOR_ADDRESS,
- ZERO_ADDRESS,
- ZERO_ADDRESS
- );
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleConditionalTransfer = new RuleConditionalTransfer(
- DEFAULT_ADMIN_ADDRESS,
- ZERO_ADDRESS,
- ruleEngineMock,
- options
- );
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleConditionalTransfer.grantRole(
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE,
- CONDITIONAL_TRANSFER_OPERATOR_ADDRESS
- );
- }
-
- function _createTransferRequest() internal {
- vm.prank(ADDRESS1);
- // Act
- vm.expectEmit(true, true, true, true);
- emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue);
-
- // Assert
- TransferRequest memory transferRequest = ruleConditionalTransfer
- .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue);
- assertEq(transferRequest.key, defaultKey);
- assertEq(transferRequest.id, 0);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, defaultValue);
- assertEq(uint256(transferRequest.status), uint256(STATUS.WAIT));
-
- TransferRequest[] memory transferRequests = ruleConditionalTransfer
- .getRequestByStatus(STATUS.WAIT);
- assertEq(transferRequests[0].key, defaultKey);
- assertEq(transferRequests.length, 1);
- }
-
- function _createTransferRequestBatch() public {
- // Arrange
- _createTransferRequest();
-
- // Second and third request
- vm.prank(ADDRESS1);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, value2);
- vm.prank(ADDRESS2);
- ruleConditionalTransfer.createTransferRequest(ADDRESS1, value3);
- //Fourth request => will be not validated
- vm.prank(ADDRESS1);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, value4);
- //fifth request => will not be treated
- vm.prank(ADDRESS1);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, value5);
- }
-
- function _checkRequestPartial() internal view {
- TransferRequest memory transferRequest = ruleConditionalTransfer
- .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue);
- assertEq(transferRequest.key, defaultKey);
- assertEq(transferRequest.id, 0);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, defaultValue);
- assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED));
-
- // 2
- transferRequest = ruleConditionalTransfer.getRequestTrade(
- ADDRESS1,
- ADDRESS2,
- value2
- );
- assertEq(transferRequest.key, key2);
- assertEq(transferRequest.id, 1);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, value2);
- assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED));
-
- // 3
- transferRequest = ruleConditionalTransfer.getRequestTrade(
- ADDRESS2,
- ADDRESS1,
- value3
- );
- assertEq(transferRequest.key, key3);
- assertEq(transferRequest.id, 2);
- assertEq(transferRequest.keyElement.from, ADDRESS2);
- assertEq(transferRequest.keyElement.to, ADDRESS1);
- assertEq(transferRequest.keyElement.value, value3);
- assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED));
-
- // 4
- transferRequest = ruleConditionalTransfer.getRequestTrade(
- ADDRESS1,
- ADDRESS2,
- value4
- );
- assertEq(transferRequest.key, key4);
- assertEq(transferRequest.id, 3);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, value4);
- assertEq(uint256(transferRequest.status), uint256(STATUS.DENIED));
- }
-
- function _checkRequestBatch() internal view {
- _checkRequestPartial();
-
- // 5
- TransferRequest memory transferRequest = ruleConditionalTransfer
- .getRequestTrade(ADDRESS1, ADDRESS2, value5);
- assertEq(transferRequest.key, key5);
- assertEq(transferRequest.id, 4);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, value5);
- assertEq(uint256(transferRequest.status), uint256(STATUS.WAIT));
- }
-
- function testCanCreateTransferRequest() public {
- _createTransferRequest();
- }
-
- /**
- * @dev test first
- */
- function testCanCreateTransferRequestWithApproval() public {
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- // Act
- vm.expectEmit(true, true, true, true);
- emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.createTransferRequestWithApproval(
- transferRequestInput
- );
- }
-
- function testCanCreateTransferRequestWithApprovalBatch() public {
- // Arrange
- TransferRequestKeyElement[]
- memory transferRequestKeyElements = new TransferRequestKeyElement[](
- 4
- );
- transferRequestKeyElements[0] = transferRequestInput;
- transferRequestKeyElements[1] = transferRequestInput2;
- transferRequestKeyElements[2] = transferRequestInput3;
- transferRequestKeyElements[3] = transferRequestInput4;
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key2, ADDRESS1, ADDRESS2, value2, 1);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key3, ADDRESS2, ADDRESS1, value3, 2);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key4, ADDRESS1, ADDRESS2, value4, 3);
- ruleConditionalTransfer.createTransferRequestWithApprovalBatch(
- transferRequestKeyElements
- );
- }
-
- function testCanCreateTransferRequestWithApprovalBatchWithEmptyArray()
- public
- {
- // Arrange
- TransferRequestKeyElement[]
- memory transferRequestKeyElements = new TransferRequestKeyElement[](
- 0
- );
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector);
- ruleConditionalTransfer.createTransferRequestWithApprovalBatch(
- transferRequestKeyElements
- );
- }
-
- /**
- * @dev test overwrite branch, previous approval
- */
- function testCanCreateTransferRequestWithApprovalAgain() public {
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- // Arrange
- bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue));
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.createTransferRequestWithApproval(
- transferRequestInput
- );
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.createTransferRequestWithApproval(
- transferRequestInput
- );
- }
-
- /**** Request approval ****** */
- function testCanHolderCreateRequestBatch() public {
- // Arrange
- uint256[] memory values = new uint256[](3);
- values[0] = defaultValue;
- values[1] = value2;
- values[2] = value4;
- address[] memory addresses = new address[](3);
- addresses[0] = ADDRESS2;
- addresses[1] = ADDRESS2;
- addresses[2] = ADDRESS2;
-
- // Act
- vm.prank(ADDRESS1);
- vm.expectEmit(true, true, true, true);
- emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- vm.expectEmit(true, true, true, true);
- emit transferWaiting(key2, ADDRESS1, ADDRESS2, value2, 1);
- vm.expectEmit(true, true, true, true);
- emit transferWaiting(key4, ADDRESS1, ADDRESS2, value4, 2);
- ruleConditionalTransfer.createTransferRequestBatch(addresses, values);
- }
-
- function testCannotHolderCreateRequestBatchEmptyArray() public {
- // Arrange
- uint256[] memory values = new uint256[](0);
- address[] memory addresses = new address[](0);
-
- // Act
- vm.prank(ADDRESS1);
- vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector);
- ruleConditionalTransfer.createTransferRequestBatch(addresses, values);
- }
-
- function testCannotHolderCreateRequestBatchIfLEngthMismatch() public {
- // Arrange
- uint256[] memory values = new uint256[](3);
- address[] memory addresses = new address[](1);
-
- // Act
- vm.prank(ADDRESS1);
- vm.expectRevert(RuleConditionalTransfer_InvalidLengthArray.selector);
- ruleConditionalTransfer.createTransferRequestBatch(addresses, values);
- }
-
- function testCanApproveRequestCreatedByHolder() public {
- // Arrange
- _createTransferRequest();
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- true
- );
- }
-
- function testCanPartiallyApproveRequestCreatedByHolder() public {
- // Arrange
- _createTransferRequest();
- uint256 partialValue = 5;
- bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, partialValue));
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- emit transferWaiting(key, ADDRESS1, ADDRESS2, partialValue, 1);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- partialValue,
- true
- );
- }
-
- function testCannotPartiallyDeniedRequestCreatedByHolder() public {
- // Arrange
- _createTransferRequest();
- uint256 partialValue = 5;
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_CannotDeniedPartially.selector);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- partialValue,
- false
- );
- }
-
- function testCannotPartiallyApprovedRequestCreatedByHolderIfPartialValueIsBiggerThanValue()
- public
- {
- // Arrange
- _createTransferRequest();
- uint256 partialValue = 5000;
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_InvalidValueApproved.selector);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- partialValue,
- false
- );
- }
-
- function testCanCreateAndApproveRequestCreatedByHolderAgain() public {
- // Arrange
- // First request
- _createTransferRequest();
-
- // First approval
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- true
- );
-
- // Second request
- vm.prank(ADDRESS1);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue);
-
- // Second approval
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- true
- );
-
- // Assert
- TransferRequest memory transferRequest = ruleConditionalTransfer
- .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue);
- assertEq(transferRequest.key, defaultKey);
- assertEq(transferRequest.id, 0);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, defaultValue);
- assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED));
- }
-
- /*** Batch */
- function testCanCreateAndApproveRequestCreatedByHolderInBatch() public {
- // Arrange
- _createTransferRequestBatch();
- uint256[] memory partialValues = new uint256[](4);
- partialValues[0] = 0;
- partialValues[1] = 0;
- partialValues[2] = 0;
- partialValues[3] = 0;
- bool[] memory isApproveds = new bool[](4);
- isApproveds[0] = true;
- isApproveds[1] = true;
- isApproveds[2] = true;
- isApproveds[3] = false;
-
- TransferRequestKeyElement[]
- memory transferRequestKeyElements = new TransferRequestKeyElement[](
- 4
- );
- transferRequestKeyElements[0] = transferRequestInput;
- transferRequestKeyElements[1] = transferRequestInput2;
- transferRequestKeyElements[2] = transferRequestInput3;
- transferRequestKeyElements[3] = transferRequestInput4;
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key2, ADDRESS1, ADDRESS2, value2, 1);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key3, ADDRESS2, ADDRESS1, value3, 2);
- vm.expectEmit(true, true, true, true);
- emit transferDenied(key4, ADDRESS1, ADDRESS2, value4, 3);
- ruleConditionalTransfer.approveTransferRequestBatch(
- transferRequestKeyElements,
- partialValues,
- isApproveds
- );
-
- // Assert
- _checkRequestBatch();
- }
-
- function testCannotCreateAndApproveRequestCreatedByHolderInBatchWithLenghtMismatch()
- public
- {
- // Arrange
- uint256[] memory partialValues = new uint256[](4);
- // Lenght mismatch
- bool[] memory isApproveds = new bool[](3);
-
- TransferRequestKeyElement[]
- memory transferRequestKeyElements = new TransferRequestKeyElement[](
- 4
- );
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_InvalidLengthArray.selector);
- ruleConditionalTransfer.approveTransferRequestBatch(
- transferRequestKeyElements,
- partialValues,
- isApproveds
- );
-
- // Act
- uint256[] memory partialValuesV2 = new uint256[](1);
- partialValuesV2[0] = 0;
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_InvalidLengthArray.selector);
- ruleConditionalTransfer.approveTransferRequestBatch(
- transferRequestKeyElements,
- partialValuesV2,
- isApproveds
- );
-
- // Act
- uint256[] memory partialValuesV3 = new uint256[](4);
- // Lenght mismatch
- bool[] memory isApprovedsV3 = new bool[](4);
- TransferRequestKeyElement[]
- memory transferRequestKeyElementsV3 = new TransferRequestKeyElement[](
- 2
- );
- transferRequestKeyElementsV3[0] = transferRequestInput;
- transferRequestKeyElementsV3[1] = transferRequestInput2;
- vm.expectRevert(RuleConditionalTransfer_InvalidLengthArray.selector);
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- ruleConditionalTransfer.approveTransferRequestBatch(
- transferRequestKeyElementsV3,
- partialValuesV3,
- isApprovedsV3
- );
- }
-
- function testCannotCreateAndApproveRequestCreatedByHolderInBatchWithEmptyArry()
- public
- {
- // Arrange
- uint256[] memory partialValues = new uint256[](0);
- // Lenght mismatch
- bool[] memory isApproveds = new bool[](0);
-
- TransferRequestKeyElement[]
- memory transferRequestKeyElements = new TransferRequestKeyElement[](
- 0
- );
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector);
- ruleConditionalTransfer.approveTransferRequestBatch(
- transferRequestKeyElements,
- partialValues,
- isApproveds
- );
- }
-
- function testCanCreateAndApproveRequestCreatedByHolderInBatchWithPartialValues()
- public
- {
- // Arrange
- _createTransferRequestBatch();
- uint256[] memory partialValues = new uint256[](5);
- partialValues[0] = 0;
- partialValues[1] = 0;
- partialValues[2] = 0;
- partialValues[3] = 0;
- // partial value
- partialValues[4] = 500;
- bytes32 key5PartialValue = keccak256(
- abi.encode(ADDRESS1, ADDRESS2, partialValues[4])
- );
- bool[] memory isApproveds = new bool[](5);
- isApproveds[0] = true;
- isApproveds[1] = true;
- isApproveds[2] = true;
- isApproveds[3] = false;
- isApproveds[4] = true;
-
- TransferRequestKeyElement[]
- memory transferRequestKeyElements = new TransferRequestKeyElement[](
- 5
- );
- transferRequestKeyElements[0] = transferRequestInput;
- transferRequestKeyElements[1] = transferRequestInput2;
- transferRequestKeyElements[2] = transferRequestInput3;
- transferRequestKeyElements[3] = transferRequestInput4;
- transferRequestKeyElements[4] = transferRequestInput5;
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key2, ADDRESS1, ADDRESS2, value2, 1);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key3, ADDRESS2, ADDRESS1, value3, 2);
- vm.expectEmit(true, true, true, true);
- emit transferDenied(key4, ADDRESS1, ADDRESS2, value4, 3);
- //partial value
- vm.expectEmit(true, true, true, true);
- emit transferDenied(key5, ADDRESS1, ADDRESS2, value5, 4);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(
- key5PartialValue,
- ADDRESS1,
- ADDRESS2,
- partialValues[4],
- 5
- );
- ruleConditionalTransfer.approveTransferRequestBatch(
- transferRequestKeyElements,
- partialValues,
- isApproveds
- );
-
- // Assert
-
- _checkRequestPartial();
- // 5
- TransferRequest memory transferRequest = ruleConditionalTransfer
- .getRequestTrade(ADDRESS1, ADDRESS2, value5);
- assertEq(transferRequest.key, key5);
- assertEq(transferRequest.id, 4);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, value5);
- assertEq(uint256(transferRequest.status), uint256(STATUS.DENIED));
- // new request
- transferRequest = ruleConditionalTransfer.getRequestTrade(
- ADDRESS1,
- ADDRESS2,
- partialValues[4]
- );
- assertEq(transferRequest.key, key5PartialValue);
- assertEq(transferRequest.id, 5);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, partialValues[4]);
- assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED));
- }
-
- /****** ID *******/
- function testCanApproveRequestCreatedByHolderWithId() public {
- // Arrange
- _createTransferRequest();
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequestWithId(0, true);
-
- // Assert
- TransferRequest memory transferRequest = ruleConditionalTransfer
- .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue);
- assertEq(transferRequest.key, defaultKey);
- assertEq(transferRequest.id, 0);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, defaultValue);
- assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED));
- }
-
- /***** Batch */
-
- function testCanApproveRequestInBatchCreatedByHolderWithId() public {
- _createTransferRequestBatch();
- uint256[] memory ids = new uint256[](4);
- ids[0] = 0;
- ids[1] = 1;
- ids[2] = 2;
- ids[3] = 3;
- bool[] memory isApproveds = new bool[](4);
- isApproveds[0] = true;
- isApproveds[1] = true;
- isApproveds[2] = true;
- isApproveds[3] = false;
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key2, ADDRESS1, ADDRESS2, value2, 1);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key3, ADDRESS2, ADDRESS1, value3, 2);
- vm.expectEmit(true, true, true, true);
- emit transferDenied(key4, ADDRESS1, ADDRESS2, value4, 3);
- ruleConditionalTransfer.approveTransferRequestBatchWithId(
- ids,
- isApproveds
- );
-
- // Assert
- _checkRequestBatch();
- }
-
- function testCannotApproveRequestInBatchCreatedByHolderWithIdWithinvalidLength()
- public
- {
- _createTransferRequestBatch();
- uint256[] memory ids = new uint256[](4);
- // Wrong length here
- bool[] memory isApproveds = new bool[](3);
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_InvalidLengthArray.selector);
- ruleConditionalTransfer.approveTransferRequestBatchWithId(
- ids,
- isApproveds
- );
- }
-
- function testCannotApproveRequestInBatchCreatedByHolderWithIdWithEmptyArray()
- public
- {
- _createTransferRequestBatch();
- uint256[] memory ids = new uint256[](0);
- // Wrong length here
- bool[] memory isApproveds = new bool[](0);
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector);
- ruleConditionalTransfer.approveTransferRequestBatchWithId(
- ids,
- isApproveds
- );
- }
-
- function testCannotApproveRequestInBatchCreatedByHolderWithWrongId()
- public
- {
- _createTransferRequestBatch();
- uint256[] memory ids = new uint256[](4);
- ids[0] = 0;
- ids[1] = 1;
- ////// Wrong id here !!!
- ids[2] = 6;
- ids[3] = 3;
- bool[] memory isApproveds = new bool[](4);
- isApproveds[0] = true;
- isApproveds[1] = true;
- isApproveds[2] = true;
- isApproveds[3] = false;
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_InvalidId.selector);
- ruleConditionalTransfer.approveTransferRequestBatchWithId(
- ids,
- isApproveds
- );
- }
-
- function testCannotApproveRequestInBatchCreatedByHolderIfTimeExceed()
- public
- {
- _createTransferRequestBatch();
- // Jump
- vm.warp(block.timestamp + 604801);
- uint256[] memory ids = new uint256[](4);
- ids[0] = 0;
- ids[1] = 1;
- ids[2] = 2;
- ids[3] = 3;
- bool[] memory isApproveds = new bool[](4);
- isApproveds[0] = true;
- isApproveds[1] = true;
- isApproveds[2] = true;
- isApproveds[3] = false;
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_timeExceeded.selector);
- ruleConditionalTransfer.approveTransferRequestBatchWithId(
- ids,
- isApproveds
- );
- }
-
- function testCannotApproveOrDeniedRequestCreatedByHolderWithWrongId()
- public
- {
- // Arrange
- _createTransferRequest();
-
- // Act
- // Approve
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_InvalidId.selector);
- ruleConditionalTransfer.approveTransferRequestWithId(1, true);
- // Denied
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_InvalidId.selector);
- ruleConditionalTransfer.approveTransferRequestWithId(1, false);
- }
-
- function testCanDeniedRequestCreatedByHolderWithId() public {
- // Arrange
- _createTransferRequest();
- // can still approve
- vm.warp(block.timestamp + 1);
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequestWithId(0, false);
-
- // Assert
- TransferRequest memory transferRequest = ruleConditionalTransfer
- .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue);
- assertEq(transferRequest.key, defaultKey);
- assertEq(transferRequest.id, 0);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, defaultValue);
- assertEq(uint256(transferRequest.status), uint256(STATUS.DENIED));
- }
-
- /***** with key ******/
- function testCanDeniedRequestCreatedByHolder() public {
- // Arrange
- _createTransferRequest();
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- false
- );
-
- // Assert
- TransferRequest memory transferRequest = ruleConditionalTransfer
- .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue);
- assertEq(transferRequest.key, defaultKey);
- assertEq(transferRequest.id, 0);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, defaultValue);
- assertEq(uint256(transferRequest.status), uint256(STATUS.DENIED));
-
- TransferRequest[] memory transferRequests = ruleConditionalTransfer
- .getRequestByStatus(STATUS.DENIED);
- assertEq(transferRequests[0].key, defaultKey);
- assertEq(transferRequests.length, 1);
- }
-
- function testCannotHolderCreateRequestIfDenied() public {
- // Arrange
- _createTransferRequest();
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- false
- );
-
- // Act
- vm.prank(ADDRESS1);
- vm.expectRevert(RuleConditionalTransfer_TransferDenied.selector);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue);
- }
-
- /****** Getter *****/
- function testCanReturnTradeByStatus() public {
- // Arrange
- // First request
- _createTransferRequest();
-
- // Change the status request to APPROVE
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- false
- );
-
- // Second request
- uint256 value = 100;
- vm.prank(ADDRESS1);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, value);
-
- // Act
- TransferRequest[] memory transferRequest = ruleConditionalTransfer
- .getRequestByStatus(STATUS.WAIT);
- // Assert
- assertEq(transferRequest.length, 1);
- bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, value));
- assertEq(transferRequest[0].key, key);
- assertEq(transferRequest[0].id, 1);
- assertEq(transferRequest[0].keyElement.from, ADDRESS1);
- assertEq(transferRequest[0].keyElement.to, ADDRESS2);
- assertEq(transferRequest[0].keyElement.value, value);
- assertEq(uint256(transferRequest[0].status), uint256(STATUS.WAIT));
-
- // third request
- uint256 valueThird = 200;
- vm.prank(ADDRESS1);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, valueThird);
-
- // Act
- transferRequest = ruleConditionalTransfer.getRequestByStatus(
- STATUS.WAIT
- );
- // Assert
- assertEq(transferRequest.length, 2);
- bytes32 keyThird = keccak256(
- abi.encode(ADDRESS1, ADDRESS2, valueThird)
- );
- assertEq(transferRequest[1].key, keyThird);
- assertEq(transferRequest[1].id, 2);
- assertEq(transferRequest[1].keyElement.from, ADDRESS1);
- assertEq(transferRequest[1].keyElement.to, ADDRESS2);
- assertEq(transferRequest[1].keyElement.value, valueThird);
- assertEq(uint256(transferRequest[1].status), uint256(STATUS.WAIT));
- }
-
- function testCannotApproveRequestIfTimeExceeded() public {
- // Arrange
- _createTransferRequest();
-
- // Timeout
- // 7 days *24*60*60 = 604800 seconds
- vm.warp(block.timestamp + 604801);
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_timeExceeded.selector);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- true
- );
- }
-
- /*** Edge case ******/
-
- function testCannotApproveRequestIfWrongStatus() public {
- // Arrange
- // No create request
-
- // Timeout
- // 7 days *24*60*60 = 604800 seconds
- vm.warp(block.timestamp + 604801);
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_Wrong_Status.selector);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- true
- );
- }
-
- function testCanSetTimeLimitWithTransferApprovalExceeded() public {
- TIME_LIMIT memory timeLimit_ = TIME_LIMIT({
- timeLimitToApprove: 1 days,
- timeLimitToTransfer: 1 days
- });
- // Arrange
- _createTransferRequest();
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- ruleConditionalTransfer.setTimeLimit(timeLimit_);
-
- // Assert
- // Timeout
- // >1 days
- vm.warp(block.timestamp + 1 days + 1 seconds);
-
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_timeExceeded.selector);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- true
- );
- }
-}
diff --git a/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol
deleted file mode 100644
index 2c4b93c..0000000
--- a/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol
+++ /dev/null
@@ -1,246 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "../HelperContract.sol";
-import "./utils/RuleCTDeployment.sol";
-
-/**
- * @title Tests on the Access Control
- */
-contract RuleConditionalTransferAccessControl is Test, HelperContract {
- // Custom error openZeppelin
- error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
- uint256 defaultValue = 10;
- bytes32 defaultKey =
- keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue));
-
- TransferRequestKeyElement transferRequestInput =
- TransferRequestKeyElement({
- from: ADDRESS1,
- to: ADDRESS2,
- value: defaultValue
- });
- RuleCTDeployment ruleCTDeployment;
-
- // Arrange
- function setUp() public {
- ruleCTDeployment = new RuleCTDeployment();
- ruleEngineMock = ruleCTDeployment.ruleEngineMock();
- ruleConditionalTransfer = ruleCTDeployment.ruleConditionalTransfer();
- }
-
- function _createTransferRequest() internal {
- vm.prank(ADDRESS1);
- // Act
- vm.expectEmit(true, true, true, true);
- emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue);
- }
-
- function testCannotAttackerApproveARequestCreatedByTokenHolder() public {
- _createTransferRequest();
-
- vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE
- )
- );
- vm.prank(ATTACKER);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- true
- );
- }
-
- function testCannotAttackerApproveWithIdARequestCreatedByTokenHolder()
- public
- {
- _createTransferRequest();
-
- vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE
- )
- );
- vm.prank(ATTACKER);
- ruleConditionalTransfer.approveTransferRequestWithId(0, true);
- }
-
- function testCannotAttackerResetARequest() public {
- _createTransferRequest();
-
- vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE
- )
- );
- vm.prank(ATTACKER);
- ruleConditionalTransfer.resetRequestStatus(0);
- }
-
- function testCannotAttackerCreateTransferRequestWithApproval() public {
- vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE
- )
- );
- vm.prank(ATTACKER);
- ruleConditionalTransfer.createTransferRequestWithApproval(
- transferRequestInput
- );
- }
-
- /*** Batch */
-
- function testCannotAttackerApproveBatchWithIdARequestCreatedByTokenHolder()
- public
- {
- _createTransferRequest();
- uint256[] memory ids = new uint256[](1);
- ids[0] = 0;
- bool[] memory isApproveds = new bool[](1);
- isApproveds[0] = true;
- vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE
- )
- );
- vm.prank(ATTACKER);
- ruleConditionalTransfer.approveTransferRequestBatchWithId(
- ids,
- isApproveds
- );
- }
-
- function testCannotAttackerApproveBatchRequestCreatedByTokenHolder()
- public
- {
- TransferRequestKeyElement[]
- memory keyElements = new TransferRequestKeyElement[](0);
- uint256[] memory partialValues = new uint256[](0);
- bool[] memory boolIsApproved = new bool[](0);
- vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE
- )
- );
- vm.prank(ATTACKER);
- ruleConditionalTransfer.approveTransferRequestBatch(
- keyElements,
- partialValues,
- boolIsApproved
- );
- }
-
- function testCannotAttackerResetBatch() public {
- uint256[] memory ids = new uint256[](0);
- bool[] memory boolIsApproved = new bool[](0);
- vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE
- )
- );
- vm.prank(ATTACKER);
- ruleConditionalTransfer.approveTransferRequestBatchWithId(
- ids,
- boolIsApproved
- );
- }
-
- function testCannotAttackerCreateTransferRequestWithApprovalBatch() public {
- TransferRequestKeyElement[]
- memory keyElements = new TransferRequestKeyElement[](0);
- vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE
- )
- );
- vm.prank(ATTACKER);
- ruleConditionalTransfer.createTransferRequestWithApprovalBatch(
- keyElements
- );
- }
-
- /******** OPTIONS CONFIGURATION *********/
- function testCannotAttackerSetTimeLimit() public {
- TIME_LIMIT memory timeLimit_ = TIME_LIMIT({
- timeLimitToApprove: 7 days,
- timeLimitToTransfer: 200 days
- });
- vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE
- )
- );
- vm.prank(ATTACKER);
- ruleConditionalTransfer.setTimeLimit(timeLimit_);
- }
-
- function testCannotAttackerSetAutomaticTransfer() public {
- AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({
- isActivate: false,
- cmtat: IERC20(address(0))
- });
- vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE
- )
- );
- vm.prank(ATTACKER);
- ruleConditionalTransfer.setAutomaticTransfer(automaticTransfer_);
- }
-
- function testCannotAttackerSetIssuanceOptions() public {
- ISSUANCE memory issuanceOption_ = ISSUANCE({
- authorizedMintWithoutApproval: false,
- authorizedBurnWithoutApproval: false
- });
- vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE
- )
- );
- vm.prank(ATTACKER);
- ruleConditionalTransfer.setIssuanceOptions(issuanceOption_);
- }
-
- function testCannotAttackerSetAuomaticApproval() public {
- AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
- isActivate: false,
- timeLimitBeforeAutomaticApproval: 0
- });
- vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE
- )
- );
- vm.prank(ATTACKER);
- ruleConditionalTransfer.setAutomaticApproval(automaticApproval_);
- }
-}
diff --git a/test/RuleConditionalTransfer/RuleConditionalTransferDeployment.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransferDeployment.t.sol
deleted file mode 100644
index 2adef6d..0000000
--- a/test/RuleConditionalTransfer/RuleConditionalTransferDeployment.t.sol
+++ /dev/null
@@ -1,80 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "../HelperContract.sol";
-import "./utils/RuleCTDeployment.sol";
-
-/**
- * @title General functions of the RuleWhitelist
- */
-contract RuleConditionalTransferDeploymentTest is Test, HelperContract {
- RuleCTDeployment ruleCTDeployment;
-
- // Arrange
- function setUp() public {}
-
- function testSetMaxLimitIfZeroForAutomaticApprovalAndAutomaticTransfer()
- public
- {
- TIME_LIMIT memory timeLimit_ = TIME_LIMIT({
- timeLimitToApprove: 7 days,
- timeLimitToTransfer: 30 days
- });
-
- AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
- isActivate: false,
- timeLimitBeforeAutomaticApproval: 0
- });
-
- ISSUANCE memory issuanceOption_ = ISSUANCE({
- authorizedMintWithoutApproval: false,
- authorizedBurnWithoutApproval: false
- });
- AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({
- isActivate: false,
- cmtat: IERC20(address(0))
- });
-
- OPTION memory options = OPTION({
- issuance: issuanceOption_,
- timeLimit: timeLimit_,
- automaticApproval: automaticApproval_,
- automaticTransfer: automaticTransfer_
- });
- ruleEngineMock = new RuleEngine(
- RULE_ENGINE_OPERATOR_ADDRESS,
- ZERO_ADDRESS,
- ZERO_ADDRESS
- );
- // Test 1
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- vm.expectRevert(
- abi.encodeWithSelector(
- RuleConditionalTransfer_AdminWithAddressZeroNotAllowed.selector
- )
- );
- ruleConditionalTransfer = new RuleConditionalTransfer(
- ZERO_ADDRESS,
- ZERO_ADDRESS,
- ruleEngineMock,
- options
- );
-
- // Test 2
- ruleCTDeployment = new RuleCTDeployment();
- ruleConditionalTransfer = ruleCTDeployment.ruleConditionalTransfer();
- ISSUANCE memory issuance;
- TIME_LIMIT memory timeLimit;
- AUTOMATIC_APPROVAL memory automaticApproval;
- AUTOMATIC_TRANSFER memory automaticTransfer;
- (
- issuance,
- timeLimit,
- automaticApproval,
- automaticTransfer
- ) = ruleConditionalTransfer.options();
- assertEq(timeLimit.timeLimitToApprove, 7 days);
- assertEq(timeLimit.timeLimitToTransfer, 30 days);
- }
-}
diff --git a/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol
deleted file mode 100644
index d6cb62a..0000000
--- a/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol
+++ /dev/null
@@ -1,440 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "../HelperContract.sol";
-import "OZ/token/ERC20/IERC20.sol";
-/**
- * @title General functions of the RuleWhitelist
- */
-contract RuleConditionalTransferResetTest is Test, HelperContract {
- uint256 defaultValue = 10;
- bytes32 defaultKey =
- keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue));
-
- TransferRequestKeyElement transferRequestInput =
- TransferRequestKeyElement({
- from: ADDRESS1,
- to: ADDRESS2,
- value: defaultValue
- });
-
- uint256 value2 = 1;
- uint256 value3 = 2;
- uint256 value4 = 1000;
- uint256 value5 = 2000;
- bytes32 key2 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value2));
- bytes32 key3 = keccak256(abi.encode(ADDRESS2, ADDRESS1, value3));
- bytes32 key3Hodler = keccak256(abi.encode(ADDRESS1, ADDRESS2, value3));
- bytes32 key4 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value4));
- bytes32 key5 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value5));
-
- TransferRequestKeyElement transferRequestInput2 =
- TransferRequestKeyElement({
- from: ADDRESS1,
- to: ADDRESS2,
- value: value2
- });
-
- TransferRequestKeyElement transferRequestInput3 =
- TransferRequestKeyElement({
- from: ADDRESS2,
- to: ADDRESS1,
- value: value3
- });
-
- // Arrange
- function setUp() public {
- TIME_LIMIT memory timeLimit_ = TIME_LIMIT({
- timeLimitToApprove: 7 days,
- timeLimitToTransfer: 30 days
- });
-
- AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
- isActivate: false,
- timeLimitBeforeAutomaticApproval: 0
- });
-
- ISSUANCE memory issuanceOption_ = ISSUANCE({
- authorizedMintWithoutApproval: false,
- authorizedBurnWithoutApproval: false
- });
- AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({
- isActivate: false,
- cmtat: IERC20(address(0))
- });
-
- OPTION memory options = OPTION({
- issuance: issuanceOption_,
- timeLimit: timeLimit_,
- automaticApproval: automaticApproval_,
- automaticTransfer: automaticTransfer_
- });
- ruleEngineMock = new RuleEngine(
- RULE_ENGINE_OPERATOR_ADDRESS,
- ZERO_ADDRESS,
- ZERO_ADDRESS
- );
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleConditionalTransfer = new RuleConditionalTransfer(
- DEFAULT_ADMIN_ADDRESS,
- ZERO_ADDRESS,
- ruleEngineMock,
- options
- );
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleConditionalTransfer.grantRole(
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE,
- CONDITIONAL_TRANSFER_OPERATOR_ADDRESS
- );
- }
-
- function _createTransferRequestBatch() public {
- // Arrange
- _createTransferRequest();
-
- // Second and third request
- vm.prank(ADDRESS1);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, value2);
- vm.prank(ADDRESS2);
- ruleConditionalTransfer.createTransferRequest(ADDRESS1, value3);
- }
-
- function _createTransferRequestBatchByHodler() public {
- // Arrange
- _createTransferRequest();
-
- // Second and third request
- vm.prank(ADDRESS1);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, value2);
- vm.prank(ADDRESS1);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, value3);
- }
-
- function _createTransferRequest() internal {
- vm.prank(ADDRESS1);
- // Act
- vm.expectEmit(true, true, true, true);
- emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue);
-
- // Assert
- TransferRequest memory transferRequest = ruleConditionalTransfer
- .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue);
- assertEq(transferRequest.key, defaultKey);
- assertEq(transferRequest.id, 0);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, defaultValue);
- assertEq(uint256(transferRequest.status), uint256(STATUS.WAIT));
-
- TransferRequest[] memory transferRequests = ruleConditionalTransfer
- .getRequestByStatus(STATUS.WAIT);
- assertEq(transferRequests[0].key, defaultKey);
- assertEq(transferRequests.length, 1);
- }
-
- /***** Reset ********/
-
- function testHolderCanResetHisRequest() public {
- // Arrange
- _createTransferRequest();
-
- // Act
- // Reset
- vm.prank(ADDRESS1);
- vm.expectEmit(true, true, true, true);
- emit transferReset(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.cancelTransferRequest(0);
-
- // Arrange
- // Second request with approval
- vm.prank(ADDRESS1);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue);
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- true
- );
-
- // Reset
- vm.prank(ADDRESS1);
- vm.expectEmit(true, true, true, true);
- emit transferReset(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.cancelTransferRequest(0);
-
- // Can create a new request
- // Id different from 0
- vm.prank(ADDRESS1);
- // Act
- vm.expectEmit(true, true, true, true);
- emit transferWaiting(key2, ADDRESS1, ADDRESS2, value2, 1);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, value2);
-
- // Can be cancel again
- vm.prank(ADDRESS1);
- vm.expectEmit(true, true, true, true);
- emit transferReset(key2, ADDRESS1, ADDRESS2, value2, 1);
- ruleConditionalTransfer.cancelTransferRequest(1);
- }
-
- function testHolderCanBatchResetHisRequest() public {
- // Arrange
- _createTransferRequestBatchByHodler();
- uint256[] memory ids = new uint256[](3);
- ids[0] = 0;
- ids[1] = 1;
- ids[2] = 2;
- // Act
- // Reset
- vm.prank(ADDRESS1);
- vm.expectEmit(true, true, true, true);
- emit transferReset(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- vm.expectEmit(true, true, true, true);
- emit transferReset(key2, ADDRESS1, ADDRESS2, value2, 1);
- vm.expectEmit(true, true, true, true);
- emit transferReset(key3Hodler, ADDRESS1, ADDRESS2, value3, 2);
- ruleConditionalTransfer.cancelTransferRequestBatch(ids);
- }
-
- function testHolderCannotBatchResetHisRequestWithWrongId() public {
- // Arrange
- _createTransferRequestBatchByHodler();
- uint256[] memory ids = new uint256[](3);
- ids[0] = 0;
- ids[1] = 4;
- ids[2] = 2;
- // Act
- // Reset
- vm.prank(ADDRESS1);
- vm.expectRevert(RuleConditionalTransfer_InvalidId.selector);
- ruleConditionalTransfer.cancelTransferRequestBatch(ids);
- }
-
- function testHolderCannotBatchResetHisRequestWithEmptyArray() public {
- // Arrange
- _createTransferRequestBatchByHodler();
- uint256[] memory ids = new uint256[](0);
- // Act
- // Reset
- vm.prank(ADDRESS1);
- vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector);
- ruleConditionalTransfer.cancelTransferRequestBatch(ids);
- }
-
- function testHolderCannotResetRequestCreatedByOther() public {
- // Arrange
- _createTransferRequest();
-
- // Act
- // Reset
- vm.prank(ADDRESS2);
- vm.expectRevert(RuleConditionalTransfer_InvalidSender.selector);
- ruleConditionalTransfer.cancelTransferRequest(0);
- }
-
- function testCannotHolderResetRequestWithWrongId() public {
- // Arrange
- _createTransferRequest();
-
- // Act
- // Reset
- vm.prank(ADDRESS1);
- vm.expectRevert(RuleConditionalTransfer_InvalidId.selector);
- ruleConditionalTransfer.cancelTransferRequest(1);
- }
-
- function testCannotHolderResetRequestWithWrongStatus() public {
- // Arrange
- _createTransferRequest();
-
- // Denied
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- false
- );
-
- // Act
- // Reset
- vm.prank(ADDRESS1);
- vm.expectRevert(RuleConditionalTransfer_Wrong_Status.selector);
- ruleConditionalTransfer.cancelTransferRequest(0);
- }
-
- /***** Reset */
-
- function testCanResetADeniedRequestCreatedByHolder() public {
- // Arrange
- _createTransferRequest();
-
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- false
- );
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferReset(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.resetRequestStatus(0);
-
- // Assert
- TransferRequest memory transferRequest = ruleConditionalTransfer
- .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue);
- assertEq(transferRequest.key, defaultKey);
- assertEq(transferRequest.id, 0);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, defaultValue);
- assertEq(uint256(transferRequest.status), uint256(STATUS.NONE));
-
- // Assert
- vm.prank(ADDRESS1);
- // Act
- vm.expectEmit(true, true, true, true);
- emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue);
-
- // Assert
- transferRequest = ruleConditionalTransfer.getRequestTrade(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
- assertEq(transferRequest.key, defaultKey);
- assertEq(transferRequest.id, 0);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, defaultValue);
- assertEq(uint256(transferRequest.status), uint256(STATUS.WAIT));
-
- // Id different from 0
- vm.prank(ADDRESS1);
- // Act
- vm.expectEmit(true, true, true, true);
- emit transferWaiting(key2, ADDRESS1, ADDRESS2, value2, 1);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, value2);
- }
-
- function testCanBatchResetADeniedRequestCreatedByHolder() public {
- // Arrange
- _createTransferRequestBatchByHodler();
- uint256[] memory ids = new uint256[](3);
- ids[0] = 0;
- ids[1] = 1;
- ids[2] = 2;
-
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- false
- );
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferReset(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- vm.expectEmit(true, true, true, true);
- emit transferReset(key2, ADDRESS1, ADDRESS2, value2, 1);
- vm.expectEmit(true, true, true, true);
- emit transferReset(key3Hodler, ADDRESS1, ADDRESS2, value3, 2);
- ruleConditionalTransfer.resetRequestStatusBatch(ids);
-
- // Assert
- TransferRequest memory transferRequest = ruleConditionalTransfer
- .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue);
- assertEq(transferRequest.key, defaultKey);
- assertEq(transferRequest.id, 0);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, defaultValue);
- assertEq(uint256(transferRequest.status), uint256(STATUS.NONE));
-
- transferRequest = ruleConditionalTransfer.getRequestTrade(
- ADDRESS1,
- ADDRESS2,
- value2
- );
- assertEq(transferRequest.key, key2);
- assertEq(transferRequest.id, 1);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, value2);
- assertEq(uint256(transferRequest.status), uint256(STATUS.NONE));
-
- transferRequest = ruleConditionalTransfer.getRequestTrade(
- ADDRESS1,
- ADDRESS2,
- value3
- );
- assertEq(transferRequest.key, key3Hodler);
- assertEq(transferRequest.id, 2);
- assertEq(transferRequest.keyElement.from, ADDRESS1);
- assertEq(transferRequest.keyElement.to, ADDRESS2);
- assertEq(transferRequest.keyElement.value, value3);
- assertEq(uint256(transferRequest.status), uint256(STATUS.NONE));
- }
-
- function testCannotBatchResetADeniedRequestCreatedByHolderWithWrongId()
- public
- {
- // Arrange
- _createTransferRequestBatchByHodler();
- uint256[] memory ids = new uint256[](3);
- ids[0] = 3;
- ids[1] = 1;
- ids[2] = 2;
-
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- false
- );
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_InvalidId.selector);
- ruleConditionalTransfer.resetRequestStatusBatch(ids);
- }
-
- function testCannotBatchResetADeniedRequestCreatedByHolderWithEmptyArray()
- public
- {
- // Arrange
- _createTransferRequestBatchByHodler();
- uint256[] memory ids = new uint256[](0);
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- false
- );
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector);
- ruleConditionalTransfer.resetRequestStatusBatch(ids);
- }
-
- function testCannotResetARequestIfWrongId() public {
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectRevert(RuleConditionalTransfer_InvalidId.selector);
- ruleConditionalTransfer.resetRequestStatus(10);
- }
-}
diff --git a/test/RuleConditionalTransfer/RuleConditionalTransferRestriction.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransferRestriction.t.sol
deleted file mode 100644
index 6ccec96..0000000
--- a/test/RuleConditionalTransfer/RuleConditionalTransferRestriction.t.sol
+++ /dev/null
@@ -1,117 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "../HelperContract.sol";
-import "OZ/token/ERC20/IERC20.sol";
-//ADmin, forwarder irrect /RuleEngine
-/**
- * @title General functions of the RuleEngine
- */
-contract RuleEngineOperationTest is Test, HelperContract {
- uint256 defaultValue = 20;
-
- TIME_LIMIT timeLimit_ =
- TIME_LIMIT({
- timeLimitToApprove: DEFAULT_TIME_LIMIT_TO_APPROVE,
- timeLimitToTransfer: DEFAULT_TIME_LIMIT_TO_TRANSFER
- });
- ISSUANCE issuanceOption_ =
- ISSUANCE({
- authorizedMintWithoutApproval: false,
- authorizedBurnWithoutApproval: false
- });
-
- AUTOMATIC_APPROVAL automaticApproval_ =
- AUTOMATIC_APPROVAL({
- isActivate: false,
- timeLimitBeforeAutomaticApproval: 0
- });
- AUTOMATIC_TRANSFER automaticTransfer_ =
- AUTOMATIC_TRANSFER({isActivate: false, cmtat: IERC20(address(0))});
- OPTION options =
- OPTION({
- issuance: issuanceOption_,
- timeLimit: timeLimit_,
- automaticApproval: automaticApproval_,
- automaticTransfer: automaticTransfer_
- });
-
- TransferRequestKeyElement transferRequestInput =
- TransferRequestKeyElement({
- from: ADDRESS1,
- to: ADDRESS2,
- value: defaultValue
- });
-
- // Arrange
- function setUp() public {
- ruleConditionalTransfer = new RuleConditionalTransfer(
- CONDITIONAL_TRANSFER_OPERATOR_ADDRESS,
- ZERO_ADDRESS,
- ruleEngineMock,
- options
- );
- }
-
- function testCanDetectTransferRestrictionOK() public {
- // Arrange - Assert
- resUint8 = ruleConditionalTransfer.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
-
- // Assert
- assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED);
- // Arrange
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue));
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.createTransferRequestWithApproval(
- transferRequestInput
- );
- // Act
- resUint8 = ruleConditionalTransfer.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
-
- // Assert
- assertEq(resUint8, 0);
- }
-
- function testCanDetectTransferRestrictionNotOk() public {
- // Act
- resUint8 = ruleConditionalTransfer.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 20
- );
-
- // Assert
- assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED);
- }
-
- function testMessageForTransferRestrictionWithUnknownRestrictionCode()
- public
- {
- // Act
- resString = ruleConditionalTransfer.messageForTransferRestriction(50);
-
- // Assert
- assertEq(resString, "Unknown restriction code");
- }
-
- function testMessageForTransferRestrictionWithValidRC() public {
- // Act
- resString = ruleConditionalTransfer.messageForTransferRestriction(
- CODE_TRANSFER_REQUEST_NOT_APPROVED
- );
-
- // Assert
- assertEq(resString, TEXT_TRANSFER_REQUEST_NOT_APPROVED);
- }
-}
diff --git a/test/RuleConditionalTransfer/utils/CMTATIntegrationShare.sol b/test/RuleConditionalTransfer/utils/CMTATIntegrationShare.sol
deleted file mode 100644
index aed15f1..0000000
--- a/test/RuleConditionalTransfer/utils/CMTATIntegrationShare.sol
+++ /dev/null
@@ -1,482 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import {CMTATStandalone} from "CMTAT/deployment/CMTATStandalone.sol";
-import "../../HelperContract.sol";
-import "OZ/token/ERC20/IERC20.sol";
-/**
- * @title Integration testShare with the CMTAT
- */
-contract CMTATIntegrationShare is Test, HelperContract {
- uint256 ADDRESS1_BALANCE_INIT = 31;
- uint256 ADDRESS2_BALANCE_INIT = 32;
- uint256 ADDRESS3_BALANCE_INIT = 33;
-
- uint256 FLAG = 5;
-
- uint256 defaultValue = 10;
- bytes32 defaultKey =
- keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue));
-
- TransferRequestKeyElement transferRequestInput =
- TransferRequestKeyElement({
- from: ADDRESS1,
- to: ADDRESS2,
- value: defaultValue
- });
-
- function _createTransferRequestShare() internal {
- vm.prank(ADDRESS1);
- // Act
- vm.expectEmit(true, true, true, true);
- emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue);
- }
-
- /******* Transfer *******/
- function testShareCannotTransferWithoutApproval() internal {
- // Arrange
- vm.prank(ADDRESS1);
- vm.expectRevert(
- abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
- ADDRESS1,
- ADDRESS2,
- 21
- )
- );
- // Act
- CMTAT_CONTRACT.transfer(ADDRESS2, 21);
- }
-
- function testShareCanMakeATransferIfApproved() internal {
- // Arrange - Assert
- // ConditionalTransfer
- resUint8 = ruleConditionalTransfer.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
- // Assert
- assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED);
- // CMTAT
- // Arrange - Assert
- resUint8 = CMTAT_CONTRACT.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
- // Assert
- assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED);
- // Arrange
- vm.prank(ADDRESS1);
- // Act
- bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue));
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue);
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- true
- );
-
- // Act
- vm.expectEmit(true, true, true, true);
- emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- vm.prank(ADDRESS1);
- CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue);
-
- // Assert
- resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1);
- assertEq(resUint256, ADDRESS1_BALANCE_INIT - defaultValue);
- resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS2);
- assertEq(resUint256, ADDRESS2_BALANCE_INIT + defaultValue);
- resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS3);
- assertEq(resUint256, 33);
- }
-
- function testShareCanMakeAPartialTransferIfPartiallyApproved() internal {
- // Arrange
- _createTransferRequestShare();
-
- uint256 partialValue = 5;
- bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, partialValue));
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key, ADDRESS1, ADDRESS2, partialValue, 1);
- emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- partialValue,
- true
- );
-
- // Act
- vm.expectEmit(true, true, true, true);
- emit transferProcessed(key, ADDRESS1, ADDRESS2, partialValue, 1);
- vm.prank(ADDRESS1);
- CMTAT_CONTRACT.transfer(ADDRESS2, partialValue);
-
- // Assert
- resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1);
- assertEq(resUint256, ADDRESS1_BALANCE_INIT - partialValue);
- resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS2);
- assertEq(resUint256, ADDRESS2_BALANCE_INIT + partialValue);
- resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS3);
- assertEq(resUint256, 33);
- }
-
- function testShareCannotMakeAWholeTransferIfPartiallyApproved() internal {
- // Arrange
- _createTransferRequestShare();
- uint256 partialValue = 5;
- bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, partialValue));
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key, ADDRESS1, ADDRESS2, partialValue, 1);
- emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- partialValue,
- true
- );
-
- // Act
- vm.expectRevert(
- abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
- ADDRESS1,
- ADDRESS2,
- defaultValue
- )
- );
- vm.prank(ADDRESS1);
- CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue);
- }
-
- function testShareCannotMakeATransferIfDelayExceeded(uint256 timeDelay) internal {
- // Arrange
- vm.prank(ADDRESS1);
- // Act
- bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue));
- ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue);
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(key, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- true
- );
-
-
- vm.warp(block.timestamp + timeDelay);
- // Act
- vm.expectRevert(
- abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
- ADDRESS1,
- ADDRESS2,
- defaultValue
- )
- );
- vm.prank(ADDRESS1);
- CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue);
- }
-
- function testShareCannotMakeATransferIfDelayJustInTime(uint256 timeDelay) internal {
- // Arrange
- _createTransferRequestShare();
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- true
- );
- // 30 days
- vm.warp(block.timestamp + timeDelay);
- // Act
- vm.prank(ADDRESS1);
- CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue);
- }
-
- function testShareCanSetTimeLimitWithTransferExceeded(uint256 timeDelay) internal {
- TIME_LIMIT memory timeLimit_ = TIME_LIMIT({
- timeLimitToApprove: 1 days,
- timeLimitToTransfer: 1 days
- });
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- ruleConditionalTransfer.setTimeLimit(timeLimit_);
- // Arrange
- _createTransferRequestShare();
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- true
- );
-
- // Assert
- // Timeout
- // >1 days
- vm.warp(block.timestamp + timeDelay);
-
- vm.expectRevert(
- abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
- ADDRESS1,
- ADDRESS2,
- defaultValue
- )
- );
- vm.prank(ADDRESS1);
- CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue);
- }
-
- function testShareCanMintWithoutApproval() internal {
- // Act
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- CMTAT_CONTRACT.mint(ADDRESS1, 11);
-
- // Assert
- resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1);
- assertEq(resUint256, ADDRESS1_BALANCE_INIT + 11);
- }
-
- function testShareCanBurnWithoutApproval() internal {
- // Act
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- CMTAT_CONTRACT.burn(ADDRESS1, defaultValue, "testShare");
-
- // Assert
- resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1);
- assertEq(resUint256, ADDRESS1_BALANCE_INIT - defaultValue);
- }
-
- function testShareCannotMintWithoutApproval() internal {
- ISSUANCE memory issuanceOption_ = ISSUANCE({
- authorizedMintWithoutApproval: false,
- authorizedBurnWithoutApproval: true
- });
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- ruleConditionalTransfer.setIssuanceOptions(issuanceOption_);
- // Act
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- vm.expectRevert(
- abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
- ZERO_ADDRESS,
- ADDRESS1,
- 11
- )
- );
- CMTAT_CONTRACT.mint(ADDRESS1, 11);
- }
-
- function testShareCannotBurnWithoutApproval() internal {
- ISSUANCE memory issuanceOption_ = ISSUANCE({
- authorizedMintWithoutApproval: true,
- authorizedBurnWithoutApproval: false
- });
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- ruleConditionalTransfer.setIssuanceOptions(issuanceOption_);
- // Act
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- vm.expectRevert(
- abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
- ADDRESS1,
- ZERO_ADDRESS,
- defaultValue
- )
- );
- CMTAT_CONTRACT.burn(ADDRESS1, defaultValue, "testShare");
- }
-
- function testShareAutomaticTransferIfOptionsSet() internal {
- AUTOMATIC_TRANSFER memory automaticTransfertestShare = AUTOMATIC_TRANSFER({
- isActivate: true,
- cmtat: IERC20(address(CMTAT_CONTRACT))
- });
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- ruleConditionalTransfer.setAutomaticTransfer(automaticTransfertestShare);
-
- // Aproval
- vm.prank(ADDRESS1);
- CMTAT_CONTRACT.approve(address(ruleConditionalTransfer), defaultValue);
-
- // Arrange
- _createTransferRequestShare();
-
- // Act
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- vm.expectEmit(true, true, true, true);
- emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- vm.expectEmit(true, true, true, true);
- emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- ruleConditionalTransfer.approveTransferRequest(
- transferRequestInput,
- 0,
- true
- );
- }
-
- function testShareCanTransferIfAutomaticApprovalSetAndTimeExceedsJustInTime()
- internal
- {
- AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
- isActivate: true,
- timeLimitBeforeAutomaticApproval: 90 days
- });
-
- resBool = ruleConditionalTransfer.canTransfer(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
- assertFalse(resBool);
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- ruleConditionalTransfer.setAutomaticApproval(automaticApproval_);
-
- resBool = ruleConditionalTransfer.canTransfer(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
- assertFalse(resBool);
- // Arrange
- _createTransferRequestShare();
-
- resBool = ruleConditionalTransfer.canTransfer(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
- assertFalse(resBool);
-
- vm.warp(block.timestamp + 90 days);
- // Act
- resBool = ruleConditionalTransfer.canTransfer(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
- assertEq(resBool, true);
- vm.prank(ADDRESS1);
- vm.expectEmit(true, true, true, true);
- emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue);
- }
-
- function testShareCanTransferIfAutomaticApprovalSetAndTimeExceeds() internal {
- AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
- isActivate: true,
- timeLimitBeforeAutomaticApproval: 90 days
- });
-
- resBool = ruleConditionalTransfer.canTransfer(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
- assertFalse(resBool);
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- ruleConditionalTransfer.setAutomaticApproval(automaticApproval_);
-
- resBool = ruleConditionalTransfer.canTransfer(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
- assertFalse(resBool);
- // Arrange
- _createTransferRequestShare();
-
- resBool = ruleConditionalTransfer.canTransfer(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
- assertFalse(resBool);
-
- vm.warp(block.timestamp + 91 days);
- // Act
- resBool = ruleConditionalTransfer.canTransfer(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
- assertEq(resBool, true);
- vm.prank(ADDRESS1);
- vm.expectEmit(true, true, true, true);
- emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
- CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue);
- }
-
- function testShareCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds()
- internal
- {
- AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
- isActivate: true,
- timeLimitBeforeAutomaticApproval: 90 days
- });
- resBool = ruleConditionalTransfer.canTransfer(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
- assertFalse(resBool);
- vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
- ruleConditionalTransfer.setAutomaticApproval(automaticApproval_);
-
- resBool = ruleConditionalTransfer.canTransfer(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
- assertFalse(resBool);
- // Arrange
- _createTransferRequestShare();
-
- resBool = ruleConditionalTransfer.canTransfer(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
- assertFalse(resBool);
-
- resBool = CMTAT_CONTRACT.canTransfer(
- ADDRESS1,
- ADDRESS2,
- defaultValue
- );
- assertFalse(resBool);
- // Time not exceeds
- vm.warp(block.timestamp + 85 days);
- // Act
- vm.prank(ADDRESS1);
- vm.expectRevert(
- abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
- ADDRESS1,
- ADDRESS2,
- defaultValue
- )
- );
- CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue);
- }
-}
diff --git a/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol b/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol
deleted file mode 100644
index 25ab9b8..0000000
--- a/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol
+++ /dev/null
@@ -1,56 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "../../HelperContract.sol";
-import "OZ/token/ERC20/IERC20.sol";
-/**
- * @title Tests on the Access Control
- */
-contract RuleCTDeployment is Test, HelperContract {
- // Arrange
- constructor() {
- TIME_LIMIT memory timeLimit_ = TIME_LIMIT({
- timeLimitToApprove: 7 days,
- timeLimitToTransfer: 30 days
- });
-
- AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
- isActivate: false,
- timeLimitBeforeAutomaticApproval: 0
- });
-
- ISSUANCE memory issuanceOption_ = ISSUANCE({
- authorizedMintWithoutApproval: false,
- authorizedBurnWithoutApproval: false
- });
- AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({
- isActivate: false,
- cmtat: IERC20(address(0))
- });
-
- OPTION memory options = OPTION({
- issuance: issuanceOption_,
- timeLimit: timeLimit_,
- automaticApproval: automaticApproval_,
- automaticTransfer: automaticTransfer_
- });
- ruleEngineMock = new RuleEngine(
- RULE_ENGINE_OPERATOR_ADDRESS,
- ZERO_ADDRESS,
- ZERO_ADDRESS
- );
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleConditionalTransfer = new RuleConditionalTransfer(
- DEFAULT_ADMIN_ADDRESS,
- ZERO_ADDRESS,
- ruleEngineMock,
- options
- );
- vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleConditionalTransfer.grantRole(
- RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE,
- CONDITIONAL_TRANSFER_OPERATOR_ADDRESS
- );
- }
-}
diff --git a/test/RuleSanctionList/RuleSanctionListAddTest.t.sol b/test/RuleSanctionList/RuleSanctionListAddTest.t.sol
index 80fc08f..be2477d 100644
--- a/test/RuleSanctionList/RuleSanctionListAddTest.t.sol
+++ b/test/RuleSanctionList/RuleSanctionListAddTest.t.sol
@@ -4,44 +4,40 @@ pragma solidity ^0.8.20;
import "forge-std/Test.sol";
import "../HelperContract.sol";
import "../utils/SanctionListOracle.sol";
-import {RuleSanctionList, SanctionsList} from "src/rules/validation/RuleSanctionList.sol";
+import {RuleSanctionsList, ISanctionsList} from "src/rules/validation/RuleSanctionsList.sol";
/**
* @title General functions of the ruleSanctionList
*/
+
contract RuleSanctionlistAddTest is Test, HelperContract {
// Custom error openZeppelin
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
+
SanctionListOracle sanctionlistOracle;
- RuleSanctionList ruleSanctionList;
+ RuleSanctionsList ruleSanctionList;
// Arrange
function setUp() public {
vm.prank(SANCTIONLIST_OPERATOR_ADDRESS);
sanctionlistOracle = new SanctionListOracle();
sanctionlistOracle.addToSanctionsList(ATTACKER);
- ruleSanctionList = new RuleSanctionList(
- SANCTIONLIST_OPERATOR_ADDRESS,
- ZERO_ADDRESS,
- ZERO_ADDRESS
- );
+ ruleSanctionList =
+ new RuleSanctionsList(SANCTIONLIST_OPERATOR_ADDRESS, ZERO_ADDRESS, ISanctionsList(ZERO_ADDRESS));
}
function testCanSetandRemoveOracle() public {
// ADD
vm.prank(SANCTIONLIST_OPERATOR_ADDRESS);
- emit SetSanctionListOracle(address(sanctionlistOracle));
- ruleSanctionList.setSanctionListOracle(address(sanctionlistOracle));
+ emit SetSanctionListOracle(sanctionlistOracle);
+ ruleSanctionList.setSanctionListOracle(sanctionlistOracle);
- SanctionsList sanctionListOracleGet = ruleSanctionList.sanctionsList();
+ ISanctionsList sanctionListOracleGet = ruleSanctionList.sanctionsList();
// Assert
- vm.assertEq(
- address(sanctionListOracleGet),
- address(sanctionlistOracle)
- );
+ vm.assertEq(address(sanctionListOracleGet), address(sanctionlistOracle));
// Remove
vm.prank(SANCTIONLIST_OPERATOR_ADDRESS);
- emit SetSanctionListOracle(ZERO_ADDRESS);
- ruleSanctionList.setSanctionListOracle(ZERO_ADDRESS);
+ emit SetSanctionListOracle(ISanctionsList(ZERO_ADDRESS));
+ ruleSanctionList.setSanctionListOracle(ISanctionsList(ZERO_ADDRESS));
// Assert
sanctionListOracleGet = ruleSanctionList.sanctionsList();
vm.assertEq(address(sanctionListOracleGet), address(ZERO_ADDRESS));
@@ -49,13 +45,7 @@ contract RuleSanctionlistAddTest is Test, HelperContract {
function testCannotAttackerSetOracle() public {
vm.prank(ATTACKER);
- vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- SANCTIONLIST_ROLE
- )
- );
- ruleSanctionList.setSanctionListOracle(address(sanctionlistOracle));
+ vm.expectRevert(abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, SANCTIONLIST_ROLE));
+ ruleSanctionList.setSanctionListOracle(sanctionlistOracle);
}
}
diff --git a/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol b/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol
index ee2e75f..5252411 100644
--- a/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol
+++ b/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol
@@ -5,13 +5,16 @@ import "forge-std/Test.sol";
import "../HelperContract.sol";
import "CMTAT/mocks/MinimalForwarderMock.sol";
import "../utils/SanctionListOracle.sol";
-import {RuleSanctionList, SanctionsList} from "src/rules/validation/RuleSanctionList.sol";
+import {RuleSanctionsList, ISanctionsList} from "src/rules/validation/RuleSanctionsList.sol";
+import {AccessControlModuleStandalone} from "../../src/modules/AccessControlModuleStandalone.sol";
/**
* @title General functions of the ruleSanctionList
*/
+
contract RuleSanctionListDeploymentTest is Test, HelperContract {
- RuleSanctionList ruleSanctionList;
+ RuleSanctionsList ruleSanctionList;
SanctionListOracle sanctionlistOracle;
+
event Testa();
// Arrange
@@ -23,17 +26,11 @@ contract RuleSanctionListDeploymentTest is Test, HelperContract {
MinimalForwarderMock forwarder = new MinimalForwarderMock();
forwarder.initialize(ERC2771ForwarderDomain);
vm.prank(SANCTIONLIST_OPERATOR_ADDRESS);
- ruleSanctionList = new RuleSanctionList(
- SANCTIONLIST_OPERATOR_ADDRESS,
- address(forwarder),
- ZERO_ADDRESS
- );
+ ruleSanctionList =
+ new RuleSanctionsList(SANCTIONLIST_OPERATOR_ADDRESS, address(forwarder), ISanctionsList(ZERO_ADDRESS));
// assert
- resBool = ruleSanctionList.hasRole(
- SANCTIONLIST_ROLE,
- SANCTIONLIST_OPERATOR_ADDRESS
- );
+ resBool = ruleSanctionList.hasRole(SANCTIONLIST_ROLE, SANCTIONLIST_OPERATOR_ADDRESS);
assertEq(resBool, true);
resBool = ruleSanctionList.isTrustedForwarder(address(forwarder));
assertEq(resBool, true);
@@ -44,31 +41,47 @@ contract RuleSanctionListDeploymentTest is Test, HelperContract {
vm.prank(SANCTIONLIST_OPERATOR_ADDRESS);
MinimalForwarderMock forwarder = new MinimalForwarderMock();
forwarder.initialize(ERC2771ForwarderDomain);
- vm.expectRevert(
- RuleSanctionList_AdminWithAddressZeroNotAllowed.selector
- );
+ vm.expectRevert(AccessControlModuleStandalone.AccessControlModuleStandalone_AddressZeroNotAllowed.selector);
vm.prank(SANCTIONLIST_OPERATOR_ADDRESS);
- ruleSanctionList = new RuleSanctionList(
- address(0),
- address(forwarder),
- ZERO_ADDRESS
- );
+ ruleSanctionList = new RuleSanctionsList(address(0), address(forwarder), ISanctionsList(ZERO_ADDRESS));
}
function testCanSetAnOracleAtDeployment() public {
sanctionlistOracle = new SanctionListOracle();
vm.prank(SANCTIONLIST_OPERATOR_ADDRESS);
// TODO: Event seems not checked by Foundry at deployment
- emit SetSanctionListOracle(address(sanctionlistOracle));
+ emit SetSanctionListOracle(sanctionlistOracle);
+
+ ruleSanctionList = new RuleSanctionsList(SANCTIONLIST_OPERATOR_ADDRESS, ZERO_ADDRESS, sanctionlistOracle);
+ assertEq(address(ruleSanctionList.sanctionsList()), address(sanctionlistOracle));
+ }
+
+ function testcanTransferIfNoOracleSet() public {
+ ruleSanctionList =
+ new RuleSanctionsList(SANCTIONLIST_OPERATOR_ADDRESS, address(ZERO_ADDRESS), ISanctionsList(ZERO_ADDRESS));
+ // Act
+ // ADDRESS1 -> ADDRESS2
+ resBool = ruleSanctionList.canTransfer(ADDRESS1, ADDRESS2, 20);
+ assertEq(resBool, true);
+
+ resBool = ruleSanctionList.canTransfer(ADDRESS1, ADDRESS2, 0, 20);
+ assertEq(resBool, true);
+
+ // ADDRESS2 -> ADDRESS1
+ resBool = ruleSanctionList.canTransfer(ADDRESS2, ADDRESS1, 20);
+ assertEq(resBool, true);
+
+ resBool = ruleSanctionList.canTransfer(ADDRESS2, ADDRESS1, 0, 20);
+ assertEq(resBool, true);
+
+ // Act
+ resUint8 = ruleSanctionList.detectTransferRestriction(ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
- ruleSanctionList = new RuleSanctionList(
- SANCTIONLIST_OPERATOR_ADDRESS,
- ZERO_ADDRESS,
- address(sanctionlistOracle)
- );
- assertEq(
- address(ruleSanctionList.sanctionsList()),
- address(sanctionlistOracle)
- );
+ // Act
+ resUint8 = ruleSanctionList.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
}
}
diff --git a/test/RuleSanctionList/RuleSanctionListTest.t.sol b/test/RuleSanctionList/RuleSanctionListTest.t.sol
index 2bd239e..058ed3f 100644
--- a/test/RuleSanctionList/RuleSanctionListTest.t.sol
+++ b/test/RuleSanctionList/RuleSanctionListTest.t.sol
@@ -4,66 +4,59 @@ pragma solidity ^0.8.20;
import "forge-std/Test.sol";
import "../HelperContract.sol";
import "../utils/SanctionListOracle.sol";
-import {RuleSanctionList, SanctionsList} from "src/rules/validation/RuleSanctionList.sol";
+import {RuleSanctionsList, ISanctionsList} from "src/rules/validation/RuleSanctionsList.sol";
/**
* @title General functions of the ruleSanctionList
*/
+
contract RuleSanctionlistTest is Test, HelperContract {
SanctionListOracle sanctionlistOracle;
- RuleSanctionList ruleSanctionList;
+ RuleSanctionsList ruleSanctionList;
// Arrange
function setUp() public {
vm.prank(SANCTIONLIST_OPERATOR_ADDRESS);
sanctionlistOracle = new SanctionListOracle();
sanctionlistOracle.addToSanctionsList(ATTACKER);
- ruleSanctionList = new RuleSanctionList(
- SANCTIONLIST_OPERATOR_ADDRESS,
- ZERO_ADDRESS,
- ZERO_ADDRESS
- );
+ ruleSanctionList =
+ new RuleSanctionsList(SANCTIONLIST_OPERATOR_ADDRESS, ZERO_ADDRESS, ISanctionsList(ZERO_ADDRESS));
vm.prank(SANCTIONLIST_OPERATOR_ADDRESS);
- ruleSanctionList.setSanctionListOracle(address(sanctionlistOracle));
+ ruleSanctionList.setSanctionListOracle(sanctionlistOracle);
}
function testCanReturnTransferRestrictionCode() public {
// Act
- resBool = ruleSanctionList.canReturnTransferRestrictionCode(
- CODE_ADDRESS_FROM_IS_SANCTIONED
- );
+ resBool = ruleSanctionList.canReturnTransferRestrictionCode(CODE_ADDRESS_FROM_IS_SANCTIONED);
// Assert
assertEq(resBool, true);
// Act
- resBool = ruleSanctionList.canReturnTransferRestrictionCode(
- CODE_ADDRESS_TO_IS_SANCTIONED
- );
+ resBool = ruleSanctionList.canReturnTransferRestrictionCode(CODE_ADDRESS_TO_IS_SANCTIONED);
// Assert
assertEq(resBool, true);
// Act
- resBool = ruleSanctionList.canReturnTransferRestrictionCode(
- CODE_NONEXISTENT
- );
+ resBool = ruleSanctionList.canReturnTransferRestrictionCode(CODE_NONEXISTENT);
// Assert
assertFalse(resBool);
}
function testReturnTheRightMessageForAGivenCode() public {
// Assert
- resString = ruleSanctionList.messageForTransferRestriction(
- CODE_ADDRESS_FROM_IS_SANCTIONED
- );
+ resString = ruleSanctionList.messageForTransferRestriction(CODE_ADDRESS_FROM_IS_SANCTIONED);
// Assert
assertEq(resString, TEXT_ADDRESS_FROM_IS_SANCTIONED);
+
// Act
- resString = ruleSanctionList.messageForTransferRestriction(
- CODE_ADDRESS_TO_IS_SANCTIONED
- );
+ resString = ruleSanctionList.messageForTransferRestriction(CODE_ADDRESS_TO_IS_SANCTIONED);
// Assert
assertEq(resString, TEXT_ADDRESS_TO_IS_SANCTIONED);
+
// Act
- resString = ruleSanctionList.messageForTransferRestriction(
- CODE_NONEXISTENT
- );
+ resString = ruleSanctionList.messageForTransferRestriction(CODE_ADDRESS_SPENDER_IS_SANCTIONED);
+ // Assert
+ assertEq(resString, TEXT_ADDRESS_SPENDER_IS_SANCTIONED);
+
+ // Act
+ resString = ruleSanctionList.messageForTransferRestriction(CODE_NONEXISTENT);
// Assert
assertEq(resString, TEXT_CODE_NOT_FOUND);
}
@@ -73,16 +66,26 @@ contract RuleSanctionlistTest is Test, HelperContract {
// ADDRESS1 -> ADDRESS2
resBool = ruleSanctionList.canTransfer(ADDRESS1, ADDRESS2, 20);
assertEq(resBool, true);
+ resBool = ruleSanctionList.canTransfer(ADDRESS1, ADDRESS2, 0, 20);
+ assertEq(resBool, true);
// ADDRESS2 -> ADDRESS1
resBool = ruleSanctionList.canTransfer(ADDRESS2, ADDRESS1, 20);
assertEq(resBool, true);
+ resBool = ruleSanctionList.canTransfer(ADDRESS2, ADDRESS1, 0, 20);
+ assertEq(resBool, true);
}
+
function testTransferFromDetectedAsInvalid() public {
// Act
resBool = ruleSanctionList.canTransfer(ATTACKER, ADDRESS2, 20);
// Assert
assertFalse(resBool);
+
+ // Act
+ resBool = ruleSanctionList.canTransfer(ATTACKER, ADDRESS2, 0, 20);
+ // Assert
+ assertFalse(resBool);
}
function testTransferToDetectedAsInvalid() public {
@@ -90,38 +93,191 @@ contract RuleSanctionlistTest is Test, HelperContract {
resBool = ruleSanctionList.canTransfer(ADDRESS1, ATTACKER, 20);
// Assert
assertFalse(resBool);
+ // Act
+ resBool = ruleSanctionList.canTransfer(ADDRESS1, ATTACKER, 0, 20);
+ // Assert
+ assertFalse(resBool);
}
function testDetectTransferRestrictionFrom() public {
// Act
- resUint8 = ruleSanctionList.detectTransferRestriction(
- ATTACKER,
- ADDRESS2,
- 20
- );
+ resUint8 = ruleSanctionList.detectTransferRestriction(ATTACKER, ADDRESS2, 20);
// Assert
assertEq(resUint8, CODE_ADDRESS_FROM_IS_SANCTIONED);
+
+ // Act
+ resUint8 = ruleSanctionList.detectTransferRestriction(ATTACKER, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_FROM_IS_SANCTIONED);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleSanctionsList_InvalidTransfer.selector,
+ address(ruleSanctionList),
+ ATTACKER,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_FROM_IS_SANCTIONED
+ )
+ );
+ // Act
+ ruleSanctionList.transferred(ATTACKER, ADDRESS2, 20);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleSanctionsList_InvalidTransfer.selector,
+ address(ruleSanctionList),
+ ATTACKER,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_FROM_IS_SANCTIONED
+ )
+ );
+ ruleSanctionList.transferred(ATTACKER, ADDRESS2, 0, 20);
}
function testDetectTransferRestrictionTo() public {
// Act
- resUint8 = ruleSanctionList.detectTransferRestriction(
- ADDRESS1,
- ATTACKER,
- 20
- );
+ resUint8 = ruleSanctionList.detectTransferRestriction(ADDRESS1, ATTACKER, 20);
// Assert
assertEq(resUint8, CODE_ADDRESS_TO_IS_SANCTIONED);
+
+ // Act
+ resUint8 = ruleSanctionList.detectTransferRestriction(ADDRESS1, ATTACKER, 0, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_TO_IS_SANCTIONED);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleSanctionsList_InvalidTransfer.selector,
+ address(ruleSanctionList),
+ ADDRESS1,
+ ATTACKER,
+ 20,
+ CODE_ADDRESS_TO_IS_SANCTIONED
+ )
+ );
+ // Act
+ ruleSanctionList.transferred(ADDRESS1, ATTACKER, 20);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleSanctionsList_InvalidTransfer.selector,
+ address(ruleSanctionList),
+ ADDRESS1,
+ ATTACKER,
+ 20,
+ CODE_ADDRESS_TO_IS_SANCTIONED
+ )
+ );
+ ruleSanctionList.transferred(ADDRESS1, ATTACKER, 0, 20);
}
function testDetectTransferRestrictionOk() public {
// Act
- resUint8 = ruleSanctionList.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 20
- );
+ resUint8 = ruleSanctionList.detectTransferRestriction(ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+
+ // Act
+ resUint8 = ruleSanctionList.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20);
// Assert
assertEq(resUint8, NO_ERROR);
+
+ // No revert
+ // Act
+ ruleSanctionList.transferred(ADDRESS1, ADDRESS2, 20);
+ ruleSanctionList.transferred(ADDRESS1, ADDRESS2, 0, 20);
+ }
+
+ function testDetectTransferRestrictionWitSpenderOk() public {
+ // Act
+ resUint8 = ruleSanctionList.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+
+ // Act
+ resUint8 = ruleSanctionList.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+
+
+ resBool = ruleSanctionList.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ assertEq(resBool, true);
+
+ resBool = ruleSanctionList.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ assertEq(resBool, true);
+
+ // No revert
+ // Act
+ ruleSanctionList.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ ruleSanctionList.transferred(ADDRESS3, ADDRESS2, 0, 20);
+ }
+
+ function testDetectTransferRestrictionWitSpender() public {
+ // Act
+ resUint8 = ruleSanctionList.detectTransferRestrictionFrom(ATTACKER, ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_SPENDER_IS_SANCTIONED);
+
+ // Act
+ resUint8 = ruleSanctionList.detectTransferRestrictionFrom(ATTACKER, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_SPENDER_IS_SANCTIONED);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleSanctionsList_InvalidTransferFrom.selector,
+ address(ruleSanctionList),
+ ATTACKER,
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_SPENDER_IS_SANCTIONED
+ )
+ );
+ // Act
+ ruleSanctionList.transferred(ATTACKER, ADDRESS1, ADDRESS2, 20);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleSanctionsList_InvalidTransferFrom.selector,
+ address(ruleSanctionList),
+ ATTACKER,
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_SPENDER_IS_SANCTIONED
+ )
+ );
+ ruleSanctionList.transferred(ATTACKER, ADDRESS1, ADDRESS2, 0, 20);
+ }
+
+ function testDetectTransferRestrictionWitSpenderTo() public {
+ // Act
+ resUint8 = ruleSanctionList.detectTransferRestrictionFrom(ADDRESS2, ADDRESS1, ATTACKER, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_TO_IS_SANCTIONED);
+
+ // Act
+ resUint8 = ruleSanctionList.detectTransferRestrictionFrom(ADDRESS2, ADDRESS1, ATTACKER, 0, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_TO_IS_SANCTIONED);
+
+ // Act
+ resBool = ruleSanctionList.canTransferFrom(ADDRESS2, ADDRESS1, ATTACKER, 20);
+ // Assert
+ assertFalse(resBool);
+
+ // Act
+ resBool = ruleSanctionList.canTransferFrom(ADDRESS2, ADDRESS1, ATTACKER, 0, 20);
+ // Assert
+ assertFalse(resBool);
}
}
diff --git a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol
index 5e5aff6..c957d28 100644
--- a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol
+++ b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol
@@ -14,33 +14,26 @@ contract RuleWhitelistAccessControl is Test, HelperContract {
// Arrange
function setUp() public {
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- ruleWhitelist = new RuleWhitelist(
- WHITELIST_OPERATOR_ADDRESS,
- ZERO_ADDRESS
- );
+ ruleWhitelist = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true);
}
- function testCannotAttackerAddAddressToTheList() public {
+ function testCannotAttackeraddAddress() public {
vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- ADDRESS_LIST_ADD_ROLE
- )
+ abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, ADDRESS_LIST_ADD_ROLE)
);
vm.prank(ATTACKER);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
// Assert
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, false);
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 0);
}
- function testCannotAttackerAddAddressesToTheList() public {
+ function testCannotAttackeraddAddresses() public {
// Arrange
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 0);
address[] memory whitelist = new address[](2);
whitelist[0] = ADDRESS1;
@@ -48,100 +41,73 @@ contract RuleWhitelistAccessControl is Test, HelperContract {
// Act
vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- ADDRESS_LIST_ADD_ROLE
- )
+ abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, ADDRESS_LIST_ADD_ROLE)
);
vm.prank(ATTACKER);
- (resCallBool, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "addAddressesToTheList(address[])",
- whitelist
- )
- );
+ (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist));
// Assert
assertEq(resCallBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, false);
- resBool = ruleWhitelist.addressIsListed(ADDRESS2);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS2);
assertEq(resBool, false);
- resBool = ruleWhitelist.addressIsListed(ADDRESS3);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS3);
assertFalse(resBool);
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 0);
}
- function testCannotAttackerRemoveAddressFromTheList() public {
+ function testCannotAttackerremoveAddress() public {
// Arrange
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
// Arrange - Assert
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
// Act
vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- ADDRESS_LIST_REMOVE_ROLE
- )
+ abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, ADDRESS_LIST_REMOVE_ROLE)
);
vm.prank(ATTACKER);
- ruleWhitelist.removeAddressFromTheList(ADDRESS1);
+ ruleWhitelist.removeAddress(ADDRESS1);
// Assert
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 1);
}
- function testCannotAttackerRemoveAddressesFromTheList() public {
+ function testCannotAttackerremoveAddresses() public {
// Arrange
address[] memory whitelist = new address[](2);
whitelist[0] = ADDRESS1;
whitelist[1] = ADDRESS2;
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- (resCallBool, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "addAddressesToTheList(address[])",
- whitelist
- )
- );
+ (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist));
assertEq(resCallBool, true);
// Arrange - Assert
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS2);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS2);
assertEq(resBool, true);
// Act
vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ATTACKER,
- ADDRESS_LIST_REMOVE_ROLE
- )
+ abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, ADDRESS_LIST_REMOVE_ROLE)
);
vm.prank(ATTACKER);
- (resCallBool, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "removeAddressesFromTheList(address[])",
- whitelist
- )
- );
+ (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("removeAddresses(address[])", whitelist));
// Assert
assertEq(resCallBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS2);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS2);
assertEq(resBool, true);
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 2);
}
}
diff --git a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol
index 2fb3bbe..6cb6ab2 100644
--- a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol
+++ b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol
@@ -12,21 +12,14 @@ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl {
// Arrange
function setUp() public {
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- ruleWhitelist = new RuleWhitelist(
- WHITELIST_OPERATOR_ADDRESS,
- ZERO_ADDRESS
- );
+ ruleWhitelist = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true);
}
function testCanGrantRoleAsAdmin() public {
// Act
vm.prank(WHITELIST_OPERATOR_ADDRESS);
vm.expectEmit(true, true, false, true);
- emit RoleGranted(
- ADDRESS_LIST_ADD_ROLE,
- ADDRESS1,
- WHITELIST_OPERATOR_ADDRESS
- );
+ emit RoleGranted(ADDRESS_LIST_ADD_ROLE, ADDRESS1, WHITELIST_OPERATOR_ADDRESS);
ruleWhitelist.grantRole(ADDRESS_LIST_ADD_ROLE, ADDRESS1);
// Assert
bool res1 = ruleWhitelist.hasRole(ADDRESS_LIST_ADD_ROLE, ADDRESS1);
@@ -44,11 +37,7 @@ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl {
// Act
vm.prank(WHITELIST_OPERATOR_ADDRESS);
vm.expectEmit(true, true, false, true);
- emit RoleRevoked(
- ADDRESS_LIST_ADD_ROLE,
- ADDRESS1,
- WHITELIST_OPERATOR_ADDRESS
- );
+ emit RoleRevoked(ADDRESS_LIST_ADD_ROLE, ADDRESS1, WHITELIST_OPERATOR_ADDRESS);
ruleWhitelist.revokeRole(ADDRESS_LIST_ADD_ROLE, ADDRESS1);
// Assert
bool res2 = ruleWhitelist.hasRole(ADDRESS_LIST_ADD_ROLE, ADDRESS1);
@@ -61,13 +50,7 @@ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl {
assertFalse(res1);
// Act
- vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ADDRESS2,
- DEFAULT_ADMIN_ROLE
- )
- );
+ vm.expectRevert(abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ADDRESS2, DEFAULT_ADMIN_ROLE));
vm.prank(ADDRESS2);
ruleWhitelist.grantRole(ADDRESS_LIST_ADD_ROLE, ADDRESS1);
// Assert
@@ -89,13 +72,7 @@ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl {
// Act
vm.prank(ADDRESS2);
- vm.expectRevert(
- abi.encodeWithSelector(
- AccessControlUnauthorizedAccount.selector,
- ADDRESS2,
- DEFAULT_ADMIN_ROLE
- )
- );
+ vm.expectRevert(abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ADDRESS2, DEFAULT_ADMIN_ROLE));
ruleWhitelist.revokeRole(ADDRESS_LIST_ADD_ROLE, ADDRESS1);
// Assert
diff --git a/test/RuleWhitelist/CMTATIntegration.t.sol b/test/RuleWhitelist/CMTATIntegration.t.sol
index 669cdda..2693f93 100644
--- a/test/RuleWhitelist/CMTATIntegration.t.sol
+++ b/test/RuleWhitelist/CMTATIntegration.t.sol
@@ -13,25 +13,19 @@ contract CMTATIntegration is Test, HelperContract {
uint256 ADDRESS2_BALANCE_INIT = 32;
uint256 ADDRESS3_BALANCE_INIT = 33;
- uint256 FLAG = 5;
-
// Arrange
function setUp() public {
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS);
+ ruleWhitelist = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true);
// global arrange
cmtatDeployment = new CMTATDeployment();
CMTAT_CONTRACT = cmtatDeployment.cmtat();
// specific arrange
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleEngineMock = new RuleEngine(
- DEFAULT_ADMIN_ADDRESS,
- ZERO_ADDRESS,
- address(CMTAT_CONTRACT)
- );
+ ruleEngineMock = new RuleEngine(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, address(CMTAT_CONTRACT));
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleEngineMock.addRuleValidation(ruleWhitelist);
+ ruleEngineMock.addRule(ruleWhitelist);
vm.prank(DEFAULT_ADMIN_ADDRESS);
CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT);
vm.prank(DEFAULT_ADMIN_ADDRESS);
@@ -43,16 +37,20 @@ contract CMTATIntegration is Test, HelperContract {
CMTAT_CONTRACT.setRuleEngine(ruleEngineMock);
}
- /******* Transfer *******/
+ /**
+ * Transfer ******
+ */
function testCannotTransferWithoutAddressWhitelisted() public {
// Arrange
vm.prank(ADDRESS1);
vm.expectRevert(
abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
+ RuleWhitelist_InvalidTransfer.selector,
+ address(ruleWhitelist),
ADDRESS1,
ADDRESS2,
- 21
+ 21,
+ CODE_ADDRESS_FROM_NOT_WHITELISTED
)
);
// Act
@@ -63,15 +61,17 @@ contract CMTATIntegration is Test, HelperContract {
// Arrange
uint256 amount = 21;
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS2);
+ ruleWhitelist.addAddress(ADDRESS2);
vm.prank(ADDRESS1);
vm.expectRevert(
abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
+ RuleWhitelist_InvalidTransfer.selector,
+ address(ruleWhitelist),
ADDRESS1,
ADDRESS2,
- amount
+ amount,
+ CODE_ADDRESS_FROM_NOT_WHITELISTED
)
);
// Act
@@ -82,15 +82,17 @@ contract CMTATIntegration is Test, HelperContract {
// Arrange
uint256 amount = 21;
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
vm.prank(ADDRESS1);
vm.expectRevert(
abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
+ RuleWhitelist_InvalidTransfer.selector,
+ address(ruleWhitelist),
ADDRESS1,
ADDRESS2,
- amount
+ amount,
+ CODE_ADDRESS_TO_NOT_WHITELISTED
)
);
// Act
@@ -103,12 +105,7 @@ contract CMTATIntegration is Test, HelperContract {
whitelist[0] = ADDRESS1;
whitelist[1] = ADDRESS2;
vm.prank(DEFAULT_ADMIN_ADDRESS);
- (bool success, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "addAddressesToTheList(address[])",
- whitelist
- )
- );
+ (bool success,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist));
require(success);
vm.prank(ADDRESS1);
@@ -124,23 +121,19 @@ contract CMTATIntegration is Test, HelperContract {
assertEq(resUint256, 33);
}
- /******* detectTransferRestriction & messageForTransferRestriction *******/
+ /**
+ * detectTransferRestriction & messageForTransferRestriction ******
+ */
function testDetectAndMessageWithFromNotWhitelisted() public {
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS2);
- resBool = ruleWhitelist.addressIsListed(ADDRESS2);
+ ruleWhitelist.addAddress(ADDRESS2);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS2);
// Assert
assertEq(resBool, true);
- uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 11
- );
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
// Assert
assertEq(res1, CODE_ADDRESS_FROM_NOT_WHITELISTED);
- string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(
- res1
- );
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
// Assert
assertEq(message1, TEXT_ADDRESS_FROM_NOT_WHITELISTED);
}
@@ -149,40 +142,28 @@ contract CMTATIntegration is Test, HelperContract {
// Arrange
// We add the sender to the whitelist
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
// Arrange - Assert
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
// Act
- uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 11
- );
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
// Assert
assertEq(res1, CODE_ADDRESS_TO_NOT_WHITELISTED);
// Act
- string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(
- res1
- );
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
// Assert
assertEq(message1, TEXT_ADDRESS_TO_NOT_WHITELISTED);
}
function testDetectAndMessageWithFromAndToNotWhitelisted() public view {
// Act
- uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 11
- );
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
// Assert
assertEq(res1, CODE_ADDRESS_FROM_NOT_WHITELISTED);
// Act
- string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(
- res1
- );
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
// Assert
assertEq(message1, TEXT_ADDRESS_FROM_NOT_WHITELISTED);
@@ -195,25 +176,14 @@ contract CMTATIntegration is Test, HelperContract {
whitelist[0] = ADDRESS1;
whitelist[1] = ADDRESS2;
vm.prank(DEFAULT_ADMIN_ADDRESS);
- (bool success, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "addAddressesToTheList(address[])",
- whitelist
- )
- );
+ (bool success,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist));
require(success);
// Act
- uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 11
- );
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
// Assert
assertEq(res1, TRANSFER_OK);
// Act
- string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(
- res1
- );
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
// Assert
assertEq(message1, TEXT_TRANSFER_OK);
}
@@ -222,11 +192,11 @@ contract CMTATIntegration is Test, HelperContract {
// Arrange
// Add address zero to the whitelist
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ZERO_ADDRESS);
+ ruleWhitelist.addAddress(ZERO_ADDRESS);
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
// Arrange - Assert
- resBool = ruleWhitelist.addressIsListed(ZERO_ADDRESS);
+ resBool = ruleWhitelist.isAddressListed(ZERO_ADDRESS);
assertEq(resBool, true);
// Act
diff --git a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol
index a06d4d7..e2e0641 100644
--- a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol
+++ b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol
@@ -4,16 +4,16 @@ pragma solidity ^0.8.20;
import "forge-std/Test.sol";
import "CMTAT/deployment/CMTATStandalone.sol";
import "../HelperContract.sol";
-
+import {AccessControlModuleStandalone} from "../../src/modules/AccessControlModuleStandalone.sol";
/**
* @title Integration test with the CMTAT
*/
+
contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
uint256 ADDRESS1_BALANCE_INIT = 31;
uint256 ADDRESS2_BALANCE_INIT = 32;
uint256 ADDRESS3_BALANCE_INIT = 33;
-
- uint256 FLAG = 5;
+
RuleWhitelist ruleWhitelist2;
RuleWhitelist ruleWhitelist3;
RuleWhitelistWrapper ruleWhitelistWrapper;
@@ -21,31 +21,24 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
// Arrange
function setUp() public {
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS);
- ruleWhitelist2 = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS);
- ruleWhitelist3 = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS);
- ruleWhitelistWrapper = new RuleWhitelistWrapper(
- DEFAULT_ADMIN_ADDRESS,
- ZERO_ADDRESS
- );
+ ruleWhitelist = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true);
+ ruleWhitelist2 = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true);
+ ruleWhitelist3 = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true);
+ ruleWhitelistWrapper = new RuleWhitelistWrapper(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true);
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelistWrapper.addRuleValidation(ruleWhitelist);
+ ruleWhitelistWrapper.addRule(ruleWhitelist);
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelistWrapper.addRuleValidation(ruleWhitelist2);
+ ruleWhitelistWrapper.addRule(ruleWhitelist2);
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelistWrapper.addRuleValidation(ruleWhitelist3);
+ ruleWhitelistWrapper.addRule(ruleWhitelist3);
// global arrange
cmtatDeployment = new CMTATDeployment();
CMTAT_CONTRACT = cmtatDeployment.cmtat();
// specific arrange
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleEngineMock = new RuleEngine(
- DEFAULT_ADMIN_ADDRESS,
- ZERO_ADDRESS,
- address(CMTAT_CONTRACT)
- );
+ ruleEngineMock = new RuleEngine(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, address(CMTAT_CONTRACT));
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleEngineMock.addRuleValidation(ruleWhitelistWrapper);
+ ruleEngineMock.addRule(ruleWhitelistWrapper);
vm.prank(DEFAULT_ADMIN_ADDRESS);
CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT);
vm.prank(DEFAULT_ADMIN_ADDRESS);
@@ -57,27 +50,29 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
CMTAT_CONTRACT.setRuleEngine(ruleEngineMock);
}
- /******* Deployment *******/
-
+ /**
+ * Deployment ******
+ */
function testCannotDeployContractIfAdminAddressIsZero() public {
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- vm.expectRevert(RuleEngine_AdminWithAddressZeroNotAllowed.selector);
- ruleWhitelistWrapper = new RuleWhitelistWrapper(
- ZERO_ADDRESS,
- ZERO_ADDRESS
- );
+ vm.expectRevert(AccessControlModuleStandalone.AccessControlModuleStandalone_AddressZeroNotAllowed.selector);
+ ruleWhitelistWrapper = new RuleWhitelistWrapper(ZERO_ADDRESS, ZERO_ADDRESS, true);
}
- /******* Transfer *******/
+ /**
+ * Transfer ******
+ */
function testCannotTransferWithoutAddressWhitelisted() public {
// Arrange
vm.prank(ADDRESS1);
vm.expectRevert(
abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
+ RuleWhitelist_InvalidTransfer.selector,
+ address(ruleWhitelistWrapper),
ADDRESS1,
ADDRESS2,
- 21
+ 21,
+ CODE_ADDRESS_FROM_NOT_WHITELISTED
)
);
// Act
@@ -88,15 +83,17 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
// Arrange
uint256 amount = 21;
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS2);
+ ruleWhitelist.addAddress(ADDRESS2);
vm.prank(ADDRESS1);
vm.expectRevert(
abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
+ RuleWhitelist_InvalidTransfer.selector,
+ address(ruleWhitelistWrapper),
ADDRESS1,
ADDRESS2,
- amount
+ amount,
+ CODE_ADDRESS_FROM_NOT_WHITELISTED
)
);
// Act
@@ -107,15 +104,17 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
// Arrange
uint256 amount = 21;
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
vm.prank(ADDRESS1);
vm.expectRevert(
abi.encodeWithSelector(
- RuleEngine_InvalidTransfer.selector,
+ RuleWhitelist_InvalidTransfer.selector,
+ address(ruleWhitelistWrapper),
ADDRESS1,
ADDRESS2,
- amount
+ amount,
+ CODE_ADDRESS_TO_NOT_WHITELISTED
)
);
// Act
@@ -125,14 +124,14 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
function testCanMakeATransferIfWhitelistedInSeveralDifferentList() public {
// Arrange
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist3.addAddressToTheList(ADDRESS1);
+ ruleWhitelist3.addAddress(ADDRESS1);
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist2.addAddressToTheList(ADDRESS2);
+ ruleWhitelist2.addAddress(ADDRESS2);
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist3.addAddressToTheList(ADDRESS2);
+ ruleWhitelist3.addAddress(ADDRESS2);
// Act
vm.prank(ADDRESS1);
@@ -150,10 +149,10 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
function testCanMakeATransferIfWhitelistedInDifferentList() public {
// Arrange
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist2.addAddressToTheList(ADDRESS2);
+ ruleWhitelist2.addAddress(ADDRESS2);
// Act
vm.prank(ADDRESS1);
@@ -174,12 +173,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
whitelist[0] = ADDRESS1;
whitelist[1] = ADDRESS2;
vm.prank(DEFAULT_ADMIN_ADDRESS);
- (bool success, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "addAddressesToTheList(address[])",
- whitelist
- )
- );
+ (bool success,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist));
require(success);
// Act
@@ -195,23 +189,19 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
assertEq(resUint256, 33);
}
- /******* detectTransferRestriction & messageForTransferRestriction *******/
+ /**
+ * detectTransferRestriction & messageForTransferRestriction ******
+ */
function testDetectAndMessageWithFromNotWhitelisted() public {
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS2);
- resBool = ruleWhitelist.addressIsListed(ADDRESS2);
+ ruleWhitelist.addAddress(ADDRESS2);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS2);
// Assert
assertEq(resBool, true);
- uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 11
- );
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
// Assert
assertEq(res1, CODE_ADDRESS_FROM_NOT_WHITELISTED);
- string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(
- res1
- );
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
// Assert
assertEq(message1, TEXT_ADDRESS_FROM_NOT_WHITELISTED);
}
@@ -220,40 +210,28 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
// Arrange
// We add the sender to the whitelist
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
// Arrange - Assert
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
// Act
- uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 11
- );
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
// Assert
assertEq(res1, CODE_ADDRESS_TO_NOT_WHITELISTED);
// Act
- string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(
- res1
- );
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
// Assert
assertEq(message1, TEXT_ADDRESS_TO_NOT_WHITELISTED);
}
function testDetectAndMessageWithFromAndToNotWhitelisted() public view {
// Act
- uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 11
- );
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
// Assert
assertEq(res1, CODE_ADDRESS_FROM_NOT_WHITELISTED);
// Act
- string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(
- res1
- );
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
// Assert
assertEq(message1, TEXT_ADDRESS_FROM_NOT_WHITELISTED);
@@ -261,9 +239,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
function testCanReturnUnknownTextMessage() public view {
// Act
- string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(
- 200
- );
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(200);
// Assert
assertEq(message1, TEXT_CODE_NOT_FOUND);
@@ -276,25 +252,14 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
whitelist[0] = ADDRESS1;
whitelist[1] = ADDRESS2;
vm.prank(DEFAULT_ADMIN_ADDRESS);
- (bool success, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "addAddressesToTheList(address[])",
- whitelist
- )
- );
+ (bool success,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist));
require(success);
// Act
- uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 11
- );
+ uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11);
// Assert
assertEq(res1, TRANSFER_OK);
// Act
- string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(
- res1
- );
+ string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1);
// Assert
assertEq(message1, TEXT_TRANSFER_OK);
}
@@ -303,11 +268,11 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
// Arrange
// Add address zero to the whitelist
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ZERO_ADDRESS);
+ ruleWhitelist.addAddress(ZERO_ADDRESS);
vm.prank(DEFAULT_ADMIN_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
// Arrange - Assert
- resBool = ruleWhitelist.addressIsListed(ZERO_ADDRESS);
+ resBool = ruleWhitelist.isAddressListed(ZERO_ADDRESS);
assertEq(resBool, true);
// Act
diff --git a/test/RuleWhitelist/RuleWhitelist.t.sol b/test/RuleWhitelist/RuleWhitelist.t.sol
index 26f1cc1..8a1535a 100644
--- a/test/RuleWhitelist/RuleWhitelist.t.sol
+++ b/test/RuleWhitelist/RuleWhitelist.t.sol
@@ -11,135 +11,127 @@ contract RuleWhitelistTest is Test, HelperContract {
// Arrange
function setUp() public {
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- ruleWhitelist = new RuleWhitelist(
- WHITELIST_OPERATOR_ADDRESS,
- ZERO_ADDRESS
- );
+ ruleWhitelist = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true);
}
- function _addAddressesToTheList() internal {
+ function _addAddresses() internal {
address[] memory whitelist = new address[](2);
whitelist[0] = ADDRESS1;
whitelist[1] = ADDRESS2;
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- (resCallBool, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "addAddressesToTheList(address[])",
- whitelist
- )
- );
+ (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist));
// Assert
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 2);
assertEq(resCallBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS2);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS2);
assertEq(resBool, true);
}
function testReturnFalseIfAddressNotWhitelisted() public {
// Act
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
// Assert
assertFalse(resBool);
// Act
- resBool = ruleWhitelist.addressIsListed(ADDRESS2);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS2);
// Assert
assertFalse(resBool);
// Act
- resBool = ruleWhitelist.addressIsListed(ADDRESS3);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS3);
// Assert
assertFalse(resBool);
// Act
- resBool = ruleWhitelist.addressIsListed(address(0x0));
+ resBool = ruleWhitelist.isAddressListed(address(0x0));
// Assert
assertFalse(resBool);
}
function testAddressIsIndicatedAsWhitelisted() public {
// Arrange - Assert
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertFalse(resBool);
// Act
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
// Assert
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
}
function testAddressesIsIndicatedAsWhitelisted() public {
// Arrange
- _addAddressesToTheList();
+ _addAddresses();
// Act
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
// Assert
assertEq(resBool, true);
// Act
- resBool = ruleWhitelist.addressIsListed(ADDRESS2);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS2);
// Assert
assertEq(resBool, true);
// Act
- resBool = ruleWhitelist.addressIsListed(ADDRESS3);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS3);
// Assert
assertFalse(resBool);
}
function testCanReturnTransferRestrictionCode() public {
// Act
- resBool = ruleWhitelist.canReturnTransferRestrictionCode(
- CODE_ADDRESS_FROM_NOT_WHITELISTED
- );
+ resBool = ruleWhitelist.canReturnTransferRestrictionCode(CODE_ADDRESS_FROM_NOT_WHITELISTED);
// Assert
assertEq(resBool, true);
// Act
- resBool = ruleWhitelist.canReturnTransferRestrictionCode(
- CODE_ADDRESS_TO_NOT_WHITELISTED
- );
+ resBool = ruleWhitelist.canReturnTransferRestrictionCode(CODE_ADDRESS_TO_NOT_WHITELISTED);
// Assert
assertEq(resBool, true);
// Act
- resBool = ruleWhitelist.canReturnTransferRestrictionCode(
- CODE_NONEXISTENT
- );
+ resBool = ruleWhitelist.canReturnTransferRestrictionCode(CODE_NONEXISTENT);
// Assert
assertFalse(resBool);
}
function testReturnTheRightMessageForAGivenCode() public {
// Assert
- resString = ruleWhitelist.messageForTransferRestriction(
- CODE_ADDRESS_FROM_NOT_WHITELISTED
- );
+ resString = ruleWhitelist.messageForTransferRestriction(CODE_ADDRESS_FROM_NOT_WHITELISTED);
// Assert
assertEq(resString, TEXT_ADDRESS_FROM_NOT_WHITELISTED);
// Act
- resString = ruleWhitelist.messageForTransferRestriction(
- CODE_ADDRESS_TO_NOT_WHITELISTED
- );
+ resString = ruleWhitelist.messageForTransferRestriction(CODE_ADDRESS_TO_NOT_WHITELISTED);
// Assert
assertEq(resString, TEXT_ADDRESS_TO_NOT_WHITELISTED);
+
// Act
- resString = ruleWhitelist.messageForTransferRestriction(
- CODE_NONEXISTENT
- );
+ resString = ruleWhitelist.messageForTransferRestriction(CODE_ADDRESS_SPENDER_NOT_WHITELISTED);
+ // Assert
+ assertEq(resString, TEXT_ADDRESS_SPENDER_NOT_WHITELISTED);
+
+
+ // Act
+ resString = ruleWhitelist.messageForTransferRestriction(CODE_NONEXISTENT);
// Assert
assertEq(resString, TEXT_CODE_NOT_FOUND);
}
function testcanTransfer() public {
// Arrange
- _addAddressesToTheList();
+ _addAddresses();
// Act
// ADDRESS1 -> ADDRESS2
resBool = ruleWhitelist.canTransfer(ADDRESS1, ADDRESS2, 20);
assertEq(resBool, true);
+ resBool = ruleWhitelist.canTransfer(ADDRESS1, ADDRESS2, 0, 20);
+ assertEq(resBool, true);
// ADDRESS2 -> ADDRESS1
resBool = ruleWhitelist.canTransfer(ADDRESS2, ADDRESS1, 20);
assertEq(resBool, true);
+
+ resBool = ruleWhitelist.canTransfer(ADDRESS2, ADDRESS1, 0, 20);
+ assertEq(resBool, true);
}
function testTransferDetectedAsInvalid() public {
@@ -147,11 +139,16 @@ contract RuleWhitelistTest is Test, HelperContract {
resBool = ruleWhitelist.canTransfer(ADDRESS1, ADDRESS2, 20);
// Assert
assertFalse(resBool);
+
+ // Act
+ resBool = ruleWhitelist.canTransfer(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertFalse(resBool);
}
- function testNumberListedAddress() public {
+ function testlistedAddressCount() public {
// Act
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
// Assert
assertEq(resUint256, 0);
@@ -160,71 +157,220 @@ contract RuleWhitelistTest is Test, HelperContract {
whitelist[0] = ADDRESS1;
whitelist[1] = ADDRESS2;
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- (resCallBool, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "addAddressesToTheList(address[])",
- whitelist
- )
- );
+ (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist));
assertEq(resCallBool, true);
// Act
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
// Assert
assertEq(resUint256, 2);
// Arrange
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- (resCallBool, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "removeAddressesFromTheList(address[])",
- whitelist
- )
- );
+ (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("removeAddresses(address[])", whitelist));
// Arrange - Assert
assertEq(resCallBool, true);
// Act
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
// Assert
assertEq(resUint256, 0);
}
function testDetectTransferRestrictionFrom() public {
// Act
- resUint8 = ruleWhitelist.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 20
- );
+ resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20);
// Assert
assertEq(resUint8, CODE_ADDRESS_FROM_NOT_WHITELISTED);
+
+ // Act
+ resBool = ruleWhitelist.canTransfer(ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resBool, false);
+
+ // Act
+ resBool = ruleWhitelist.canTransfer(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resBool, false);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleWhitelist_InvalidTransfer.selector,
+ address(ruleWhitelist),
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_FROM_NOT_WHITELISTED
+ )
+ );
+ // Act
+ ruleWhitelist.transferred(ADDRESS1, ADDRESS2, 20);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleWhitelist_InvalidTransfer.selector,
+ address(ruleWhitelist),
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_FROM_NOT_WHITELISTED
+ )
+ );
+ ruleWhitelist.transferred(ADDRESS1, ADDRESS2, 0, 20);
}
function testDetectTransferRestrictionTo() public {
// Arrange
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
// Act
- resUint8 = ruleWhitelist.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 20
- );
+ resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20);
// Assert
assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED);
+
+ // With tokenId
+ resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleWhitelist_InvalidTransfer.selector,
+ address(ruleWhitelist),
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_TO_NOT_WHITELISTED
+ )
+ );
+ // Act
+ ruleWhitelist.transferred(ADDRESS1, ADDRESS2, 20);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleWhitelist_InvalidTransfer.selector,
+ address(ruleWhitelist),
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_TO_NOT_WHITELISTED
+ )
+ );
+ ruleWhitelist.transferred(ADDRESS1, ADDRESS2, 0, 20);
}
- function testDetectTransferRestrictionOk() public {
+ function testDetectTransferRestrictionWithSpender() public {
// Arrange
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
+
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS2);
+ ruleWhitelist.addAddress(ADDRESS2);
+ // Act
+ resUint8 = ruleWhitelist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_SPENDER_NOT_WHITELISTED);
+
+ // Act
+ resBool = ruleWhitelist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resBool, false);
+
+ // With tokenId
+ resUint8 = ruleWhitelist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_SPENDER_NOT_WHITELISTED);
+
+ // Act
+ resBool = ruleWhitelist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resBool, false);
+
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleWhitelist_InvalidTransferFrom.selector,
+ address(ruleWhitelist),
+ ADDRESS3,
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_SPENDER_NOT_WHITELISTED
+ )
+ );
// Act
- resUint8 = ruleWhitelist.detectTransferRestriction(
- ADDRESS1,
- ADDRESS2,
- 20
+ ruleWhitelist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleWhitelist_InvalidTransferFrom.selector,
+ address(ruleWhitelist),
+ ADDRESS3,
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_SPENDER_NOT_WHITELISTED
+ )
);
+ ruleWhitelist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ }
+
+ function testDetectTransferRestrictionOk() public {
+ // Arrange
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS1);
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS2);
+ // Act
+ resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+
+ // With tokenId
+ resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+
+ // With tokenId
+ resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+ }
+
+ function testDetectTransferRestrictionWithSpenderOk() public {
+ // Arrange
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS1);
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS2);
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS3);
+ // Act
+ resUint8 = ruleWhitelist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
// Assert
assertEq(resUint8, NO_ERROR);
+
+ // Act
+ resBool = ruleWhitelist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resBool, true);
+
+ // Act
+ resBool = ruleWhitelist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resBool, true);
+
+ // With tokenId
+ resUint8 = ruleWhitelist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+
+ // No revert
+ // Act
+ ruleWhitelist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ ruleWhitelist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
}
}
diff --git a/test/RuleWhitelist/RuleWhitelistAdd.t.sol b/test/RuleWhitelist/RuleWhitelistAdd.t.sol
index 054af69..94fe2e3 100644
--- a/test/RuleWhitelist/RuleWhitelistAdd.t.sol
+++ b/test/RuleWhitelist/RuleWhitelistAdd.t.sol
@@ -11,93 +11,81 @@ contract RuleWhitelistAddTest is Test, HelperContract {
// Arrange
function setUp() public {
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- ruleWhitelist = new RuleWhitelist(
- WHITELIST_OPERATOR_ADDRESS,
- ZERO_ADDRESS
- );
+ ruleWhitelist = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true);
}
- function _addAddressesToTheList() internal {
+ function _addAddresses() internal {
address[] memory whitelist = new address[](2);
whitelist[0] = ADDRESS1;
whitelist[1] = ADDRESS2;
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- (resCallBool, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "addAddressesToTheList(address[])",
- whitelist
- )
- );
+ (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist));
// Assert
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 2);
assertEq(resCallBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS2);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS2);
assertEq(resBool, true);
address[] memory addressesListInput = new address[](2);
addressesListInput[0] = ADDRESS1;
addressesListInput[1] = ADDRESS2;
- bool[] memory resBools = ruleWhitelist.addressIsListedBatch(
- addressesListInput
- );
+ bool[] memory resBools = ruleWhitelist.areAddressesListed(addressesListInput);
assertEq(resBools[0], true);
assertEq(resBools[1], true);
assertEq(resBools.length, 2);
}
- function testAddAddressToTheList() public {
+ function testaddAddress() public {
// Act
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- emit AddAddressToTheList(ADDRESS1);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ emit IAddressList.AddAddress(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
// Assert
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
address[] memory addressesListInput = new address[](1);
addressesListInput[0] = ADDRESS1;
- bool[] memory resBools = ruleWhitelist.addressIsListedBatch(
- addressesListInput
- );
+ bool[] memory resBools = ruleWhitelist.areAddressesListed(addressesListInput);
assertEq(resBools[0], true);
assertEq(resBools.length, 1);
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 1);
}
- function testAddAddressesToTheList() public {
+ function testaddAddresses() public {
// Arrange
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 0);
// Act
- _addAddressesToTheList();
+ _addAddresses();
// Assert
- resBool = ruleWhitelist.addressIsListed(ADDRESS3);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS3);
assertFalse(resBool);
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 2);
}
function testCanAddAddressZeroToTheWhitelist() public {
// Arrange - Assert
- resBool = ruleWhitelist.addressIsListed(address(0x0));
+ resBool = ruleWhitelist.isAddressListed(address(0x0));
assertEq(resBool, false);
// Act
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- emit AddAddressToTheList(address(0x0));
- ruleWhitelist.addAddressToTheList(address(0x0));
+ emit IAddressList.AddAddress(address(0x0));
+ ruleWhitelist.addAddress(address(0x0));
// Assert
- resBool = ruleWhitelist.addressIsListed(address(0x0));
+ resBool = ruleWhitelist.isAddressListed(address(0x0));
assertEq(resBool, true);
}
function testCanAddAddressesZeroToTheWhitelist() public {
// Arrange
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 0);
address[] memory whitelist = new address[](3);
whitelist[0] = ADDRESS1;
@@ -107,54 +95,49 @@ contract RuleWhitelistAddTest is Test, HelperContract {
// Act
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- emit AddAddressesToTheList(whitelist);
- (resCallBool, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "addAddressesToTheList(address[])",
- whitelist
- )
- );
+ emit IAddressList.AddAddresses(whitelist);
+ (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist));
// Assert - Main
// Seem that call returns true even if the function is reverted
// TODO : check the return value of call
- resBool = ruleWhitelist.addressIsListed(address(0x0));
+ resBool = ruleWhitelist.isAddressListed(address(0x0));
assertEq(resBool, true);
// Assert - Secondary
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS2);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS2);
assertEq(resBool, true);
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 3);
}
function testAddAddressTwiceToTheWhitelist() public {
// Arrange
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
// Arrange - Assert
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
/// Arrange
- vm.expectRevert(Rulelist_AddressAlreadylisted.selector);
+ vm.expectRevert(RuleAddressSet_AddressAlreadyListed.selector);
// Act
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
// no change
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 1);
}
function testAddAddressesTwiceToTheWhitelist() public {
// Arrange
// Arrange - first addition
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 0);
- _addAddressesToTheList();
+ _addAddresses();
// Arrange - second addition
address[] memory whitelistDuplicate = new address[](3);
// Duplicate address
@@ -164,23 +147,19 @@ contract RuleWhitelistAddTest is Test, HelperContract {
whitelistDuplicate[2] = ADDRESS3;
// Act
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- (resCallBool, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "addAddressesToTheList(address[])",
- whitelistDuplicate
- )
- );
+ (resCallBool,) =
+ address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelistDuplicate));
// Assert
// no change
assertEq(resCallBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS2);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS2);
assertEq(resBool, true);
// ADDRESS3 is whitelisted
- resBool = ruleWhitelist.addressIsListed(ADDRESS3);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS3);
assertEq(resBool, true);
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 3);
}
}
diff --git a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol
index ef219a9..add51c3 100644
--- a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol
+++ b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol
@@ -4,10 +4,11 @@ pragma solidity ^0.8.20;
import "forge-std/Test.sol";
import "../HelperContract.sol";
import "CMTAT/mocks/MinimalForwarderMock.sol";
-
+import {AccessControlModuleStandalone} from "../../src/modules/AccessControlModuleStandalone.sol";
/**
* @title General functions of the RuleWhitelist
*/
+
contract RuleWhitelistDeploymentTest is Test, HelperContract {
// Arrange
function setUp() public {}
@@ -18,21 +19,12 @@ contract RuleWhitelistDeploymentTest is Test, HelperContract {
MinimalForwarderMock forwarder = new MinimalForwarderMock();
forwarder.initialize(ERC2771ForwarderDomain);
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- ruleWhitelist = new RuleWhitelist(
- WHITELIST_OPERATOR_ADDRESS,
- address(forwarder)
- );
+ ruleWhitelist = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, address(forwarder), true);
// assert
- resBool = ruleWhitelist.hasRole(
- ADDRESS_LIST_ADD_ROLE,
- WHITELIST_OPERATOR_ADDRESS
- );
+ resBool = ruleWhitelist.hasRole(ADDRESS_LIST_ADD_ROLE, WHITELIST_OPERATOR_ADDRESS);
assertEq(resBool, true);
- resBool = ruleWhitelist.hasRole(
- ADDRESS_LIST_REMOVE_ROLE,
- WHITELIST_OPERATOR_ADDRESS
- );
+ resBool = ruleWhitelist.hasRole(ADDRESS_LIST_REMOVE_ROLE, WHITELIST_OPERATOR_ADDRESS);
assertEq(resBool, true);
resBool = ruleWhitelist.isTrustedForwarder(address(forwarder));
assertEq(resBool, true);
@@ -43,10 +35,8 @@ contract RuleWhitelistDeploymentTest is Test, HelperContract {
vm.prank(WHITELIST_OPERATOR_ADDRESS);
MinimalForwarderMock forwarder = new MinimalForwarderMock();
forwarder.initialize(ERC2771ForwarderDomain);
- vm.expectRevert(
- RuleAddressList_AdminWithAddressZeroNotAllowed.selector
- );
+ vm.expectRevert(AccessControlModuleStandalone.AccessControlModuleStandalone_AddressZeroNotAllowed.selector);
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- ruleWhitelist = new RuleWhitelist(address(0), address(forwarder));
+ ruleWhitelist = new RuleWhitelist(address(0), address(forwarder), true);
}
}
diff --git a/test/RuleWhitelist/RuleWhitelistRemove.t.sol b/test/RuleWhitelist/RuleWhitelistRemove.t.sol
index f992563..d0c1bc9 100644
--- a/test/RuleWhitelist/RuleWhitelistRemove.t.sol
+++ b/test/RuleWhitelist/RuleWhitelistRemove.t.sol
@@ -11,113 +11,95 @@ contract RuleWhitelistRemoveTest is Test, HelperContract {
// Arrange
function setUp() public {
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- ruleWhitelist = new RuleWhitelist(
- WHITELIST_OPERATOR_ADDRESS,
- ZERO_ADDRESS
- );
+ ruleWhitelist = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true);
}
- function _addAddressesToTheList() internal {
+ function _addAddresses() internal {
address[] memory whitelist = new address[](2);
whitelist[0] = ADDRESS1;
whitelist[1] = ADDRESS2;
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- emit AddAddressesToTheList(whitelist);
- (resCallBool, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "addAddressesToTheList(address[])",
- whitelist
- )
- );
+ emit IAddressList.AddAddresses(whitelist);
+ (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist));
// Assert
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 2);
assertEq(resCallBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS2);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS2);
assertEq(resBool, true);
}
- function testremoveAddressFromTheList() public {
+ function testRemoveAddress() public {
// Arrange
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- ruleWhitelist.addAddressToTheList(ADDRESS1);
+ ruleWhitelist.addAddress(ADDRESS1);
// Arrange - Assert
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
// Act
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- emit RemoveAddressFromTheList(ADDRESS1);
- ruleWhitelist.removeAddressFromTheList(ADDRESS1);
+ emit IAddressList.RemoveAddress(ADDRESS1);
+ ruleWhitelist.removeAddress(ADDRESS1);
// Assert
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertFalse(resBool);
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 0);
}
- function testremoveAddressesFromTheList() public {
+ function testRemoveAddressWhenArrayContainSeveralAddresses() public {
// Arrange
address[] memory whitelist = new address[](2);
whitelist[0] = ADDRESS1;
whitelist[1] = ADDRESS2;
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- (resCallBool, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "addAddressesToTheList(address[])",
- whitelist
- )
- );
+ (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist));
assertEq(resCallBool, true);
// Arrange - Assert
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertEq(resBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS2);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS2);
assertEq(resBool, true);
// Act
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- emit RemoveAddressesFromTheList(whitelist);
- (resCallBool, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "removeAddressesFromTheList(address[])",
- whitelist
- )
- );
+ emit IAddressList.RemoveAddresses(whitelist);
+ (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("removeAddresses(address[])", whitelist));
// Assert
assertEq(resCallBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertFalse(resBool);
- resBool = ruleWhitelist.addressIsListed(ADDRESS2);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS2);
assertFalse(resBool);
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 0);
}
function testRemoveAddressNotPresentFromTheWhitelist() public {
// Arrange
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertFalse(resBool);
- vm.expectRevert(Rulelist_AddressNotPresent.selector);
+ vm.expectRevert(RuleAddressSet_AddressNotFound.selector);
// Act
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- emit RemoveAddressFromTheList(ADDRESS1);
- ruleWhitelist.removeAddressFromTheList(ADDRESS1);
+ emit IAddressList.RemoveAddress(ADDRESS1);
+ ruleWhitelist.removeAddress(ADDRESS1);
// Assert
// no change
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertFalse(resBool);
}
function testRemoveAddressesNotPresentFromTheWhitelist() public {
// Arrange
- _addAddressesToTheList();
+ _addAddresses();
// Arrange
address[] memory whitelistRemove = new address[](3);
whitelistRemove[0] = ADDRESS1;
@@ -127,20 +109,16 @@ contract RuleWhitelistRemoveTest is Test, HelperContract {
// Act
vm.prank(WHITELIST_OPERATOR_ADDRESS);
- emit RemoveAddressesFromTheList(whitelistRemove);
- (resCallBool, ) = address(ruleWhitelist).call(
- abi.encodeWithSignature(
- "removeAddressesFromTheList(address[])",
- whitelistRemove
- )
- );
+ emit IAddressList.RemoveAddresses(whitelistRemove);
+ (resCallBool,) =
+ address(ruleWhitelist).call(abi.encodeWithSignature("removeAddresses(address[])", whitelistRemove));
// Assert
assertEq(resCallBool, true);
- resBool = ruleWhitelist.addressIsListed(ADDRESS1);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS1);
assertFalse(resBool);
- resBool = ruleWhitelist.addressIsListed(ADDRESS2);
+ resBool = ruleWhitelist.isAddressListed(ADDRESS2);
assertFalse(resBool);
- resUint256 = ruleWhitelist.numberListedAddress();
+ resUint256 = ruleWhitelist.listedAddressCount();
assertEq(resUint256, 0);
}
}
diff --git a/test/RuleWhitelist/WhitelistWrapper.t.sol b/test/RuleWhitelist/WhitelistWrapper.t.sol
new file mode 100644
index 0000000..99b31df
--- /dev/null
+++ b/test/RuleWhitelist/WhitelistWrapper.t.sol
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: MPL-2.0
+pragma solidity ^0.8.20;
+
+import "forge-std/Test.sol";
+import "CMTAT/deployment/CMTATStandalone.sol";
+import "../HelperContract.sol";
+import {AccessControlModuleStandalone} from "../../src/modules/AccessControlModuleStandalone.sol";
+/**
+ * @title Integration test with the CMTAT
+ */
+
+contract CMTATIntegrationWhitelistWrapper is Test, HelperContract {
+ uint256 ADDRESS1_BALANCE_INIT = 31;
+ uint256 ADDRESS2_BALANCE_INIT = 32;
+ uint256 ADDRESS3_BALANCE_INIT = 33;
+
+ uint256 FLAG = 5;
+ RuleWhitelist ruleWhitelist2;
+ RuleWhitelist ruleWhitelist3;
+ RuleWhitelistWrapper ruleWhitelistWrapper;
+
+ // Arrange
+ function setUp() public {
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true);
+ ruleWhitelist2 = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true);
+ ruleWhitelist3 = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true);
+ ruleWhitelistWrapper = new RuleWhitelistWrapper(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true);
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelistWrapper.addRule(ruleWhitelist);
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelistWrapper.addRule(ruleWhitelist2);
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelistWrapper.addRule(ruleWhitelist3);
+ }
+
+ /**
+ * Deployment ******
+ */
+ function testCannotDeployContractIfAdminAddressIsZero() public {
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ vm.expectRevert(AccessControlModuleStandalone.AccessControlModuleStandalone_AddressZeroNotAllowed.selector);
+ ruleWhitelistWrapper = new RuleWhitelistWrapper(ZERO_ADDRESS, ZERO_ADDRESS, true);
+ }
+
+ function testReturnTheRightMessageForAGivenCode() public {
+ // Assert
+ resString = ruleWhitelistWrapper.messageForTransferRestriction(CODE_ADDRESS_FROM_NOT_WHITELISTED);
+ // Assert
+ assertEq(resString, TEXT_ADDRESS_FROM_NOT_WHITELISTED);
+ // Act
+ resString = ruleWhitelistWrapper.messageForTransferRestriction(CODE_ADDRESS_TO_NOT_WHITELISTED);
+ // Assert
+ assertEq(resString, TEXT_ADDRESS_TO_NOT_WHITELISTED);
+
+ // Act
+ resString = ruleWhitelistWrapper.messageForTransferRestriction(CODE_ADDRESS_SPENDER_NOT_WHITELISTED);
+ // Assert
+ assertEq(resString, TEXT_ADDRESS_SPENDER_NOT_WHITELISTED);
+
+ // Act
+ resString = ruleWhitelistWrapper.messageForTransferRestriction(CODE_NONEXISTENT);
+ // Assert
+ assertEq(resString, TEXT_CODE_NOT_FOUND);
+ }
+
+ function testDetectTransferRestrictionFrom() public {
+ // Act
+ resUint8 = ruleWhitelistWrapper.detectTransferRestriction(ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_FROM_NOT_WHITELISTED);
+
+ // Act
+ resBool = ruleWhitelistWrapper.canTransfer(ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resBool, false);
+
+ // Act
+ resBool = ruleWhitelistWrapper.canTransfer(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resBool, false);
+
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleWhitelist_InvalidTransfer.selector,
+ address(ruleWhitelistWrapper),
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_FROM_NOT_WHITELISTED
+ )
+ );
+ // Act
+ ruleWhitelistWrapper.transferred(ADDRESS1, ADDRESS2, 20);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleWhitelist_InvalidTransfer.selector,
+ address(ruleWhitelistWrapper),
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_FROM_NOT_WHITELISTED
+ )
+ );
+ ruleWhitelistWrapper.transferred(ADDRESS1, ADDRESS2, 0, 20);
+ }
+
+ function testDetectTransferRestrictionTo() public {
+ // Arrange
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS1);
+ // Act
+ resUint8 = ruleWhitelistWrapper.detectTransferRestriction(ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED);
+
+ // With tokenId
+ resUint8 = ruleWhitelistWrapper.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED);
+
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleWhitelist_InvalidTransfer.selector,
+ address(ruleWhitelistWrapper),
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_TO_NOT_WHITELISTED
+ )
+ );
+ // Act
+ ruleWhitelistWrapper.transferred(ADDRESS1, ADDRESS2, 20);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleWhitelist_InvalidTransfer.selector,
+ address(ruleWhitelistWrapper),
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_TO_NOT_WHITELISTED
+ )
+ );
+ ruleWhitelistWrapper.transferred(ADDRESS1, ADDRESS2, 0, 20);
+
+ }
+
+ function testDetectTransferRestrictionWithSpender() public {
+ // Arrange
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS1);
+
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS2);
+ // Act
+ resUint8 = ruleWhitelistWrapper.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_SPENDER_NOT_WHITELISTED);
+
+ // Act
+ resBool = ruleWhitelistWrapper.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resBool, false);
+
+ // With tokenId
+ resUint8 = ruleWhitelistWrapper.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, CODE_ADDRESS_SPENDER_NOT_WHITELISTED);
+
+ // Act
+ resBool = ruleWhitelistWrapper.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resBool, false);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleWhitelist_InvalidTransferFrom.selector,
+ address(ruleWhitelistWrapper),
+ ADDRESS3,
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_SPENDER_NOT_WHITELISTED
+ )
+ );
+ // Act
+ ruleWhitelistWrapper.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ RuleWhitelist_InvalidTransferFrom.selector,
+ address(ruleWhitelistWrapper),
+ ADDRESS3,
+ ADDRESS1,
+ ADDRESS2,
+ 20,
+ CODE_ADDRESS_SPENDER_NOT_WHITELISTED
+ )
+ );
+ ruleWhitelistWrapper.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ }
+
+ function testDetectTransferRestrictionOk() public {
+ // Arrange
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS1);
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS2);
+ // Act
+ resUint8 = ruleWhitelistWrapper.detectTransferRestriction(ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+
+ // With tokenId
+ resUint8 = ruleWhitelistWrapper.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+
+ // With tokenId
+ resUint8 = ruleWhitelistWrapper.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+
+ // No revert
+ // Act
+ ruleWhitelistWrapper.transferred(ADDRESS1, ADDRESS2, 20);
+ ruleWhitelistWrapper.transferred(ADDRESS1, ADDRESS2, 0, 20);
+ }
+
+ function testDetectTransferRestrictionWithSpenderOk() public {
+ // Arrange
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS1);
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS2);
+ vm.prank(WHITELIST_OPERATOR_ADDRESS);
+ ruleWhitelist.addAddress(ADDRESS3);
+ // Act
+ resUint8 = ruleWhitelistWrapper.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+
+ // Act
+ resBool = ruleWhitelistWrapper.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ // Assert
+ assertEq(resBool, true);
+
+ // Act
+ resBool = ruleWhitelistWrapper.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resBool, true);
+
+ // With tokenId
+ resUint8 = ruleWhitelistWrapper.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ // Assert
+ assertEq(resUint8, NO_ERROR);
+
+ // No revert
+ // Act
+ ruleWhitelistWrapper.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 20);
+ ruleWhitelistWrapper.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20);
+ }
+
+
+}
diff --git a/test/utils/CMTATDeployment.sol b/test/utils/CMTATDeployment.sol
deleted file mode 100644
index 1f7d310..0000000
--- a/test/utils/CMTATDeployment.sol
+++ /dev/null
@@ -1,50 +0,0 @@
-//SPDX-License-Identifier: MPL-2.0
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "OZ/access/AccessControl.sol";
-import {ICMTATConstructor, CMTATStandalone} from "CMTAT/deployment/CMTATStandalone.sol";
-import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
-import {ISnapshotEngine} from "CMTAT/interfaces/engine/ISnapshotEngine.sol";
-import {IDocumentEngine} from "CMTAT/interfaces/engine/IDocumentEngine.sol";
-import {IERC1643CMTAT} from "CMTAT/interfaces/tokenization/draft-IERC1643CMTAT.sol";
-contract CMTATDeployment {
- // Share with helper contract
- address constant ZERO_ADDRESS = address(0);
- address constant DEFAULT_ADMIN_ADDRESS = address(1);
-
- CMTATStandalone public cmtat;
-
- constructor() {
- // CMTAT
- ICMTATConstructor.ERC20Attributes
- memory erc20Attributes = ICMTATConstructor.ERC20Attributes(
- "CMTA Token",
- "CMTAT",
- 0
- );
- ICMTATConstructor.ExtraInformationAttributes
- memory ExtraInformationAttributes = ICMTATConstructor
- .ExtraInformationAttributes(
- "CMTAT_ISIN",
- IERC1643CMTAT.DocumentInfo(
- "Terms",
- "https://cmta.ch",
- 0x9ff867f6592aa9d6d039e7aad6bd71f1659720cbc4dd9eae1554f6eab490098b
- ),
- "CMTAT_info"
- );
- ICMTATConstructor.Engine memory engines = ICMTATConstructor.Engine(
- IRuleEngine(ZERO_ADDRESS),
- ISnapshotEngine(ZERO_ADDRESS),
- IDocumentEngine(ZERO_ADDRESS)
- );
- cmtat = new CMTATStandalone(
- ZERO_ADDRESS,
- DEFAULT_ADMIN_ADDRESS,
- erc20Attributes,
- ExtraInformationAttributes,
- engines
- );
- }
-}
diff --git a/test/utils/SanctionListOracle.sol b/test/utils/SanctionListOracle.sol
index 2edaee7..1eab28a 100644
--- a/test/utils/SanctionListOracle.sol
+++ b/test/utils/SanctionListOracle.sol
@@ -1,11 +1,13 @@
// SPDX-License-Identifier: MPL-2.0
pragma solidity ^0.8.20;
+import {ISanctionsList} from "../../src/rules/interfaces/ISanctionsList.sol";
/**
* @notice Test contract from
* https://etherscan.io/address/0x40c57923924b5c5c5455c48d93317139addac8fb#code
*/
-contract SanctionListOracle {
+
+contract SanctionListOracle is ISanctionsList {
constructor() {}
mapping(address => bool) private sanctionedAddresses;