diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 34a4a52..f6a89cf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,22 +16,30 @@ jobs: name: Foundry project runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2 with: submodules: recursive + + - name: Setup NodeJS 20.5.0 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 #v4.4.0 + with: + node-version: 20.5.0 + + - name: Install nodes modules inside CMTAT lib + run: npm install + working-directory: ./lib/CMTAT + - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 + #v1.5.0 + uses: foundry-rs/foundry-toolchain@50d5a8956f2e319df19e6b57539d7e2acb9f8c1e + with: + version: nightly - name: Show Forge version run: | forge --version - - name: Run Forge fmt - run: | - forge fmt --check - id: fmt - - name: Run Forge build run: | forge build --sizes diff --git a/.gitignore b/.gitignore index 85198aa..ecd40ca 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ docs/ # Dotenv file .env +# node_modules +node_modules/ + diff --git a/CHANGELOG.md b/CHANGELOG.md index dbdc5d6..0290e02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,3 +16,7 @@ Please follow [https://changelog.md/](https://changelog.md/) conventions. - Perform an audit with several audit tools (Mythril and Slither), update the report in the corresponding directory [./doc/security/audits/tools](./doc/security/audits/tools) - Update surya doc by running the 3 scripts in [./doc/script](./doc/script) - Update changelog + +## v0.1.0 + +First release ! diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ba78c6..08fa470 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,10 @@ # Contributing Guidelines -There are many ways to contribute to RuleEngine Contracts. +There are many ways to contribute to Rules Contracts. + +## Development branch + +If you want to propose some improvement to the codebase, use the current development branch `dev` to perform the modification. ## Opening an issue diff --git a/README.md b/README.md index 1810d64..92e0b5f 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,265 @@ # RuleEngine - Rules -> This repository includes the rules contract for the CMTAT [RuleEngine](https://github.com/CMTA/RuleEngine) -> -> This repository is currently under development +**Rules** is a collection of on-chain compliance and transfer-restriction rules designed for use with the [CMTA RuleEngine](https://github.com/CMTA/RuleEngine) and the [CMTAT token standard](https://github.com/CMTA/CMTAT). -- The RuleEngine is an external contract used to apply transfer restrictions to another contract such as a CMTAT or ERC-3643 tokens. Acting as a controller, it can call different contract rules and apply these rules on each transfer. -- Rules: - - There are two types of rules in our RuleEngine implementation: validation and operation rules. - - Validation rules are read-only rules. These rules cannot update the state of the blockchain during a transfer call; they can only read information from the blockchain. - - The second type of rules, known as operation rules, can also modify the state of the blockchain (write) during a transfer call. +Each rule can be used **standalone**, directly plugged into a CMTAT token, **or** managed collectively via a RuleEngine. -## Rules details +**Status:** *Repository under active development* + +## Overview + +The **RuleEngine** is an external smart contract that applies transfer restrictions to security tokens such as **CMTAT** or ERC-3643-compatible tokens through a RuleEngine. +Rules are modular validator contracts that the `RuleEngine` or `CMTAT` compatible token can call on every transfer to ensure regulatory and business-logic compliance. + +### Key Concepts + +- **Rules are controllers** that validate or modify token transfers. +- They can be applied: + - Directly on **CMTAT** (no RuleEngine required), **or** + - Through the **RuleEngine** (for multi-rule orchestration). +- Rules enforce conditions such as: + - Whitelisting / blacklisting + - Sanctions checks + - Multi-party operator-managed lists + - Conditional approvals + - Arbitrary compliance logic + +## Compatibility + +| Component | Compatible Versions | +| ---------------- | ----------------------------------------- | +| **Rules v0.1.0** | CMTAT ≥ v3.0.0
RuleEngine v3.0.0-rc0 | + +Each Rule implements the interface `IRuleEngine` defined in CMTAT. + +This interface declares the ERC-3643 functions `transferred`(read-write) and `canTransfer`(ready-only) with several other functions related to [ERC-1404](https://github.com/ethereum/eips/issues/1404), [ERC-7551](https://ethereum-magicians.org/t/erc-7551-crypto-security-token-smart-contract-interface-ewpg-reworked/25477) and [ERC-3643](https://eips.ethereum.org/EIPS/eip-3643). + +### ERC-3643 + +Each rule implements the following functions from the ERC-3643 `ICompliance`interface + +```solidity +function canTransfer(address _from, address _to, uint256 _amount) external view returns (bool); +function transferred(address _from, address _to, uint256 _amount) external; +``` + +However, contrary to the RuleEngine, the whole interface is currently not implemented (e.g. `created`and `destroyed`) and as a result, the rule can not directly supported ERC-3643 token. + +The alternative to use a Rule with an ERC-3643 token is trough the RuleEngine, which implements the whole `ICompliance` interface. + +## Architecture + +### 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 | +| | CODE_ADDRESS_TO_NOT_WHITELISTED | 22 | +| | CODE_ADDRESS_SPENDER_NOT_WHITELISTED | 23 | +| | Free slot | 24-29 | +| RuleSanctionList | CODE_ADDRESS_FROM_IS_SANCTIONED | 30 | +| | CODE_ADDRESS_TO_IS_SANCTIONED | 31 | +| | CODE_ADDRESS_SPENDER_IS_SANCTIONED | 32 | +| | Free slot | 33-35 | +| RuleBlacklist | CODE_ADDRESS_FROM_IS_BLACKLISTED | 36 | +| | CODE_ADDRESS_TO_IS_BLACKLISTED | 37 | +| | CODE_ADDRESS_SPENDER_IS_BLACKLISTED | 38 | +| | Free slot | 39-44 | +| RuleConditionalTransfer | CODE_TRANSFER_REQUEST_NOT_APPROVED | 45 | +| | Free slot | 46-50 | + +Note: + +- The CMTAT already uses the code 0-6 and the code 7-12 should be left free to allow further additions in the CMTAT. +- If you decide to create your own rules, we encourage you to use code > 100 to leave free the other restriction codes for future rules added in this project. + +### Rules as Standalone Compliance Contracts + +Every rule implements the minimal interface expected by **CMTAT**, notably: + +```solidity +function transferred(address from, address to, uint256 value) +function transferred(address spender, address from, address to, uint256 value) +``` + +This makes rules directly pluggable into CMTAT without any intermediary RuleEngine. + +### Using Rules via RuleEngine +When used through the RuleEngine, a rule must also implement: +```solidity +interface IRule is IRuleEngine { + function canReturnTransferRestrictionCode(uint8 restrictionCode) + external + view + returns (bool); +} +``` + +The RuleEngine can then: + +- Aggregate multiple rules +- Execute them sequentially on each transfer +- Return restriction codes +- Mutate rule state (operation rules) + +#### CMTAT + +Each rule can be directly plugged to a CMTAT token similar to a RuleEngine. + +Indeed, each rules implements the required interface (`IRuleEngine`) with notably the following function as entrypoint. + +```solidity +function transferred(address from,address to,uint256 value) +function transferred(address spender,address from,address to,uint256 value) +``` + +```solidity +/* +* @title Minimum interface to define a RuleEngine +*/ +interface IRuleEngine is IERC1404Extend, IERC7551Compliance, IERC3643IComplianceContract { + /** + * @notice + * Function called whenever tokens are transferred from one wallet to another + * @dev + * Must revert if the transfer is invalid + * Same name as ERC-3643 but with one supplementary argument `spender` + * This function can be used to update state variables of the RuleEngine contract + * This function can be called ONLY by the token contract bound to the RuleEngine + * @param spender spender address (sender) + * @param from token holder address + * @param to receiver address + * @param value value of tokens involved in the transfer + */ + function transferred(address spender, address from, address to, uint256 value) external; +} +``` + + + +#### RuleEngine + +For a RuleEngine, each rule implements also the required entry point similar to CMTAT, and as well some specific interface for the RuleEngine through the implementation of `IRule`interface dfeined in the RuleEngine repository + +```solidity +interface IRule is IRuleEngine { + /** + * @dev Returns true if the restriction code exists, and false otherwise. + */ + function canReturnTransferRestrictionCode( + uint8 restrictionCode + ) external view returns (bool); +} + +``` + + + +## Types of Rules + +There are two categories of rules: validation rules (Read-only) and operation rules (read-write). + +### Validation Rules (Read-Only) + +- Cannot modify blockchain state during transfers. +- Used for simple eligibility checks. +- Examples: + - Whitelist + - Whitelist Wrapper + - Blacklist + - Sanction list (Chainalysis) + +### Operation Rules (Read-Write) + +- Can update state during transfer calls. +- Example: + - Conditional Transfer (approval-based) + +## Rules details -### Validation rule +### Read-only (validation) rule Currently, there are four validation rules: whitelist, whitelistWrapper, blacklist, and sanctionlist. #### Whitelist -With a whitelist rule, only whitelisted addresses can hold the token. Thus, a transfer will fail if either the origin (current token holder) or the destination is not in the list. +Only whitelisted addresses may hold or receive tokens. + Transfers are rejected if: + +- `from` is not whitelisted +- `to` is not whitelisted + +The rule is read-only: it only checks stored state. + +**Example** During a transfer, this rule, called by the RuleEngine, will check if the address concerned is in the list, applying a read operation on the blockchain. +![surya_inheritance_RuleWhitelist.sol](./doc/surya/surya_inheritance/surya_inheritance_RuleWhitelist.sol.png) + #### Whitelist wrapper -This rule can be used to restrict transfers only from/to addresses inside a group of whitelist rules managed by different operators. Thus, each operator can manage independently their own whitelist. Here is an explanation schema: +Allows independent whitelist groups managed by different operators. + +- Each operator manages a dedicated whitelist. +- A transfer is allowed only if both addresses belong to *at least one* operator-managed list. +- Enables multi-party compliance + + + +##### 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 `setRules` or `addRule`. + + + +![surya_inheritance_RuleWhitelistWrapper.sol](./doc/surya/surya_inheritance/surya_inheritance_RuleWhitelistWrapper.sol.png) + + #### Blacklist -The blacklist rule works similarly to the whitelist rule but in the opposite way. With this rule, the addresses must not be on the list to allow the transfer to succeed. +Opposite of whitelist: + +- Transfer fails if **either** address is blacklisted. + +![surya_inheritance_RuleWhitelistWrapper.sol](./doc/surya/surya_inheritance/surya_inheritance_RuleBlacklist.sol.png) #### Sanction list with Chainalysis -The purpose of this contract is to use the oracle contract from [Chainalysis](https://www.chainalysis.com/) to forbid transfers from/to an address included in a sanctions designation (US, EU, or UN). Documentation and the contracts addresses are available here: [Chainalysis oracle for sanctions screening](https://go.chainalysis.com/chainalysis-oracle-docs.html). +Uses the [Chainalysis](https://www.chainalysis.com/) Oracle to reject transfers involving sanctioned addresses. + +- Checks lists for: **US**, **EU**, and **UN** sanctions. +- Documentation: *Chainalysis Oracle for sanctions screening* +- If `from` or `to` is sanctioned, transfer is rejected. + +Documentation and the contracts addresses are available here: [Chainalysis oracle for sanctions screening](https://go.chainalysis.com/chainalysis-oracle-docs.html). + +**Example** During a transfer, if either address (from or to) is in the sanction list of the Oracle, the rule will return false, and the transfer will be rejected by the CMTAT. -### Operation rule -For the moment, there is only one operation rule available: ConditionalTransfer. -Currently, we only have one operation rule: *ConditionalTransfer*. This rule requires that transfers must be approved before being executed by the token holders. During the transfer call, the rule will check if the transfer has been approved. If it has, the approval will be removed since the transfer has been processed, applying a write operation on the blockchain. +![surya_inheritance_RuleWhitelistWrapper.sol](./doc/surya/surya_inheritance/surya_inheritance_RuleSanctionList.sol.png) + +### Read-Write (Operation) rule + +For the moment, there is only one operation rule available: ConditionalTransfer. #### Conditional transfer +> This rule has been moved to a dedicated repository: [RuleConditionalTransfer](https://github.com/CMTA/RuleConditionalTransfer) + +This rule requires that transfers must be approved before being executed by the token holders. During the transfer call, the rule will check if the transfer has been approved. If it has, the approval will be removed since the transfer has been processed, applying a write operation on the blockchain. + This rule requires that transfers be approved by the token holders before being executed. Initially, this rule was designed to implement a specific requirement in Swiss law (Vinkulierung), but it has since been generalized to be more flexible. @@ -56,93 +270,927 @@ We have added another option, not required by Swiss law, to automatically perfor Reference: [Taurus - Token Transfer Management: How to Apply Restrictions with CMTAT and ERC-1404](https://www.taurushq.com/blog/token-transfer-management-how-to-apply-restrictions-with-cmtat-and-erc-1404/) -## Dependencies -The toolchain includes the following components, where the versions are the latest ones that we tested: -- Foundry [v1.9.4](https://github.com/foundry-rs/forge-std/releases/tag/v1.9.4) -- Solidity 0.8.30 (via solc-js) -- OpenZeppelin Contracts (submodule) [v5.3.0](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.3.0) -- CMTAT [v3.0.0](https://github.com/CMTA/CMTAT) - - This repository includes the RuleEngine contract for the [CMTAT](https://github.com/CMTA/CMTAT) token. +## Access Control +The modules `AccessControlModuleStandalone` allows to implement RBAC access control by inheriting from the contract `AccessControl`from OpenZeppelin. -The RuleEngine is an external contract used to apply transfer restrictions to another contract, initially the CMTAT. Acting as a controller, it can call different contract rules and apply these rules on each transfer. +This module overrides the OpenZeppelin function `hasRole`to give by default all the roles to the `admin`. -## Dependencies +Each rule implements its own access control by inheriting from the module `AccessControlModuleStandalone`. -The toolchain includes the following components, where the versions are the latest ones that we tested: +For all rules, the default admin is the address put in argument(`admin`) inside the constructor and set when the contract is deployed. -- Foundry [v1.9.4](https://github.com/foundry-rs/forge-std/releases/tag/v1.9.4) -- Solidity 0.8.30 (via solc-js) -- OpenZeppelin Contracts (submodule) [v5.3.0](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.3.0) -- CMTAT [v3.0.0](https://github.com/CMTA/CMTAT) +See also [docs.openzeppelin.com - AccessControl](https://docs.openzeppelin.com/contracts/5.x/api/access#AccessControl) +### Address List +Common access control between `blacklistRule`and `WhitelistRule` -## Foundry +Here a schema of the Access Control. +![alt text](./doc/security/accessControl/access-control-RuleWhitelist.png) -**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** -Foundry consists of: -- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). -- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. -- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. -- **Chisel**: Fast, utilitarian, and verbose solidity REPL. +### RuleSanctionList -## Documentation +![alt text](./doc/security/accessControl/access-control-RuleSanctionList.drawio.png) -https://book.getfoundry.sh/ -## Usage -### Build +## Toolchains and Usage -```shell -$ forge build +*Explain how it works.* + +### Configuration + +Here are the settings for [Hardhat](https://hardhat.org) and [Foundry](https://getfoundry.sh). + +- `hardhat.config.js` + + - Solidity [v0.8.30](https://docs.soliditylang.org/en/v0.8.30/) + - EVM version: Prague (Pectra upgrade) + - Optimizer: true, 200 runs + +- `foundry.toml` + + - Solidity [v0.8.30](https://docs.soliditylang.org/en/v0.8.30/) + - EVM version: Prague (Pectra upgrade) + - Optimizer: true, 200 runs + +- Library + + - Foundry [v1.5.0](https://github.com/foundry-rs/foundry) + + - Forge std [v1.12.0](https://github.com/foundry-rs/forge-std/releases/tag/v1.12.0 ) + + - OpenZeppelin Contracts (submodule) [v5.5.0](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.5.0) + + - CMTAT [v3.0.0](https://github.com/CMTA/CMTAT) + + - RuleEngine [v3.0.0-rc0](https://github.com/CMTA/RuleEngine/releases/tag/v3.0.0-rc0) + +### Toolchain installation + +The contracts are developed and tested with [Foundry](https://book.getfoundry.sh), a smart contract development toolchain. + +To install the Foundry suite, please refer to the official instructions in the [Foundry book](https://book.getfoundry.sh/getting-started/installation). + +### Initialization + +You must first initialize the submodules, with + +``` +forge install ``` -### Test +See also the command's [documentation](https://book.getfoundry.sh/reference/forge/forge-install). -```shell -$ forge test +Later you can update all the submodules with: + +``` +forge update ``` -### Format +See also the command's [documentation](https://book.getfoundry.sh/reference/forge/forge-update). + +#### CMTAT + +You also have to install OpenZeppelin inside CMTAT repository (submodule) + +```bash +cd CMTAT +npm install +``` + + + +### Compilation + +The official documentation is available in the Foundry [website](https://book.getfoundry.sh/reference/forge/build-commands) + +``` + forge build +``` + +### Contract size + +```bash + forge compile --sizes +``` + +### Testing + +You can run the tests with + +```bash +forge test +``` + +To run a specific test, use + +```bash +forge test --match-contract --match-test +``` + +Generate gas report + +```bash +forge test --gas-report +``` + +See also the test framework's [official documentation](https://book.getfoundry.sh/forge/tests), and that of the [test commands](https://book.getfoundry.sh/reference/forge/test-commands). + +### Coverage + +A code coverage is available in [index.html](./doc/coverage/coverage/index.html). + +* Perform a code coverage + +``` +forge coverage +``` + +* Generate LCOV report + +``` +forge coverage --report lcov +``` + +- Generate `index.html` + +```bash +forge coverage --no-match-coverage "(script|mocks|test)" --report lcov && genhtml lcov.info --branch-coverage --output-dir coverage +``` + +See [Solidity Coverage in VS Code with Foundry](https://mirror.xyz/devanon.eth/RrDvKPnlD-pmpuW7hQeR5wWdVjklrpOgPCOA-PJkWFU) & [Foundry forge coverage]( + +### Other + +Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.* + +Foundry consists of: + +- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). +- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. +- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. +- **Chisel**: Fast, utilitarian, and verbose solidity REPL. + +#### Documentation + +https://book.getfoundry.sh/ + +#### Format ```shell $ forge fmt ``` -### Gas Snapshots +#### Gas Snapshots ```shell $ forge snapshot ``` -### Anvil +#### Anvil ```shell $ anvil ``` -### Deploy +#### Deploy ```shell $ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key ``` -### Cast +#### Cast ```shell $ cast ``` -### 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 @@ - - + + - +
Current view:top level - src/rules/validation/abstract - RuleWhitelistCommon.sol (source / functions)top level - home/ryan/Pictures/dev/Rules/src/modules - AccessControlModuleStandalone.sol (source / functions) Hit
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions: 2 Branches:4433 100.0 %
- - + + - - + + - - + +

Function Name Sort by function nameHit count Sort by hit countFunction Name Sort by function nameHit count Sort by hit count
RuleWhitelistCommon.canReturnTransferRestrictionCode12AccessControlModuleStandalone.constructor161
RuleWhitelistCommon.messageForTransferRestriction10AccessControlModuleStandalone.hasRole228

- +
Generated by: LCOV version 1.16

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 @@ - - + + - +
Current view:top level - src/rules/validation/abstract - RuleWhitelistCommon.sol (source / functions)top level - home/ryan/Pictures/dev/Rules/src/modules - AccessControlModuleStandalone.sol (source / functions) Hit
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions: 2 Branches:4433 100.0 %
- - + + - - + + - - + +

Function Name Sort by function nameHit count Sort by hit countFunction Name Sort by function nameHit count Sort by hit count
RuleWhitelistCommon.messageForTransferRestriction10AccessControlModuleStandalone.constructor161
RuleWhitelistCommon.canReturnTransferRestrictionCode12AccessControlModuleStandalone.hasRole228

- +
Generated by: LCOV version 1.16

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 @@ - - + + - +
Current view:top level - src/rules/validation/abstract - RuleWhitelistCommon.sol (source / functions)top level - home/ryan/Pictures/dev/Rules/src/modules - AccessControlModuleStandalone.sol (source / functions) Hit
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions: 2 Branches:4433 100.0 %
@@ -69,47 +69,52 @@ @@ -117,7 +122,7 @@
           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                 :            : }
 
- +
Generated by: LCOV version 1.16

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 @@ - - + + - +
Current view:top level - src/rules/operation/abstracttop level - /home/ryan/Pictures/dev/Rules/src/modules Hitlcov.info Lines:11311388 100.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:202022 100.0 %
Branches:313133 100.0 %
@@ -76,29 +76,29 @@ - Filename Sort by name - Line Coverage Sort by line coverage - Functions Sort by function coverage - Branches Sort by branch coverage + Filename Sort by name + Line Coverage Sort by line coverage + Functions Sort by function coverage + Branches Sort by branch coverage - RuleConditionalTransferOperator.sol + AccessControlModuleStandalone.sol -
100.0%
+
100.0%
100.0 % - 113 / 113 + 8 / 8 100.0 % - 20 / 20 + 2 / 2 100.0 % - 31 / 31 + 3 / 3

- +
Generated by: LCOV version 1.16

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 @@ - - + + - +
Current view:top level - src/rules/operation/abstracttop level - /home/ryan/Pictures/dev/Rules/src/modules Hitlcov.info Lines:11311388 100.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:202022 100.0 %
Branches:313133 100.0 %
@@ -76,29 +76,29 @@ - Filename Sort by name - Line Coverage Sort by line coverage - Functions Sort by function coverage - Branches Sort by branch coverage + Filename Sort by name + Line Coverage Sort by line coverage + Functions Sort by function coverage + Branches Sort by branch coverage - RuleConditionalTransferOperator.sol + AccessControlModuleStandalone.sol -
100.0%
+
100.0%
100.0 % - 113 / 113 + 8 / 8 100.0 % - 20 / 20 + 2 / 2 100.0 % - 31 / 31 + 3 / 3

- +
Generated by: LCOV version 1.16

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 @@ - - + + - +
Current view:top level - src/rules/operation/abstracttop level - /home/ryan/Pictures/dev/Rules/src/modules Hitlcov.info Lines:11311388 100.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:202022 100.0 %
Branches:313133 100.0 %
@@ -76,29 +76,29 @@ - Filename Sort by name - Line Coverage Sort by line coverage - Functions Sort by function coverage - Branches Sort by branch coverage + Filename Sort by name + Line Coverage Sort by line coverage + Functions Sort by function coverage + Branches Sort by branch coverage - RuleConditionalTransferOperator.sol + AccessControlModuleStandalone.sol -
100.0%
+
100.0%
100.0 % - 113 / 113 + 8 / 8 100.0 % - 20 / 20 + 2 / 2 100.0 % - 31 / 31 + 3 / 3

- +
Generated by: LCOV version 1.16

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 @@ - - + + - +
Current view:top level - src/rules/operation/abstracttop level - /home/ryan/Pictures/dev/Rules/src/modules Hitlcov.info Lines:11311388 100.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:202022 100.0 %
Branches:313133 100.0 %
@@ -76,29 +76,29 @@ - Filename Sort by name - Line Coverage Sort by line coverage - Functions Sort by function coverage - Branches Sort by branch coverage + Filename Sort by name + Line Coverage Sort by line coverage + Functions Sort by function coverage + Branches Sort by branch coverage - RuleConditionalTransferOperator.sol + AccessControlModuleStandalone.sol -
100.0%
+
100.0%
100.0 % - 113 / 113 + 8 / 8 100.0 % - 20 / 20 + 2 / 2 100.0 % - 31 / 31 + 3 / 3

- +
Generated by: LCOV version 1.16

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 @@ lcov.info Lines: - 479 - 511 - 93.7 % + 230 + 253 + 90.9 % Date: - 2024-12-20 10:41:14 + 2025-12-03 15:05:37 Functions: - 117 - 125 - 93.6 % + 66 + 76 + 86.8 % Branches: - 126 - 128 - 98.4 % + 65 + 68 + 95.6 % @@ -82,124 +82,52 @@ Branches Sort by branch coverage - script + validation -
0.0%
+
89.9%89.9%
- 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 -
100.0%
+
91.3%91.3%
+ 91.3 % + 42 / 46 + 88.2 % + 15 / 17 100.0 % - 10 / 10 - 100.0 % - 1 / 1 - - - 0 / 0 + 2 / 2 - test/utils - -
85.7%85.7%
- - 85.7 % - 6 / 7 - 80.0 % - 4 / 5 - - - 0 / 0 - - - src/rules/validation/abstract + /home/ryan/Pictures/dev/Rules/src/modules
100.0%
100.0 % - 10 / 10 - 100.0 % - 3 / 3 - 100.0 % - 4 / 4 - - - src/rules/validation/abstract/RuleAddressList - -
97.8%97.8%
- - 97.8 % - 44 / 45 - 94.4 % - 17 / 18 - 100.0 % - 6 / 6 - - - src - -
97.4%97.4%
- - 97.4 % - 38 / 39 - 88.9 % - 8 / 9 - 100.0 % 8 / 8 - - - src/modules - -
100.0%
- - 100.0 % - 81 / 81 100.0 % - 27 / 27 + 2 / 2 100.0 % - 12 / 12 - - - src/rules/operation/abstract - -
100.0%
- - 100.0 % - 113 / 113 - 100.0 % - 20 / 20 - 100.0 % - 31 / 31 + 3 / 3 - src/rules/validation + validation/abstract -
97.3%97.3%
+
93.5%93.5%
- 97.3 % - 72 / 74 + 93.5 % + 29 / 31 90.9 % - 20 / 22 - 100.0 % - 32 / 32 - - - src/rules/operation - -
99.1%99.1%
- - 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 @@ lcov.info Lines: - 479 - 511 - 93.7 % + 230 + 253 + 90.9 % Date: - 2024-12-20 10:41:14 + 2025-12-03 15:05:37 Functions: - 117 - 125 - 93.6 % + 66 + 76 + 86.8 % Branches: - 126 - 128 - 98.4 % + 65 + 68 + 95.6 % @@ -82,124 +82,52 @@ Branches Sort by branch coverage - script + validation -
0.0%
+
89.9%89.9%
- 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%85.7%
+
91.3%91.3%
- 85.7 % - 6 / 7 - 80.0 % - 4 / 5 - - - 0 / 0 - - - src - -
97.4%97.4%
- - 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%97.3%
+
93.5%93.5%
- 97.3 % - 72 / 74 + 93.5 % + 29 / 31 90.9 % - 20 / 22 - 100.0 % - 32 / 32 - - - src/rules/validation/abstract/RuleAddressList - -
97.8%97.8%
- - 97.8 % - 44 / 45 - 94.4 % - 17 / 18 - 100.0 % - 6 / 6 - - - src/rules/operation - -
99.1%99.1%
- - 99.1 % - 105 / 106 - 94.4 % - 17 / 18 - 100.0 % - 33 / 33 - - - test/RuleConditionalTransfer/utils - -
100.0%
- + 10 / 11 100.0 % 10 / 10 - 100.0 % - 1 / 1 - - - 0 / 0 - - - src/rules/validation/abstract - -
100.0%
- - 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%
100.0 % - 113 / 113 - 100.0 % - 20 / 20 - 100.0 % - 31 / 31 - - - src/modules - -
100.0%
- - 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 @@ lcov.info Lines: - 479 - 511 - 93.7 % + 230 + 253 + 90.9 % Date: - 2024-12-20 10:41:14 + 2025-12-03 15:05:37 Functions: - 117 - 125 - 93.6 % + 66 + 76 + 86.8 % Branches: - 126 - 128 - 98.4 % + 65 + 68 + 95.6 % @@ -82,124 +82,52 @@ Branches Sort by branch coverage - script + validation -
0.0%
+
89.9%89.9%
- 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%85.7%
- - 85.7 % - 6 / 7 - 80.0 % - 4 / 5 - - - 0 / 0 - - - src/rules/validation - -
97.3%97.3%
- - 97.3 % - 72 / 74 - 90.9 % - 20 / 22 - 100.0 % - 32 / 32 - - - src - -
97.4%97.4%
- - 97.4 % - 38 / 39 - 88.9 % - 8 / 9 - 100.0 % - 8 / 8 - - - src/rules/validation/abstract/RuleAddressList - -
97.8%97.8%
- - 97.8 % - 44 / 45 - 94.4 % - 17 / 18 - 100.0 % - 6 / 6 - - - src/rules/operation - -
99.1%99.1%
- - 99.1 % - 105 / 106 - 94.4 % - 17 / 18 - 100.0 % - 33 / 33 - - - src/rules/validation/abstract - -
100.0%
+
91.3%91.3%
+ 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 -
100.0%
+
93.5%93.5%
+ 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%
100.0 % - 81 / 81 - 100.0 % - 27 / 27 - 100.0 % - 12 / 12 - - - src/rules/operation/abstract - -
100.0%
- - 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 @@ lcov.info Lines: - 479 - 511 - 93.7 % + 230 + 253 + 90.9 % Date: - 2024-12-20 10:41:14 + 2025-12-03 15:05:37 Functions: - 117 - 125 - 93.6 % + 66 + 76 + 86.8 % Branches: - 126 - 128 - 98.4 % + 65 + 68 + 95.6 % @@ -82,124 +82,52 @@ Branches Sort by branch coverage - script - -
0.0%
- - 0.0 % - 0 / 26 - 0.0 % - 0 / 2 - 0.0 % - 0 / 2 - - - src - -
97.4%97.4%
- - 97.4 % - 38 / 39 - 88.9 % - 8 / 9 - 100.0 % - 8 / 8 - - - src/modules + /home/ryan/Pictures/dev/Rules/src/modules
100.0%
100.0 % - 81 / 81 - 100.0 % - 27 / 27 + 8 / 8 100.0 % - 12 / 12 - - - src/rules/operation - -
99.1%99.1%
- - 99.1 % - 105 / 106 - 94.4 % - 17 / 18 + 2 / 2 100.0 % - 33 / 33 + 3 / 3 - src/rules/operation/abstract + validation -
100.0%
+
89.9%89.9%
- 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%97.3%
+
93.5%93.5%
- 97.3 % - 72 / 74 + 93.5 % + 29 / 31 90.9 % - 20 / 22 - 100.0 % - 32 / 32 - - - src/rules/validation/abstract - -
100.0%
- + 10 / 11 100.0 % 10 / 10 - 100.0 % - 3 / 3 - 100.0 % - 4 / 4 - src/rules/validation/abstract/RuleAddressList + validation/abstract/RuleAddressSet -
97.8%97.8%
+
91.3%91.3%
- 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%
- - 100.0 % - 10 / 10 - 100.0 % - 1 / 1 - - - 0 / 0 - - - test/utils - -
85.7%85.7%
- - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - script - CMTATWithRuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0140.0 %
Date:2024-12-20 10:41:14Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
CMTATWithRuleEngineScript.run0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - script - CMTATWithRuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0140.0 %
Date:2024-12-20 10:41:14Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
CMTATWithRuleEngineScript.run0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - script - CMTATWithRuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0140.0 %
Date:2024-12-20 10:41:14Functions:010.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: UNLICENSED
-       2                 :            : // Documentation :
-       3                 :            : // https://book.getfoundry.sh/tutorials/solidity-scripting
-       4                 :            : pragma solidity ^0.8.17;
-       5                 :            : 
-       6                 :            : import "forge-std/Script.sol";
-       7                 :            : import "../test/HelperContract.sol";
-       8                 :            : import "src/RuleEngine.sol";
-       9                 :            : import "src/rules/validation/RuleWhitelist.sol";
-      10                 :            : 
-      11                 :            : /**
-      12                 :            : @title Deploy a CMTAT, a RuleWhitelist and a RuleEngine
-      13                 :            : */
-      14                 :            : contract CMTATWithRuleEngineScript is Script, HelperContract {
-      15                 :            :     function run() external {
-      16                 :            :         // Get env variable
-      17                 :          0 :         uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
-      18                 :          0 :         address ADMIN = vm.addr(deployerPrivateKey);
-      19                 :          0 :         address trustedForwarder = address(0x0);
-      20                 :          0 :         vm.startBroadcast(deployerPrivateKey);
-      21                 :            :         // CMTAT
-      22                 :          0 :         cmtatDeployment = new CMTATDeployment();
-      23                 :          0 :         CMTAT_CONTRACT = cmtatDeployment.cmtat();
-      24                 :          0 :         console.log("CMTAT CMTAT_CONTRACT : ", address(CMTAT_CONTRACT));
-      25                 :            :         // whitelist
-      26                 :          0 :         RuleWhitelist ruleWhitelist = new RuleWhitelist(
-      27                 :            :             ADMIN,
-      28                 :            :             trustedForwarder
-      29                 :            :         );
-      30                 :          0 :         console.log("whitelist: ", address(ruleWhitelist));
-      31                 :            :         // ruleEngine
-      32                 :          0 :         RuleEngine RULE_ENGINE = new RuleEngine(
-      33                 :            :             ADMIN,
-      34                 :            :             trustedForwarder,
-      35                 :            :             address(CMTAT_CONTRACT)
-      36                 :            :         );
-      37                 :          0 :         console.log("RuleEngine : ", address(RULE_ENGINE));
-      38                 :          0 :         RULE_ENGINE.addRuleValidation(ruleWhitelist);
-      39                 :          0 :         CMTAT_CONTRACT.setRuleEngine(RULE_ENGINE);
-      40                 :            : 
-      41                 :          0 :         vm.stopBroadcast();
-      42                 :            :     }
-      43                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - script - RuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2024-12-20 10:41:14Functions:010.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleEngineScript.run0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - script - RuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2024-12-20 10:41:14Functions:010.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleEngineScript.run0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - script - RuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2024-12-20 10:41:14Functions:010.0 %
Branches:020.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: UNLICENSED
-       2                 :            : // Documentation :
-       3                 :            : // https://book.getfoundry.sh/tutorials/solidity-scripting
-       4                 :            : pragma solidity ^0.8.17;
-       5                 :            : 
-       6                 :            : import "forge-std/Script.sol";
-       7                 :            : import "CMTAT/CMTAT_STANDALONE.sol";
-       8                 :            : import "src/RuleEngine.sol";
-       9                 :            : import "src/rules/validation/RuleWhitelist.sol";
-      10                 :            : import "CMTAT/modules/wrapper/controllers/ValidationModule.sol";
-      11                 :            : 
-      12                 :            : /**
-      13                 :            : @title Deploy a RuleWhitelist and a RuleEngine. The CMTAT is considred already deployed
-      14                 :            : */
-      15                 :            : contract RuleEngineScript is Script {
-      16                 :            :     function run() external {
-      17                 :            :         // Get env variable
-      18                 :          0 :         uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
-      19                 :          0 :         address ADMIN = vm.addr(deployerPrivateKey);
-      20                 :          0 :         address CMTAT_Address = vm.envAddress("CMTAT_ADDRESS");
-      21                 :          0 :         vm.startBroadcast(deployerPrivateKey);
-      22                 :            :         //whitelist
-      23                 :          0 :         RuleWhitelist ruleWhitelist = new RuleWhitelist(ADMIN, address(0));
-      24                 :          0 :         console.log("whitelist: ", address(ruleWhitelist));
-      25                 :            :         // ruleEngine
-      26                 :          0 :         RuleEngine RULE_ENGINE = new RuleEngine(ADMIN, address(0), address(0));
-      27                 :          0 :         console.log("RuleEngine: ", address(RULE_ENGINE));
-      28                 :          0 :         RULE_ENGINE.addRuleValidation(ruleWhitelist);
-      29                 :            :         // Configure the new ruleEngine for CMTAT
-      30                 :          0 :         (bool success, ) = address(CMTAT_Address).call(
-      31                 :            :             abi.encodeCall(ValidationModule.setRuleEngine, RULE_ENGINE)
-      32                 :            :         );
-      33         [ #  # ]:          0 :         require(success);
-      34                 :          0 :         vm.stopBroadcast();
-      35                 :            :     }
-      36                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - scriptHitTotalCoverage
Test:lcov.infoLines:0260.0 %
Date:2024-12-20 10:41:14Functions:020.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 10.0 %0 / 2
CMTATWithRuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 140.0 %0 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - scriptHitTotalCoverage
Test:lcov.infoLines:0260.0 %
Date:2024-12-20 10:41:14Functions:020.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
CMTATWithRuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 140.0 %0 / 1-0 / 0
RuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 10.0 %0 / 2
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - scriptHitTotalCoverage
Test:lcov.infoLines:0260.0 %
Date:2024-12-20 10:41:14Functions:020.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 10.0 %0 / 2
CMTATWithRuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 140.0 %0 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - scriptHitTotalCoverage
Test:lcov.infoLines:0260.0 %
Date:2024-12-20 10:41:14Functions:020.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
CMTATWithRuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 140.0 %0 / 1-0 / 0
RuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 10.0 %0 / 2
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modules - RuleEngineOperation.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2525100.0 %
Date:2024-12-20 10:41:14Functions:1111100.0 %
Branches:22100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleEngineOperation.ruleOperation1
RuleEngineOperation.getRuleIndexOperation3
RuleEngineOperation.clearRulesOperation4
RuleEngineOperation.removeRuleOperation5
RuleEngineOperation.rulesOperation5
RuleEngineOperation.setRulesOperation11
RuleEngineOperation._clearRulesOperation14
RuleEngineOperation._removeRuleOperation22
RuleEngineOperation.rulesCountOperation41
RuleEngineOperation._operateOnTransfer58
RuleEngineOperation.addRuleOperation85
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modules - RuleEngineOperation.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2525100.0 %
Date:2024-12-20 10:41:14Functions:1111100.0 %
Branches:22100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleEngineOperation._clearRulesOperation14
RuleEngineOperation._operateOnTransfer58
RuleEngineOperation._removeRuleOperation22
RuleEngineOperation.addRuleOperation85
RuleEngineOperation.clearRulesOperation4
RuleEngineOperation.getRuleIndexOperation3
RuleEngineOperation.removeRuleOperation5
RuleEngineOperation.ruleOperation1
RuleEngineOperation.rulesCountOperation41
RuleEngineOperation.rulesOperation5
RuleEngineOperation.setRulesOperation11
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modules - RuleEngineOperation.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2525100.0 %
Date:2024-12-20 10:41:14Functions:1111100.0 %
Branches:22100.0 %
-
- - - - - - - - -

-
           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                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modules - RuleEngineValidation.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:88100.0 %
Date:2024-12-20 10:41:14Functions:22100.0 %
Branches:11100.0 %
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleEngineValidation.validateTransferValidation2
RuleEngineValidation.detectTransferRestrictionValidation3
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modules - RuleEngineValidation.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:88100.0 %
Date:2024-12-20 10:41:14Functions:22100.0 %
Branches:11100.0 %
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleEngineValidation.detectTransferRestrictionValidation3
RuleEngineValidation.validateTransferValidation2
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modules - RuleEngineValidation.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:88100.0 %
Date:2024-12-20 10:41:14Functions:22100.0 %
Branches:11100.0 %
-
- - - - - - - - -

-
           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                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modules - RuleEngineValidationCommon.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1919100.0 %
Date:2024-12-20 10:41:14Functions:1010100.0 %
Branches:11100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleEngineValidationCommon.ruleValidation1
RuleEngineValidationCommon.getRuleIndexValidation3
RuleEngineValidationCommon.rulesValidation5
RuleEngineValidationCommon.clearRulesValidation6
RuleEngineValidationCommon.removeRuleValidation6
RuleEngineValidationCommon.setRulesValidation22
RuleEngineValidationCommon._clearRulesValidation25
RuleEngineValidationCommon._removeRuleValidation33
RuleEngineValidationCommon.rulesCountValidation69
RuleEngineValidationCommon.addRuleValidation119
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modules - RuleEngineValidationCommon.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1919100.0 %
Date:2024-12-20 10:41:14Functions:1010100.0 %
Branches:11100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleEngineValidationCommon._clearRulesValidation25
RuleEngineValidationCommon._removeRuleValidation33
RuleEngineValidationCommon.addRuleValidation119
RuleEngineValidationCommon.clearRulesValidation6
RuleEngineValidationCommon.getRuleIndexValidation3
RuleEngineValidationCommon.removeRuleValidation6
RuleEngineValidationCommon.ruleValidation1
RuleEngineValidationCommon.rulesCountValidation69
RuleEngineValidationCommon.rulesValidation5
RuleEngineValidationCommon.setRulesValidation22
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modulesHitTotalCoverage
Test:lcov.infoLines:8181100.0 %
Date:2024-12-20 10:41:14Functions:2727100.0 %
Branches:1212100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngineValidationCommon.sol -
100.0%
-
100.0 %19 / 19100.0 %10 / 10100.0 %1 / 1
RuleEngineValidation.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %1 / 1
RuleEngineOperation.sol -
100.0%
-
100.0 %25 / 25100.0 %11 / 11100.0 %2 / 2
RuleInternal.sol -
100.0%
-
100.0 %29 / 29100.0 %4 / 4100.0 %8 / 8
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modulesHitTotalCoverage
Test:lcov.infoLines:8181100.0 %
Date:2024-12-20 10:41:14Functions:2727100.0 %
Branches:1212100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngineValidation.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %1 / 1
RuleInternal.sol -
100.0%
-
100.0 %29 / 29100.0 %4 / 4100.0 %8 / 8
RuleEngineValidationCommon.sol -
100.0%
-
100.0 %19 / 19100.0 %10 / 10100.0 %1 / 1
RuleEngineOperation.sol -
100.0%
-
100.0 %25 / 25100.0 %11 / 11100.0 %2 / 2
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modulesHitTotalCoverage
Test:lcov.infoLines:8181100.0 %
Date:2024-12-20 10:41:14Functions:2727100.0 %
Branches:1212100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngineValidation.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %1 / 1
RuleEngineValidationCommon.sol -
100.0%
-
100.0 %19 / 19100.0 %10 / 10100.0 %1 / 1
RuleEngineOperation.sol -
100.0%
-
100.0 %25 / 25100.0 %11 / 11100.0 %2 / 2
RuleInternal.sol -
100.0%
-
100.0 %29 / 29100.0 %4 / 4100.0 %8 / 8
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modulesHitTotalCoverage
Test:lcov.infoLines:8181100.0 %
Date:2024-12-20 10:41:14Functions:2727100.0 %
Branches:1212100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngineOperation.sol -
100.0%
-
100.0 %25 / 25100.0 %11 / 11100.0 %2 / 2
RuleEngineValidation.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %1 / 1
RuleEngineValidationCommon.sol -
100.0%
-
100.0 %19 / 19100.0 %10 / 10100.0 %1 / 1
RuleInternal.sol -
100.0%
-
100.0 %29 / 29100.0 %4 / 4100.0 %8 / 8
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation - RuleConditionalTransfer.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:10510699.1 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:3333100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleConditionalTransfer._msgData0
RuleConditionalTransfer.canReturnTransferRestrictionCode2
RuleConditionalTransfer.cancelTransferRequestBatch3
RuleConditionalTransfer.createTransferRequestBatch3
RuleConditionalTransfer.messageForTransferRestriction3
RuleConditionalTransfer.cancelTransferRequest6
RuleConditionalTransfer._cancelTransferRequest9
RuleConditionalTransfer.getRequestByStatus35
RuleConditionalTransfer.operateOnTransfer50
RuleConditionalTransfer.detectTransferRestriction56
RuleConditionalTransfer.getRequestTrade57
RuleConditionalTransfer._validateApproval97
RuleConditionalTransfer._validateBurnMint103
RuleConditionalTransfer._validateTransfer106
RuleConditionalTransfer.createTransferRequest114
RuleConditionalTransfer.158
RuleConditionalTransfer._contextSuffixLength829
RuleConditionalTransfer._msgSender829
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation - RuleConditionalTransfer.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:10510699.1 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:3333100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleConditionalTransfer.158
RuleConditionalTransfer._cancelTransferRequest9
RuleConditionalTransfer._contextSuffixLength829
RuleConditionalTransfer._msgData0
RuleConditionalTransfer._msgSender829
RuleConditionalTransfer._validateApproval97
RuleConditionalTransfer._validateBurnMint103
RuleConditionalTransfer._validateTransfer106
RuleConditionalTransfer.canReturnTransferRestrictionCode2
RuleConditionalTransfer.cancelTransferRequest6
RuleConditionalTransfer.cancelTransferRequestBatch3
RuleConditionalTransfer.createTransferRequest114
RuleConditionalTransfer.createTransferRequestBatch3
RuleConditionalTransfer.detectTransferRestriction56
RuleConditionalTransfer.getRequestByStatus35
RuleConditionalTransfer.getRequestTrade57
RuleConditionalTransfer.messageForTransferRestriction3
RuleConditionalTransfer.operateOnTransfer50
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation - RuleConditionalTransfer.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:10510699.1 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:3333100.0 %
-
- - - - - - - - -

-
           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                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation/abstract - RuleConditionalTransferOperator.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:113113100.0 %
Date:2024-12-20 10:41:14Functions:2020100.0 %
Branches:3131100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch3
RuleConditionalTransferOperator.resetRequestStatus3
RuleConditionalTransferOperator.resetRequestStatusBatch3
RuleConditionalTransferOperator.setAutomaticTransfer4
RuleConditionalTransferOperator.approveTransferRequestWithId5
RuleConditionalTransferOperator.setTimeLimit5
RuleConditionalTransferOperator.createTransferRequestWithApproval6
RuleConditionalTransferOperator.approveTransferRequestBatch7
RuleConditionalTransferOperator.approveTransferRequestBatchWithId7
RuleConditionalTransferOperator.setIssuanceOptions7
RuleConditionalTransferOperator._resetRequestStatus10
RuleConditionalTransferOperator.setAutomaticApproval10
RuleConditionalTransferOperator._createTransferRequestWithApproval17
RuleConditionalTransferOperator._updateProcessedTransfer18
RuleConditionalTransferOperator.setConditionalWhitelist26
RuleConditionalTransferOperator.approveTransferRequest40
RuleConditionalTransferOperator._approveTransferRequestKeyElement48
RuleConditionalTransferOperator._approveRequest53
RuleConditionalTransferOperator._checkRequestStatus133
RuleConditionalTransferOperator.hasRole310
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation/abstract - RuleConditionalTransferOperator.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:113113100.0 %
Date:2024-12-20 10:41:14Functions:2020100.0 %
Branches:3131100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleConditionalTransferOperator._approveRequest53
RuleConditionalTransferOperator._approveTransferRequestKeyElement48
RuleConditionalTransferOperator._checkRequestStatus133
RuleConditionalTransferOperator._createTransferRequestWithApproval17
RuleConditionalTransferOperator._resetRequestStatus10
RuleConditionalTransferOperator._updateProcessedTransfer18
RuleConditionalTransferOperator.approveTransferRequest40
RuleConditionalTransferOperator.approveTransferRequestBatch7
RuleConditionalTransferOperator.approveTransferRequestBatchWithId7
RuleConditionalTransferOperator.approveTransferRequestWithId5
RuleConditionalTransferOperator.createTransferRequestWithApproval6
RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch3
RuleConditionalTransferOperator.hasRole310
RuleConditionalTransferOperator.resetRequestStatus3
RuleConditionalTransferOperator.resetRequestStatusBatch3
RuleConditionalTransferOperator.setAutomaticApproval10
RuleConditionalTransferOperator.setAutomaticTransfer4
RuleConditionalTransferOperator.setConditionalWhitelist26
RuleConditionalTransferOperator.setIssuanceOptions7
RuleConditionalTransferOperator.setTimeLimit5
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation/abstract - RuleConditionalTransferOperator.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:113113100.0 %
Date:2024-12-20 10:41:14Functions:2020100.0 %
Branches:3131100.0 %
-
- - - - - - - - -

-
           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                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operationHitTotalCoverage
Test:lcov.infoLines:10510699.1 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:3333100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransfer.sol -
99.1%99.1%
-
99.1 %105 / 10694.4 %17 / 18100.0 %33 / 33
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operationHitTotalCoverage
Test:lcov.infoLines:10510699.1 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:3333100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransfer.sol -
99.1%99.1%
-
99.1 %105 / 10694.4 %17 / 18100.0 %33 / 33
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operationHitTotalCoverage
Test:lcov.infoLines:10510699.1 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:3333100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransfer.sol -
99.1%99.1%
-
99.1 %105 / 10694.4 %17 / 18100.0 %33 / 33
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operationHitTotalCoverage
Test:lcov.infoLines:10510699.1 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:3333100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransfer.sol -
99.1%99.1%
-
99.1 %105 / 10694.4 %17 / 18100.0 %33 / 33
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation - RuleBlacklist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1313100.0 %
Date:2024-12-20 10:41:14Functions:44100.0 %
Branches:88100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleBlacklist.canReturnTransferRestrictionCode4
RuleBlacklist.messageForTransferRestriction4
RuleBlacklist.detectTransferRestriction10
RuleBlacklist.12
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation - RuleBlacklist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1313100.0 %
Date:2024-12-20 10:41:14Functions:44100.0 %
Branches:88100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleBlacklist.12
RuleBlacklist.canReturnTransferRestrictionCode4
RuleBlacklist.detectTransferRestriction10
RuleBlacklist.messageForTransferRestriction4
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation - RuleSanctionList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:272896.4 %
Date:2024-12-20 10:41:14Functions:91090.0 %
Branches:1111100.0 %
-
- - - - - - - - -

-
           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                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation - RuleWhitelist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:55100.0 %
Date:2024-12-20 10:41:14Functions:22100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelist.detectTransferRestriction28
RuleWhitelist.173
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation - RuleWhitelist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:55100.0 %
Date:2024-12-20 10:41:14Functions:22100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelist.173
RuleWhitelist.detectTransferRestriction28
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation - RuleWhitelist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:55100.0 %
Date:2024-12-20 10:41:14Functions:22100.0 %
Branches:44100.0 %
-
- - - - - - - - -

-
           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/RuleAddressList.sol";
-       6                 :            : import "./abstract/RuleWhitelistCommon.sol";
-       7                 :            : 
-       8                 :            : /**
-       9                 :            :  * @title a whitelist manager
-      10                 :            :  */
-      11                 :            : contract RuleWhitelist is RuleAddressList, RuleWhitelistCommon {
-      12                 :            :     /**
-      13                 :            :      * @param admin Address of the contract (Access Control)
-      14                 :            :      * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
-      15                 :            :      */
-      16                 :            :     constructor(
-      17                 :            :         address admin,
-      18                 :            :         address forwarderIrrevocable
-      19                 :            :     ) RuleAddressList(admin, forwarderIrrevocable) {}
-      20                 :            : 
-      21                 :            :     /**
-      22                 :            :      * @notice Check if an addres is in the whitelist or not
-      23                 :            :      * @param _from the origin address
-      24                 :            :      * @param _to the destination address
-      25                 :            :      * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
-      26                 :            :      **/
-      27                 :            :     function detectTransferRestriction(
-      28                 :            :         address _from,
-      29                 :            :         address _to,
-      30                 :            :         uint256 /*_amount */
-      31                 :            :     ) public view override returns (uint8) {
-      32         [ +  + ]:         28 :         if (!addressIsListed(_from)) {
-      33                 :         13 :             return CODE_ADDRESS_FROM_NOT_WHITELISTED;
-      34         [ +  + ]:         15 :         } else if (!addressIsListed(_to)) {
-      35                 :          5 :             return CODE_ADDRESS_TO_NOT_WHITELISTED;
-      36                 :            :         } else {
-      37                 :         10 :             return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
-      38                 :            :         }
-      39                 :            :     }
-      40                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation - RuleWhitelistWrapper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:272896.4 %
Date:2024-12-20 10:41:14Functions:5683.3 %
Branches:99100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistWrapper._msgData0
RuleWhitelistWrapper.detectTransferRestriction11
RuleWhitelistWrapper.hasRole13
RuleWhitelistWrapper.14
RuleWhitelistWrapper._contextSuffixLength52
RuleWhitelistWrapper._msgSender52
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation - RuleWhitelistWrapper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:272896.4 %
Date:2024-12-20 10:41:14Functions:5683.3 %
Branches:99100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistWrapper.14
RuleWhitelistWrapper._contextSuffixLength52
RuleWhitelistWrapper._msgData0
RuleWhitelistWrapper._msgSender52
RuleWhitelistWrapper.detectTransferRestriction11
RuleWhitelistWrapper.hasRole13
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressList - RuleAddressList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:222395.7 %
Date:2024-12-20 10:41:14Functions:111291.7 %
Branches:22100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleAddressList._msgData0
RuleAddressList.removeAddressFromTheList3
RuleAddressList.removeAddressesFromTheList4
RuleAddressList.addAddressesToTheList17
RuleAddressList.numberListedAddress24
RuleAddressList.addressIsListedBatch28
RuleAddressList.addAddressToTheList52
RuleAddressList.addressIsListed101
RuleAddressList.185
RuleAddressList.hasRole194
RuleAddressList._contextSuffixLength270
RuleAddressList._msgSender270
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressList - RuleAddressList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:222395.7 %
Date:2024-12-20 10:41:14Functions:111291.7 %
Branches:22100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleAddressList.185
RuleAddressList._contextSuffixLength270
RuleAddressList._msgData0
RuleAddressList._msgSender270
RuleAddressList.addAddressToTheList52
RuleAddressList.addAddressesToTheList17
RuleAddressList.addressIsListed101
RuleAddressList.addressIsListedBatch28
RuleAddressList.hasRole194
RuleAddressList.numberListedAddress24
RuleAddressList.removeAddressFromTheList3
RuleAddressList.removeAddressesFromTheList4
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressList - RuleAddressListInternal.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2222100.0 %
Date:2024-12-20 10:41:14Functions:66100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleAddressListInternal._removeAddressFromThelist2
RuleAddressListInternal._removeAddressesFromThelist3
RuleAddressListInternal._addAddressesToThelist16
RuleAddressListInternal._numberListedAddress24
RuleAddressListInternal._addAddressToThelist51
RuleAddressListInternal._addressIsListed214
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressList - RuleAddressListInternal.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2222100.0 %
Date:2024-12-20 10:41:14Functions:66100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleAddressListInternal._addAddressToThelist51
RuleAddressListInternal._addAddressesToThelist16
RuleAddressListInternal._addressIsListed214
RuleAddressListInternal._numberListedAddress24
RuleAddressListInternal._removeAddressFromThelist2
RuleAddressListInternal._removeAddressesFromThelist3
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressList - RuleAddressListInternal.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2222100.0 %
Date:2024-12-20 10:41:14Functions:66100.0 %
Branches:44100.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.20;
-       4                 :            : 
-       5                 :            : /**
-       6                 :            :  * @title a list manager
-       7                 :            :  */
-       8                 :            : 
-       9                 :            : abstract contract RuleAddressListInternal {
-      10                 :            :     error Rulelist_AddressAlreadylisted();
-      11                 :            :     error Rulelist_AddressNotPresent();
-      12                 :            : 
-      13                 :            :     mapping(address => bool) private list;
-      14                 :            :     // Number of addresses in the list at the moment
-      15                 :            :     uint256 private numAddressesList;
-      16                 :            : 
-      17                 :            :     /**
-      18                 :            :      * @notice Add addresses to the list
-      19                 :            :      * If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert).
-      20                 :            :      * @param listTargetAddresses an array with the addresses to list
-      21                 :            :      */
-      22                 :            :     function _addAddressesToThelist(
-      23                 :            :         address[] calldata listTargetAddresses
-      24                 :            :     ) internal {
-      25                 :         16 :         uint256 numAddressesListLocal = numAddressesList;
-      26                 :         16 :         for (uint256 i = 0; i < listTargetAddresses.length; ++i) {
-      27            [ + ]:         34 :             if (!list[listTargetAddresses[i]]) {
-      28                 :         32 :                 list[listTargetAddresses[i]] = true;
-      29                 :         32 :                 ++numAddressesListLocal;
-      30                 :            :             }
-      31                 :            :         }
-      32                 :         16 :         numAddressesList = numAddressesListLocal;
-      33                 :            :     }
-      34                 :            : 
-      35                 :            :     /**
-      36                 :            :      * @notice Remove addresses from the list
-      37                 :            :      * If the address does not exist in the list, there is no change for this address.
-      38                 :            :      * The transaction remains valid (no revert).
-      39                 :            :      * @param listTargetAddresses an array with the addresses to remove
-      40                 :            :      */
-      41                 :            :     function _removeAddressesFromThelist(
-      42                 :            :         address[] calldata listTargetAddresses
-      43                 :            :     ) internal {
-      44                 :          3 :         uint256 numAddressesListLocal = numAddressesList;
-      45                 :          3 :         for (uint256 i = 0; i < listTargetAddresses.length; ++i) {
-      46            [ + ]:          6 :             if (list[listTargetAddresses[i]]) {
-      47                 :          6 :                 list[listTargetAddresses[i]] = false;
-      48                 :          6 :                 --numAddressesListLocal;
-      49                 :            :             }
-      50                 :            :         }
-      51                 :          3 :         numAddressesList = numAddressesListLocal;
-      52                 :            :     }
-      53                 :            : 
-      54                 :            :     /**
-      55                 :            :      * @notice Add one address to the list
-      56                 :            :      * If the address already exists, the transaction is reverted to save gas.
-      57                 :            :      * @param targetAddress The address to list
-      58                 :            :      */
-      59                 :            :     function _addAddressToThelist(address targetAddress) internal {
-      60            [ + ]:          1 :         if (list[targetAddress]) {
-      61                 :          1 :             revert Rulelist_AddressAlreadylisted();
-      62                 :            :         }
-      63                 :         50 :         list[targetAddress] = true;
-      64                 :         50 :         ++numAddressesList;
-      65                 :            :     }
-      66                 :            : 
-      67                 :            :     /**
-      68                 :            :      * @notice Remove one address from the list
-      69                 :            :      * If the address does not exist in the list, the transaction is reverted to save gas.
-      70                 :            :      * @param targetAddress The address to remove
-      71                 :            :      *
-      72                 :            :      */
-      73                 :            :     function _removeAddressFromThelist(address targetAddress) internal {
-      74            [ + ]:          2 :         if (!list[targetAddress]) {
-      75                 :          1 :             revert Rulelist_AddressNotPresent();
-      76                 :            :         }
-      77                 :          1 :         list[targetAddress] = false;
-      78                 :          1 :         --numAddressesList;
-      79                 :            :     }
-      80                 :            : 
-      81                 :            :     /**
-      82                 :            :      * @notice Get the number of listed addresses
-      83                 :            :      * @return Number of listed addresses
-      84                 :            :      *
-      85                 :            :      */
-      86                 :            :     function _numberListedAddress() internal view returns (uint256) {
-      87                 :         24 :         return numAddressesList;
-      88                 :            :     }
-      89                 :            : 
-      90                 :            :     /**
-      91                 :            :      * @notice Know if an address is listed or not
-      92                 :            :      * @param _targetAddress The concerned address
-      93                 :            :      * @return True if the address is listed, false otherwise
-      94                 :            :      *
-      95                 :            :      */
-      96                 :            :     function _addressIsListed(
-      97                 :            :         address _targetAddress
-      98                 :            :     ) internal view returns (bool) {
-      99                 :        214 :         return list[_targetAddress];
-     100                 :            :     }
-     101                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressListHitTotalCoverage
Test:lcov.infoLines:444597.8 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:66100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleAddressList.sol -
95.7%95.7%
-
95.7 %22 / 2391.7 %11 / 12100.0 %2 / 2
RuleAddressListInternal.sol -
100.0%
-
100.0 %22 / 22100.0 %6 / 6100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressListHitTotalCoverage
Test:lcov.infoLines:444597.8 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:66100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleAddressList.sol -
95.7%95.7%
-
95.7 %22 / 2391.7 %11 / 12100.0 %2 / 2
RuleAddressListInternal.sol -
100.0%
-
100.0 %22 / 22100.0 %6 / 6100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressListHitTotalCoverage
Test:lcov.infoLines:444597.8 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:66100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleAddressList.sol -
95.7%95.7%
-
95.7 %22 / 2391.7 %11 / 12100.0 %2 / 2
RuleAddressListInternal.sol -
100.0%
-
100.0 %22 / 22100.0 %6 / 6100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressListHitTotalCoverage
Test:lcov.infoLines:444597.8 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:66100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleAddressList.sol -
95.7%95.7%
-
95.7 %22 / 2391.7 %11 / 12100.0 %2 / 2
RuleAddressListInternal.sol -
100.0%
-
100.0 %22 / 22100.0 %6 / 6100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract - RuleValidateTransfer.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleValidateTransfer.validateTransfer40
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract - RuleValidateTransfer.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleValidateTransfer.validateTransfer40
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract - RuleValidateTransfer.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.20;
-       4                 :            : 
-       5                 :            : import "../../../interfaces/IRuleValidation.sol";
-       6                 :            : 
-       7                 :            : abstract contract RuleValidateTransfer is IRuleValidation {
-       8                 :            :     /**
-       9                 :            :      * @notice Validate a transfer
-      10                 :            :      * @param _from the origin address
-      11                 :            :      * @param _to the destination address
-      12                 :            :      * @param _amount to transfer
-      13                 :            :      * @return isValid => true if the transfer is valid, false otherwise
-      14                 :            :      **/
-      15                 :            :     function validateTransfer(
-      16                 :            :         address _from,
-      17                 :            :         address _to,
-      18                 :            :         uint256 _amount
-      19                 :            :     ) public view override returns (bool isValid) {
-      20                 :            :         // does not work without this keyword "Undeclared identifier"
-      21                 :         40 :         return
-      22                 :         40 :             this.detectTransferRestriction(_from, _to, _amount) ==
-      23                 :            :             uint8(REJECTED_CODE_BASE.TRANSFER_OK);
-      24                 :            :     }
-      25                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstractHitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2024-12-20 10:41:14Functions:33100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleValidateTransfer.sol -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
RuleWhitelistCommon.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstractHitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2024-12-20 10:41:14Functions:33100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleValidateTransfer.sol -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
RuleWhitelistCommon.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstractHitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2024-12-20 10:41:14Functions:33100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleValidateTransfer.sol -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
RuleWhitelistCommon.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstractHitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2024-12-20 10:41:14Functions:33100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleValidateTransfer.sol -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
RuleWhitelistCommon.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validationHitTotalCoverage
Test:lcov.infoLines:727497.3 %
Date:2024-12-20 10:41:14Functions:202290.9 %
Branches:3232100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleWhitelist.sol -
100.0%
-
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
RuleBlacklist.sol -
100.0%
-
100.0 %13 / 13100.0 %4 / 4100.0 %8 / 8
RuleWhitelistWrapper.sol -
96.4%96.4%
-
96.4 %27 / 2883.3 %5 / 6100.0 %9 / 9
RuleSanctionList.sol -
96.4%96.4%
-
96.4 %27 / 2890.0 %9 / 10100.0 %11 / 11
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validationHitTotalCoverage
Test:lcov.infoLines:727497.3 %
Date:2024-12-20 10:41:14Functions:202290.9 %
Branches:3232100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleWhitelistWrapper.sol -
96.4%96.4%
-
96.4 %27 / 2883.3 %5 / 6100.0 %9 / 9
RuleSanctionList.sol -
96.4%96.4%
-
96.4 %27 / 2890.0 %9 / 10100.0 %11 / 11
RuleWhitelist.sol -
100.0%
-
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
RuleBlacklist.sol -
100.0%
-
100.0 %13 / 13100.0 %4 / 4100.0 %8 / 8
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validationHitTotalCoverage
Test:lcov.infoLines:727497.3 %
Date:2024-12-20 10:41:14Functions:202290.9 %
Branches:3232100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleSanctionList.sol -
96.4%96.4%
-
96.4 %27 / 2890.0 %9 / 10100.0 %11 / 11
RuleWhitelistWrapper.sol -
96.4%96.4%
-
96.4 %27 / 2883.3 %5 / 6100.0 %9 / 9
RuleWhitelist.sol -
100.0%
-
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
RuleBlacklist.sol -
100.0%
-
100.0 %13 / 13100.0 %4 / 4100.0 %8 / 8
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validationHitTotalCoverage
Test:lcov.infoLines:727497.3 %
Date:2024-12-20 10:41:14Functions:202290.9 %
Branches:3232100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleBlacklist.sol -
100.0%
-
100.0 %13 / 13100.0 %4 / 4100.0 %8 / 8
RuleSanctionList.sol -
96.4%96.4%
-
96.4 %27 / 2890.0 %9 / 10100.0 %11 / 11
RuleWhitelist.sol -
100.0%
-
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
RuleWhitelistWrapper.sol -
96.4%96.4%
-
96.4 %27 / 2883.3 %5 / 6100.0 %9 / 9
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/RuleConditionalTransfer/utils - RuleCTDeployment.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- - - - - - - - -

-
           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                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utils - CMTATDeployment.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:44100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
CMTATDeployment.86
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utils - CMTATDeployment.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:44100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
CMTATDeployment.86
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utils - CMTATDeployment.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:44100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- - - - - - - - -

-
           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                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utils - SanctionListOracle.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2366.7 %
Date:2024-12-20 10:41:14Functions:3475.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : pragma solidity ^0.8.20;
-       3                 :            : 
-       4                 :            : /**
-       5                 :            :  * @notice Test contract from
-       6                 :            :  * https://etherscan.io/address/0x40c57923924b5c5c5455c48d93317139addac8fb#code
-       7                 :            :  */
-       8                 :            : contract SanctionListOracle {
-       9                 :            :     constructor() {}
-      10                 :            : 
-      11                 :            :     mapping(address => bool) private sanctionedAddresses;
-      12                 :            : 
-      13                 :            :     function addToSanctionsList(address newSanction) public {
-      14                 :         10 :         sanctionedAddresses[newSanction] = true;
-      15                 :            :     }
-      16                 :            : 
-      17                 :            :     function removeFromSanctionsList(address removeSanction) public {
-      18                 :          0 :         sanctionedAddresses[removeSanction] = true;
-      19                 :            :     }
-      20                 :            : 
-      21                 :            :     function isSanctioned(address addr) public view returns (bool) {
-      22                 :         12 :         return sanctionedAddresses[addr] == true;
-      23                 :            :     }
-      24                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - 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
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleBlacklist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:353794.6 %
Date:2025-12-03 15:05:37Functions:101190.9 %
Branches:1616100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleBlacklist.supportsInterface0
RuleBlacklist.transferred.12
RuleBlacklist.transferred.22
RuleBlacklist.transferred.33
RuleBlacklist.canReturnTransferRestrictionCode4
RuleBlacklist.detectTransferRestrictionFrom.14
RuleBlacklist.detectTransferRestriction.17
RuleBlacklist.messageForTransferRestriction8
RuleBlacklist.transferred.09
RuleBlacklist.detectTransferRestrictionFrom.016
RuleBlacklist.detectTransferRestriction.022
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + 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
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleBlacklist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:353794.6 %
Date:2025-12-03 15:05:37Functions:101190.9 %
Branches:1616100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleBlacklist.canReturnTransferRestrictionCode4
RuleBlacklist.detectTransferRestriction.022
RuleBlacklist.detectTransferRestriction.17
RuleBlacklist.detectTransferRestrictionFrom.016
RuleBlacklist.detectTransferRestrictionFrom.14
RuleBlacklist.messageForTransferRestriction8
RuleBlacklist.supportsInterface0
RuleBlacklist.transferred.09
RuleBlacklist.transferred.12
RuleBlacklist.transferred.22
RuleBlacklist.transferred.33
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + 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
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleBlacklist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:353794.6 %
Date:2025-12-03 15:05:37Functions:101190.9 %
Branches:1616100.0 %
+
+ + + + + + + + +

+
           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                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + 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
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleSanctionsList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:505492.6 %
Date:2025-12-03 15:05:37Functions:151788.2 %
Branches:1818100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleSanctionsList._msgData0
RuleSanctionsList.supportsInterface0
RuleSanctionsList.transferred.21
RuleSanctionsList.transferred.12
RuleSanctionsList.canReturnTransferRestrictionCode3
RuleSanctionsList.detectTransferRestrictionFrom.13
RuleSanctionsList.transferred.03
RuleSanctionsList.messageForTransferRestriction4
RuleSanctionsList.transferred.34
RuleSanctionsList.detectTransferRestriction.19
RuleSanctionsList.detectTransferRestrictionFrom.011
RuleSanctionsList._setSanctionListOracle14
RuleSanctionsList.setSanctionListOracle14
RuleSanctionsList.constructor17
RuleSanctionsList.detectTransferRestriction.017
RuleSanctionsList._contextSuffixLength30
RuleSanctionsList._msgSender30
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + 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
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleSanctionsList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:505492.6 %
Date:2025-12-03 15:05:37Functions:151788.2 %
Branches:1818100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleSanctionsList._contextSuffixLength30
RuleSanctionsList._msgData0
RuleSanctionsList._msgSender30
RuleSanctionsList._setSanctionListOracle14
RuleSanctionsList.canReturnTransferRestrictionCode3
RuleSanctionsList.constructor17
RuleSanctionsList.detectTransferRestriction.017
RuleSanctionsList.detectTransferRestriction.19
RuleSanctionsList.detectTransferRestrictionFrom.011
RuleSanctionsList.detectTransferRestrictionFrom.13
RuleSanctionsList.messageForTransferRestriction4
RuleSanctionsList.setSanctionListOracle14
RuleSanctionsList.supportsInterface0
RuleSanctionsList.transferred.03
RuleSanctionsList.transferred.12
RuleSanctionsList.transferred.21
RuleSanctionsList.transferred.34
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + 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
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleSanctionsList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:505492.6 %
Date:2025-12-03 15:05:37Functions:151788.2 %
Branches:1818100.0 %
+
+ + + + + + + + +

+
           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                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + 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 @@
Current view:top level - src - RuleEngine.sol (source / functions)top level - validation - RuleWhitelist.sol (source / functions) Hitlcov.info Lines:383997.4 %162080.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:8988.9 %5771.4 %
Branches:8855 100.0 %
- + - + - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + +

Function Name Sort by function nameFunction Name Sort by function name Hit count Sort by hit count
RuleEngine._msgDataRuleWhitelist.isVerified 0
RuleEngine.validateTransfer12
RuleEngine.messageForTransferRestriction18
RuleEngine.detectTransferRestriction20RuleWhitelist.supportsInterface0
RuleEngine.operateOnTransfer69RuleWhitelist.detectTransferRestrictionFrom.12
RuleEngine.205RuleWhitelist.detectTransferRestriction.17
RuleEngine.hasRole299RuleWhitelist.detectTransferRestrictionFrom.010
RuleEngine._contextSuffixLength588RuleWhitelist.detectTransferRestriction.020
RuleEngine._msgSender588RuleWhitelist.constructor102

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 @@ - + @@ -31,26 +31,26 @@ - - - + + + - + - - - + + + - - + + @@ -66,43 +66,35 @@ - + - - + + - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + +
Current view:top level - src - RuleEngine.sol (source / functions)top level - validation - RuleWhitelist.sol (source / functions) Hitlcov.info Lines:383997.4 %162080.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:8988.9 %5771.4 %
Branches:8855 100.0 %

Function Name Sort by function nameHit count Sort by hit countHit count Sort by hit count
RuleEngine.205RuleWhitelist.constructor102
RuleEngine._contextSuffixLength588
RuleEngine._msgData0
RuleEngine._msgSender588RuleWhitelist.detectTransferRestriction.020
RuleEngine.detectTransferRestriction20RuleWhitelist.detectTransferRestriction.17
RuleEngine.hasRole299RuleWhitelist.detectTransferRestrictionFrom.010
RuleEngine.messageForTransferRestriction18RuleWhitelist.detectTransferRestrictionFrom.12
RuleEngine.operateOnTransfer69RuleWhitelist.isVerified0
RuleEngine.validateTransfer12RuleWhitelist.supportsInterface0

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 @@ - - - + + + - + - - - + + + - - + + - +
Current view:top level - src/modules - RuleEngineValidationCommon.sol (source / functions)top level - validation - RuleWhitelist.sol (source / functions) Hitlcov.info Lines:1919100.0 %162080.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:1010100.0 %5771.4 %
Branches:1155 100.0 %
@@ -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 @@
- +
Generated by: LCOV version 1.16

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
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleWhitelistWrapper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:505787.7 %
Date:2025-12-03 15:05:37Functions:91181.8 %
Branches:111478.6 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistWrapper._msgData0
RuleWhitelistWrapper.supportsInterface0
RuleWhitelistWrapper.detectTransferRestrictionFrom.12
RuleWhitelistWrapper.detectTransferRestriction.14
RuleWhitelistWrapper.detectTransferRestrictionFrom.010
RuleWhitelistWrapper.hasRole20
RuleWhitelistWrapper.detectTransferRestriction.021
RuleWhitelistWrapper.constructor22
RuleWhitelistWrapper._detectTransferRestriction37
RuleWhitelistWrapper._contextSuffixLength80
RuleWhitelistWrapper._msgSender80
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + 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
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleWhitelistWrapper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:505787.7 %
Date:2025-12-03 15:05:37Functions:91181.8 %
Branches:111478.6 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistWrapper._contextSuffixLength80
RuleWhitelistWrapper._detectTransferRestriction37
RuleWhitelistWrapper._msgData0
RuleWhitelistWrapper._msgSender80
RuleWhitelistWrapper.constructor22
RuleWhitelistWrapper.detectTransferRestriction.021
RuleWhitelistWrapper.detectTransferRestriction.14
RuleWhitelistWrapper.detectTransferRestrictionFrom.010
RuleWhitelistWrapper.detectTransferRestrictionFrom.12
RuleWhitelistWrapper.hasRole20
RuleWhitelistWrapper.supportsInterface0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + 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 @@ - - - + + + - + - - + + - - - + + +
Current view:top level - src - RuleEngine.sol (source / functions)top level - validation - RuleWhitelistWrapper.sol (source / functions) Hitlcov.info Lines:383997.4 %505787.7 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:8 988.9 %1181.8 %
Branches:88100.0 %111478.6 %
@@ -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 @@
Current view:top level - src/rules/validation - RuleSanctionList.sol (source / functions)top level - validation/abstract/RuleAddressSet - RuleAddressSet.sol (source / functions) Hitlcov.info Lines:27 2896.4 %3287.5 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions: 91090.0 %1181.8 %
Branches:111122 100.0 %
- + - + - - + + - + - - + + + + + + - - + + - - + + - - + + - - + + - - + + - - + +

Function Name Sort by function nameFunction Name Sort by function name Hit count Sort by hit count
RuleSanctionList._msgDataRuleAddressSet._msgData 0
RuleSanctionList.canReturnTransferRestrictionCode3RuleAddressSet.contains0
RuleSanctionList.messageForTransferRestrictionRuleAddressSet.removeAddress 3
RuleSanctionList.detectTransferRestriction7RuleAddressSet.removeAddresses4
RuleAddressSet.addAddresses17
RuleSanctionList._setSanctionListOracle11RuleAddressSet.listedAddressCount24
RuleSanctionList.setSanctionListOracle11RuleAddressSet.addAddress52
RuleSanctionList.13RuleAddressSet.isAddressListed60
RuleSanctionList.hasRole13RuleAddressSet.areAddressesListed84
RuleSanctionList._contextSuffixLength23RuleAddressSet._contextSuffixLength207
RuleSanctionList._msgSender23RuleAddressSet._msgSender207

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 @@ - + @@ -31,26 +31,26 @@ - - + + - + - - + + - - + + @@ -66,47 +66,51 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + + + + + - - + + - - + + - + - - + +
Current view:top level - src/rules/validation - RuleSanctionList.sol (source / functions)top level - validation/abstract/RuleAddressSet - RuleAddressSet.sol (source / functions) Hitlcov.info Lines:27 2896.4 %3287.5 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions: 91090.0 %1181.8 %
Branches:111122 100.0 %

Function Name Sort by function nameHit count Sort by hit countHit count Sort by hit count
RuleSanctionList.13RuleAddressSet._contextSuffixLength207
RuleSanctionList._contextSuffixLength23RuleAddressSet._msgData0
RuleSanctionList._msgData0RuleAddressSet._msgSender207
RuleSanctionList._msgSender23RuleAddressSet.addAddress52
RuleSanctionList._setSanctionListOracle11RuleAddressSet.addAddresses17
RuleSanctionList.canReturnTransferRestrictionCode3RuleAddressSet.areAddressesListed84
RuleAddressSet.contains0
RuleSanctionList.detectTransferRestriction7RuleAddressSet.isAddressListed60
RuleSanctionList.hasRole13RuleAddressSet.listedAddressCount24
RuleSanctionList.messageForTransferRestrictionRuleAddressSet.removeAddress 3
RuleSanctionList.setSanctionListOracle11RuleAddressSet.removeAddresses4

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 @@ - +
Current view:top level - src/rules/validation/abstract/RuleAddressList - RuleAddressList.sol (source / functions)top level - validation/abstract/RuleAddressSet - RuleAddressSet.sol (source / functions) Hitlcov.info Lines:222395.7 %283287.5 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:9 111291.7 %81.8 %
2 100.0 %
@@ -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 @@
- +
Generated by: LCOV version 1.16

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 @@
Current view:top level - test/RuleConditionalTransfer/utils - RuleCTDeployment.sol (source / functions)top level - validation/abstract/RuleAddressSet - RuleAddressSetInternal.sol (source / functions) Hitlcov.info Lines:10101414 100.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:1166 100.0 %
- + - - + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameFunction Name Sort by function name Hit count Sort by hit count
RuleCTDeployment.13RuleAddressSetInternal._removeAddress1
RuleAddressSetInternal._removeAddresses3
RuleAddressSetInternal._addAddresses16
RuleAddressSetInternal._listedAddressCount24
RuleAddressSetInternal._addAddress50
RuleAddressSetInternal._isAddressListed463

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 @@ - + @@ -31,17 +31,17 @@ - - + + - + - - + + @@ -66,11 +66,31 @@ - + - - + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test/RuleConditionalTransfer/utils - RuleCTDeployment.sol (source / functions)top level - validation/abstract/RuleAddressSet - RuleAddressSetInternal.sol (source / functions) Hitlcov.info Lines:10101414 100.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:1166 100.0 %

Function Name Sort by function nameHit count Sort by hit countHit count Sort by hit count
RuleCTDeployment.13RuleAddressSetInternal._addAddress50
RuleAddressSetInternal._addAddresses16
RuleAddressSetInternal._isAddressListed463
RuleAddressSetInternal._listedAddressCount24
RuleAddressSetInternal._removeAddress1
RuleAddressSetInternal._removeAddresses3

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 @@ - - - + + +
Current view:top level - src/rules/validation - RuleBlacklist.sol (source / functions)top level - validation/abstract/RuleAddressSet - RuleAddressSetInternal.sol (source / functions) Hitlcov.info Lines:13131414 100.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:4466 100.0 %
Branches:88100.0 %00-
@@ -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 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/RuleConditionalTransfer/utilstop level - validation/abstract/RuleAddressSet Hitlcov.info Lines:1010100.0 %424691.3 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:11100.0 %151788.2 %
Branches:00-22100.0 %
@@ -82,17 +82,29 @@ Branches Sort by branch coverage - RuleCTDeployment.sol + RuleAddressSetInternal.sol
100.0%
100.0 % - 10 / 10 + 14 / 14 100.0 % - 1 / 1 + 6 / 6 - 0 / 0 + + RuleAddressSet.sol + +
87.5%87.5%
+ + 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 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/RuleConditionalTransfer/utilstop level - validation/abstract/RuleAddressSet Hitlcov.info Lines:1010100.0 %424691.3 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:11100.0 %151788.2 %
Branches:00-22100.0 %
@@ -82,14 +82,26 @@ Branches Sort by branch coverage - RuleCTDeployment.sol + RuleAddressSet.sol + +
87.5%87.5%
+ + 87.5 % + 28 / 32 + 81.8 % + 9 / 11 + 100.0 % + 2 / 2 + + + RuleAddressSetInternal.sol
100.0%
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 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/RuleConditionalTransfer/utilstop level - validation/abstract/RuleAddressSet Hitlcov.info Lines:1010100.0 %424691.3 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:11100.0 %151788.2 %
Branches:00-22100.0 %
@@ -82,14 +82,26 @@ Branches Sort by branch coverage - RuleCTDeployment.sol + RuleAddressSet.sol + +
87.5%87.5%
+ + 87.5 % + 28 / 32 + 81.8 % + 9 / 11 + 100.0 % + 2 / 2 + + + RuleAddressSetInternal.sol
100.0%
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 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/RuleConditionalTransfer/utilstop level - validation/abstract/RuleAddressSet Hitlcov.info Lines:1010100.0 %424691.3 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:11100.0 %151788.2 %
Branches:00-22100.0 %
@@ -82,14 +82,26 @@ Branches Sort by branch coverage - RuleCTDeployment.sol + RuleAddressSet.sol + +
87.5%87.5%
+ + 87.5 % + 28 / 32 + 81.8 % + 9 / 11 + 100.0 % + 2 / 2 + + + RuleAddressSetInternal.sol
100.0%
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 @@
Current view:top level - test/utils - SanctionListOracle.sol (source / functions)top level - validation/abstract - RuleValidateTransfer.sol (source / functions) Hitlcov.info Lines:2366.7 %81080.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:3 475.0 %580.0 %
- + - + - + - - + + + + + + - - + +

Function Name Sort by function nameFunction Name Sort by function name Hit count Sort by hit count
SanctionListOracle.removeFromSanctionsListRuleValidateTransfer.supportsInterface 0
SanctionListOracle.addToSanctionsListRuleValidateTransfer.canTransferFrom.0 10
SanctionListOracle.11RuleValidateTransfer.canTransferFrom.110
RuleValidateTransfer.canTransfer.014
SanctionListOracle.isSanctioned12RuleValidateTransfer.canTransfer.114

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 @@ - + @@ -31,18 +31,18 @@ - - - + + + - + - - + + @@ -66,22 +66,26 @@ - + - - + + - + + + + + - - + + - +
Current view:top level - test/utils - SanctionListOracle.sol (source / functions)top level - validation/abstract - RuleValidateTransfer.sol (source / functions) Hitlcov.info Lines:2366.7 %81080.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:3 475.0 %580.0 %

Function Name Sort by function nameHit count Sort by hit countHit count Sort by hit count
SanctionListOracle.11RuleValidateTransfer.canTransfer.014
SanctionListOracle.addToSanctionsListRuleValidateTransfer.canTransfer.114
RuleValidateTransfer.canTransferFrom.0 10
SanctionListOracle.isSanctioned12RuleValidateTransfer.canTransferFrom.110
SanctionListOracle.removeFromSanctionsListRuleValidateTransfer.supportsInterface 0
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 @@ - - - + + + - + - - + + - - - + + +
Current view:top level - src/modules - RuleInternal.sol (source / functions)top level - validation/abstract - RuleValidateTransfer.sol (source / functions) Hitlcov.info Lines:2929100.0 %81080.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions: 44100.0 %580.0 %
Branches:88100.0 %00-
@@ -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 @@
Current view:top level - src/modules - RuleInternal.sol (source / functions)top level - validation/abstract - RuleWhitelistCommon.sol (source / functions) Hitlcov.info Lines:29292121 100.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:4466 100.0 %
Branches:881010 100.0 %
- + - - + + - - + + - - + + - - + + + + + + + + + +

Function Name Sort by function nameFunction Name Sort by function name Hit count Sort by hit count
RuleInternal._getRuleIndex6RuleWhitelistCommon.transferred.14
RuleInternal._setRules32RuleWhitelistCommon.transferred.24
RuleInternal._removeRule55RuleWhitelistCommon.transferred.35
RuleInternal._addRule203RuleWhitelistCommon.canReturnTransferRestrictionCode10
RuleWhitelistCommon.messageForTransferRestriction14
RuleWhitelistCommon.transferred.017

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 @@ - + @@ -31,17 +31,17 @@ - - + + - + - - + + @@ -49,8 +49,8 @@ - - + + @@ -66,23 +66,31 @@ - + - - + + - - + + - - + + - - + + + + + + + + + +
Current view:top level - src/modules - RuleInternal.sol (source / functions)top level - validation/abstract - RuleWhitelistCommon.sol (source / functions) Hitlcov.info Lines:29292121 100.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:4466 100.0 %
Branches:881010 100.0 %

Function Name Sort by function nameHit count Sort by hit countHit count Sort by hit count
RuleInternal._addRule203RuleWhitelistCommon.canReturnTransferRestrictionCode10
RuleInternal._getRuleIndex6RuleWhitelistCommon.messageForTransferRestriction14
RuleInternal._removeRule55RuleWhitelistCommon.transferred.017
RuleInternal._setRules32RuleWhitelistCommon.transferred.14
RuleWhitelistCommon.transferred.24
RuleWhitelistCommon.transferred.35

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 @@ - - - + + + - + - - + + - - + + - +
Current view:top level - src/rules/validation - RuleWhitelistWrapper.sol (source / functions)top level - validation/abstract - RuleWhitelistCommon.sol (source / functions) Hitlcov.info Lines:272896.4 %2121100.0 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:5 683.3 %6100.0 %
Branches:991010 100.0 %
@@ -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 @@
- +
Generated by: LCOV version 1.16

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 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/utilstop level - validation/abstract Hitlcov.info Lines:6785.7 %293193.5 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:4580.0 %101190.9 %
Branches:00-1010100.0 %
@@ -82,28 +82,28 @@ Branches Sort by branch coverage - CMTATDeployment.sol + RuleValidateTransfer.sol -
100.0%
+
80.0%80.0%
- 100.0 % - 4 / 4 - 100.0 % - 1 / 1 + 80.0 % + 8 / 10 + 80.0 % + 4 / 5 - 0 / 0 - SanctionListOracle.sol + RuleWhitelistCommon.sol -
66.7%66.7%
+
100.0%
- 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 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/utilstop level - validation/abstract Hitlcov.info Lines:6785.7 %293193.5 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:4580.0 %101190.9 %
Branches:00-1010100.0 %
@@ -82,28 +82,28 @@ Branches Sort by branch coverage - SanctionListOracle.sol + RuleValidateTransfer.sol -
66.7%66.7%
+
80.0%80.0%
- 66.7 % - 2 / 3 - 75.0 % - 3 / 4 + 80.0 % + 8 / 10 + 80.0 % + 4 / 5 - 0 / 0 - CMTATDeployment.sol + RuleWhitelistCommon.sol
100.0%
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 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/utilstop level - validation/abstract Hitlcov.info Lines:6785.7 %293193.5 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:4580.0 %101190.9 %
Branches:00-1010100.0 %
@@ -82,28 +82,28 @@ Branches Sort by branch coverage - SanctionListOracle.sol + RuleValidateTransfer.sol -
66.7%66.7%
+
80.0%80.0%
- 66.7 % - 2 / 3 - 75.0 % - 3 / 4 + 80.0 % + 8 / 10 + 80.0 % + 4 / 5 - 0 / 0 - CMTATDeployment.sol + RuleWhitelistCommon.sol
100.0%
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 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/utilstop level - validation/abstract Hitlcov.info Lines:6785.7 %293193.5 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:4580.0 %101190.9 %
Branches:00-1010100.0 %
@@ -82,28 +82,28 @@ Branches Sort by branch coverage - CMTATDeployment.sol + RuleValidateTransfer.sol -
100.0%
+
80.0%80.0%
- 100.0 % - 4 / 4 - 100.0 % - 1 / 1 + 80.0 % + 8 / 10 + 80.0 % + 4 / 5 - 0 / 0 - SanctionListOracle.sol + RuleWhitelistCommon.sol -
66.7%66.7%
+
100.0%
- 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 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - srctop level - validation Hitlcov.info Lines:383997.4 %15116889.9 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:8988.9 %394684.8 %
Branches:88100.0 %505394.3 %
@@ -82,16 +82,52 @@ Branches Sort by branch coverage - RuleEngine.sol + RuleWhitelistWrapper.sol + +
87.7%87.7%
+ + 87.7 % + 50 / 57 + 81.8 % + 9 / 11 + 78.6 % + 11 / 14 + + + RuleWhitelist.sol + +
80.0%80.0%
+ + 80.0 % + 16 / 20 + 71.4 % + 5 / 7 + 100.0 % + 5 / 5 + + + RuleBlacklist.sol + +
94.6%94.6%
+ + 94.6 % + 35 / 37 + 90.9 % + 10 / 11 + 100.0 % + 16 / 16 + + + RuleSanctionsList.sol -
97.4%97.4%
+
92.6%92.6%
- 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 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - srctop level - validation Hitlcov.info Lines:383997.4 %15116889.9 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:8988.9 %394684.8 %
Branches:88100.0 %505394.3 %
@@ -82,16 +82,52 @@ Branches Sort by branch coverage - RuleEngine.sol + RuleWhitelist.sol + +
80.0%80.0%
+ + 80.0 % + 16 / 20 + 71.4 % + 5 / 7 + 100.0 % + 5 / 5 + + + RuleWhitelistWrapper.sol + +
87.7%87.7%
+ + 87.7 % + 50 / 57 + 81.8 % + 9 / 11 + 78.6 % + 11 / 14 + + + RuleSanctionsList.sol + +
92.6%92.6%
+ + 92.6 % + 50 / 54 + 88.2 % + 15 / 17 + 100.0 % + 18 / 18 + + + RuleBlacklist.sol -
97.4%97.4%
+
94.6%94.6%
- 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 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - srctop level - validation Hitlcov.info Lines:383997.4 %15116889.9 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:8988.9 %394684.8 %
Branches:88100.0 %505394.3 %
@@ -82,16 +82,52 @@ Branches Sort by branch coverage - RuleEngine.sol + RuleWhitelist.sol + +
80.0%80.0%
+ + 80.0 % + 16 / 20 + 71.4 % + 5 / 7 + 100.0 % + 5 / 5 + + + RuleWhitelistWrapper.sol + +
87.7%87.7%
+ + 87.7 % + 50 / 57 + 81.8 % + 9 / 11 + 78.6 % + 11 / 14 + + + RuleSanctionsList.sol + +
92.6%92.6%
+ + 92.6 % + 50 / 54 + 88.2 % + 15 / 17 + 100.0 % + 18 / 18 + + + RuleBlacklist.sol -
97.4%97.4%
+
94.6%94.6%
- 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 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - srctop level - validation Hitlcov.info Lines:383997.4 %15116889.9 %
Date:2024-12-20 10:41:142025-12-03 15:05:37 Functions:8988.9 %394684.8 %
Branches:88100.0 %505394.3 %
@@ -82,16 +82,52 @@ Branches Sort by branch coverage - RuleEngine.sol + RuleBlacklist.sol + +
94.6%94.6%
+ + 94.6 % + 35 / 37 + 90.9 % + 10 / 11 + 100.0 % + 16 / 16 + + + RuleSanctionsList.sol + +
92.6%92.6%
+ + 92.6 % + 50 / 54 + 88.2 % + 15 / 17 + 100.0 % + 18 / 18 + + + RuleWhitelist.sol -
97.4%97.4%
+
80.0%80.0%
- 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%87.7%
+ + 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 ![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleBlacklist.sol.png) -## 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. -![alt text](../security/accessControl/access-control-RuleWhitelist.png) - - - - - -## 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 - -![RuleEngine](../schema/RuleEngine.png) - -### Graph - - - -![surya_graph_RuleEngine](../surya/surya_graph/surya_graph_RuleEngine.sol.png) - - - -## 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. -![alt text](../security/accessControl/access-control-RuleEngine.png) - -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 -![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleSanctionList.sol.png) + ## 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** - -![alt text](../security/accessControl/access-control-RuleSanctionList.drawio.png) - 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 -![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleWhitelist.sol.png) + ## 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 -![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleWhitelistWrapper.sol.png) + ## 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;