diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c07a3e..7df76fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,9 +11,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2 - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 + uses: foundry-rs/foundry-toolchain@de808b1eea699e761c404bda44ba8f21aba30b2c #v1.3.1 with: version: nightly @@ -21,7 +21,7 @@ jobs: run: forge install - name: Setup NodeJS 20.5.0 - uses: actions/setup-node@v3 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 #v4.4.0 with: node-version: 20.5.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 22cc998..a37ec0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,24 @@ Please follow [https://changelog.md/](https://changelog.md/) conventions. - Update surya doc by running the 3 scripts in [./doc/script](./doc/script) - Update changelog +## v3.0.0-rc1 +- Rule contracts, requires to perform compliance check, have now their own dedicated [GitHub repository](https://github.com/CMTA/Rules). It means that these contract will be developed and audited separately from the `RuleEngine`. This provides more flexibility and makes it easier to manage audits. + +- There is now only one type of rule (read-write rules). Before that: + - First RuleEngine version (audited) had only one type of rule, read-only (whitelist, blacklist) + - A second RuleEngine version (not audited) had two types of rules: operation (read-write) and validation (read-only). A read-write rule is typically a ConditionalTransfer check which require each transfer must be pre-approved. +- Implement ERC-3643 compliance interface, which means that the RuleEngine can be also used with an ERC-3643 token to perform supplementary compliance check on transfer. +- Technical: + - Use [EnumerableSet](https://docs.openzeppelin.com/contracts/5.x/api/utils#EnumerableSet) from OpenZeppelin to store rules, which reduce the whole contract code size. + - Rename several abstract contract + - `RuleEngineOperation`-> `RulesManagementModule` + - `MetaTxModuleStandalone` -> `ERC2771ModuleStandalone` + +## v3.0.0-rc0 + +- Improve test +- Move rules contracts to a dedicated repository, only keep some rules as mock contracts for testing purpose ## v2.1.0 @@ -126,4 +143,4 @@ Whitelist - Improve integration test with CMTAT ## 1.0.0 - 20221114 -- 🎉 first release! +- 🎉 first release!< diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ba78c6..f9267c8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ There are many ways to contribute to RuleEngine Contracts. ## Opening an issue -You can [open an issue] to suggest a feature, a difficulty you have or report a minor bug. For serious bugs in an audited version please do not open an issue, instead refer to our [security policy] for appropriate steps. See [SECURITY.md](./SECURITY.MD) in CMTAT project. +You can [open an issue] to suggest a feature, a difficulty you have or report a minor bug. For serious bugs in an audited version please do not open an issue, instead refer to our [security policy] for appropriate steps. See [SECURITY.md](https://github.com/CMTA/CMTAT/blob/master/SECURITY.md) in CMTAT project. Before opening an issue, be sure to search through the existing open and closed issues, and consider posting a comment in one of those instead. diff --git a/README.md b/README.md index 0cb8dc0..9aac504 100644 --- a/README.md +++ b/README.md @@ -2,106 +2,1060 @@ # RuleEngine -This repository includes the RuleEngine contract for the [CMTAT](https://github.com/CMTA/CMTAT) token. +This repository includes the RuleEngine contract for [CMTAT](https://github.com/CMTA/CMTAT) and [ERC-3643](https://eips.ethereum.org/EIPS/eip-3643) tokens. -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. +The RuleEngine is an external contract used to apply transfer restrictions to another contract, such as CMTAT and ERC-3643 tokens. Acting as a controller, it can call different contract rules and apply these rules on each transfer. -## Dependencies +## Motivation + +- Why use a dedicated contract with rules instead of implementing it directly in CMTAT or [ERC-3643](https://eips.ethereum.org/EIPS/eip-3643) tokens? + +There are several reasons to do this: + +- Flexibility: These different features are not standard and common to all tokens. From an implementation perspective, using a rule engine with custom rules allows for each issuer or contract user to decide which rules to apply. + +- Code efficiency: The CMTAT token (and generally also all ERC-3643 tokens) is currently "heavy," meaning its contract code size is close to the maximum limit. This makes it challenging to add new features directly inside the token contract. + +- Reusability: + + - We can use the RuleEngine inside other contracts besides CMTAT. For instance, the RuleEngine has been used it in [our contract to distribute dividends](https://www.taurushq.com/blog/equity-tokenization-how-to-pay-dividend-on-chain-using-cmtat/). + + - A same deployed `RuleEngine`can also be used with several different tokens if the rules allowed it, which is the case for all ready-only rule. + +Why use this `RuleEngine` contract instead of setting directly the `rule` in the token contract? + +- Using a RuleEngine allows to call several different rules. For example, a blacklist rule to allow the issuer to manage its own list of blacklisted addresses and a sanctionlist rule to use the [Chainalysis oracle for sanctions screening](https://go.chainalysis.com/chainalysis-oracle-docs.html) to forbid transfers from addresses listed in sanctions designations by organizations such as the US, EU, or UN. + +When the use of `RuleEngine` may not be appropriate? + +If you plan to call only one rule (e.g a whitelist rule), it could make sense to directly set the rule in the token contract instead of using a RuleEngine. This will simplify configuration and reduce runtime gas costs. + +## How it works + +This diagram illustrates how a transfer with a CMTAT or ERC-3643 token with a RuleEngine works: + +![RuleEngine.drawio](./doc/schema/RuleEngine.drawio.png) + + + +1. The token holders initiate a transfer transaction on the token contract. +2. The transfer function inside the token calls the ERC-3643 function `transferred` from the RuleEngine with the following parameters inside: `from, to, value`. +3. The Rule Engine calls each rule separately. If the transfer is not authorized by the rule, the rule must directly revert (no return value). + +### How to set it + +#### CMTAT v3.0.0 + +CMTAT provides the following function to set a RuleEngine inside a CMTAT token: + +```solidity + setRuleEngine(IRuleEngine ruleEngine_) +``` + +This function is defined in the extension module `ValidationModuleRuleEngine` + +#### ERC-3643 token + +[ERC-3643](https://eips.ethereum.org/EIPS/eip-3643) defined the following function in the standard interface to set a compliance contract + +```solidity +setCompliance(address _compliance) +``` -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/releases/tag/v3.0.0) ## How to include it -While it has been designed for the CMTAT, the ruleEngine can be used with others contracts to apply restriction on transfer. +While the RuleEngine has been designed for CMTAT and ERC-3643 tokens, it can be used with other contracts to apply transfer restrictions. + +For that, the only thing to do is to import in your contract the interface `IRuleEngine`(CMTAT) or `IERC3643Compliance` (ERC-3643), which declares the corresponding functions to call by the token contract. This interface can be found [here](https://github.com/CMTA/CMTAT/blob/23a1e59f913d079d0c09d32fafbd95ab2d426093/contracts/interfaces/engine/IRuleEngine.sol). + +### Like CMTAT + +Before each ERC-20 transfer, the CMTAT calls the function `transferred` which is the entrypoint for the RuleEngine. + +```solidity +function transferred(address from,address to,uint256 value) +``` + +If you want to apply restriction on the spender address, you have to call the `transferred` function which takes the spender argument in your ERC-20 function `transferFrom`. + +```solidity +function transferred(address spender,address from,address to,uint256 value) +``` + +For example, CMTAT defines the interaction with the RuleEngine inside a specific module, [ValidationModuleRuleEngine](https://github.com/CMTA/CMTAT/blob/master/contracts/modules/wrapper/extensions/ValidationModule/ValidationModuleRuleEngine.sol) and [CMTATBaseRuleEngine](https://github.com/CMTA/CMTAT/blob/master/contracts/modules/1_CMTATBaseRuleEngine.sol). + +- ValidationModuleRuleEngine + +![transferred](./doc/other/CMTAT/transferred.png) + +- CMTATBaseRuleEngine + +![checkTransferred](./doc/other/CMTAT/checkTransferred.png) + +This function `_transferred` is called before each transfer/burn/mint through the internal function `_checkTransferred` defined in [CMTAT_BASE](https://github.com/CMTA/CMTAT/blob/23a1e59f913d079d0c09d32fafbd95ab2d426093/contracts/modules/CMTAT_BASE.sol#L198). + +### Like ERC-3643 + +The ERC-3643 defines several functions used as entrypoint for an ERC-3643 token. + +They are the following: + +```solidity +// read-only function +function canTransfer(address from, address to, uint256 value) external view returns (bool); +// ERC-20 transfer +function transferred(address from, address to, uint256 value) external; +// mint +function created(address to, uint256 value) external; +// burn +function destroyed(address from, uint256 value) external; +``` + +## Interface + +### CMTAT + +The `RuleEngine` base interface is defined in CMTAT repository. + +![cmtat_surya_inheritance_IRuleEngine.sol](./doc/schema/cmtat_surya_inheritance_IRuleEngine.sol.png) + +It inherits from several others interface: `IERC1404Extend`, `IERC7551Compliance`, `IERC3643ComplianceContract` + +```solidity +// IRuleEngine +function transferred(address spender, address from, address to, uint256 value) +external; + +// IERC-1404 +function detectTransferRestriction(address from,address to,uint256 value) +external view returns (uint8); + +function messageForTransferRestriction(uint8 restrictionCode) +external view returns (string memory); + +// IERC-1404Extend +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 + } + +function detectTransferRestrictionFrom(address spender,address from,address to,uint256 value) +external view returns (uint8); + + +// IERC7551Compliance +function canTransferFrom(address spender,address from,address to,uint256 value) +external view returns (bool); + + +// IER3643ComplianceRead +function canTransfer(address from,address to,uint256 value) +external view returns (bool isValid); + +// IERC3643IComplianceContract +function transferred(address from, address to, uint256 value) +external; +``` + + -For that, the only thing to do is to import in your contract the interface `IRuleEngine` which declares the function `operateOnTransfer` +### ERC-3643 -This interface can be found in [CMTAT/contracts/interfaces/engine/IRuleEngine.sol](https://github.com/CMTA/CMTAT/blob/23a1e59f913d079d0c09d32fafbd95ab2d426093/contracts/interfaces/engine/IRuleEngine.sol) +The [ERC-3643](https://eips.ethereum.org/EIPS/eip-3643) compliance interface is defined in [IERC3643Compliance.sol](src/interfaces/IERC3643Compliance.sol). -Before each transfer, your contract must call the function `operateOnTransfer` which is the entrypoint for the RuleEngine. -## Schema -![Engine-RuleEngine.drawio](./doc/schema/Engine-RuleEngine.drawio.png) +A specific module implements this interface for the RuleEngine: [ERC3643Compliance.sol](src/modules/ERC3643Compliance.sol) + +![ERC3643ComplianceModuleUML](./doc/schema/vscode-uml/ERC3643ComplianceModuleUML.png) + +## Technical + +### Dependencies + +The toolchain includes the following components, where the versions are the latest ones that we tested: + +- Foundry (forge-std) [v1.10.0](https://github.com/foundry-rs/forge-std/releases/tag/v1.10.0) +- Solidity [0.8.30](https://docs.soliditylang.org/en/v0.8.30/) (via solc-js) +- OpenZeppelin Contracts (submodule) [v5.4.0](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.4.0) +- CMTAT [v3.0.0-rc7](https://github.com/CMTA/CMTAT/releases/tag/v3.0.0-rc7) + + + +### Contracts Description Table + +### Access Control (RBAC) + +CMTAT uses a RBAC access control by using the contract `AccessControl`from OpenZeppelin. + +Each module defines the roles useful to restrict its functions. + +The `AccessControlModule` which is used by all base and deployment contracts override the OpenZeppelin function `hasRole` to give by default all the roles to the `admin`. + +See also [docs.openzeppelin.com - AccessControl](https://docs.openzeppelin.com/contracts/5.x/api/access#AccessControl) + +#### Role list + +Here is the list of roles and their 32 bytes identifier. + +The default admin is the address put in argument(`admin`) inside the constructor. + +It is set in the constructor when the contract is deployed. + +| | Defined in | 32 bytes identifier | +| ----------------------- | -------------------------------- | ------------------------------------------------------------ | +| DEFAULT_ADMIN_ROLE | OpenZeppelin
AccessControl | 0x0000000000000000000000000000000000000000000000000000000000000000 | +| **Modules** | | | +| COMPLIANCE_MANAGER_ROLE | ERC3643Compliance | 0xe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede600028568 | +| RULES_MANAGEMENT_ROLE | RuleEngineInvariantStorageCommon | 0xea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e | + + + +#### Schema + +Here a schema of the Access Control. +![alt text](./doc/security/accessControl/access-control-RuleEngine.png) + + + + + +#### Role by modules + +Here a summary tab for each restricted functions defined in a module +For function signatures, struct arguments are represented with their corresponding native type. + +| | Function signature | Visibility [public/external] | Input variables (Function arguments) | Output variables
(return value) | Role Required | +| -------------------- | ------------------ | ---------------------------- | ------------------------------------ | ------------------------------------ | ------------- | +| **Modules** | | | | | | +| RulesManagementModule | | | | | | +| | `setRules(address[] rules_)` | public | `IRule[] rules_` | - | RULES_MANAGEMENT_ROLE | +| | `clearRules()` | public | - |-|RULES_MANAGEMENT_ROLE| +| | `addRule(address rule_)` | public | `IRule rule_` |-|RULES_MANAGEMENT_ROLE| +| | `removeRule(address rule_)` | public | `IRule rule_` |-|RULES_MANAGEMENT_ROLE| +| ERC3643ComplianceModule | | | | | | +| | `bindToken(address token)` | public | `address token` | - | COMPLIANCE_MANAGER_ROLE | +| | `unbindToken(address token)` | public | `address token` | - | COMPLIANCE_MANAGER_ROLE | +| RuleEngineBase | | | | | | +| | `transferred(address from,address to,uint256 value)` | public | `address from,address to, uint256 value` | - | onlyBoundToken (modifier) | +| | `transferred(address spender,address from,address to,uint256 value)` | public | `address spender,address from,address to, uint256 value` | - | onlyBoundToken (modifier) | + + ### UML -#### Global +![RuleEngineUML](./doc/schema/vscode-uml/RuleEngineUML.png) + + -> npm run-script uml -> -> No longer works, generate the following error: RangeError: Maximum call stack size exceeded -![uml](./doc/schema/classDiagram.svg) +### Graph -#### RuleEngine -> npm run-script uml:ruleEngine -> -> No longer works, instead: -> -> forge flatten src/RuleEngine.sol -o RuleEngine.sol -> -> npx sol2uml class RuleEngine.sol +![surya_graph_RuleEngine](./doc/schema/surya/surya_graph/surya_graph_RuleEngine.sol.png) + +## Functionality + +Several functionalities are not implemented because it makes more sense to directly implement them in the token smart contract + +The RuleEngine can be removed from the main token contract by calling these dedicated functions -![uml](./doc/schema/RuleEngine.svg) +- CMTAT v3.0.0: `setRuleEngine(address ruleEngine)` +- ERC-3643 token: `setCompliance(address _compliance)` -## Available Rules +### Available Rules + +Rules have their own dedicated repository: [github.com/CMTA/Rules](https://github.com/CMTA/Rules) The following rules are available: -| Rule | Type | Description | Doc | -| ------------------------------------------------------------ | -------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | -| [RuleWhitelist](src/rules/validation/RuleWhitelist.sol) | RuleValidation | This rule can be used to restrict transfers from/to only addresses inside a whitelist. | [RuleWhitelist.md](./doc/technical/RuleWhitelist.md)
[surya-report](./doc/surya/surya_report/surya_report_RuleWhitelist.sol.md) | -| [RuleWhitelistWrapper](src/rules/validation/RuleWhitelistWrapper.sol) | RuleValidation | This rule can be used to restrict transfers from/to only addresses inside a group of whitelist rules managed by different operators. | [RuleWhitelistWrapper.md](./doc/technical/RuleWhitelistWrapper.md)
[surya-report](./doc/surya/surya_report/surya_report_RuleWhitelistWrapper.sol.md) | -| [RuleBlacklist](src/rules/validation/RuleBlacklist.sol) | RuleValidation | This rule can be used to forbid transfer from/to addresses in the blacklist | [RuleBlacklist.md](./doc/technical/RuleBlacklist.md)
[surya-report](./doc/surya/surya_report/surya_report_RuleBlacklist.sol.md) | -| [RuleSanctionList](src/rules/validation/RuleSanctionList.sol) | RuleValidation | The purpose of this contract is to use the oracle contract from Chainalysis to forbid transfer from/to an address included in a sanctions designation (US, EU, or UN). | [RuleSanctionList.md](./doc/technical/RuleSanctionList.md)
[surya-report](./doc/surya/surya_report/surya_report_RuleSanctionList.sol.md) | -| [RuleConditionalTransfer](src/rules/operation/RuleConditionalTransfer.sol) | RuleOperation | This page describes a Conditional Transfer implementation. This rule requires that transfers have to be approved before being executed by the token holders. | [RuleConditionalTransfer.md](./doc/technical/RuleConditionalTransfer.md)
[surya-report](./doc/surya/surya_report/surya_report_RuleConditionalTransfer.sol.md) | +| Rule | Type
[ready-only / read-write] | Audit planned | Description | +| ----------------------- | ----------------------------------- | --------------------------------- | ------------------------------------------------------------ | +| RuleWhitelist | Ready-only | ☑ | This rule can be used to restrict transfers from/to only addresses inside a whitelist. | +| RuleWhitelistWrapper | Ready-only | ☑ | This rule can be used to restrict transfers from/to only addresses inside a group of whitelist rules managed by different operators. | +| RuleBlacklist | Ready-only | ☑ | This rule can be used to forbid transfer from/to addresses in the blacklist | +| RuleSanctionList | Ready-only | ☑ | The purpose of this contract is to use the oracle contract from Chainalysis to forbid transfer from/to an address included in a sanctions designation (US, EU, or UN). | +| RuleConditionalTransfer | Ready-Write | ☒
(experimental rule) | This rule requires that transfers have to be approved before being executed by the token holders. | + +### Gasless support (ERC-2771) +![ERC2771ModuleUML](./doc/schema/vscode-uml/ERC2771ModuleUML.png) +The RuleEngine supports client-side gasless transactions using the standard [ERC-2771](https://eips.ethereum.org/EIPS/eip-2771). -## Functionality +The contract uses the OpenZeppelin contract `ERC2771ContextUpgradeable`, which allows a contract to get the original client with `_msgSender()` instead of the feepayer given by `msg.sender`. + +At deployment, the parameter `forwarder` inside the RuleEngine contract constructor has to be set with the defined address of the forwarder. + +After deployment, the forwarder is immutable and can not be changed. + +References: + +- [OpenZeppelin Meta Transactions](https://docs.openzeppelin.com/contracts/5.x/api/metatx) + +- OpenGSN has deployed several forwarders, see their [documentation](https://docs.opengsn.org/contracts/#receiving-a-relayed-call) to see some examples. ### Upgradeable -The Rule Engine and the other rules are not upgradeable. The reason is the following: -If we need a new on, we just issue a new one, and set inside the CMTAT token (or the RuleEngine for the rules) to use the new. +A proxy architecture (upgradeable) increases the code complexity as well as the runtime gas cost for each transaction. This is why the RuleEngine is not upgradeable. + +Moreover, in a proxy architecture, each new implementation must be compatible (storage) with the precedent implementation, which can reduce the ability to improve the code. + +In case you use the same RuleEngine for several different tokens, unfortunately, you will have to update the address of the RuleEngine set in each token contract separately. ### Urgency mechanism -- Pause +#### Pause -There are no functionalities to put in pause the contracts. +There are no functionalities to put in pause the RuleEngine. -* Kill / Deactivate the contracts +The RuleEngine can be removed from the main token contract by calling the dedicated functions to manage the RuleEngine + +#### Kill / Deactivate the contracts There are no functionalities to kill/deactivate the contracts. +Similar to the pause functionality, the RuleEngine can be directly removed from the main token contract. -### Gasless support (ERC-2771) +## Ethereum API + +### RuleEngineBase + +![RuleEngineBaseUML](./doc/schema/vscode-uml/RuleEngineBaseUML.png) + +#### IRuleEngine + +![IRuleEngineUML](./doc/schema/vscode-uml/IRuleEngineUML.png) + +##### transferred(address spender, address from, address to, uint256 value) + +```solidity +function transferred(address spender,address from,address to,uint256 value) +public virtual override(IRuleEngine) +onlyBoundToken +``` + +Function called whenever tokens are transferred from one wallet to another. + +Must revert if the transfer is invalid. + Same name as ERC-3643 but with an additional `spender` parameter. + This function can be used to update state variables of the RuleEngine contract. + Can only be called by the token contract bound to the RuleEngine. -> The gasless integration was not part of the audit performed by ABDK on the version [1.0.1](https://github.com/CMTA/RuleEngine/releases/tag/1.0.1) +**Input Parameters:** -The RuleEngine contracts and the other rules support client-side gasless transactions using the [Gas Station Network](https://docs.opengsn.org/#the-problem) (GSN) pattern, the main open standard for transfering fee payment to another account than that of the transaction issuer. The contract uses the OpenZeppelin contract `ERC2771Context`, which allows a contract to get the original client with `_msgSender()` instead of the fee payer given by `msg.sender` . +| Name | Type | Description | +| ------- | ------- | ---------------------------------------------- | +| spender | address | The spender address initiating the transfer. | +| from | address | The token holder address. | +| to | address | The receiver address. | +| value | uint256 | The amount of tokens involved in the transfer. | -At deployment, the parameter `forwarder` inside the contract constructor has to be set with the defined address of the forwarder. Please note that the forwarder can not be changed after deployment. +#### IERC7551Compliance -Please see the OpenGSN [documentation](https://docs.opengsn.org/contracts/#receiving-a-relayed-call) for more details on what is done to support GSN in the contract. +![IERC7551ComplianceUML](./doc/schema/vscode-uml/IERC7551ComplianceUML.png) -## Audit +##### canTransferFrom(address spender, address from, address to, uint256 value) -> bool + +Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules. + +Does not check balances or access rights (Access Control). + +**Input Parameters:** + +| Name | Type | Description | +| ------- | ------- | ------------------------------------ | +| spender | address | The address performing the transfer. | +| from | address | The source address. | +| to | address | The destination address. | +| value | uint256 | The number of tokens to transfer. | + + + +**Return Values:** + +| Type | Description | +| ---- | ------------------------------------------ | +| bool | True if the transfer complies with policy. | + +#### IERC3643ComplianceRead + +![IERC3643ComplianceReadUML](./doc/schema/vscode-uml/IERC3643ComplianceReadUML.png) + +------ + +##### canTransfer(address from, address to, uint256 value) -> bool + +Returns true if the transfer is valid, and false otherwise. + +Does not check balances or access rights (Access Control). + +**Input Parameters:** + +| Name | Type | Description | +| ----- | ------- | --------------------------------- | +| from | address | The source address. | +| to | address | The destination address. | +| value | uint256 | The number of tokens to transfer. | + + + +**Return Values:** + +| Type | Description | +| ---- | ----------------------------------------------- | +| bool | True if the transfer is valid, false otherwise. | + +#### IERC3643IComplianceContract + +![IERC3643IComplianceContractUML](./doc/schema/vscode-uml/IERC3643IComplianceContractUML.png) + +------ + +##### transferred(address from, address to, uint256 value) + +```solidity +function transferred(address from,address to,uint256 value) +public virtual override(IERC3643IComplianceContract) +onlyBoundToken +``` + +Updates the compliance contract state whenever tokens are transferred. + +Can only be called by the token contract bound to this compliance logic. + This function can be used to update internal state variables. + +**Input Parameters:** + +| Name | Type | Description | +| ----- | ------- | ---------------------------------------------- | +| from | address | The address of the sender. | +| to | address | The address of the receiver. | +| value | uint256 | The number of tokens involved in the transfer. | + + + +#### IERC3643Compliance + +------ + +##### created(address to, uint256 value) + +```solidity +function created(address to, uint256 value) +public virtual override(IERC3643Compliance) +onlyBoundToken +``` + +Updates the compliance contract state when tokens are created (minted). + +Called by the token contract when new tokens are issued to an account. + Reverts if the minting does not comply with the rules. + +**Input Parameters:** + +| Name | Type | Description | +| ----- | ------- | ---------------------------------------- | +| to | address | The address receiving the minted tokens. | +| value | uint256 | The number of tokens created. | + + + +------ + +##### destroyed(address from, uint256 value) + +```solidity +function destroyed(address from, uint256 value) +public virtual override(IERC3643Compliance) +onlyBoundToken +``` + +Updates the compliance contract state when tokens are destroyed (burned). + +Called by the token contract when tokens are redeemed or burned. + Reverts if the burning does not comply with the rules. + +**Input Parameters:** + +| Name | Type | Description | +| ----- | ------- | --------------------------------------------- | +| from | address | The address whose tokens are being destroyed. | +| value | uint256 | The number of tokens destroyed. | + + + +#### IERC1404 + +![IERC1404UML](./doc/schema/vscode-uml/IERC1404UML.png) + +------ + +##### detectTransferRestriction(address from, address to, uint256 value) -> uint8 + +Returns a uint8 code to indicate if a transfer is restricted or not. + +Implements the restriction logic of {ERC-1404}. + Examples of restriction logic include: + +- checking if the recipient is whitelisted, +- checking if the sender’s tokens are frozen during a lock-up period, etc. + +**Input Parameters:** + +| Name | Type | Description | +| ----- | ------- | --------------------------------- | +| from | address | The source address. | +| to | address | The destination address. | +| value | uint256 | The number of tokens to transfer. | + + + +**Return Values:** + +| Type | Description | +| ----- | ------------------------------------------------------ | +| uint8 | Restriction code (0 means the transfer is authorized). | + + + +------ + +##### messageForTransferRestriction(uint8 restrictionCode) -> string + +Returns a human-readable explanation for a transfer restriction code. + +Implements {ERC-1404} standard message accessor. + +**Input Parameters:** + +| Name | Type | Description | +| --------------- | ----- | ---------------------------------- | +| restrictionCode | uint8 | The restriction code to interpret. | + + + +**Return Values:** + +| Type | Description | +| ------ | ---------------------------------------------------- | +| string | A message describing why the transfer is restricted. | + + + +------ + +#### IERC1404Extend + +![IERC1404ExtendUML](./doc/schema/vscode-uml/IERC1404ExtendUML.png) + +##### enum REJECTED_CODE_BASE + +Error codes for transfer restrictions. + Codes `6–9` are reserved for future CMTAT ruleEngine extensions. + +| Name | Value | Description | +| -------------------------------------------------- | ----- | ------------------------------------------------------------ | +| TRANSFER_OK | 0 | Transfer authorized. | +| TRANSFER_REJECTED_PAUSED | 1 | Transfer rejected because the token is paused. | +| TRANSFER_REJECTED_FROM_FROZEN | 2 | Transfer rejected because the sender’s address is frozen. | +| TRANSFER_REJECTED_TO_FROZEN | 3 | Transfer rejected because the recipient’s address is frozen. | +| TRANSFER_REJECTED_SPENDER_FROZEN | 4 | Transfer rejected because the spender’s address is frozen. | +| TRANSFER_REJECTED_FROM_INSUFFICIENT_ACTIVE_BALANCE | 5 | Transfer rejected because the sender does not have enough active (unfrozen) balance. | + + + +------ + +##### detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) -> uint8 + +Returns a uint8 code to indicate if a transfer is restricted or not. + +This is an extension of {ERC-1404} with an additional `spender` parameter to enforce restriction logic on delegated transfers. + Examples of restriction logic include: + +- verifying if the recipient is whitelisted, +- verifying if tokens are locked for either sender or spender, etc. + +**Input Parameters:** + +| Name | Type | Description | +| ------- | ------- | ------------------------------------------------------------ | +| spender | address | The address initiating the transfer (for delegated transfers). | +| from | address | The source address. | +| to | address | The destination address. | +| value | uint256 | The number of tokens to transfer. | + + + +**Return Values:** + +| Type | Description | +| ----- | ------------------------------------------------------ | +| uint8 | Restriction code (0 means the transfer is authorized). | + + + +------ + +### VersionModule + +![VersionModuleUML](./doc/schema/vscode-uml/VersionModuleUML.png) + +#### version() + +```solidity +function version() external view returns (string memory version_); +``` + +```solidity +function version() +public view virtual override(IERC3643Base) +returns (string memory version_) +``` + + **Description** + +Returns the current version of the token contract. +Useful for identifying which version of the smart contract is deployed and in use. + +**Return** + +| Name | Type | Description | +| ---------- | ------ | ------------------------------------------------------------ | +| `version_` | string | The version string of the token implementation (e.g., "1.0.0"). | + + + +### ERC3643ComplianceModule + +![ERC3643ComplianceModuleUML](./doc/schema/vscode-uml/ERC3643ComplianceModuleUML.png) + +#### Events + +##### TokenBound(address token) + +```solidity +event TokenBound(address token) +``` + +Emitted when a token is successfully bound to the compliance contract. + +**Event Parameters:** + +| Name | Type | Description | +| ----- | ------- | ---------------------------------------- | +| token | address | The address of the token that was bound. | + + + +------ + +##### TokenUnbound(address token) + +```solidity +event TokenUnbound(address token) +``` + +Emitted when a token is successfully unbound from the compliance contract. + +**Event Parameters:** + +| Name | Type | Description | +| ----- | ------- | ------------------------------------------ | +| token | address | The address of the token that was unbound. | + + + +------ + +#### Functions + +##### bindToken(address token) + +```solidity +function bindToken(address token) +public override virtual +onlyRole(COMPLIANCE_MANAGER_ROLE) +``` + +Associates a token contract with this compliance contract. + +The compliance contract may restrict operations on the bound token according to its internal compliance logic. + Reverts if the token is already bound. + +**Input Parameters:** + +| Name | Type | Description | +| ----- | ------- | --------------------------------- | +| token | address | The address of the token to bind. | + + + +------ + +##### unbindToken(address token) + +```solidity +function unbindToken(address token) +public override virtual +onlyRole(COMPLIANCE_MANAGER_ROLE) +``` + +Removes the association of a token contract from this compliance contract. + +Reverts if the token is not currently bound. + +**Input Parameters:** + +| Name | Type | Description | +| ----- | ------- | ----------------------------------- | +| token | address | The address of the token to unbind. | + + + +------ + +##### isTokenBound(address token) -> bool + +```solidity +function isTokenBound(address token) +public view virtual override +returns (bool) +``` + +Checks whether a token is currently bound to this compliance contract. + +**Input Parameters:** + +| Name | Type | Description | +| ----- | ------- | ---------------------------- | +| token | address | The token address to verify. | + + + +**Return Values:** + +| Type | Description | +| ---- | -------------------------------------------- | +| bool | True if the token is bound, false otherwise. | + + + +------ + +##### getTokenBound() -> address + +```solidity +function getTokenBound() +public view virtual override +returns (address) +``` + +Returns the single token currently bound to this compliance contract. + +If multiple tokens are supported, consider using `getTokenBounds()`. + +Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed. + +**Return Values:** + +| Type | Description | +| ------- | ----------------------------------------- | +| address | The address of the currently bound token. | + + + +------ + +##### getTokenBounds() -> address[] + +```solidity +function getTokenBounds() +public view override +returns (address[] memory) +``` + +Returns all tokens currently bound to this compliance contract. + +This is a view-only function and does not modify state. +This function is not part of the original ERC-3643 specification. + +This operation will copy the entire storage to memory, which can be quite expensive. + +This is designed to mostly be used by view accessors that are queried without any gas fees. + +**Return Values:** + +| Type | Description | +| --------- | ----------------------------------------------- | +| address[] | An array of addresses of bound token contracts. | + + + +### RulesManagementModule + +![RuleManagementModuleUML](./doc/schema/vscode-uml/RuleManagementModuleUML.png) + +#### Events + +#### event AddRule(address rule) + +```solidity +event AddRule(IRule indexed rule) +``` + +Emitted when a new rule is added to the rule set. + +**Event Parameters:** + +| Name | Type | Description | +| ---- | ----- | ------------------------------------------------ | +| rule | IRule | The address of the rule contract that was added. | + +------ + +#### event RemoveRule(address rule) + +```solidity +event RemoveRule(IRule indexed rule) +``` + +Emitted when a rule is removed from the rule set. + +**Event Parameters:** + +| Name | Type | Description | +| ---- | ----- | -------------------------------------------------- | +| rule | IRule | The address of the rule contract that was removed. | + +------ + +#### event ClearRules() + +```solidity +event ClearRules() +``` + +Emitted when all rules are cleared from the rule set. + +This event has no parameters. + +#### Functions + +##### setRules(address[] rules_) + +```solidity +function setRules(IRule[] calldata rules_) +public virtual override(IRulesManagementModule) +onlyRole(RULES_MANAGEMENT_ROLE) +``` + +Defines the complete list of rules for the rule engine. + +Any previously configured rules are completely replaced. + Rules must be deployed contracts implementing the expected `IRule` interface. + Reverts if any rule address is zero or if duplicates are detected. + +This function calls _clearRules if at least one rule is still configured + +**Input Parameters:** + +| Name | Type | Description | +| ------ | ------- | ------------------------------------------------------------ | +| rules_ | IRule[] | The array of IRule contracts to configure as the active rules. | + + + +------ + +##### rulesCount() -> uint256 + +```solidity +function rulesCount() +public view virtual override(IRulesManagementModule) +returns (uint256) +``` + +Returns the total number of currently configured rules. + +Equivalent to the length of the internal rules array. + +**Return Values:** + +| Type | Description | +| ------- | --------------------------- | +| uint256 | The number of active rules. | + + + +------ + +##### rule(uint256 ruleId) -> address + +```solidity +function rule(uint256 ruleId) +public view virtual override(IRulesManagementModule) +returns (address) +``` + +Retrieves the rule address at a specific index. + +Return the`zero address` is out of bounds. + +Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed. + +**Input Parameters:** + +| Name | Type | Description | +| ------ | ------- | ------------------------------------------- | +| ruleId | uint256 | The index of the desired rule in the array. | + + + +**Return Values:** + +| Type | Description | +| ------- | ------------------------------------------------ | +| address | The address of the corresponding IRule contract. | + + + +------ + +##### rules() -> address[] + +```solidity +function rules() +public view virtual override(IRulesManagementModule) +returns (address[] memory) +``` + +Returns the full list of currently configured rules. + +This is a view-only function and does not modify state. + +This operation will copy the entire storage to memory, which can be quite expensive. + +This is designed to mostly be used by view accessors that are queried without any gas fees. + +**Return Values:** + +| Type | Description | +| --------- | ------------------------------------------------------- | +| address[] | An array containing all active rule contract addresses. | + + + +------ + +##### clearRules() + +```solidity +function clearRules() +public virtual override(IRulesManagementModule) +onlyRole(RULES_MANAGEMENT_ROLE) +``` + +Removes all configured rules. + +After calling this function, no rules will remain set. + +Developers should keep in mind that this function has an unbounded cost and using it may render the function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block. + +------ + +##### addRule(address rule_) + +```solidity +function addRule(IRule rule_) +public virtual override(IRulesManagementModule) +onlyRole(RULES_MANAGEMENT_ROLE) +``` + +Adds a new rule to the current rule set. + +Reverts if the rule address is zero or already exists in the set. + +**Input Parameters:** + +| Name | Type | Description | +| ----- | ----- | -------------------------- | +| rule_ | IRule | The IRule contract to add. | + + + +------ + +##### removeRule(address rule_) + +```solidity + function removeRule(IRule rule_) + public virtual + override(IRulesManagementModule) + onlyRole(RULES_MANAGEMENT_ROLE) +``` + +Removes a specific rule from the current rule set. + +Reverts if the provided rule is not found or does not match the stored rule at its index. + +**Input Parameters:** + +| Name | Type | Description | +| ----- | ----- | ----------------------------- | +| rule_ | IRule | The IRule contract to remove. | + + + +------ + +##### containsRule(address rule_) -> bool + +```solidity +function containsRule(IRule rule_) +public view virtual override(IRulesManagementModule) +returns (bool) +``` + +Checks whether a specific rule is currently configured. + +**Input Parameters:** + +| Name | Type | Description | +| ----- | ----- | ------------------------------------------- | +| rule_ | IRule | The IRule contract to check for membership. | + + + +**Return Values:** + +| Type | Description | +| ---- | --------------------------------------------- | +| bool | True if the rule is present, false otherwise. | + +## Security + +### Vulnerability disclosure + +Please see [SECURITY.md](https://github.com/CMTA/CMTAT/blob/master/SECURITY.md) (CMTAT main repository). The contracts have been audited by [ABDKConsulting](https://www.abdk.consulting/), a globally recognized firm specialized in smart contracts' security. -### First Audit - March 2022 +### Audit + +#### First Audit - March 2022 Fixed version : [v1.0.2](https://github.com/CMTA/RuleEngine/releases/tag/v1.0.2) @@ -115,31 +1069,63 @@ The final report is available in [ABDK_CMTA_CMTATRuleEngine_v_1_0.pdf](https://g ### Tools -You will find the report performed with [Slither](https://github.com/crytic/slither) in +#### Slither + +Here is the list of report performed with [Slither](https://github.com/crytic/slither) | Version | File | | ------- | ------------------------------------------------------------ | | latest | [slither-report.md](./doc/security/audits/tools/slither-report.md) | +```bash +slither . --checklist --filter-paths "openzeppelin-contracts|test|CMTAT|forge-std|mocks" > slither-report.md +``` + +#### Aderyn + +Here is the list of report performed with [Aderyn](https://github.com/Cyfrin/aderyn) + +```bash +aderyn -x mocks --output aderyn-report.md +``` + +| Version | File | +| ------- | ------------------------------------------------------------ | +| latest | [aderyn-report.md](./doc/security/audits/tools/aderyn-report.md) | + ## Documentation Here a summary of the main documentation -| Document | Link/Files | -| ----------------------- | ---------------------------------------------------- | -| Technical documentation | [doc/technical/](./doc/technical/) | -| Toolchain | [doc/TOOLCHAIN.md](./doc/TOOLCHAIN.md) | -| Functionalities | [doc/functionalities.pdf](./doc/functionalities.pdf) | -| Surya report | [doc/surya](./doc/surya/) | +| Document | Link/Files | +| ------------ | --------------------------------------- | +| Toolchain | [doc/TOOLCHAIN.md](./doc/TOOLCHAIN.md) | +| Surya report | [doc/schema/surya](./doc/schema/surya/) | -See also [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/) (CMTAT v2.4.0) +See also [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/) (RuleEngine v2.02 and CMTAT v2.4.0) -## Usage +## Toolchains and Usage *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 + + + ### Toolchain installation The contracts are developed and tested with [Foundry](https://book.getfoundry.sh), a smart contract development toolchain. @@ -164,19 +1150,23 @@ forge update See also the command's [documentation](https://book.getfoundry.sh/reference/forge/forge-update). - - ### Compilation The official documentation is available in the Foundry [website](https://book.getfoundry.sh/reference/forge/build-commands) ``` forge build --contracts src/RuleEngine.sol ``` -``` - forge build --contracts src/RuleWhiteList.sol +### Contract size + +```bash + forge compile --sizes ``` + +![contract-size](./doc/compilation/contract-size.png) + ### Testing + You can run the tests with ```bash @@ -198,6 +1188,11 @@ 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). + +![code-coverage](./doc/coverage/code-coverage.png) + * Perform a code coverage ``` forge coverage @@ -211,13 +1206,13 @@ forge coverage --report lcov - Generate `index.html` ```bash -forge coverage --report lcov && genhtml lcov.info --branch-coverage --output-dir coverage +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](https://www.rareskills.io/post/foundry-forge-coverage) ### Deployment -The official documentation is available in the Foundry [website](https://book.getfoundry.sh/reference/forge/deploy-commands) +The official documentation is available in the Foundry [website](https://getfoundry.sh/forge/deploying) #### Script > This documentation has been written for the version v1.0.2 @@ -237,7 +1232,13 @@ CMTAT with RuleEngine ```bash forge script script/CMTATWithRuleEngineScript.s.sol:CMTATWithRuleEngineScript --rpc-url=$RPC_URL --broadcast --verify -vvv ``` -Value of YOUR_RPC_URL with a local instance of anvil : [127.0.0.1:8545](http://127.0.0.1:8545) + + +- Value of YOUR_RPC_URL with a local instance of anvil : [127.0.0.1:8545](http://127.0.0.1:8545) + +```bash +forge script script/CMTATWithRuleEngineScript.s.sol:CMTATWithRuleEngineScript --rpc-url=127.0.0.1:8545 --broadcast --verify -vvv +``` Only RuleEngine with a Whitelist contract @@ -245,6 +1246,48 @@ Only RuleEngine with a Whitelist contract forge script script/RuleEngineScript.s.sol:RuleEngineScript --rpc-url=$RPC_URL --broadcast --verify -vvv ``` +- With anvil + +```bash +forge script script/RuleEngineScript.s.sol:RuleEngineScript --rpc-url=127.0.0.1:8545 --broadcast --verify -vvv +``` + +### Solidity style guideline + +RuleEngine follows the [solidity style guideline](https://docs.soliditylang.org/en/latest/style-guide.html) and the [natspec format](https://docs.soliditylang.org/en/latest/natspec-format.html) for comments + +- Orders of Functions + +Functions are grouped according to their visibility and ordered: + +``` +1. constructor + +2. receive function (if exists) + +3. fallback function (if exists) + +4. external + +5. public + +6. internal + +7. private +``` + +Within a grouping, place the `view` and `pure` functions last + +- Function declaration + +``` +1. Visibility +2. Mutability +3. Virtual +4. Override +5. Custom modifiers +``` + ## Intellectual property -The code is copyright (c) Capital Market and Technology Association, 2018-2024, and is released under [Mozilla Public License 2.0](https://github.com/CMTA/CMTAT/blob/master/LICENSE.md). +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..0603622 100644 --- a/doc/TOOLCHAIN.md +++ b/doc/TOOLCHAIN.md @@ -74,38 +74,37 @@ npm run-script uml:test Or only specified contracts -RuleEngine - ``` npx sol2uml class -i -c src/RuleEngine.sol ``` -Whitelist - -``` -npx sol2uml class src/Whitelist.sol -``` - The related component can be installed with `npm install` (see [package.json](./package.json)). +> To avoid the error "Maximum call stack size exceeded", you can flatten the contract before +> +> forge flatten src/RuleEngine.sol > RuleEngineFlatten.sol + ### [Surya](https://github.com/ConsenSys/surya) -#### Graph +To generate documentation with surya, you can call the three bash scripts in `doc/script` -To generate graphs with Surya, you can run the following command +| Task | Script | +| -------------------- | ----------------------------- | +| Generate graph | `script_surya_graph.sh` | +| Generate inheritance | `script_surya_inheritance.sh` | +| Generate report | `script_surya_report.sh` | + +In the report, the path for the different files are indicated in absolute. You have to remove the part which correspond to your local filesystem. -```bash -npm run-script surya:graph -``` -OR -- RuleWhitelist +#### Graph + +To generate graphs with Surya, you can run the following command ```bash - npx surya graph src/RuleWhitelist.sol | dot -Tpng > surya_graph_Whitelist.png +npm run-script surya:graph ``` -- RuleEngine ```bash npx surya graph src/RuleEngine.sol | dot -Tpng > surya_graph_RuleEngine.png 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/compilation/contract-size.png b/doc/compilation/contract-size.png new file mode 100644 index 0000000..cd7e963 Binary files /dev/null and b/doc/compilation/contract-size.png differ diff --git a/doc/compilation/flatten/RuleEngineFlatten.sol b/doc/compilation/flatten/RuleEngineFlatten.sol new file mode 100644 index 0000000..e1899d0 --- /dev/null +++ b/doc/compilation/flatten/RuleEngineFlatten.sol @@ -0,0 +1,5494 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity >=0.4.16 >=0.8.4 ^0.8.20; + +// lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol + +/** +* Note: +* Parameter names may differ slightly from the original ERC3643 spec +* to align with OpenZeppelin v5.3.0 naming conventions +* (e.g., `amount` → `value`). +*/ + +/** + * @title IERC3643Pause + * @dev Interface for pausing and unpausing token transfers. + * Common interface shared between CMTAT and ERC3643 implementations. + * + */ +interface IERC3643Pause { + /** + * @notice Indicates whether the contract is currently paused. + * @dev When paused, token transfers are disabled. + * @return True if the contract is paused, false otherwise. + */ + function paused() external view returns (bool); + /** + * @notice Pauses all token transfers. + * @dev Once paused, calls to transfer-related functions will revert. + * Can only be called by an account with the appropriate permission. + * + * Emits a {Paused} event. + */ + function pause() external; + + /** + * @notice Unpauses token transfers. + * @dev Restores normal token transfer behavior after a pause. + * Can only be called by an account with the appropriate permission. + * + * Emits an {Unpaused} event. + */ + function unpause() external; +} +/** + * @title ERC-3643 Base Interface for ERC-20 Token Metadata + * @dev Provides functions to update token name and symbol. + */ +interface IERC3643ERC20Base { + /** + * @notice Updates the name of the token. + * @dev Can be used to rename the token post-deployment. + * @param name The new name to assign to the token. + */ + function setName(string calldata name) external; + + /** + * @notice Updates the symbol of the token. + * @dev Can be used to change the token's symbol (e.g. for branding or reissuance). + * @param symbol The new symbol to assign to the token. + */ + function setSymbol(string calldata symbol) external; +} + +/** + * @title IERC3643BatchTransfer + * @notice Interface for batch token transfers under the ERC-3643 standard. + */ +interface IERC3643BatchTransfer { + /** + * @notice Transfers tokens to multiple recipient addresses in a single transaction. + * @dev + * Batch version of `transfer` + * - Each recipient receives the number of tokens specified in the `values` array. + * Requirement: + * - The `tos` array must not be empty. + * - `tos.length` must equal `values.length`. + * - `tos`cannot contain a zero address + * - the caller must have a balance cooresponding to the total values + * Events: + * - Emits one `Transfer` event per recipient (i.e., `tos.length` total). + * + * Enforcement-specific behavior: + * - If `IERC3643Enforcement` is implemented: + * - The sender (`msg.sender`) and each recipient in `tos` MUST NOT be frozen. + * - If `IERC3643ERC20Enforcement` is implemented: + * - The total amount transferred MUST NOT exceed the sender's available (unfrozen) balance. + * + * Note: This implementation differs from the base ERC-3643 specification by returning a `bool` + * value for compatibility with the ERC-20 `transfer` function semantics. + * + * @param tos The list of recipient addresses. + * @param values The list of token amounts corresponding to each recipient. + * @return success_ A boolean indicating whether the batch transfer was successful. + */ + function batchTransfer(address[] calldata tos,uint256[] calldata values) external returns (bool success_); +} + +/** + * @title IERC3643Base + * @notice Interface to retrieve version + */ +interface IERC3643Base { + /** + * @notice Returns the current version of the token contract. + * @dev This value is useful to know which smart contract version has been used + * @return version_ A string representing the version of the token implementation (e.g., "1.0.0"). + */ + function version() external view returns (string memory version_); +} + +/** + * @title IERC3643EnforcementEvent + * @notice Interface defining the event for account freezing and unfreezing. + */ +interface IERC3643EnforcementEvent { + /** + * @notice Emitted when an account's frozen status is changed. + * @dev + * - `account` is the address whose status changed. + * - `isFrozen` reflects the new status after the function execution: + * - `true`: account is frozen. + * - `false`: account is unfrozen. + * - `enforcer` is the address that executed the freezing/unfreezing. + * - `data` provides optional contextual information for auditing or documentation purposes. + * The event is emitted by `setAddressFrozen` and `batchSetAddressFrozen` functions + * Note: This event extends the ERC-3643 specification by including the `data` field. + * + * @param account The address that was frozen or unfrozen. + * @param isFrozen The resulting freeze status of the account. + * @param enforcer The address that initiated the change. + * @param data Additional data related to the freezing action. + */ + event AddressFrozen(address indexed account, bool indexed isFrozen, address indexed enforcer, bytes data); +} + +/** + * @title IERC3643Enforcement + * @notice Interface for account-level freezing logic. + * @dev Provides methods to check and update whether an address is frozen. + */ +interface IERC3643Enforcement { + /** + * @notice Checks whether a given account is currently frozen. + * @param account The address to query. + * @return isFrozen_ A boolean indicating if the account is frozen (`true`) or not (`false`). + */ + function isFrozen(address account) external view returns (bool isFrozen_); + /** + * @notice Sets the frozen status of a specific address. + * @dev Emits an `AddressFrozen` event. + * @param account The address whose frozen status is being updated. + * @param freeze The new frozen status (`true` to freeze, `false` to unfreeze). + */ + function setAddressFrozen(address account, bool freeze) external; + /** + * @notice Batch version of {setAddressFrozen}, allowing multiple addresses to be updated in one call. + * @param accounts An array of addresses to update. + * @param freeze An array of corresponding frozen statuses for each address. + * Requirements: + * - `accounts.length` must be equal to `freeze.length`. + */ + function batchSetAddressFrozen(address[] calldata accounts, bool[] calldata freeze) external; +} + +/** + * @title IERC3643ERC20Enforcement + * @notice Interface for enforcing partial token freezes and forced transfers, typically used in compliance-sensitive ERC-1400 scenarios. + * @dev For event definitions, see {IERC7551ERC20Enforcement}. + */ +interface IERC3643ERC20Enforcement { + /* ============ View Functions ============ */ + /** + * @notice Returns the number of tokens that are currently frozen (i.e., non-transferable) for a given account. + * @dev The frozen amount is always less than or equal to the total balance of the account. + * @param account The address of the wallet being queried. + * @return frozenBalance_ The amount of frozen tokens held by the account. + */ + function getFrozenTokens(address account) external view returns (uint256 frozenBalance_); + + /* ============ State Functions ============ */ + + /** + * @notice Freezes a specific amount of tokens for a given account. + * @dev Emits a `TokensFrozen` event. Prevents the frozen amount from being transferred. + * @param account The wallet address whose tokens are to be frozen. + * @param value The amount of tokens to freeze. + */ + function freezePartialTokens(address account, uint256 value) external; + + /** + * @notice unfreezes token amount specified for given address + * @dev Emits a TokensUnfrozen event + * @param account The address for which to update frozen tokens + * @param value Amount of Tokens to be unfrozen + */ + function unfreezePartialTokens(address account, uint256 value) external; + /** + * + * @notice Triggers a forced transfer. + * @dev +* * Force a transfer of tokens between 2 token holders + * If IERC364320Enforcement is implemented: + * Require that the total value should not exceed available balance. + * In case the `from` address has not enough free tokens (unfrozen tokens) + * but has a total balance higher or equal to the `amount` + * the amount of frozen tokens is reduced in order to have enough free tokens + * to proceed the transfer, in such a case, the remaining balance on the `from` + * account is 100% composed of frozen tokens post-transfer. + * emits a `TokensUnfrozen` event if `value` is higher than the free balance of `from` + * Emits a `Transfer` event + * @param from The address of the token holder + * @param to The address of the receiver + * @param value amount of tokens to transfer + * @return success_ `true` if successful and revert if unsuccessful + + */ + function forcedTransfer(address from, address to, uint256 value) external returns (bool success_); + +} +/** +* @title IERC3643Mint — Token Minting Interface +* @dev Interface for mintint ERC-20 compatible tokens under the ERC-3643 standard. +* Implements both single and batch mint functionalities, with support for frozen address logic if enforced. +*/ +interface IERC3643Mint{ + /** + * @notice Creates (`mints`) a specified `value` of tokens and assigns them to the `account`. + * @dev Tokens are minted by transferring them from the zero address (`address(0)`). + * Emits a {Mint} event and a {Transfer} event with `from` set to `address(0)`. + * Requirement: + * Account must not be the zero address. + * @param account The address that will receive the newly minted tokens. + * @param value The amount of tokens to mint to `account`. + */ + function mint(address account, uint256 value) external; + /** + * @notice Batch version of {mint}, allowing multiple mint operations in a single transaction. + * @dev + * For each mint action: + * - Emits a {Mint} event. + * - Emits a {Transfer} event with `from` set to the zero address. + * - Requires that `accounts` and `values` arrays have the same length. + * - None of the addresses in `accounts` can be the zero address. + * - Be cautious with large arrays as the transaction may run out of gas. + * @param accounts The list of recipient addresses for the minted tokens. + * @param values The respective amounts of tokens to mint for each recipient. + */ + function batchMint( address[] calldata accounts,uint256[] calldata values) external; +} + +/** +* @title IERC3643Burn — Token Burning Interface +* @dev Interface for burning ERC-20 compatible tokens under the ERC-3643 standard. +* Implements both single and batch burn functionalities, with support for frozen token logic if enforced. +*/ +interface IERC3643Burn{ + /** + * @notice Burns a specified amount of tokens from a given account by transferring them to `address(0)`. + * @dev + * - Decreases the total token supply by the specified `value`. + * - Emits a `Transfer` event to indicate the burn (with `to` set to `address(0)`). + * - If `IERC364320Enforcement` is implemented: + * - If the account has insufficient free (unfrozen) tokens but a sufficient total balance, + * frozen tokens are reduced to complete the burn. + * - The remaining balance on the account will consist entirely of frozen tokens after the burn. + * - Emits a `TokensUnfrozen` event if frozen tokens are unfrozen to allow the burn. + * + * @param account The address from which tokens will be burned. + * @param value The amount of tokens to burn. + */ + function burn(address account,uint256 value) external; + /** + * @notice Performs a batch burn operation, removing tokens from multiple accounts in a single transaction. + * @dev + * - Batch version of {burn} + * - Executes the burn operation for each account in the `accounts` array, using corresponding amounts in the `values` array. + * - Emits a `Transfer` event for each burn (with `to` set to `address(0)`). + * - This operation is gas-intensive and may fail if the number of accounts (`accounts.length`) is too large, causing an "out of gas" error. + * - Use with caution to avoid unnecessary transaction fees. + * Requirement: + * - `accounts` and `values` must have the same length + * @param accounts An array of addresses from which tokens will be burned. + * @param values An array of token amounts to burn, corresponding to each address in `accounts`. + */ + function batchBurn(address[] calldata accounts,uint256[] calldata values) external; +} + +interface IERC3643ComplianceRead { + /** + * @notice Returns true if the transfer is valid, and false otherwise. + * @dev Don't check the balance and the user's right (access control) + */ + function canTransfer( + address from, + address to, + uint256 value + ) external view returns (bool isValid); +} + +interface IERC3643IComplianceContract { + /** + * @notice + * Function called whenever tokens are transferred + * from one wallet to another + * @dev + * This function can be used to update state variables of the compliance contract + * This function can be called ONLY by the token contract bound to the compliance + * @param from The address of the sender + * @param to The address of the receiver + * @param value value of tokens involved in the transfer + */ + function transferred(address from, address to, uint256 value) external; +} + +// lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol + +/* +* @dev Contrary to the ERC-1404, +* this interface does not inherit directly from the ERC20 interface +*/ +interface IERC1404 { + + /** + * @notice Returns a uint8 code to indicate if a transfer is restricted or not + * @dev + * See {ERC-1404} + * This function is where an issuer enforces the restriction logic of their token transfers. + * Some examples of this might include: + * - checking if the token recipient is whitelisted, + * - checking if a sender's tokens are frozen in a lock-up period, etc. + * @return uint8 restricted code, 0 means the transfer is authorized + * + */ + function detectTransferRestriction( + address from, + address to, + uint256 value + ) external view returns (uint8); + + /** + * @dev See {ERC-1404} + * This function is effectively an accessor for the "message", + * a human-readable explanation as to why a transaction is restricted. + * + */ + function messageForTransferRestriction( + uint8 restrictionCode + ) external view returns (string memory); +} + +/** +* @title IERC1404 with custom related extensions +*/ +interface IERC1404Extend is IERC1404{ + /* + * @dev leave the code 7-12 free/unused for further CMTAT additions in your ruleEngine implementation + */ + 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 + } + + /** + * @notice Returns a uint8 code to indicate if a transfer is restricted or not + * @dev + * See {ERC-1404} + * Add an additionnal argument `spender` + * This function is where an issuer enforces the restriction logic of their token transfers. + * Some examples of this might include: + * - checking if the token recipient is whitelisted, + * - checking if a sender's tokens are frozen in a lock-up period, etc. + * @return uint8 restricted code, 0 means the transfer is authorized + * + */ + function detectTransferRestrictionFrom( + address spender, + address from, + address to, + uint256 value + ) external view returns (uint8); +} + +// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol + +// OpenZeppelin Contracts (last updated v5.4.0) (access/IAccessControl.sol) + +/** + * @dev External interface of AccessControl declared to support ERC-165 detection. + */ +interface IAccessControl { + /** + * @dev The `account` is missing a role. + */ + error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); + + /** + * @dev The caller of a function is not the expected one. + * + * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. + */ + error AccessControlBadConfirmation(); + + /** + * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` + * + * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite + * {RoleAdminChanged} not being emitted to signal this. + */ + event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); + + /** + * @dev Emitted when `account` is granted `role`. + * + * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role). + * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}. + */ + event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Emitted when `account` is revoked `role`. + * + * `sender` is the account that originated the contract call: + * - if using `revokeRole`, it is the admin role bearer + * - if using `renounceRole`, it is the role bearer (i.e. `account`) + */ + event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole(bytes32 role, address account) external view returns (bool); + + /** + * @dev Returns the admin role that controls `role`. See {grantRole} and + * {revokeRole}. + * + * To change a role's admin, use {AccessControl-_setRoleAdmin}. + */ + function getRoleAdmin(bytes32 role) external view returns (bytes32); + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function grantRole(bytes32 role, address account) external; + + /** + * @dev Revokes `role` from `account`. + * + * If `account` had been granted `role`, emits a {RoleRevoked} event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function revokeRole(bytes32 role, address account) external; + + /** + * @dev Revokes `role` from the calling account. + * + * Roles are often managed via {grantRole} and {revokeRole}: this function's + * purpose is to provide a mechanism for accounts to lose their privileges + * if they are compromised (such as when a trusted device is misplaced). + * + * If the calling account had been granted `role`, emits a {RoleRevoked} + * event. + * + * Requirements: + * + * - the caller must be `callerConfirmation`. + */ + function renounceRole(bytes32 role, address callerConfirmation) external; +} + +// lib/openzeppelin-contracts/contracts/utils/Comparators.sol + +// OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol) + +/** + * @dev Provides a set of functions to compare values. + * + * _Available since v5.1._ + */ +library Comparators { + function lt(uint256 a, uint256 b) internal pure returns (bool) { + return a < b; + } + + function gt(uint256 a, uint256 b) internal pure returns (bool) { + return a > b; + } +} + +// lib/openzeppelin-contracts/contracts/utils/Context.sol + +// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) + +/** + * @dev Provides information about the current execution context, including the + * sender of the transaction and its data. While these are generally available + * via msg.sender and msg.data, they should not be accessed in such a direct + * manner, since when dealing with meta-transactions the account sending and + * paying for execution may not be the actual sender (as far as an application + * is concerned). + * + * This contract is only required for intermediate, library-like contracts. + */ +abstract contract Context { + function _msgSender() internal view virtual returns (address) { + return msg.sender; + } + + function _msgData() internal view virtual returns (bytes calldata) { + return msg.data; + } + + function _contextSuffixLength() internal view virtual returns (uint256) { + return 0; + } +} + +// lib/openzeppelin-contracts/contracts/utils/Panic.sol + +// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol) + +/** + * @dev Helper library for emitting standardized panic codes. + * + * ```solidity + * contract Example { + * using Panic for uint256; + * + * // Use any of the declared internal constants + * function foo() { Panic.GENERIC.panic(); } + * + * // Alternatively + * function foo() { Panic.panic(Panic.GENERIC); } + * } + * ``` + * + * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil]. + * + * _Available since v5.1._ + */ +// slither-disable-next-line unused-state +library Panic { + /// @dev generic / unspecified error + uint256 internal constant GENERIC = 0x00; + /// @dev used by the assert() builtin + uint256 internal constant ASSERT = 0x01; + /// @dev arithmetic underflow or overflow + uint256 internal constant UNDER_OVERFLOW = 0x11; + /// @dev division or modulo by zero + uint256 internal constant DIVISION_BY_ZERO = 0x12; + /// @dev enum conversion error + uint256 internal constant ENUM_CONVERSION_ERROR = 0x21; + /// @dev invalid encoding in storage + uint256 internal constant STORAGE_ENCODING_ERROR = 0x22; + /// @dev empty array pop + uint256 internal constant EMPTY_ARRAY_POP = 0x31; + /// @dev array out of bounds access + uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32; + /// @dev resource error (too large allocation or too large array) + uint256 internal constant RESOURCE_ERROR = 0x41; + /// @dev calling invalid internal function + uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51; + + /// @dev Reverts with a panic code. Recommended to use with + /// the internal constants with predefined codes. + function panic(uint256 code) internal pure { + assembly ("memory-safe") { + mstore(0x00, 0x4e487b71) + mstore(0x20, code) + revert(0x1c, 0x24) + } + } +} + +// lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol + +// OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol) +// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js. + +/** + * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots + * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by + * the solidity language / compiler. + * + * See https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays[Solidity docs for mappings and dynamic arrays.]. + * + * Example usage: + * ```solidity + * contract Example { + * // Add the library methods + * using StorageSlot for bytes32; + * using SlotDerivation for bytes32; + * + * // Declare a namespace + * string private constant _NAMESPACE = ""; // eg. OpenZeppelin.Slot + * + * function setValueInNamespace(uint256 key, address newValue) internal { + * _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue; + * } + * + * function getValueInNamespace(uint256 key) internal view returns (address) { + * return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value; + * } + * } + * ``` + * + * TIP: Consider using this library along with {StorageSlot}. + * + * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking + * upgrade safety will ignore the slots accessed through this library. + * + * _Available since v5.1._ + */ +library SlotDerivation { + /** + * @dev Derive an ERC-7201 slot from a string (namespace). + */ + function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) { + assembly ("memory-safe") { + mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1)) + slot := and(keccak256(0x00, 0x20), not(0xff)) + } + } + + /** + * @dev Add an offset to a slot to get the n-th element of a structure or an array. + */ + function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) { + unchecked { + return bytes32(uint256(slot) + pos); + } + } + + /** + * @dev Derive the location of the first element in an array from the slot where the length is stored. + */ + function deriveArray(bytes32 slot) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + mstore(0x00, slot) + result := keccak256(0x00, 0x20) + } + } + + /** + * @dev Derive the location of a mapping element from the key. + */ + function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + mstore(0x00, and(key, shr(96, not(0)))) + mstore(0x20, slot) + result := keccak256(0x00, 0x40) + } + } + + /** + * @dev Derive the location of a mapping element from the key. + */ + function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + mstore(0x00, iszero(iszero(key))) + mstore(0x20, slot) + result := keccak256(0x00, 0x40) + } + } + + /** + * @dev Derive the location of a mapping element from the key. + */ + function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + mstore(0x00, key) + mstore(0x20, slot) + result := keccak256(0x00, 0x40) + } + } + + /** + * @dev Derive the location of a mapping element from the key. + */ + function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + mstore(0x00, key) + mstore(0x20, slot) + result := keccak256(0x00, 0x40) + } + } + + /** + * @dev Derive the location of a mapping element from the key. + */ + function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + mstore(0x00, key) + mstore(0x20, slot) + result := keccak256(0x00, 0x40) + } + } + + /** + * @dev Derive the location of a mapping element from the key. + */ + function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + let length := mload(key) + let begin := add(key, 0x20) + let end := add(begin, length) + let cache := mload(end) + mstore(end, slot) + result := keccak256(begin, add(length, 0x20)) + mstore(end, cache) + } + } + + /** + * @dev Derive the location of a mapping element from the key. + */ + function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) { + assembly ("memory-safe") { + let length := mload(key) + let begin := add(key, 0x20) + let end := add(begin, length) + let cache := mload(end) + mstore(end, slot) + result := keccak256(begin, add(length, 0x20)) + mstore(end, cache) + } + } +} + +// lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol + +// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol) +// This file was procedurally generated from scripts/generate/templates/StorageSlot.js. + +/** + * @dev Library for reading and writing primitive types to specific storage slots. + * + * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. + * This library helps with reading and writing to such slots without the need for inline assembly. + * + * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. + * + * Example usage to set ERC-1967 implementation slot: + * ```solidity + * contract ERC1967 { + * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot. + * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + * + * function _getImplementation() internal view returns (address) { + * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; + * } + * + * function _setImplementation(address newImplementation) internal { + * require(newImplementation.code.length > 0); + * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; + * } + * } + * ``` + * + * TIP: Consider using this library along with {SlotDerivation}. + */ +library StorageSlot { + struct AddressSlot { + address value; + } + + struct BooleanSlot { + bool value; + } + + struct Bytes32Slot { + bytes32 value; + } + + struct Uint256Slot { + uint256 value; + } + + struct Int256Slot { + int256 value; + } + + struct StringSlot { + string value; + } + + struct BytesSlot { + bytes value; + } + + /** + * @dev Returns an `AddressSlot` with member `value` located at `slot`. + */ + function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { + assembly ("memory-safe") { + r.slot := slot + } + } + + /** + * @dev Returns a `BooleanSlot` with member `value` located at `slot`. + */ + function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { + assembly ("memory-safe") { + r.slot := slot + } + } + + /** + * @dev Returns a `Bytes32Slot` with member `value` located at `slot`. + */ + function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { + assembly ("memory-safe") { + r.slot := slot + } + } + + /** + * @dev Returns a `Uint256Slot` with member `value` located at `slot`. + */ + function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { + assembly ("memory-safe") { + r.slot := slot + } + } + + /** + * @dev Returns a `Int256Slot` with member `value` located at `slot`. + */ + function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) { + assembly ("memory-safe") { + r.slot := slot + } + } + + /** + * @dev Returns a `StringSlot` with member `value` located at `slot`. + */ + function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { + assembly ("memory-safe") { + r.slot := slot + } + } + + /** + * @dev Returns an `StringSlot` representation of the string storage pointer `store`. + */ + function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { + assembly ("memory-safe") { + r.slot := store.slot + } + } + + /** + * @dev Returns a `BytesSlot` with member `value` located at `slot`. + */ + function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { + assembly ("memory-safe") { + r.slot := slot + } + } + + /** + * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. + */ + function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { + assembly ("memory-safe") { + r.slot := store.slot + } + } +} + +// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol + +// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol) + +/** + * @dev Interface of the ERC-165 standard, as defined in the + * https://eips.ethereum.org/EIPS/eip-165[ERC]. + * + * Implementers can declare support of contract interfaces, which can then be + * queried by others ({ERC165Checker}). + * + * For an implementation, see {ERC165}. + */ +interface IERC165 { + /** + * @dev Returns true if this contract implements the interface defined by + * `interfaceId`. See the corresponding + * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] + * to learn more about how these ids are created. + * + * This function call must use less than 30 000 gas. + */ + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} + +// lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol + +// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol) +// This file was procedurally generated from scripts/generate/templates/SafeCast.js. + +/** + * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow + * checks. + * + * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can + * easily result in undesired exploitation or bugs, since developers usually + * assume that overflows raise errors. `SafeCast` restores this intuition by + * reverting the transaction when such an operation overflows. + * + * Using this library instead of the unchecked operations eliminates an entire + * class of bugs, so it's recommended to use it always. + */ +library SafeCast { + /** + * @dev Value doesn't fit in an uint of `bits` size. + */ + error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); + + /** + * @dev An int value doesn't fit in an uint of `bits` size. + */ + error SafeCastOverflowedIntToUint(int256 value); + + /** + * @dev Value doesn't fit in an int of `bits` size. + */ + error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); + + /** + * @dev An uint value doesn't fit in an int of `bits` size. + */ + error SafeCastOverflowedUintToInt(uint256 value); + + /** + * @dev Returns the downcasted uint248 from uint256, reverting on + * overflow (when the input is greater than largest uint248). + * + * Counterpart to Solidity's `uint248` operator. + * + * Requirements: + * + * - input must fit into 248 bits + */ + function toUint248(uint256 value) internal pure returns (uint248) { + if (value > type(uint248).max) { + revert SafeCastOverflowedUintDowncast(248, value); + } + return uint248(value); + } + + /** + * @dev Returns the downcasted uint240 from uint256, reverting on + * overflow (when the input is greater than largest uint240). + * + * Counterpart to Solidity's `uint240` operator. + * + * Requirements: + * + * - input must fit into 240 bits + */ + function toUint240(uint256 value) internal pure returns (uint240) { + if (value > type(uint240).max) { + revert SafeCastOverflowedUintDowncast(240, value); + } + return uint240(value); + } + + /** + * @dev Returns the downcasted uint232 from uint256, reverting on + * overflow (when the input is greater than largest uint232). + * + * Counterpart to Solidity's `uint232` operator. + * + * Requirements: + * + * - input must fit into 232 bits + */ + function toUint232(uint256 value) internal pure returns (uint232) { + if (value > type(uint232).max) { + revert SafeCastOverflowedUintDowncast(232, value); + } + return uint232(value); + } + + /** + * @dev Returns the downcasted uint224 from uint256, reverting on + * overflow (when the input is greater than largest uint224). + * + * Counterpart to Solidity's `uint224` operator. + * + * Requirements: + * + * - input must fit into 224 bits + */ + function toUint224(uint256 value) internal pure returns (uint224) { + if (value > type(uint224).max) { + revert SafeCastOverflowedUintDowncast(224, value); + } + return uint224(value); + } + + /** + * @dev Returns the downcasted uint216 from uint256, reverting on + * overflow (when the input is greater than largest uint216). + * + * Counterpart to Solidity's `uint216` operator. + * + * Requirements: + * + * - input must fit into 216 bits + */ + function toUint216(uint256 value) internal pure returns (uint216) { + if (value > type(uint216).max) { + revert SafeCastOverflowedUintDowncast(216, value); + } + return uint216(value); + } + + /** + * @dev Returns the downcasted uint208 from uint256, reverting on + * overflow (when the input is greater than largest uint208). + * + * Counterpart to Solidity's `uint208` operator. + * + * Requirements: + * + * - input must fit into 208 bits + */ + function toUint208(uint256 value) internal pure returns (uint208) { + if (value > type(uint208).max) { + revert SafeCastOverflowedUintDowncast(208, value); + } + return uint208(value); + } + + /** + * @dev Returns the downcasted uint200 from uint256, reverting on + * overflow (when the input is greater than largest uint200). + * + * Counterpart to Solidity's `uint200` operator. + * + * Requirements: + * + * - input must fit into 200 bits + */ + function toUint200(uint256 value) internal pure returns (uint200) { + if (value > type(uint200).max) { + revert SafeCastOverflowedUintDowncast(200, value); + } + return uint200(value); + } + + /** + * @dev Returns the downcasted uint192 from uint256, reverting on + * overflow (when the input is greater than largest uint192). + * + * Counterpart to Solidity's `uint192` operator. + * + * Requirements: + * + * - input must fit into 192 bits + */ + function toUint192(uint256 value) internal pure returns (uint192) { + if (value > type(uint192).max) { + revert SafeCastOverflowedUintDowncast(192, value); + } + return uint192(value); + } + + /** + * @dev Returns the downcasted uint184 from uint256, reverting on + * overflow (when the input is greater than largest uint184). + * + * Counterpart to Solidity's `uint184` operator. + * + * Requirements: + * + * - input must fit into 184 bits + */ + function toUint184(uint256 value) internal pure returns (uint184) { + if (value > type(uint184).max) { + revert SafeCastOverflowedUintDowncast(184, value); + } + return uint184(value); + } + + /** + * @dev Returns the downcasted uint176 from uint256, reverting on + * overflow (when the input is greater than largest uint176). + * + * Counterpart to Solidity's `uint176` operator. + * + * Requirements: + * + * - input must fit into 176 bits + */ + function toUint176(uint256 value) internal pure returns (uint176) { + if (value > type(uint176).max) { + revert SafeCastOverflowedUintDowncast(176, value); + } + return uint176(value); + } + + /** + * @dev Returns the downcasted uint168 from uint256, reverting on + * overflow (when the input is greater than largest uint168). + * + * Counterpart to Solidity's `uint168` operator. + * + * Requirements: + * + * - input must fit into 168 bits + */ + function toUint168(uint256 value) internal pure returns (uint168) { + if (value > type(uint168).max) { + revert SafeCastOverflowedUintDowncast(168, value); + } + return uint168(value); + } + + /** + * @dev Returns the downcasted uint160 from uint256, reverting on + * overflow (when the input is greater than largest uint160). + * + * Counterpart to Solidity's `uint160` operator. + * + * Requirements: + * + * - input must fit into 160 bits + */ + function toUint160(uint256 value) internal pure returns (uint160) { + if (value > type(uint160).max) { + revert SafeCastOverflowedUintDowncast(160, value); + } + return uint160(value); + } + + /** + * @dev Returns the downcasted uint152 from uint256, reverting on + * overflow (when the input is greater than largest uint152). + * + * Counterpart to Solidity's `uint152` operator. + * + * Requirements: + * + * - input must fit into 152 bits + */ + function toUint152(uint256 value) internal pure returns (uint152) { + if (value > type(uint152).max) { + revert SafeCastOverflowedUintDowncast(152, value); + } + return uint152(value); + } + + /** + * @dev Returns the downcasted uint144 from uint256, reverting on + * overflow (when the input is greater than largest uint144). + * + * Counterpart to Solidity's `uint144` operator. + * + * Requirements: + * + * - input must fit into 144 bits + */ + function toUint144(uint256 value) internal pure returns (uint144) { + if (value > type(uint144).max) { + revert SafeCastOverflowedUintDowncast(144, value); + } + return uint144(value); + } + + /** + * @dev Returns the downcasted uint136 from uint256, reverting on + * overflow (when the input is greater than largest uint136). + * + * Counterpart to Solidity's `uint136` operator. + * + * Requirements: + * + * - input must fit into 136 bits + */ + function toUint136(uint256 value) internal pure returns (uint136) { + if (value > type(uint136).max) { + revert SafeCastOverflowedUintDowncast(136, value); + } + return uint136(value); + } + + /** + * @dev Returns the downcasted uint128 from uint256, reverting on + * overflow (when the input is greater than largest uint128). + * + * Counterpart to Solidity's `uint128` operator. + * + * Requirements: + * + * - input must fit into 128 bits + */ + function toUint128(uint256 value) internal pure returns (uint128) { + if (value > type(uint128).max) { + revert SafeCastOverflowedUintDowncast(128, value); + } + return uint128(value); + } + + /** + * @dev Returns the downcasted uint120 from uint256, reverting on + * overflow (when the input is greater than largest uint120). + * + * Counterpart to Solidity's `uint120` operator. + * + * Requirements: + * + * - input must fit into 120 bits + */ + function toUint120(uint256 value) internal pure returns (uint120) { + if (value > type(uint120).max) { + revert SafeCastOverflowedUintDowncast(120, value); + } + return uint120(value); + } + + /** + * @dev Returns the downcasted uint112 from uint256, reverting on + * overflow (when the input is greater than largest uint112). + * + * Counterpart to Solidity's `uint112` operator. + * + * Requirements: + * + * - input must fit into 112 bits + */ + function toUint112(uint256 value) internal pure returns (uint112) { + if (value > type(uint112).max) { + revert SafeCastOverflowedUintDowncast(112, value); + } + return uint112(value); + } + + /** + * @dev Returns the downcasted uint104 from uint256, reverting on + * overflow (when the input is greater than largest uint104). + * + * Counterpart to Solidity's `uint104` operator. + * + * Requirements: + * + * - input must fit into 104 bits + */ + function toUint104(uint256 value) internal pure returns (uint104) { + if (value > type(uint104).max) { + revert SafeCastOverflowedUintDowncast(104, value); + } + return uint104(value); + } + + /** + * @dev Returns the downcasted uint96 from uint256, reverting on + * overflow (when the input is greater than largest uint96). + * + * Counterpart to Solidity's `uint96` operator. + * + * Requirements: + * + * - input must fit into 96 bits + */ + function toUint96(uint256 value) internal pure returns (uint96) { + if (value > type(uint96).max) { + revert SafeCastOverflowedUintDowncast(96, value); + } + return uint96(value); + } + + /** + * @dev Returns the downcasted uint88 from uint256, reverting on + * overflow (when the input is greater than largest uint88). + * + * Counterpart to Solidity's `uint88` operator. + * + * Requirements: + * + * - input must fit into 88 bits + */ + function toUint88(uint256 value) internal pure returns (uint88) { + if (value > type(uint88).max) { + revert SafeCastOverflowedUintDowncast(88, value); + } + return uint88(value); + } + + /** + * @dev Returns the downcasted uint80 from uint256, reverting on + * overflow (when the input is greater than largest uint80). + * + * Counterpart to Solidity's `uint80` operator. + * + * Requirements: + * + * - input must fit into 80 bits + */ + function toUint80(uint256 value) internal pure returns (uint80) { + if (value > type(uint80).max) { + revert SafeCastOverflowedUintDowncast(80, value); + } + return uint80(value); + } + + /** + * @dev Returns the downcasted uint72 from uint256, reverting on + * overflow (when the input is greater than largest uint72). + * + * Counterpart to Solidity's `uint72` operator. + * + * Requirements: + * + * - input must fit into 72 bits + */ + function toUint72(uint256 value) internal pure returns (uint72) { + if (value > type(uint72).max) { + revert SafeCastOverflowedUintDowncast(72, value); + } + return uint72(value); + } + + /** + * @dev Returns the downcasted uint64 from uint256, reverting on + * overflow (when the input is greater than largest uint64). + * + * Counterpart to Solidity's `uint64` operator. + * + * Requirements: + * + * - input must fit into 64 bits + */ + function toUint64(uint256 value) internal pure returns (uint64) { + if (value > type(uint64).max) { + revert SafeCastOverflowedUintDowncast(64, value); + } + return uint64(value); + } + + /** + * @dev Returns the downcasted uint56 from uint256, reverting on + * overflow (when the input is greater than largest uint56). + * + * Counterpart to Solidity's `uint56` operator. + * + * Requirements: + * + * - input must fit into 56 bits + */ + function toUint56(uint256 value) internal pure returns (uint56) { + if (value > type(uint56).max) { + revert SafeCastOverflowedUintDowncast(56, value); + } + return uint56(value); + } + + /** + * @dev Returns the downcasted uint48 from uint256, reverting on + * overflow (when the input is greater than largest uint48). + * + * Counterpart to Solidity's `uint48` operator. + * + * Requirements: + * + * - input must fit into 48 bits + */ + function toUint48(uint256 value) internal pure returns (uint48) { + if (value > type(uint48).max) { + revert SafeCastOverflowedUintDowncast(48, value); + } + return uint48(value); + } + + /** + * @dev Returns the downcasted uint40 from uint256, reverting on + * overflow (when the input is greater than largest uint40). + * + * Counterpart to Solidity's `uint40` operator. + * + * Requirements: + * + * - input must fit into 40 bits + */ + function toUint40(uint256 value) internal pure returns (uint40) { + if (value > type(uint40).max) { + revert SafeCastOverflowedUintDowncast(40, value); + } + return uint40(value); + } + + /** + * @dev Returns the downcasted uint32 from uint256, reverting on + * overflow (when the input is greater than largest uint32). + * + * Counterpart to Solidity's `uint32` operator. + * + * Requirements: + * + * - input must fit into 32 bits + */ + function toUint32(uint256 value) internal pure returns (uint32) { + if (value > type(uint32).max) { + revert SafeCastOverflowedUintDowncast(32, value); + } + return uint32(value); + } + + /** + * @dev Returns the downcasted uint24 from uint256, reverting on + * overflow (when the input is greater than largest uint24). + * + * Counterpart to Solidity's `uint24` operator. + * + * Requirements: + * + * - input must fit into 24 bits + */ + function toUint24(uint256 value) internal pure returns (uint24) { + if (value > type(uint24).max) { + revert SafeCastOverflowedUintDowncast(24, value); + } + return uint24(value); + } + + /** + * @dev Returns the downcasted uint16 from uint256, reverting on + * overflow (when the input is greater than largest uint16). + * + * Counterpart to Solidity's `uint16` operator. + * + * Requirements: + * + * - input must fit into 16 bits + */ + function toUint16(uint256 value) internal pure returns (uint16) { + if (value > type(uint16).max) { + revert SafeCastOverflowedUintDowncast(16, value); + } + return uint16(value); + } + + /** + * @dev Returns the downcasted uint8 from uint256, reverting on + * overflow (when the input is greater than largest uint8). + * + * Counterpart to Solidity's `uint8` operator. + * + * Requirements: + * + * - input must fit into 8 bits + */ + function toUint8(uint256 value) internal pure returns (uint8) { + if (value > type(uint8).max) { + revert SafeCastOverflowedUintDowncast(8, value); + } + return uint8(value); + } + + /** + * @dev Converts a signed int256 into an unsigned uint256. + * + * Requirements: + * + * - input must be greater than or equal to 0. + */ + function toUint256(int256 value) internal pure returns (uint256) { + if (value < 0) { + revert SafeCastOverflowedIntToUint(value); + } + return uint256(value); + } + + /** + * @dev Returns the downcasted int248 from int256, reverting on + * overflow (when the input is less than smallest int248 or + * greater than largest int248). + * + * Counterpart to Solidity's `int248` operator. + * + * Requirements: + * + * - input must fit into 248 bits + */ + function toInt248(int256 value) internal pure returns (int248 downcasted) { + downcasted = int248(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(248, value); + } + } + + /** + * @dev Returns the downcasted int240 from int256, reverting on + * overflow (when the input is less than smallest int240 or + * greater than largest int240). + * + * Counterpart to Solidity's `int240` operator. + * + * Requirements: + * + * - input must fit into 240 bits + */ + function toInt240(int256 value) internal pure returns (int240 downcasted) { + downcasted = int240(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(240, value); + } + } + + /** + * @dev Returns the downcasted int232 from int256, reverting on + * overflow (when the input is less than smallest int232 or + * greater than largest int232). + * + * Counterpart to Solidity's `int232` operator. + * + * Requirements: + * + * - input must fit into 232 bits + */ + function toInt232(int256 value) internal pure returns (int232 downcasted) { + downcasted = int232(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(232, value); + } + } + + /** + * @dev Returns the downcasted int224 from int256, reverting on + * overflow (when the input is less than smallest int224 or + * greater than largest int224). + * + * Counterpart to Solidity's `int224` operator. + * + * Requirements: + * + * - input must fit into 224 bits + */ + function toInt224(int256 value) internal pure returns (int224 downcasted) { + downcasted = int224(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(224, value); + } + } + + /** + * @dev Returns the downcasted int216 from int256, reverting on + * overflow (when the input is less than smallest int216 or + * greater than largest int216). + * + * Counterpart to Solidity's `int216` operator. + * + * Requirements: + * + * - input must fit into 216 bits + */ + function toInt216(int256 value) internal pure returns (int216 downcasted) { + downcasted = int216(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(216, value); + } + } + + /** + * @dev Returns the downcasted int208 from int256, reverting on + * overflow (when the input is less than smallest int208 or + * greater than largest int208). + * + * Counterpart to Solidity's `int208` operator. + * + * Requirements: + * + * - input must fit into 208 bits + */ + function toInt208(int256 value) internal pure returns (int208 downcasted) { + downcasted = int208(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(208, value); + } + } + + /** + * @dev Returns the downcasted int200 from int256, reverting on + * overflow (when the input is less than smallest int200 or + * greater than largest int200). + * + * Counterpart to Solidity's `int200` operator. + * + * Requirements: + * + * - input must fit into 200 bits + */ + function toInt200(int256 value) internal pure returns (int200 downcasted) { + downcasted = int200(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(200, value); + } + } + + /** + * @dev Returns the downcasted int192 from int256, reverting on + * overflow (when the input is less than smallest int192 or + * greater than largest int192). + * + * Counterpart to Solidity's `int192` operator. + * + * Requirements: + * + * - input must fit into 192 bits + */ + function toInt192(int256 value) internal pure returns (int192 downcasted) { + downcasted = int192(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(192, value); + } + } + + /** + * @dev Returns the downcasted int184 from int256, reverting on + * overflow (when the input is less than smallest int184 or + * greater than largest int184). + * + * Counterpart to Solidity's `int184` operator. + * + * Requirements: + * + * - input must fit into 184 bits + */ + function toInt184(int256 value) internal pure returns (int184 downcasted) { + downcasted = int184(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(184, value); + } + } + + /** + * @dev Returns the downcasted int176 from int256, reverting on + * overflow (when the input is less than smallest int176 or + * greater than largest int176). + * + * Counterpart to Solidity's `int176` operator. + * + * Requirements: + * + * - input must fit into 176 bits + */ + function toInt176(int256 value) internal pure returns (int176 downcasted) { + downcasted = int176(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(176, value); + } + } + + /** + * @dev Returns the downcasted int168 from int256, reverting on + * overflow (when the input is less than smallest int168 or + * greater than largest int168). + * + * Counterpart to Solidity's `int168` operator. + * + * Requirements: + * + * - input must fit into 168 bits + */ + function toInt168(int256 value) internal pure returns (int168 downcasted) { + downcasted = int168(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(168, value); + } + } + + /** + * @dev Returns the downcasted int160 from int256, reverting on + * overflow (when the input is less than smallest int160 or + * greater than largest int160). + * + * Counterpart to Solidity's `int160` operator. + * + * Requirements: + * + * - input must fit into 160 bits + */ + function toInt160(int256 value) internal pure returns (int160 downcasted) { + downcasted = int160(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(160, value); + } + } + + /** + * @dev Returns the downcasted int152 from int256, reverting on + * overflow (when the input is less than smallest int152 or + * greater than largest int152). + * + * Counterpart to Solidity's `int152` operator. + * + * Requirements: + * + * - input must fit into 152 bits + */ + function toInt152(int256 value) internal pure returns (int152 downcasted) { + downcasted = int152(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(152, value); + } + } + + /** + * @dev Returns the downcasted int144 from int256, reverting on + * overflow (when the input is less than smallest int144 or + * greater than largest int144). + * + * Counterpart to Solidity's `int144` operator. + * + * Requirements: + * + * - input must fit into 144 bits + */ + function toInt144(int256 value) internal pure returns (int144 downcasted) { + downcasted = int144(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(144, value); + } + } + + /** + * @dev Returns the downcasted int136 from int256, reverting on + * overflow (when the input is less than smallest int136 or + * greater than largest int136). + * + * Counterpart to Solidity's `int136` operator. + * + * Requirements: + * + * - input must fit into 136 bits + */ + function toInt136(int256 value) internal pure returns (int136 downcasted) { + downcasted = int136(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(136, value); + } + } + + /** + * @dev Returns the downcasted int128 from int256, reverting on + * overflow (when the input is less than smallest int128 or + * greater than largest int128). + * + * Counterpart to Solidity's `int128` operator. + * + * Requirements: + * + * - input must fit into 128 bits + */ + function toInt128(int256 value) internal pure returns (int128 downcasted) { + downcasted = int128(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(128, value); + } + } + + /** + * @dev Returns the downcasted int120 from int256, reverting on + * overflow (when the input is less than smallest int120 or + * greater than largest int120). + * + * Counterpart to Solidity's `int120` operator. + * + * Requirements: + * + * - input must fit into 120 bits + */ + function toInt120(int256 value) internal pure returns (int120 downcasted) { + downcasted = int120(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(120, value); + } + } + + /** + * @dev Returns the downcasted int112 from int256, reverting on + * overflow (when the input is less than smallest int112 or + * greater than largest int112). + * + * Counterpart to Solidity's `int112` operator. + * + * Requirements: + * + * - input must fit into 112 bits + */ + function toInt112(int256 value) internal pure returns (int112 downcasted) { + downcasted = int112(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(112, value); + } + } + + /** + * @dev Returns the downcasted int104 from int256, reverting on + * overflow (when the input is less than smallest int104 or + * greater than largest int104). + * + * Counterpart to Solidity's `int104` operator. + * + * Requirements: + * + * - input must fit into 104 bits + */ + function toInt104(int256 value) internal pure returns (int104 downcasted) { + downcasted = int104(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(104, value); + } + } + + /** + * @dev Returns the downcasted int96 from int256, reverting on + * overflow (when the input is less than smallest int96 or + * greater than largest int96). + * + * Counterpart to Solidity's `int96` operator. + * + * Requirements: + * + * - input must fit into 96 bits + */ + function toInt96(int256 value) internal pure returns (int96 downcasted) { + downcasted = int96(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(96, value); + } + } + + /** + * @dev Returns the downcasted int88 from int256, reverting on + * overflow (when the input is less than smallest int88 or + * greater than largest int88). + * + * Counterpart to Solidity's `int88` operator. + * + * Requirements: + * + * - input must fit into 88 bits + */ + function toInt88(int256 value) internal pure returns (int88 downcasted) { + downcasted = int88(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(88, value); + } + } + + /** + * @dev Returns the downcasted int80 from int256, reverting on + * overflow (when the input is less than smallest int80 or + * greater than largest int80). + * + * Counterpart to Solidity's `int80` operator. + * + * Requirements: + * + * - input must fit into 80 bits + */ + function toInt80(int256 value) internal pure returns (int80 downcasted) { + downcasted = int80(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(80, value); + } + } + + /** + * @dev Returns the downcasted int72 from int256, reverting on + * overflow (when the input is less than smallest int72 or + * greater than largest int72). + * + * Counterpart to Solidity's `int72` operator. + * + * Requirements: + * + * - input must fit into 72 bits + */ + function toInt72(int256 value) internal pure returns (int72 downcasted) { + downcasted = int72(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(72, value); + } + } + + /** + * @dev Returns the downcasted int64 from int256, reverting on + * overflow (when the input is less than smallest int64 or + * greater than largest int64). + * + * Counterpart to Solidity's `int64` operator. + * + * Requirements: + * + * - input must fit into 64 bits + */ + function toInt64(int256 value) internal pure returns (int64 downcasted) { + downcasted = int64(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(64, value); + } + } + + /** + * @dev Returns the downcasted int56 from int256, reverting on + * overflow (when the input is less than smallest int56 or + * greater than largest int56). + * + * Counterpart to Solidity's `int56` operator. + * + * Requirements: + * + * - input must fit into 56 bits + */ + function toInt56(int256 value) internal pure returns (int56 downcasted) { + downcasted = int56(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(56, value); + } + } + + /** + * @dev Returns the downcasted int48 from int256, reverting on + * overflow (when the input is less than smallest int48 or + * greater than largest int48). + * + * Counterpart to Solidity's `int48` operator. + * + * Requirements: + * + * - input must fit into 48 bits + */ + function toInt48(int256 value) internal pure returns (int48 downcasted) { + downcasted = int48(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(48, value); + } + } + + /** + * @dev Returns the downcasted int40 from int256, reverting on + * overflow (when the input is less than smallest int40 or + * greater than largest int40). + * + * Counterpart to Solidity's `int40` operator. + * + * Requirements: + * + * - input must fit into 40 bits + */ + function toInt40(int256 value) internal pure returns (int40 downcasted) { + downcasted = int40(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(40, value); + } + } + + /** + * @dev Returns the downcasted int32 from int256, reverting on + * overflow (when the input is less than smallest int32 or + * greater than largest int32). + * + * Counterpart to Solidity's `int32` operator. + * + * Requirements: + * + * - input must fit into 32 bits + */ + function toInt32(int256 value) internal pure returns (int32 downcasted) { + downcasted = int32(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(32, value); + } + } + + /** + * @dev Returns the downcasted int24 from int256, reverting on + * overflow (when the input is less than smallest int24 or + * greater than largest int24). + * + * Counterpart to Solidity's `int24` operator. + * + * Requirements: + * + * - input must fit into 24 bits + */ + function toInt24(int256 value) internal pure returns (int24 downcasted) { + downcasted = int24(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(24, value); + } + } + + /** + * @dev Returns the downcasted int16 from int256, reverting on + * overflow (when the input is less than smallest int16 or + * greater than largest int16). + * + * Counterpart to Solidity's `int16` operator. + * + * Requirements: + * + * - input must fit into 16 bits + */ + function toInt16(int256 value) internal pure returns (int16 downcasted) { + downcasted = int16(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(16, value); + } + } + + /** + * @dev Returns the downcasted int8 from int256, reverting on + * overflow (when the input is less than smallest int8 or + * greater than largest int8). + * + * Counterpart to Solidity's `int8` operator. + * + * Requirements: + * + * - input must fit into 8 bits + */ + function toInt8(int256 value) internal pure returns (int8 downcasted) { + downcasted = int8(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(8, value); + } + } + + /** + * @dev Converts an unsigned uint256 into a signed int256. + * + * Requirements: + * + * - input must be less than or equal to maxInt256. + */ + function toInt256(uint256 value) internal pure returns (int256) { + // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive + if (value > uint256(type(int256).max)) { + revert SafeCastOverflowedUintToInt(value); + } + return int256(value); + } + + /** + * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. + */ + function toUint(bool b) internal pure returns (uint256 u) { + assembly ("memory-safe") { + u := iszero(iszero(b)) + } + } +} + +// src/modules/library/RuleEngineInvariantStorage.sol + +abstract contract RuleEngineInvariantStorage { + /* ==== Errors === */ + error RuleEngine_AdminWithAddressZeroNotAllowed(); +} + +// lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol + +/** + * @title IERC7551Mint + * @dev Interface for token minting operations. + */ +interface IERC7551Mint { + /** + * @notice Emitted when new tokens are minted and assigned to an account. + * @param minter The address that initiated the mint operation. + * @param account The address receiving the newly minted tokens. + * @param value The amount of tokens created. + * @param data Optional metadata associated with the mint (e.g., reason, reference ID). + */ + event Mint(address indexed minter, address indexed account, uint256 value, bytes data); + /** + * @notice Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0) + * @dev + * - Increases the total supply of tokens. + * - Emits both a `Mint` event and a standard ERC-20 `Transfer` event (with `from` set to the zero address). + * - The `data` parameter can be used to attach off-chain metadata or audit information. + * - If {IERC7551Pause} is implemented: + * - Token issuance MUST NOT be blocked by paused transfer state. + * Requirements: + * - `account` cannot be the zero address + * @param account The address that will receive the newly minted tokens. + * @param value The amount of tokens to mint. + * @param data Additional contextual data to include with the mint (optional). + */ + function mint(address account, uint256 value, bytes calldata data) external; +} + +/** +* @title interface for burn operation +*/ +interface IERC7551Burn { + /** + * @notice Emitted when tokens are burned from an account. + * @param burner The address that initiated the burn. + * @param account The address from which tokens were burned. + * @param value The amount of tokens burned. + * @param data Additional data related to the burn. + */ + event Burn(address indexed burner, address indexed account, uint256 value, bytes data); + + /** + * @notice Burns a specific number of tokens from the given account by transferring it to address(0) + * @dev + * - The account's balance is decreased by the specified amount. + * - Emits a `Burn` event and a standard `Transfer` event with `to` set to `address(0)`. + * - If the account balance (including frozen tokens) is less than the burn amount, the transaction MUST revert. + * - If the token contract supports {IERC7551Pause}, paused transfers MUST NOT prevent this burn operation. + * - The `data` parameter MAY be used to provide additional context (e.g., audit trail or documentation). + * @param account The address whose tokens will be burned. + * @param amount The number of tokens to remove from circulation. + * @param data Arbitrary additional data to document the burn. + */ + function burn(address account, uint256 amount, bytes calldata data) external; +} + +interface IERC7551Pause { + /** + * @notice Returns true if token transfers are currently paused. + * @return True if paused, false otherwise. + * @dev + * If this function returns true, it MUST NOT be possible to transfer tokens to other accounts + * and the function canTransfer() MUST return false. + */ + function paused() external view returns (bool); + /** + * @notice Pauses token transfers. + * @dev Reverts if already paused. + * Emits a `Paused` event + */ + function pause() external; + /** + * @notice Unpauses token transfers. + * @dev Reverts if token is not in pause state. + * emits an `Unpaused` event + */ + function unpause() external; +} +interface IERC7551ERC20EnforcementEvent { + /** + * @notice Emitted when a forced transfer or burn occurs. + * @param enforcer The address that initiated the enforcement. + * @param account The address affected by the enforcement. + * @param amount The number of tokens involved. + * @param data Additional data related to the enforcement. + */ + event Enforcement (address indexed enforcer, address indexed account, uint256 amount, bytes data); +} + +interface IERC7551ERC20EnforcementTokenFrozenEvent { + /** + * @notice Emitted when a specific amount of tokens are frozen on an address. + * @param account The address whose tokens are frozen. + * @param value The number of tokens frozen. + * @param data Additional data related to the freezing action. + * @dev + * Same name as ERC-3643 but with a supplementary data parameter + * The event is emitted by freezePartialTokens and batchFreezePartialTokens functions + */ + event TokensFrozen(address indexed account, uint256 value, bytes data); + + /** + * @notice Emitted when a specific amount of tokens are unfrozen on an address. + * @param account The address whose tokens are unfrozen. + * @param value The number of tokens unfrozen. + * @param data Additional data related to the unfreezing action. + * @dev + * Same name as ERC-3643 but with a supplementary data parameter + * The event is emitted by `unfreezePartialTokens`, `batchUnfreezePartialTokens`and potentially `forcedTransfer` functions + */ + event TokensUnfrozen(address indexed account, uint256 value, bytes data); +} + +interface IERC7551ERC20Enforcement { + /* ============ View Functions ============ */ + /** + * @notice Returns the active (unfrozen) token balance of a given account. + * @param account The address to query. + * @return activeBalance_ The amount of tokens that can be transferred using standard ERC-20 functions. + */ + function getActiveBalanceOf(address account) external view returns (uint256 activeBalance_); + + /** + * @notice Returns the frozen token balance of a given account. + * @dev Frozen tokens cannot be transferred using standard ERC-20 functions. + * Implementations MAY support transferring frozen tokens using other mechanisms like `forcedTransfer`. + * If the active balance is insufficient to cover a transfer, `canTransfer` and `canTransferFrom` MUST return false. + * @param account The address to query. + * @return frozenBalance_ The amount of tokens that are frozen and non-transferable via ERC-20 `transfer` and `transferFrom`. + */ + function getFrozenTokens(address account) external view returns (uint256 frozenBalance_); + + /* ============ State Functions ============ */ + /** + * @notice Freezes a specified amount of tokens for a given account. + * @dev Emits a `TokensFrozen` event. + * @param account The address whose tokens will be frozen. + * @param amount The number of tokens to freeze. + * @param data Arbitrary additional data for logging or business logic. + */ + function freezePartialTokens(address account, uint256 amount, bytes memory data) external; + + + /** + * @notice Unfreezes a specified amount of tokens for a given account. + * @dev Emits a `TokensUnfrozen` event. + * @param account The address whose tokens will be unfrozen. + * @param amount The number of tokens to unfreeze. + * @param data Arbitrary additional data for logging or business logic. + */ + function unfreezePartialTokens(address account, uint256 amount, bytes memory data) external; + /** + * @notice Executes a forced transfer of tokens from one account to another. + * @dev Transfers `value` tokens from `account` to `to` without requiring the account’s consent. + * If the `account` does not have enough active (unfrozen) tokens, frozen tokens may be automatically unfrozen to fulfill the transfer. + * Emits a `Transfer` event. Emits a `TokensUnfrozen` event if frozen tokens are used. + * @param account The address to debit tokens from. + * @param to The address to credit tokens to. + * @param value The amount of tokens to transfer. + * @param data Optional additional metadata to accompany the transfer. + * @return success_ Returns true if the transfer was successful. + */ + function forcedTransfer(address account, address to, uint256 value, bytes calldata data) external returns (bool success_); +} + +interface IERC7551Compliance is IERC3643ComplianceRead { + /** + * @notice Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules. + * @dev Does not check balances or access rights (Access Control). + * @param spender The address performing the transfer. + * @param from The source address. + * @param to The destination address. + * @param value The number of tokens to transfer. + * @return isCompliant True if the transfer complies with policy. + */ + function canTransferFrom( + address spender, + address from, + address to, + uint256 value + ) external view returns (bool); +} + +interface IERC7551Document { + /** + * @notice Returns the hash of the "Terms" document. + * @return hash_ The `bytes32` hash of the terms document. + */ + function termsHash() external view returns (bytes32 hash_); + + /** + * @notice Sets the terms hash and URI. + * @param _hash The new hash of the document. + * @param _uri The corresponding URI. + */ + function setTerms(bytes32 _hash, string calldata _uri) external; + + /** + * @notice Returns the metadata string (e.g. URL). + * @return metadata_ The metadata string. + */ + function metaData() external view returns (string memory metadata_); + + /** + * @notice Sets a new metadata string (e.g. URL). + * @param metaData_ The new metadata value. + */ + function setMetaData(string calldata metaData_) external; +} + +// lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol + +// OpenZeppelin Contracts (last updated v5.4.0) (metatx/ERC2771Context.sol) + +/** + * @dev Context variant with ERC-2771 support. + * + * WARNING: Avoid using this pattern in contracts that rely in a specific calldata length as they'll + * be affected by any forwarder whose `msg.data` is suffixed with the `from` address according to the ERC-2771 + * specification adding the address size in bytes (20) to the calldata size. An example of an unexpected + * behavior could be an unintended fallback (or another function) invocation while trying to invoke the `receive` + * function only accessible if `msg.data.length == 0`. + * + * WARNING: The usage of `delegatecall` in this contract is dangerous and may result in context corruption. + * Any forwarded request to this contract triggering a `delegatecall` to itself will result in an invalid {_msgSender} + * recovery. + */ +abstract contract ERC2771Context is Context { + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + address private immutable _trustedForwarder; + + /** + * @dev Initializes the contract with a trusted forwarder, which will be able to + * invoke functions on this contract on behalf of other accounts. + * + * NOTE: The trusted forwarder can be replaced by overriding {trustedForwarder}. + */ + /// @custom:oz-upgrades-unsafe-allow constructor + constructor(address trustedForwarder_) { + _trustedForwarder = trustedForwarder_; + } + + /** + * @dev Returns the address of the trusted forwarder. + */ + function trustedForwarder() public view virtual returns (address) { + return _trustedForwarder; + } + + /** + * @dev Indicates whether any particular address is the trusted forwarder. + */ + function isTrustedForwarder(address forwarder) public view virtual returns (bool) { + return forwarder == trustedForwarder(); + } + + /** + * @dev Override for `msg.sender`. Defaults to the original `msg.sender` whenever + * a call is not performed by the trusted forwarder or the calldata length is less than + * 20 bytes (an address length). + */ + function _msgSender() internal view virtual override returns (address) { + uint256 calldataLength = msg.data.length; + uint256 contextSuffixLength = _contextSuffixLength(); + if (calldataLength >= contextSuffixLength && isTrustedForwarder(msg.sender)) { + unchecked { + return address(bytes20(msg.data[calldataLength - contextSuffixLength:])); + } + } else { + return super._msgSender(); + } + } + + /** + * @dev Override for `msg.data`. Defaults to the original `msg.data` whenever + * a call is not performed by the trusted forwarder or the calldata length is less than + * 20 bytes (an address length). + */ + function _msgData() internal view virtual override returns (bytes calldata) { + uint256 calldataLength = msg.data.length; + uint256 contextSuffixLength = _contextSuffixLength(); + if (calldataLength >= contextSuffixLength && isTrustedForwarder(msg.sender)) { + unchecked { + return msg.data[:calldataLength - contextSuffixLength]; + } + } else { + return super._msgData(); + } + } + + /** + * @dev ERC-2771 specifies the context as being a single address (20 bytes). + */ + function _contextSuffixLength() internal view virtual override returns (uint256) { + return 20; + } +} + +// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol + +// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol) + +/** + * @dev Implementation of the {IERC165} interface. + * + * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check + * for the additional interface id that will be supported. For example: + * + * ```solidity + * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); + * } + * ``` + */ +abstract contract ERC165 is IERC165 { + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { + return interfaceId == type(IERC165).interfaceId; + } +} + +// src/interfaces/IERC3643Compliance.sol + +/* ==== CMTAT === */ + +interface IERC3643Compliance is IERC3643ComplianceRead, IERC3643IComplianceContract { + /* ============ Events ============ */ + /** + * @notice Emitted when a token is successfully bound to the compliance contract. + * @param token The address of the token that was bound. + */ + event TokenBound(address token); + + /** + * @notice Emitted when a token is successfully unbound from the compliance contract. + * @param token The address of the token that was unbound. + */ + event TokenUnbound(address token); + + /* ============ Functions ============ */ + /** + * @notice Associates a token contract with this compliance contract. + * @dev The compliance contract may restrict operations on the bound token + * according to the compliance logic. + * Reverts if the token is already bound. + * Complexity: O(1). + * @param token The address of the token to bind. + */ + function bindToken(address token) external; + /** + * @notice Removes the association of a token contract from this compliance contract. + * @dev Reverts if the token is not currently bound. + * Complexity: O(1). + * @param token The address of the token to unbind. + */ + function unbindToken(address token) external; + + /** + * @notice Checks whether a token is currently bound to this compliance contract. + * @dev + * Complexity: O(1). + * Note that there are no guarantees on the ordering of values inside the array, + * and it may change when more values are added or removed. + * @param token The token address to verify. + * @return isBound True if the token is bound, false otherwise. + */ + function isTokenBound(address token) external view returns (bool isBound); + /** + * @notice Returns the single token currently bound to this compliance contract. + * @dev If multiple tokens are supported, consider using getTokenBounds(). + * @return token The address of the currently bound token. + */ + function getTokenBound() external view returns (address token); + + /** + * @notice Returns all tokens currently bound to this compliance contract. + * @dev This is a view-only function and does not modify state. + * This function is not part of the original ERC-3643 specification + * This operation will copy the entire storage to memory, which can be quite expensive. + * This is designed to mostly be used by view accessors that are queried without any gas fees. + * @return tokens An array of addresses of bound token contracts. + */ + function getTokenBounds() external view returns (address[] memory tokens); + + /** + * @notice Updates the compliance contract state when tokens are created (minted). + * @dev Called by the token contract when new tokens are issued to an account. + * Reverts if the minting does not comply with the rules. + * @param to The address receiving the minted tokens. + * @param value The number of tokens created. + */ + function created(address to, uint256 value) external; + + /** + * @notice Updates the compliance contract state when tokens are destroyed (burned). + * @dev Called by the token contract when tokens are redeemed or burned. + * Reverts if the burning does not comply with the rules. + * @param from The address whose tokens are being destroyed. + * @param value The number of tokens destroyed. + */ + function destroyed(address from, uint256 value) external; +} + +// src/modules/VersionModule.sol + +/* ==== CMTAT === */ + +abstract contract VersionModule is IERC3643Base { + /* ============ State Variables ============ */ + /** + * @dev + * Get the current version of the smart contract + */ + string private constant VERSION = "3.0.0"; + /* ============ Events ============ */ + /*////////////////////////////////////////////////////////////// + PUBLIC/EXTERNAL FUNCTIONS + //////////////////////////////////////////////////////////////*/ + /** + * @inheritdoc IERC3643Base + */ + function version() public view virtual override(IERC3643Base) returns (string memory version_) { + return VERSION; + } +} + +// lib/openzeppelin-contracts/contracts/utils/math/Math.sol + +// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol) + +/** + * @dev Standard math utilities missing in the Solidity language. + */ +library Math { + enum Rounding { + Floor, // Toward negative infinity + Ceil, // Toward positive infinity + Trunc, // Toward zero + Expand // Away from zero + } + + /** + * @dev Return the 512-bit addition of two uint256. + * + * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low. + */ + function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) { + assembly ("memory-safe") { + low := add(a, b) + high := lt(low, a) + } + } + + /** + * @dev Return the 512-bit multiplication of two uint256. + * + * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low. + */ + function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) { + // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use + // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 + // variables such that product = high * 2²⁵⁶ + low. + assembly ("memory-safe") { + let mm := mulmod(a, b, not(0)) + low := mul(a, b) + high := sub(sub(mm, low), lt(mm, low)) + } + } + + /** + * @dev Returns the addition of two unsigned integers, with a success flag (no overflow). + */ + function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { + unchecked { + uint256 c = a + b; + success = c >= a; + result = c * SafeCast.toUint(success); + } + } + + /** + * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow). + */ + function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { + unchecked { + uint256 c = a - b; + success = c <= a; + result = c * SafeCast.toUint(success); + } + } + + /** + * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow). + */ + function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { + unchecked { + uint256 c = a * b; + assembly ("memory-safe") { + // Only true when the multiplication doesn't overflow + // (c / a == b) || (a == 0) + success := or(eq(div(c, a), b), iszero(a)) + } + // equivalent to: success ? c : 0 + result = c * SafeCast.toUint(success); + } + } + + /** + * @dev Returns the division of two unsigned integers, with a success flag (no division by zero). + */ + function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { + unchecked { + success = b > 0; + assembly ("memory-safe") { + // The `DIV` opcode returns zero when the denominator is 0. + result := div(a, b) + } + } + } + + /** + * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero). + */ + function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { + unchecked { + success = b > 0; + assembly ("memory-safe") { + // The `MOD` opcode returns zero when the denominator is 0. + result := mod(a, b) + } + } + } + + /** + * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing. + */ + function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) { + (bool success, uint256 result) = tryAdd(a, b); + return ternary(success, result, type(uint256).max); + } + + /** + * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing. + */ + function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) { + (, uint256 result) = trySub(a, b); + return result; + } + + /** + * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing. + */ + function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) { + (bool success, uint256 result) = tryMul(a, b); + return ternary(success, result, type(uint256).max); + } + + /** + * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. + * + * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. + * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute + * one branch when needed, making this function more expensive. + */ + function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) { + unchecked { + // branchless ternary works because: + // b ^ (a ^ b) == a + // b ^ 0 == b + return b ^ ((a ^ b) * SafeCast.toUint(condition)); + } + } + + /** + * @dev Returns the largest of two numbers. + */ + function max(uint256 a, uint256 b) internal pure returns (uint256) { + return ternary(a > b, a, b); + } + + /** + * @dev Returns the smallest of two numbers. + */ + function min(uint256 a, uint256 b) internal pure returns (uint256) { + return ternary(a < b, a, b); + } + + /** + * @dev Returns the average of two numbers. The result is rounded towards + * zero. + */ + function average(uint256 a, uint256 b) internal pure returns (uint256) { + // (a + b) / 2 can overflow. + return (a & b) + (a ^ b) / 2; + } + + /** + * @dev Returns the ceiling of the division of two numbers. + * + * This differs from standard division with `/` in that it rounds towards infinity instead + * of rounding towards zero. + */ + function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { + if (b == 0) { + // Guarantee the same behavior as in a regular Solidity division. + Panic.panic(Panic.DIVISION_BY_ZERO); + } + + // The following calculation ensures accurate ceiling division without overflow. + // Since a is non-zero, (a - 1) / b will not overflow. + // The largest possible result occurs when (a - 1) / b is type(uint256).max, + // but the largest value we can obtain is type(uint256).max - 1, which happens + // when a = type(uint256).max and b = 1. + unchecked { + return SafeCast.toUint(a > 0) * ((a - 1) / b + 1); + } + } + + /** + * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or + * denominator == 0. + * + * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by + * Uniswap Labs also under MIT license. + */ + function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { + unchecked { + (uint256 high, uint256 low) = mul512(x, y); + + // Handle non-overflow cases, 256 by 256 division. + if (high == 0) { + // Solidity will revert if denominator == 0, unlike the div opcode on its own. + // The surrounding unchecked block does not change this fact. + // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. + return low / denominator; + } + + // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0. + if (denominator <= high) { + Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW)); + } + + /////////////////////////////////////////////// + // 512 by 256 division. + /////////////////////////////////////////////// + + // Make division exact by subtracting the remainder from [high low]. + uint256 remainder; + assembly ("memory-safe") { + // Compute remainder using mulmod. + remainder := mulmod(x, y, denominator) + + // Subtract 256 bit number from 512 bit number. + high := sub(high, gt(remainder, low)) + low := sub(low, remainder) + } + + // Factor powers of two out of denominator and compute largest power of two divisor of denominator. + // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. + + uint256 twos = denominator & (0 - denominator); + assembly ("memory-safe") { + // Divide denominator by twos. + denominator := div(denominator, twos) + + // Divide [high low] by twos. + low := div(low, twos) + + // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one. + twos := add(div(sub(0, twos), twos), 1) + } + + // Shift in bits from high into low. + low |= high * twos; + + // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such + // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for + // four bits. That is, denominator * inv ≡ 1 mod 2⁴. + uint256 inverse = (3 * denominator) ^ 2; + + // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also + // works in modular arithmetic, doubling the correct bits in each step. + inverse *= 2 - denominator * inverse; // inverse mod 2⁸ + inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶ + inverse *= 2 - denominator * inverse; // inverse mod 2³² + inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴ + inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸ + inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶ + + // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. + // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is + // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high + // is no longer required. + result = low * inverse; + return result; + } + } + + /** + * @dev Calculates x * y / denominator with full precision, following the selected rounding direction. + */ + function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { + return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0); + } + + /** + * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256. + */ + function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) { + unchecked { + (uint256 high, uint256 low) = mul512(x, y); + if (high >= 1 << n) { + Panic.panic(Panic.UNDER_OVERFLOW); + } + return (high << (256 - n)) | (low >> n); + } + } + + /** + * @dev Calculates x * y >> n with full precision, following the selected rounding direction. + */ + function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) { + return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0); + } + + /** + * @dev Calculate the modular multiplicative inverse of a number in Z/nZ. + * + * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0. + * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible. + * + * If the input value is not inversible, 0 is returned. + * + * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the + * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}. + */ + function invMod(uint256 a, uint256 n) internal pure returns (uint256) { + unchecked { + if (n == 0) return 0; + + // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version) + // Used to compute integers x and y such that: ax + ny = gcd(a, n). + // When the gcd is 1, then the inverse of a modulo n exists and it's x. + // ax + ny = 1 + // ax = 1 + (-y)n + // ax ≡ 1 (mod n) # x is the inverse of a modulo n + + // If the remainder is 0 the gcd is n right away. + uint256 remainder = a % n; + uint256 gcd = n; + + // Therefore the initial coefficients are: + // ax + ny = gcd(a, n) = n + // 0a + 1n = n + int256 x = 0; + int256 y = 1; + + while (remainder != 0) { + uint256 quotient = gcd / remainder; + + (gcd, remainder) = ( + // The old remainder is the next gcd to try. + remainder, + // Compute the next remainder. + // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd + // where gcd is at most n (capped to type(uint256).max) + gcd - remainder * quotient + ); + + (x, y) = ( + // Increment the coefficient of a. + y, + // Decrement the coefficient of n. + // Can overflow, but the result is casted to uint256 so that the + // next value of y is "wrapped around" to a value between 0 and n - 1. + x - y * int256(quotient) + ); + } + + if (gcd != 1) return 0; // No inverse exists. + return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative. + } + } + + /** + * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`. + * + * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is + * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that + * `a**(p-2)` is the modular multiplicative inverse of a in Fp. + * + * NOTE: this function does NOT check that `p` is a prime greater than `2`. + */ + function invModPrime(uint256 a, uint256 p) internal view returns (uint256) { + unchecked { + return Math.modExp(a, p - 2, p); + } + } + + /** + * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m) + * + * Requirements: + * - modulus can't be zero + * - underlying staticcall to precompile must succeed + * + * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make + * sure the chain you're using it on supports the precompiled contract for modular exponentiation + * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, + * the underlying function will succeed given the lack of a revert, but the result may be incorrectly + * interpreted as 0. + */ + function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) { + (bool success, uint256 result) = tryModExp(b, e, m); + if (!success) { + Panic.panic(Panic.DIVISION_BY_ZERO); + } + return result; + } + + /** + * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m). + * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying + * to operate modulo 0 or if the underlying precompile reverted. + * + * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain + * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in + * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack + * of a revert, but the result may be incorrectly interpreted as 0. + */ + function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) { + if (m == 0) return (false, 0); + assembly ("memory-safe") { + let ptr := mload(0x40) + // | Offset | Content | Content (Hex) | + // |-----------|------------|--------------------------------------------------------------------| + // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 | + // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 | + // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 | + // | 0x60:0x7f | value of b | 0x<.............................................................b> | + // | 0x80:0x9f | value of e | 0x<.............................................................e> | + // | 0xa0:0xbf | value of m | 0x<.............................................................m> | + mstore(ptr, 0x20) + mstore(add(ptr, 0x20), 0x20) + mstore(add(ptr, 0x40), 0x20) + mstore(add(ptr, 0x60), b) + mstore(add(ptr, 0x80), e) + mstore(add(ptr, 0xa0), m) + + // Given the result < m, it's guaranteed to fit in 32 bytes, + // so we can use the memory scratch space located at offset 0. + success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20) + result := mload(0x00) + } + } + + /** + * @dev Variant of {modExp} that supports inputs of arbitrary length. + */ + function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) { + (bool success, bytes memory result) = tryModExp(b, e, m); + if (!success) { + Panic.panic(Panic.DIVISION_BY_ZERO); + } + return result; + } + + /** + * @dev Variant of {tryModExp} that supports inputs of arbitrary length. + */ + function tryModExp( + bytes memory b, + bytes memory e, + bytes memory m + ) internal view returns (bool success, bytes memory result) { + if (_zeroBytes(m)) return (false, new bytes(0)); + + uint256 mLen = m.length; + + // Encode call args in result and move the free memory pointer + result = abi.encodePacked(b.length, e.length, mLen, b, e, m); + + assembly ("memory-safe") { + let dataPtr := add(result, 0x20) + // Write result on top of args to avoid allocating extra memory. + success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen) + // Overwrite the length. + // result.length > returndatasize() is guaranteed because returndatasize() == m.length + mstore(result, mLen) + // Set the memory pointer after the returned data. + mstore(0x40, add(dataPtr, mLen)) + } + } + + /** + * @dev Returns whether the provided byte array is zero. + */ + function _zeroBytes(bytes memory byteArray) private pure returns (bool) { + for (uint256 i = 0; i < byteArray.length; ++i) { + if (byteArray[i] != 0) { + return false; + } + } + return true; + } + + /** + * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded + * towards zero. + * + * This method is based on Newton's method for computing square roots; the algorithm is restricted to only + * using integer operations. + */ + function sqrt(uint256 a) internal pure returns (uint256) { + unchecked { + // Take care of easy edge cases when a == 0 or a == 1 + if (a <= 1) { + return a; + } + + // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a + // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between + // the current value as `ε_n = | x_n - sqrt(a) |`. + // + // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root + // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is + // bigger than any uint256. + // + // By noticing that + // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)` + // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar + // to the msb function. + uint256 aa = a; + uint256 xn = 1; + + if (aa >= (1 << 128)) { + aa >>= 128; + xn <<= 64; + } + if (aa >= (1 << 64)) { + aa >>= 64; + xn <<= 32; + } + if (aa >= (1 << 32)) { + aa >>= 32; + xn <<= 16; + } + if (aa >= (1 << 16)) { + aa >>= 16; + xn <<= 8; + } + if (aa >= (1 << 8)) { + aa >>= 8; + xn <<= 4; + } + if (aa >= (1 << 4)) { + aa >>= 4; + xn <<= 2; + } + if (aa >= (1 << 2)) { + xn <<= 1; + } + + // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1). + // + // We can refine our estimation by noticing that the middle of that interval minimizes the error. + // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2). + // This is going to be our x_0 (and ε_0) + xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2) + + // From here, Newton's method give us: + // x_{n+1} = (x_n + a / x_n) / 2 + // + // One should note that: + // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a + // = ((x_n² + a) / (2 * x_n))² - a + // = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a + // = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²) + // = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²) + // = (x_n² - a)² / (2 * x_n)² + // = ((x_n² - a) / (2 * x_n))² + // ≥ 0 + // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n + // + // This gives us the proof of quadratic convergence of the sequence: + // ε_{n+1} = | x_{n+1} - sqrt(a) | + // = | (x_n + a / x_n) / 2 - sqrt(a) | + // = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) | + // = | (x_n - sqrt(a))² / (2 * x_n) | + // = | ε_n² / (2 * x_n) | + // = ε_n² / | (2 * x_n) | + // + // For the first iteration, we have a special case where x_0 is known: + // ε_1 = ε_0² / | (2 * x_0) | + // ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2))) + // ≤ 2**(2*e-4) / (3 * 2**(e-1)) + // ≤ 2**(e-3) / 3 + // ≤ 2**(e-3-log2(3)) + // ≤ 2**(e-4.5) + // + // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n: + // ε_{n+1} = ε_n² / | (2 * x_n) | + // ≤ (2**(e-k))² / (2 * 2**(e-1)) + // ≤ 2**(2*e-2*k) / 2**e + // ≤ 2**(e-2*k) + xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above + xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5 + xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9 + xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18 + xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36 + xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72 + + // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision + // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either + // sqrt(a) or sqrt(a) + 1. + return xn - SafeCast.toUint(xn > a / xn); + } + } + + /** + * @dev Calculates sqrt(a), following the selected rounding direction. + */ + function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = sqrt(a); + return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a); + } + } + + /** + * @dev Return the log in base 2 of a positive value rounded towards zero. + * Returns 0 if given 0. + */ + function log2(uint256 x) internal pure returns (uint256 r) { + // If value has upper 128 bits set, log2 result is at least 128 + r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7; + // If upper 64 bits of 128-bit half set, add 64 to result + r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6; + // If upper 32 bits of 64-bit half set, add 32 to result + r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5; + // If upper 16 bits of 32-bit half set, add 16 to result + r |= SafeCast.toUint((x >> r) > 0xffff) << 4; + // If upper 8 bits of 16-bit half set, add 8 to result + r |= SafeCast.toUint((x >> r) > 0xff) << 3; + // If upper 4 bits of 8-bit half set, add 4 to result + r |= SafeCast.toUint((x >> r) > 0xf) << 2; + + // Shifts value right by the current result and use it as an index into this lookup table: + // + // | x (4 bits) | index | table[index] = MSB position | + // |------------|---------|-----------------------------| + // | 0000 | 0 | table[0] = 0 | + // | 0001 | 1 | table[1] = 0 | + // | 0010 | 2 | table[2] = 1 | + // | 0011 | 3 | table[3] = 1 | + // | 0100 | 4 | table[4] = 2 | + // | 0101 | 5 | table[5] = 2 | + // | 0110 | 6 | table[6] = 2 | + // | 0111 | 7 | table[7] = 2 | + // | 1000 | 8 | table[8] = 3 | + // | 1001 | 9 | table[9] = 3 | + // | 1010 | 10 | table[10] = 3 | + // | 1011 | 11 | table[11] = 3 | + // | 1100 | 12 | table[12] = 3 | + // | 1101 | 13 | table[13] = 3 | + // | 1110 | 14 | table[14] = 3 | + // | 1111 | 15 | table[15] = 3 | + // + // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes. + assembly ("memory-safe") { + r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000)) + } + } + + /** + * @dev Return the log in base 2, following the selected rounding direction, of a positive value. + * Returns 0 if given 0. + */ + function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = log2(value); + return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value); + } + } + + /** + * @dev Return the log in base 10 of a positive value rounded towards zero. + * Returns 0 if given 0. + */ + function log10(uint256 value) internal pure returns (uint256) { + uint256 result = 0; + unchecked { + if (value >= 10 ** 64) { + value /= 10 ** 64; + result += 64; + } + if (value >= 10 ** 32) { + value /= 10 ** 32; + result += 32; + } + if (value >= 10 ** 16) { + value /= 10 ** 16; + result += 16; + } + if (value >= 10 ** 8) { + value /= 10 ** 8; + result += 8; + } + if (value >= 10 ** 4) { + value /= 10 ** 4; + result += 4; + } + if (value >= 10 ** 2) { + value /= 10 ** 2; + result += 2; + } + if (value >= 10 ** 1) { + result += 1; + } + } + return result; + } + + /** + * @dev Return the log in base 10, following the selected rounding direction, of a positive value. + * Returns 0 if given 0. + */ + function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = log10(value); + return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value); + } + } + + /** + * @dev Return the log in base 256 of a positive value rounded towards zero. + * Returns 0 if given 0. + * + * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. + */ + function log256(uint256 x) internal pure returns (uint256 r) { + // If value has upper 128 bits set, log2 result is at least 128 + r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7; + // If upper 64 bits of 128-bit half set, add 64 to result + r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6; + // If upper 32 bits of 64-bit half set, add 32 to result + r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5; + // If upper 16 bits of 32-bit half set, add 16 to result + r |= SafeCast.toUint((x >> r) > 0xffff) << 4; + // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8 + return (r >> 3) | SafeCast.toUint((x >> r) > 0xff); + } + + /** + * @dev Return the log in base 256, following the selected rounding direction, of a positive value. + * Returns 0 if given 0. + */ + function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = log256(value); + return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value); + } + } + + /** + * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. + */ + function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { + return uint8(rounding) % 2 == 1; + } +} + +// src/modules/ERC2771ModuleStandalone.sol + +/* ==== OpenZeppelin === */ + +/** + * @dev Meta transaction (gasless) module. + */ +abstract contract ERC2771ModuleStandalone is ERC2771Context { + constructor(address trustedForwarder) ERC2771Context(trustedForwarder) { + // Nothing to do + } +} + +// lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol + +/* +* @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; +} + +// lib/openzeppelin-contracts/contracts/access/AccessControl.sol + +// OpenZeppelin Contracts (last updated v5.4.0) (access/AccessControl.sol) + +/** + * @dev Contract module that allows children to implement role-based access + * control mechanisms. This is a lightweight version that doesn't allow enumerating role + * members except through off-chain means by accessing the contract event logs. Some + * applications may benefit from on-chain enumerability, for those cases see + * {AccessControlEnumerable}. + * + * Roles are referred to by their `bytes32` identifier. These should be exposed + * in the external API and be unique. The best way to achieve this is by + * using `public constant` hash digests: + * + * ```solidity + * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); + * ``` + * + * Roles can be used to represent a set of permissions. To restrict access to a + * function call, use {hasRole}: + * + * ```solidity + * function foo() public { + * require(hasRole(MY_ROLE, msg.sender)); + * ... + * } + * ``` + * + * Roles can be granted and revoked dynamically via the {grantRole} and + * {revokeRole} functions. Each role has an associated admin role, and only + * accounts that have a role's admin role can call {grantRole} and {revokeRole}. + * + * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means + * that only accounts with this role will be able to grant or revoke other + * roles. More complex role relationships can be created by using + * {_setRoleAdmin}. + * + * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to + * grant and revoke this role. Extra precautions should be taken to secure + * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} + * to enforce additional security measures for this role. + */ +abstract contract AccessControl is Context, IAccessControl, ERC165 { + struct RoleData { + mapping(address account => bool) hasRole; + bytes32 adminRole; + } + + mapping(bytes32 role => RoleData) private _roles; + + bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; + + /** + * @dev Modifier that checks that an account has a specific role. Reverts + * with an {AccessControlUnauthorizedAccount} error including the required role. + */ + modifier onlyRole(bytes32 role) { + _checkRole(role); + _; + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); + } + + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole(bytes32 role, address account) public view virtual returns (bool) { + return _roles[role].hasRole[account]; + } + + /** + * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` + * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. + */ + function _checkRole(bytes32 role) internal view virtual { + _checkRole(role, _msgSender()); + } + + /** + * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` + * is missing `role`. + */ + function _checkRole(bytes32 role, address account) internal view virtual { + if (!hasRole(role, account)) { + revert AccessControlUnauthorizedAccount(account, role); + } + } + + /** + * @dev Returns the admin role that controls `role`. See {grantRole} and + * {revokeRole}. + * + * To change a role's admin, use {_setRoleAdmin}. + */ + function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { + return _roles[role].adminRole; + } + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + * + * May emit a {RoleGranted} event. + */ + function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { + _grantRole(role, account); + } + + /** + * @dev Revokes `role` from `account`. + * + * If `account` had been granted `role`, emits a {RoleRevoked} event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + * + * May emit a {RoleRevoked} event. + */ + function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { + _revokeRole(role, account); + } + + /** + * @dev Revokes `role` from the calling account. + * + * Roles are often managed via {grantRole} and {revokeRole}: this function's + * purpose is to provide a mechanism for accounts to lose their privileges + * if they are compromised (such as when a trusted device is misplaced). + * + * If the calling account had been revoked `role`, emits a {RoleRevoked} + * event. + * + * Requirements: + * + * - the caller must be `callerConfirmation`. + * + * May emit a {RoleRevoked} event. + */ + function renounceRole(bytes32 role, address callerConfirmation) public virtual { + if (callerConfirmation != _msgSender()) { + revert AccessControlBadConfirmation(); + } + + _revokeRole(role, callerConfirmation); + } + + /** + * @dev Sets `adminRole` as ``role``'s admin role. + * + * Emits a {RoleAdminChanged} event. + */ + function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { + bytes32 previousAdminRole = getRoleAdmin(role); + _roles[role].adminRole = adminRole; + emit RoleAdminChanged(role, previousAdminRole, adminRole); + } + + /** + * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. + * + * Internal function without access restriction. + * + * May emit a {RoleGranted} event. + */ + function _grantRole(bytes32 role, address account) internal virtual returns (bool) { + if (!hasRole(role, account)) { + _roles[role].hasRole[account] = true; + emit RoleGranted(role, account, _msgSender()); + return true; + } else { + return false; + } + } + + /** + * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked. + * + * Internal function without access restriction. + * + * May emit a {RoleRevoked} event. + */ + function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { + if (hasRole(role, account)) { + _roles[role].hasRole[account] = false; + emit RoleRevoked(role, account, _msgSender()); + return true; + } else { + return false; + } + } +} + +// src/interfaces/IRule.sol + +/* ==== CMTAT === */ + +/* ==== Interfaces === */ + +interface IRule is IRuleEngine { + /** + * @dev Returns true if the restriction code exists, and false otherwise. + */ + function canReturnTransferRestrictionCode( + uint8 restrictionCode + ) external view returns (bool); +} + +// src/interfaces/IRulesManagementModule.sol + +/* ==== Interfaces === */ + +interface IRulesManagementModule { + /** + * @notice Defines the rules for the rule engine. + * @dev Sets the list of rule contract addresses for s. + * Any previously set rules will be completely overwritten by the new list. + * Rules should be deployed contracts that implement the expected interface. + * @param rules_ The array of addresses representing the new rules to be set. + * @dev Revert if one rule is a zero address or if the rule is already present + * This function calls _clearRules if at least one rule is still configured + */ + function setRules(IRule[] calldata rules_) external; + + /** + * @notice Returns the total number of currently configured rules. + * @dev Equivalent to the length of the internal rules array. + * Complexity: O(1) + * @return numberOfrules The number of active rules. + */ + function rulesCount() external view returns (uint256 numberOfrules); + + /** + * @notice Retrieves the rule address at a specific index. + * @dev Reverts if `ruleId` is out of bounds. + * Complexity: O(1). + * Note that there are no guarantees on the ordering of values inside the array, + * and it may change when more values are added or removed. + * @param ruleId The index of the desired rule in the array. + * @return ruleAddress The address of the corresponding IRule contract, return the `zero address` is out of bounds. + */ + function rule(uint256 ruleId) external view returns (address ruleAddress); + + /** + * @notice Returns the full list of currently configured rules. + * @dev This is a view-only function that does not modify state. + * This operation will copy the entire storage to memory, which can be quite expensive. + * This is designed to mostly be used by view accessors that are queried without any gas fees. + * @return ruleAddresses An array of all active rule contract addresses. + */ + function rules() external view returns (address[] memory ruleAddresses); + + /** + * @notice Removes all configured rules. + * @dev After calling this function, no rules will remain set. + * Developers should keep in mind that this function has an unbounded cost + * and using it may render the function uncallable if the set grows to the point + * where clearing it consumes too much gas to fit in a block. + */ + function clearRules() external; + + /** + * @notice Adds a new rule to the current rule set. + * @dev Reverts if the rule address is zero or already exists in the set. + * Complexity: O(1). + * @param rule_ The IRule contract to add. + */ + function addRule( + IRule rule_ + ) external; + + /** + * @notice Removes a specific rule from the current rule set. + * @dev Reverts if the provided rule is not found or does not match the stored rule at its index. + * Complexity: O(1). + * @param rule_ The IRule contract to remove. + */ + function removeRule( + IRule rule_ + ) external; + + /** + * @notice Checks whether a specific rule is currently configured. + * @param rule_ The IRule contract to check for membership. + * @dev Complexity: O(1). + * @return exists True if the rule is present, false otherwise. + */ + function containsRule(IRule rule_) external returns (bool exists); +} + +// src/modules/library/RulesManagementModuleInvariantStorage.sol + +abstract contract RulesManagementModuleInvariantStorage { + /* ==== Errors === */ + error RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed(); + error RuleEngine_RulesManagementModule_RuleAlreadyExists(); + error RuleEngine_RulesManagementModule_RuleDoNotMatch(); + error RuleEngine_RulesManagementModule_ArrayIsEmpty(); + error RuleEngine_RulesManagementModule_OperationNotSuccessful(); + + /* ============ Events ============ */ + /** + * @notice Emitted when a new rule is added to the rule set. + * @param rule The address of the rule contract that was added. + */ + event AddRule(IRule indexed rule); + + /** + * @notice Emitted when a rule is removed from the rule set. + * @param rule The address of the rule contract that was removed. + */ + event RemoveRule(IRule indexed rule); + + /** + * @notice Emitted when all rules are cleared from the rule set. + */ + event ClearRules(); + + /* ==== Constant === */ + /// @notice Role to manage the ruleEngine + bytes32 public constant RULES_MANAGEMENT_ROLE = + keccak256("RULES_MANAGEMENT_ROLE"); +} + +// lib/openzeppelin-contracts/contracts/utils/Arrays.sol + +// OpenZeppelin Contracts (last updated v5.4.0) (utils/Arrays.sol) +// This file was procedurally generated from scripts/generate/templates/Arrays.js. + +/** + * @dev Collection of functions related to array types. + */ +library Arrays { + using SlotDerivation for bytes32; + using StorageSlot for bytes32; + + /** + * @dev Sort an array of uint256 (in memory) following the provided comparator function. + * + * This function does the sorting "in place", meaning that it overrides the input. The object is returned for + * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array. + * + * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the + * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful + * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may + * consume more gas than is available in a block, leading to potential DoS. + * + * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way. + */ + function sort( + uint256[] memory array, + function(uint256, uint256) pure returns (bool) comp + ) internal pure returns (uint256[] memory) { + _quickSort(_begin(array), _end(array), comp); + return array; + } + + /** + * @dev Variant of {sort} that sorts an array of uint256 in increasing order. + */ + function sort(uint256[] memory array) internal pure returns (uint256[] memory) { + sort(array, Comparators.lt); + return array; + } + + /** + * @dev Sort an array of address (in memory) following the provided comparator function. + * + * This function does the sorting "in place", meaning that it overrides the input. The object is returned for + * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array. + * + * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the + * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful + * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may + * consume more gas than is available in a block, leading to potential DoS. + * + * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way. + */ + function sort( + address[] memory array, + function(address, address) pure returns (bool) comp + ) internal pure returns (address[] memory) { + sort(_castToUint256Array(array), _castToUint256Comp(comp)); + return array; + } + + /** + * @dev Variant of {sort} that sorts an array of address in increasing order. + */ + function sort(address[] memory array) internal pure returns (address[] memory) { + sort(_castToUint256Array(array), Comparators.lt); + return array; + } + + /** + * @dev Sort an array of bytes32 (in memory) following the provided comparator function. + * + * This function does the sorting "in place", meaning that it overrides the input. The object is returned for + * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array. + * + * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the + * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful + * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may + * consume more gas than is available in a block, leading to potential DoS. + * + * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way. + */ + function sort( + bytes32[] memory array, + function(bytes32, bytes32) pure returns (bool) comp + ) internal pure returns (bytes32[] memory) { + sort(_castToUint256Array(array), _castToUint256Comp(comp)); + return array; + } + + /** + * @dev Variant of {sort} that sorts an array of bytes32 in increasing order. + */ + function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) { + sort(_castToUint256Array(array), Comparators.lt); + return array; + } + + /** + * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops + * at end (exclusive). Sorting follows the `comp` comparator. + * + * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls. + * + * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should + * be used only if the limits are within a memory array. + */ + function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure { + unchecked { + if (end - begin < 0x40) return; + + // Use first element as pivot + uint256 pivot = _mload(begin); + // Position where the pivot should be at the end of the loop + uint256 pos = begin; + + for (uint256 it = begin + 0x20; it < end; it += 0x20) { + if (comp(_mload(it), pivot)) { + // If the value stored at the iterator's position comes before the pivot, we increment the + // position of the pivot and move the value there. + pos += 0x20; + _swap(pos, it); + } + } + + _swap(begin, pos); // Swap pivot into place + _quickSort(begin, pos, comp); // Sort the left side of the pivot + _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot + } + } + + /** + * @dev Pointer to the memory location of the first element of `array`. + */ + function _begin(uint256[] memory array) private pure returns (uint256 ptr) { + assembly ("memory-safe") { + ptr := add(array, 0x20) + } + } + + /** + * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word + * that comes just after the last element of the array. + */ + function _end(uint256[] memory array) private pure returns (uint256 ptr) { + unchecked { + return _begin(array) + array.length * 0x20; + } + } + + /** + * @dev Load memory word (as a uint256) at location `ptr`. + */ + function _mload(uint256 ptr) private pure returns (uint256 value) { + assembly { + value := mload(ptr) + } + } + + /** + * @dev Swaps the elements memory location `ptr1` and `ptr2`. + */ + function _swap(uint256 ptr1, uint256 ptr2) private pure { + assembly { + let value1 := mload(ptr1) + let value2 := mload(ptr2) + mstore(ptr1, value2) + mstore(ptr2, value1) + } + } + + /// @dev Helper: low level cast address memory array to uint256 memory array + function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) { + assembly { + output := input + } + } + + /// @dev Helper: low level cast bytes32 memory array to uint256 memory array + function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) { + assembly { + output := input + } + } + + /// @dev Helper: low level cast address comp function to uint256 comp function + function _castToUint256Comp( + function(address, address) pure returns (bool) input + ) private pure returns (function(uint256, uint256) pure returns (bool) output) { + assembly { + output := input + } + } + + /// @dev Helper: low level cast bytes32 comp function to uint256 comp function + function _castToUint256Comp( + function(bytes32, bytes32) pure returns (bool) input + ) private pure returns (function(uint256, uint256) pure returns (bool) output) { + assembly { + output := input + } + } + + /** + * @dev Searches a sorted `array` and returns the first index that contains + * a value greater or equal to `element`. If no such index exists (i.e. all + * values in the array are strictly less than `element`), the array length is + * returned. Time complexity O(log n). + * + * NOTE: The `array` is expected to be sorted in ascending order, and to + * contain no repeated elements. + * + * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks + * support for repeated elements in the array. The {lowerBound} function should + * be used instead. + */ + function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { + uint256 low = 0; + uint256 high = array.length; + + if (high == 0) { + return 0; + } + + while (low < high) { + uint256 mid = Math.average(low, high); + + // Note that mid will always be strictly less than high (i.e. it will be a valid array index) + // because Math.average rounds towards zero (it does integer division with truncation). + if (unsafeAccess(array, mid).value > element) { + high = mid; + } else { + low = mid + 1; + } + } + + // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound. + if (low > 0 && unsafeAccess(array, low - 1).value == element) { + return low - 1; + } else { + return low; + } + } + + /** + * @dev Searches an `array` sorted in ascending order and returns the first + * index that contains a value greater or equal than `element`. If no such index + * exists (i.e. all values in the array are strictly less than `element`), the array + * length is returned. Time complexity O(log n). + * + * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound]. + */ + function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) { + uint256 low = 0; + uint256 high = array.length; + + if (high == 0) { + return 0; + } + + while (low < high) { + uint256 mid = Math.average(low, high); + + // Note that mid will always be strictly less than high (i.e. it will be a valid array index) + // because Math.average rounds towards zero (it does integer division with truncation). + if (unsafeAccess(array, mid).value < element) { + // this cannot overflow because mid < high + unchecked { + low = mid + 1; + } + } else { + high = mid; + } + } + + return low; + } + + /** + * @dev Searches an `array` sorted in ascending order and returns the first + * index that contains a value strictly greater than `element`. If no such index + * exists (i.e. all values in the array are strictly less than `element`), the array + * length is returned. Time complexity O(log n). + * + * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound]. + */ + function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { + uint256 low = 0; + uint256 high = array.length; + + if (high == 0) { + return 0; + } + + while (low < high) { + uint256 mid = Math.average(low, high); + + // Note that mid will always be strictly less than high (i.e. it will be a valid array index) + // because Math.average rounds towards zero (it does integer division with truncation). + if (unsafeAccess(array, mid).value > element) { + high = mid; + } else { + // this cannot overflow because mid < high + unchecked { + low = mid + 1; + } + } + } + + return low; + } + + /** + * @dev Same as {lowerBound}, but with an array in memory. + */ + function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) { + uint256 low = 0; + uint256 high = array.length; + + if (high == 0) { + return 0; + } + + while (low < high) { + uint256 mid = Math.average(low, high); + + // Note that mid will always be strictly less than high (i.e. it will be a valid array index) + // because Math.average rounds towards zero (it does integer division with truncation). + if (unsafeMemoryAccess(array, mid) < element) { + // this cannot overflow because mid < high + unchecked { + low = mid + 1; + } + } else { + high = mid; + } + } + + return low; + } + + /** + * @dev Same as {upperBound}, but with an array in memory. + */ + function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) { + uint256 low = 0; + uint256 high = array.length; + + if (high == 0) { + return 0; + } + + while (low < high) { + uint256 mid = Math.average(low, high); + + // Note that mid will always be strictly less than high (i.e. it will be a valid array index) + // because Math.average rounds towards zero (it does integer division with truncation). + if (unsafeMemoryAccess(array, mid) > element) { + high = mid; + } else { + // this cannot overflow because mid < high + unchecked { + low = mid + 1; + } + } + } + + return low; + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) { + bytes32 slot; + assembly ("memory-safe") { + slot := arr.slot + } + return slot.deriveArray().offset(pos).getAddressSlot(); + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) { + bytes32 slot; + assembly ("memory-safe") { + slot := arr.slot + } + return slot.deriveArray().offset(pos).getBytes32Slot(); + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) { + bytes32 slot; + assembly ("memory-safe") { + slot := arr.slot + } + return slot.deriveArray().offset(pos).getUint256Slot(); + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeAccess(bytes[] storage arr, uint256 pos) internal pure returns (StorageSlot.BytesSlot storage) { + bytes32 slot; + assembly ("memory-safe") { + slot := arr.slot + } + return slot.deriveArray().offset(pos).getBytesSlot(); + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeAccess(string[] storage arr, uint256 pos) internal pure returns (StorageSlot.StringSlot storage) { + bytes32 slot; + assembly ("memory-safe") { + slot := arr.slot + } + return slot.deriveArray().offset(pos).getStringSlot(); + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) { + assembly { + res := mload(add(add(arr, 0x20), mul(pos, 0x20))) + } + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) { + assembly { + res := mload(add(add(arr, 0x20), mul(pos, 0x20))) + } + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) { + assembly { + res := mload(add(add(arr, 0x20), mul(pos, 0x20))) + } + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeMemoryAccess(bytes[] memory arr, uint256 pos) internal pure returns (bytes memory res) { + assembly { + res := mload(add(add(arr, 0x20), mul(pos, 0x20))) + } + } + + /** + * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. + * + * WARNING: Only use if you are certain `pos` is lower than the array length. + */ + function unsafeMemoryAccess(string[] memory arr, uint256 pos) internal pure returns (string memory res) { + assembly { + res := mload(add(add(arr, 0x20), mul(pos, 0x20))) + } + } + + /** + * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden. + * + * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. + */ + function unsafeSetLength(address[] storage array, uint256 len) internal { + assembly ("memory-safe") { + sstore(array.slot, len) + } + } + + /** + * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden. + * + * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. + */ + function unsafeSetLength(bytes32[] storage array, uint256 len) internal { + assembly ("memory-safe") { + sstore(array.slot, len) + } + } + + /** + * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden. + * + * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. + */ + function unsafeSetLength(uint256[] storage array, uint256 len) internal { + assembly ("memory-safe") { + sstore(array.slot, len) + } + } + + /** + * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden. + * + * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. + */ + function unsafeSetLength(bytes[] storage array, uint256 len) internal { + assembly ("memory-safe") { + sstore(array.slot, len) + } + } + + /** + * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden. + * + * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. + */ + function unsafeSetLength(string[] storage array, uint256 len) internal { + assembly ("memory-safe") { + sstore(array.slot, len) + } + } +} + +// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol + +// OpenZeppelin Contracts (last updated v5.4.0) (utils/structs/EnumerableSet.sol) +// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. + +/** + * @dev Library for managing + * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive + * types. + * + * Sets have the following properties: + * + * - Elements are added, removed, and checked for existence in constant time + * (O(1)). + * - Elements are enumerated in O(n). No guarantees are made on the ordering. + * - Set can be cleared (all elements removed) in O(n). + * + * ```solidity + * contract Example { + * // Add the library methods + * using EnumerableSet for EnumerableSet.AddressSet; + * + * // Declare a set state variable + * EnumerableSet.AddressSet private mySet; + * } + * ``` + * + * The following types are supported: + * + * - `bytes32` (`Bytes32Set`) since v3.3.0 + * - `address` (`AddressSet`) since v3.3.0 + * - `uint256` (`UintSet`) since v3.3.0 + * - `string` (`StringSet`) since v5.4.0 + * - `bytes` (`BytesSet`) since v5.4.0 + * + * [WARNING] + * ==== + * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure + * unusable. + * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. + * + * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an + * array of EnumerableSet. + * ==== + */ +library EnumerableSet { + // To implement this library for multiple types with as little code + // repetition as possible, we write it in terms of a generic Set type with + // bytes32 values. + // The Set implementation uses private functions, and user-facing + // implementations (such as AddressSet) are just wrappers around the + // underlying Set. + // This means that we can only create new EnumerableSets for types that fit + // in bytes32. + + struct Set { + // Storage of set values + bytes32[] _values; + // Position is the index of the value in the `values` array plus 1. + // Position 0 is used to mean a value is not in the set. + mapping(bytes32 value => uint256) _positions; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function _add(Set storage set, bytes32 value) private returns (bool) { + if (!_contains(set, value)) { + set._values.push(value); + // The value is stored at length-1, but we add 1 to all indexes + // and use 0 as a sentinel value + set._positions[value] = set._values.length; + return true; + } else { + return false; + } + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function _remove(Set storage set, bytes32 value) private returns (bool) { + // We cache the value's position to prevent multiple reads from the same storage slot + uint256 position = set._positions[value]; + + if (position != 0) { + // Equivalent to contains(set, value) + // To delete an element from the _values array in O(1), we swap the element to delete with the last one in + // the array, and then remove the last element (sometimes called as 'swap and pop'). + // This modifies the order of the array, as noted in {at}. + + uint256 valueIndex = position - 1; + uint256 lastIndex = set._values.length - 1; + + if (valueIndex != lastIndex) { + bytes32 lastValue = set._values[lastIndex]; + + // Move the lastValue to the index where the value to delete is + set._values[valueIndex] = lastValue; + // Update the tracked position of the lastValue (that was just moved) + set._positions[lastValue] = position; + } + + // Delete the slot where the moved value was stored + set._values.pop(); + + // Delete the tracked position for the deleted slot + delete set._positions[value]; + + return true; + } else { + return false; + } + } + + /** + * @dev Removes all the values from a set. O(n). + * + * WARNING: This function has an unbounded cost that scales with set size. Developers should keep in mind that + * using it may render the function uncallable if the set grows to the point where clearing it consumes too much + * gas to fit in a block. + */ + function _clear(Set storage set) private { + uint256 len = _length(set); + for (uint256 i = 0; i < len; ++i) { + delete set._positions[set._values[i]]; + } + Arrays.unsafeSetLength(set._values, 0); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function _contains(Set storage set, bytes32 value) private view returns (bool) { + return set._positions[value] != 0; + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function _length(Set storage set) private view returns (uint256) { + return set._values.length; + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function _at(Set storage set, uint256 index) private view returns (bytes32) { + return set._values[index]; + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function _values(Set storage set) private view returns (bytes32[] memory) { + return set._values; + } + + /** + * @dev Return a slice of the set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function _values(Set storage set, uint256 start, uint256 end) private view returns (bytes32[] memory) { + unchecked { + end = Math.min(end, _length(set)); + start = Math.min(start, end); + + uint256 len = end - start; + bytes32[] memory result = new bytes32[](len); + for (uint256 i = 0; i < len; ++i) { + result[i] = Arrays.unsafeAccess(set._values, start + i).value; + } + return result; + } + } + + // Bytes32Set + + struct Bytes32Set { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _add(set._inner, value); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _remove(set._inner, value); + } + + /** + * @dev Removes all the values from a set. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(Bytes32Set storage set) internal { + _clear(set._inner); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { + return _contains(set._inner, value); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(Bytes32Set storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { + return _at(set._inner, index); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { + bytes32[] memory store = _values(set._inner); + bytes32[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + /** + * @dev Return a slice of the set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) { + bytes32[] memory store = _values(set._inner, start, end); + bytes32[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + // AddressSet + + struct AddressSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(AddressSet storage set, address value) internal returns (bool) { + return _add(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(AddressSet storage set, address value) internal returns (bool) { + return _remove(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes all the values from a set. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(AddressSet storage set) internal { + _clear(set._inner); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(AddressSet storage set, address value) internal view returns (bool) { + return _contains(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(AddressSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(AddressSet storage set, uint256 index) internal view returns (address) { + return address(uint160(uint256(_at(set._inner, index)))); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(AddressSet storage set) internal view returns (address[] memory) { + bytes32[] memory store = _values(set._inner); + address[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + /** + * @dev Return a slice of the set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) { + bytes32[] memory store = _values(set._inner, start, end); + address[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + // UintSet + + struct UintSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(UintSet storage set, uint256 value) internal returns (bool) { + return _add(set._inner, bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(UintSet storage set, uint256 value) internal returns (bool) { + return _remove(set._inner, bytes32(value)); + } + + /** + * @dev Removes all the values from a set. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(UintSet storage set) internal { + _clear(set._inner); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(UintSet storage set, uint256 value) internal view returns (bool) { + return _contains(set._inner, bytes32(value)); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(UintSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintSet storage set, uint256 index) internal view returns (uint256) { + return uint256(_at(set._inner, index)); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(UintSet storage set) internal view returns (uint256[] memory) { + bytes32[] memory store = _values(set._inner); + uint256[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + /** + * @dev Return a slice of the set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) { + bytes32[] memory store = _values(set._inner, start, end); + uint256[] memory result; + + assembly ("memory-safe") { + result := store + } + + return result; + } + + struct StringSet { + // Storage of set values + string[] _values; + // Position is the index of the value in the `values` array plus 1. + // Position 0 is used to mean a value is not in the set. + mapping(string value => uint256) _positions; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(StringSet storage set, string memory value) internal returns (bool) { + if (!contains(set, value)) { + set._values.push(value); + // The value is stored at length-1, but we add 1 to all indexes + // and use 0 as a sentinel value + set._positions[value] = set._values.length; + return true; + } else { + return false; + } + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(StringSet storage set, string memory value) internal returns (bool) { + // We cache the value's position to prevent multiple reads from the same storage slot + uint256 position = set._positions[value]; + + if (position != 0) { + // Equivalent to contains(set, value) + // To delete an element from the _values array in O(1), we swap the element to delete with the last one in + // the array, and then remove the last element (sometimes called as 'swap and pop'). + // This modifies the order of the array, as noted in {at}. + + uint256 valueIndex = position - 1; + uint256 lastIndex = set._values.length - 1; + + if (valueIndex != lastIndex) { + string memory lastValue = set._values[lastIndex]; + + // Move the lastValue to the index where the value to delete is + set._values[valueIndex] = lastValue; + // Update the tracked position of the lastValue (that was just moved) + set._positions[lastValue] = position; + } + + // Delete the slot where the moved value was stored + set._values.pop(); + + // Delete the tracked position for the deleted slot + delete set._positions[value]; + + return true; + } else { + return false; + } + } + + /** + * @dev Removes all the values from a set. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(StringSet storage set) internal { + uint256 len = length(set); + for (uint256 i = 0; i < len; ++i) { + delete set._positions[set._values[i]]; + } + Arrays.unsafeSetLength(set._values, 0); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(StringSet storage set, string memory value) internal view returns (bool) { + return set._positions[value] != 0; + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function length(StringSet storage set) internal view returns (uint256) { + return set._values.length; + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(StringSet storage set, uint256 index) internal view returns (string memory) { + return set._values[index]; + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(StringSet storage set) internal view returns (string[] memory) { + return set._values; + } + + /** + * @dev Return a slice of the set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(StringSet storage set, uint256 start, uint256 end) internal view returns (string[] memory) { + unchecked { + end = Math.min(end, length(set)); + start = Math.min(start, end); + + uint256 len = end - start; + string[] memory result = new string[](len); + for (uint256 i = 0; i < len; ++i) { + result[i] = Arrays.unsafeAccess(set._values, start + i).value; + } + return result; + } + } + + struct BytesSet { + // Storage of set values + bytes[] _values; + // Position is the index of the value in the `values` array plus 1. + // Position 0 is used to mean a value is not in the set. + mapping(bytes value => uint256) _positions; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(BytesSet storage set, bytes memory value) internal returns (bool) { + if (!contains(set, value)) { + set._values.push(value); + // The value is stored at length-1, but we add 1 to all indexes + // and use 0 as a sentinel value + set._positions[value] = set._values.length; + return true; + } else { + return false; + } + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(BytesSet storage set, bytes memory value) internal returns (bool) { + // We cache the value's position to prevent multiple reads from the same storage slot + uint256 position = set._positions[value]; + + if (position != 0) { + // Equivalent to contains(set, value) + // To delete an element from the _values array in O(1), we swap the element to delete with the last one in + // the array, and then remove the last element (sometimes called as 'swap and pop'). + // This modifies the order of the array, as noted in {at}. + + uint256 valueIndex = position - 1; + uint256 lastIndex = set._values.length - 1; + + if (valueIndex != lastIndex) { + bytes memory lastValue = set._values[lastIndex]; + + // Move the lastValue to the index where the value to delete is + set._values[valueIndex] = lastValue; + // Update the tracked position of the lastValue (that was just moved) + set._positions[lastValue] = position; + } + + // Delete the slot where the moved value was stored + set._values.pop(); + + // Delete the tracked position for the deleted slot + delete set._positions[value]; + + return true; + } else { + return false; + } + } + + /** + * @dev Removes all the values from a set. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(BytesSet storage set) internal { + uint256 len = length(set); + for (uint256 i = 0; i < len; ++i) { + delete set._positions[set._values[i]]; + } + Arrays.unsafeSetLength(set._values, 0); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(BytesSet storage set, bytes memory value) internal view returns (bool) { + return set._positions[value] != 0; + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function length(BytesSet storage set) internal view returns (uint256) { + return set._values.length; + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(BytesSet storage set, uint256 index) internal view returns (bytes memory) { + return set._values[index]; + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(BytesSet storage set) internal view returns (bytes[] memory) { + return set._values; + } + + /** + * @dev Return a slice of the set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(BytesSet storage set, uint256 start, uint256 end) internal view returns (bytes[] memory) { + unchecked { + end = Math.min(end, length(set)); + start = Math.min(start, end); + + uint256 len = end - start; + bytes[] memory result = new bytes[](len); + for (uint256 i = 0; i < len; ++i) { + result[i] = Arrays.unsafeAccess(set._values, start + i).value; + } + return result; + } + } +} + +// src/modules/ERC3643ComplianceModule.sol + +/* ==== OpenZeppelin === */ + +/* ==== Interface and other library === */ + +abstract contract ERC3643ComplianceModule is IERC3643Compliance, AccessControl { + /* ==== Type declaration === */ + using EnumerableSet for EnumerableSet.AddressSet; + /* ==== State Variables === */ + // Token binding tracking + EnumerableSet.AddressSet private _boundTokens; + // Access Control + bytes32 public constant COMPLIANCE_MANAGER_ROLE = keccak256("COMPLIANCE_MANAGER_ROLE"); + + /* ==== Errors === */ + error RuleEngine_ERC3643Compliance_InvalidTokenAddress(); + error RuleEngine_ERC3643Compliance_TokenAlreadyBound(); + error RuleEngine_ERC3643Compliance_TokenNotBound(); + error RuleEngine_ERC3643Compliance_UnauthorizedCaller(); + error RuleEngine_ERC3643Compliance_OperationNotSuccessful(); + + /* ==== Modifier === */ + modifier onlyBoundToken() { + if (!_boundTokens.contains(_msgSender())) { + revert RuleEngine_ERC3643Compliance_UnauthorizedCaller(); + } + _; + } + + /*////////////////////////////////////////////////////////////// + PUBLIC/public FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + /* ============ State functions ============ */ + /// @inheritdoc IERC3643Compliance + function bindToken(address token) public override virtual onlyRole(COMPLIANCE_MANAGER_ROLE) { + _bindToken(token); + } + + /// @inheritdoc IERC3643Compliance + function unbindToken(address token) public override virtual onlyRole(COMPLIANCE_MANAGER_ROLE) { + _unbindToken(token); + } + + /// @inheritdoc IERC3643Compliance + function isTokenBound(address token) public view virtual override returns (bool) { + return _boundTokens.contains(token); + } + + /// @inheritdoc IERC3643Compliance + function getTokenBound() public view virtual override returns (address) { + if(_boundTokens.length() > 0){ + // Note that there are no guarantees on the ordering of values inside the array, + // and it may change when more values are added or removed. + return _boundTokens.at(0); + } else { + return address(0); + } + } + + /// @inheritdoc IERC3643Compliance + function getTokenBounds() public view override returns (address[] memory) { + return _boundTokens.values(); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL/PRIVATE FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + function _unbindToken(address token) internal { + require (_boundTokens.contains(token), RuleEngine_ERC3643Compliance_TokenNotBound()); + // Should never revert because we check if the token address is already set before + require(_boundTokens.remove(token), RuleEngine_ERC3643Compliance_OperationNotSuccessful()); + + emit TokenUnbound(token); + } + function _bindToken(address token) internal{ + require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); + require(!_boundTokens.contains(token), RuleEngine_ERC3643Compliance_TokenAlreadyBound()); + // Should never revert because we check if the token address is already set before + require(_boundTokens.add(token), RuleEngine_ERC3643Compliance_OperationNotSuccessful()); + emit TokenBound(token); + } +} + +// src/modules/RulesManagementModule.sol + +/* ==== OpenZeppelin === */ + +/* ==== Interface and other library === */ + +/** + * @title RuleEngine - part + */ +abstract contract RulesManagementModule is + AccessControl, + RulesManagementModuleInvariantStorage, + IRulesManagementModule +{ + /* ==== Type declaration === */ + using EnumerableSet for EnumerableSet.AddressSet; + + /* ==== State Variables === */ + /// @dev Array of rules + EnumerableSet.AddressSet internal _rules; + + /*////////////////////////////////////////////////////////////// + PUBLIC/EXTERNAL FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + /* ============ State functions ============ */ + + /** + * @inheritdoc IRulesManagementModule + */ + function setRules( + IRule[] calldata rules_ + ) public virtual override(IRulesManagementModule) onlyRole(RULES_MANAGEMENT_ROLE) { + if (rules_.length == 0) { + revert RuleEngine_RulesManagementModule_ArrayIsEmpty(); + } + if (_rules.length() > 0) { + _clearRules(); + } + for(uint256 i = 0; i < rules_.length; ++i){ + _checkRule(address(rules_[i])); + // Should never revert because we check the presence of the rule before + require(_rules.add(address(rules_[i])), RuleEngine_RulesManagementModule_OperationNotSuccessful()); + emit AddRule(rules_[i]); + } + } + + /** + * @inheritdoc IRulesManagementModule + */ + function clearRules() public virtual override(IRulesManagementModule) onlyRole(RULES_MANAGEMENT_ROLE) { + _clearRules(); + } + + /** + * @inheritdoc IRulesManagementModule + */ + function addRule( + IRule rule_ + ) public virtual override(IRulesManagementModule) onlyRole(RULES_MANAGEMENT_ROLE) { + _checkRule(address(rule_)); + require(_rules.add(address(rule_)), RuleEngine_RulesManagementModule_OperationNotSuccessful()); + emit AddRule(rule_); + } + + /** + * @inheritdoc IRulesManagementModule + */ + function removeRule( + IRule rule_ + ) public virtual override(IRulesManagementModule) onlyRole(RULES_MANAGEMENT_ROLE) { + require(_rules.contains(address(rule_)), RuleEngine_RulesManagementModule_RuleDoNotMatch()); + _removeRule(rule_); + } + + /* ============ View functions ============ */ + + /** + * @inheritdoc IRulesManagementModule + */ + function rulesCount() public view virtual override(IRulesManagementModule) returns (uint256) { + return _rules.length(); + } + + /** + * @inheritdoc IRulesManagementModule + */ + function containsRule(IRule rule_) public view virtual override(IRulesManagementModule) returns (bool){ + return _rules.contains(address(rule_)); + } + + /** + * @inheritdoc IRulesManagementModule + */ + function rule( + uint256 ruleId + ) public view virtual override(IRulesManagementModule) returns (address) { + if(ruleId < _rules.length()){ + // Note that there are no guarantees on the ordering of values inside the array, + // and it may change when more values are added or removed. + return _rules.at(ruleId); + } else { + return address(0); + } + } + + /** + * @inheritdoc IRulesManagementModule + */ + function rules() + public + view + virtual + override(IRulesManagementModule) + returns (address[] memory) + { + return _rules.values(); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL/PRIVATE FUNCTIONS + //////////////////////////////////////////////////////////////*/ + /** + * @notice Clear all the rules of the array of rules + * + */ + function _clearRules() internal virtual { + emit ClearRules(); + _rules.clear(); + } + + /** + * @notice Remove a rule from the array of rules + * Revert if the rule found at the specified index does not match the rule in argument + * @param rule_ address of the target rule + * + * + */ + function _removeRule(IRule rule_) internal virtual { + // Should never revert because we check the presence of the rule before + require(_rules.remove(address(rule_)), RuleEngine_RulesManagementModule_OperationNotSuccessful()); + emit RemoveRule(rule_); + } + + /** + * @dev check if a rule is valid, revert otherwise + */ + function _checkRule(address rule_) internal view{ + if (rule_ == address(0x0)) { + revert RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed(); + } + if (_rules.contains(rule_)) { + revert RuleEngine_RulesManagementModule_RuleAlreadyExists(); + } + } + + /* ============ Transferred functions ============ */ + + /** + * @notice Go through all the rule to know if a restriction exists on the transfer + * @param from the origin address + * @param to the destination address + * @param value to transfer + **/ + function _transferred( + address from, + address to, + uint256 value + ) internal virtual{ + uint256 rulesLength = _rules.length(); + for (uint256 i = 0; i < rulesLength; ++i) { + IRule(_rules.at(i)).transferred( + from, + to, + value + ); + } + } + + /** + * @notice Go through all the rule to know if a restriction exists on the transfer + * @param spender the spender address (transferFrom) + * @param from the origin address + * @param to the destination address + * @param value to transfer + **/ + function _transferred( + address spender, + address from, + address to, + uint256 value + ) internal virtual{ + uint256 rulesLength = _rules.length(); + for (uint256 i = 0; i < rulesLength; ++i) { + IRule(_rules.at(i)).transferred( + spender, + from, + to, + value + ); + } + } +} + +// src/RuleEngineBase.sol + +/* ==== OpenZeppelin === */ + +/* ==== CMTAT === */ + +/* ==== Modules === */ + +/* ==== Interface and other library === */ + +/** + * @title Implementation of a ruleEngine as defined by the CMTAT + */ +abstract contract RuleEngineBase is + VersionModule, + RulesManagementModule, + ERC3643ComplianceModule, + RuleEngineInvariantStorage, + IRuleEngine +{ + /* ============ State functions ============ */ + /* + * @inheritdoc IRuleEngine + */ + function transferred( + address spender, + address from, + address to, + uint256 value + ) public virtual override(IRuleEngine) onlyBoundToken { + // Apply on RuleEngine + RulesManagementModule._transferred(spender, from, to, value); + } + + /** + * @inheritdoc IERC3643IComplianceContract + */ + function transferred( + address from, + address to, + uint256 value + ) public virtual override(IERC3643IComplianceContract) onlyBoundToken { + _transferred(from, to, value); + } + + /// @inheritdoc IERC3643Compliance + function created(address to, uint256 value) public virtual override(IERC3643Compliance) onlyBoundToken{ + _transferred(address(0), to, value); + } + + /// @inheritdoc IERC3643Compliance + function destroyed(address from, uint256 value) public virtual override(IERC3643Compliance) onlyBoundToken { + _transferred(from, address(0), value); + } + + /* ============ View functions ============ */ + /** + * @notice Go through all the rule to know if a restriction exists on the transfer + * @param from the origin address + * @param to the destination address + * @param value to transfer + * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid + **/ + function detectTransferRestriction( + address from, + address to, + uint256 value + ) public view virtual override returns (uint8) { + uint256 rulesLength = rulesCount(); + for (uint256 i = 0; i < rulesLength; ++i) { + uint8 restriction = IRule(rule(i)) + .detectTransferRestriction(from, to, value); + if (restriction > 0) { + return restriction; + } + } + return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + /** + * @inheritdoc IERC1404Extend + */ + function detectTransferRestrictionFrom( + address spender, + address from, + address to, + uint256 value + ) public view virtual override(IERC1404Extend) returns (uint8) { + uint256 rulesLength = rulesCount(); + for (uint256 i = 0; i < rulesLength; ++i) { + uint8 restriction = IRule(rule(i)) + .detectTransferRestrictionFrom(spender,from, to, value); + if (restriction > 0) { + return restriction; + } + } + + return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + /** + * @inheritdoc IERC1404 + */ + function messageForTransferRestriction( + uint8 restrictionCode + ) public virtual view override(IERC1404) returns (string memory) { + // + uint256 rulesLength = rulesCount(); + for (uint256 i = 0; i < rulesLength; ++i) { + if ( + IRule(rule(i)) + .canReturnTransferRestrictionCode(restrictionCode) + ) { + return + IRule(rule(i)) + .messageForTransferRestriction(restrictionCode); + } + } + return "Unknown restriction code"; + } + + /** + * @inheritdoc IERC3643ComplianceRead + */ + function canTransfer( + address from, + address to, + uint256 value + ) public virtual view override(IERC3643ComplianceRead) returns (bool) { + return + detectTransferRestriction(from, to, value) == + uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + /** + * @inheritdoc IERC7551Compliance + */ + function canTransferFrom( + address spender, + address from, + address to, + uint256 value + ) public virtual view override(IERC7551Compliance) returns (bool) { + return + detectTransferRestrictionFrom(spender, from, to, value) == + uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + /* ============ ACCESS CONTROL ============ */ + /** + * @notice Returns `true` if `account` has been granted `role`. + * @dev The Default Admin has all roles + */ + function hasRole( + bytes32 role, + address account + ) public view virtual override(AccessControl) returns (bool) { + if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { + return true; + } else { + return AccessControl.hasRole(role, account); + } + } +} + +// src/RuleEngine.sol + +/* ==== OpenZeppelin === */ + +/* ==== Modules === */ + +/* ==== Base contract === */ + +/** + * @title Implementation of a ruleEngine as defined by the CMTAT + */ +contract RuleEngine is + ERC2771ModuleStandalone, + RuleEngineBase +{ + /** + * @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 tokenContract + ) ERC2771ModuleStandalone(forwarderIrrevocable) { + if (admin == address(0)) { + revert RuleEngine_AdminWithAddressZeroNotAllowed(); + } + if (tokenContract != address(0)) { + _bindToken(tokenContract); + } + _grantRole(DEFAULT_ADMIN_ROLE, admin); + } + + /*////////////////////////////////////////////////////////////// + ERC-2771 + //////////////////////////////////////////////////////////////*/ + + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ + function _msgSender() + internal + view + virtual + 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 + virtual + 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 + virtual + override(ERC2771Context, Context) + returns (uint256) + { + return ERC2771Context._contextSuffixLength(); + } +} + diff --git a/doc/compilation/hardhat/src/RuleEngine.sol/RuleEngine.dbg.json b/doc/compilation/hardhat/src/RuleEngine.sol/RuleEngine.dbg.json new file mode 100644 index 0000000..4d68568 --- /dev/null +++ b/doc/compilation/hardhat/src/RuleEngine.sol/RuleEngine.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/RuleEngine.sol/RuleEngine.json b/doc/compilation/hardhat/src/RuleEngine.sol/RuleEngine.json new file mode 100644 index 0000000..884035d --- /dev/null +++ b/doc/compilation/hardhat/src/RuleEngine.sol/RuleEngine.json @@ -0,0 +1,854 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleEngine", + "sourceName": "src/RuleEngine.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "address", + "name": "forwarderIrrevocable", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenContract", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_AdminWithAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_ERC3643Compliance_InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_ERC3643Compliance_OperationNotSuccessful", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_ERC3643Compliance_TokenAlreadyBound", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_ERC3643Compliance_TokenNotBound", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_ERC3643Compliance_UnauthorizedCaller", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_ArrayIsEmpty", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_OperationNotSuccessful", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleDoNotMatch", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "AddRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ClearRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "RemoveRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenBound", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenUnbound", + "type": "event" + }, + { + "inputs": [], + "name": "COMPLIANCE_MANAGER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RULES_MANAGEMENT_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "addRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "bindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clearRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "containsRule", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "created", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "destroyed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestriction", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestrictionFrom", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBound", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBounds", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenBound", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isTrustedForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "messageForTransferRestriction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "removeRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "ruleId", + "type": "uint256" + } + ], + "name": "rule", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rules", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rulesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule[]", + "name": "rules_", + "type": "address[]" + } + ], + "name": "setRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "trustedForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unbindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "version_", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60a060405234801561000f575f5ffd5b5060405161316338038061316383398181016040528101906100319190610641565b81808073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff168152505050505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036100ce576040517f21c89ccc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610111576101108161012c60201b60201c565b5b6101235f5f1b8461026060201b60201c565b5050505061079a565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610191576040517fdc418b8000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101a581600361035560201b90919060201c565b156101dc576040517ff423354700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101f081600361038860201b90919060201c565b610226576040517f369bb9e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b8160405161025591906106a0565b60405180910390a150565b5f61027183836103bb60201b60201c565b61034b5760015f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506102e86103f560201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001905061034f565b5f90505b92915050565b5f610380835f018373ffffffffffffffffffffffffffffffffffffffff165f1b61040960201b60201c565b905092915050565b5f6103b3835f018373ffffffffffffffffffffffffffffffffffffffff165f1b61042960201b60201c565b905092915050565b5f6103ce5f5f1b8361049660201b60201c565b156103dc57600190506103ef565b6103ec838361049660201b60201c565b90505b92915050565b5f6104046104f960201b60201c565b905090565b5f5f836001015f8481526020019081526020015f20541415905092915050565b5f61043a838361040960201b60201c565b61048c57825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f208190555060019050610490565b5f90505b92915050565b5f5f5f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f5f5f36905090505f61051061057360201b60201c565b905080821015801561052d575061052c3361058760201b60201c565b5b1561055d575f36828403908092610546939291906106c1565b90610551919061073c565b60601c92505050610570565b61056b6105cb60201b60201c565b925050505b90565b5f6105826105d260201b60201c565b905090565b5f6105966105da60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b5f33905090565b5f6014905090565b5f608051905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610610826105e7565b9050919050565b61062081610606565b811461062a575f5ffd5b50565b5f8151905061063b81610617565b92915050565b5f5f5f60608486031215610658576106576105e3565b5b5f6106658682870161062d565b93505060206106768682870161062d565b92505060406106878682870161062d565b9150509250925092565b61069a81610606565b82525050565b5f6020820190506106b35f830184610691565b92915050565b5f5ffd5b5f5ffd5b5f5f858511156106d4576106d36106b9565b5b838611156106e5576106e46106bd565b5b6001850283019150848603905094509492505050565b5f82905092915050565b5f7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b5f82821b905092915050565b5f61074783836106fb565b826107528135610705565b925060148210156107925761078d7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000083601403600802610730565b831692505b505092915050565b6080516129b16107b25f395f610a4701526129b15ff3fe608060405234801561000f575f5ffd5b5060043610610204575f3560e01c80638baf29b411610118578063bc13eacc116100ab578063db18af6c1161007a578063db18af6c146105fa578063df21950f1461062a578063e3c4602c14610646578063e46638e614610662578063e54621d21461069257610204565b8063bc13eacc14610560578063d32c7bb51461057e578063d4ce1415146105ae578063d547741f146105de57610204565b80639b11c115116100e75780639b11c115146104fe578063a217fddf1461051c578063b043572e1461053a578063b27aef3a1461054457610204565b80638baf29b4146104665780638d2ea7721461048257806391d148541461049e578063993e8b95146104ce57610204565b806352f6747a1161019b5780635f8dead31161016a5780635f8dead3146103ae5780636a3edf28146103ca5780637157797f146103e85780637da0a877146104185780637f4ab1dd1461043657610204565b806352f6747a1461031257806354e4b9451461033057806354fd4d5014610360578063572b6c051461037e57610204565b806336568abe116101d757806336568abe146102a25780633e5af4ca146102be5780633ff5aa02146102da57806340db3b50146102f657610204565b806301ffc9a71461020857806303c26bcd14610238578063248a9ca3146102565780632f2ff15d14610286575b5f5ffd5b610222600480360381019061021d9190611ed6565b6106b0565b60405161022f9190611f1b565b60405180910390f35b610240610729565b60405161024d9190611f4c565b60405180910390f35b610270600480360381019061026b9190611f8f565b61074d565b60405161027d9190611f4c565b60405180910390f35b6102a0600480360381019061029b9190612014565b610769565b005b6102bc60048036038101906102b79190612014565b61078b565b005b6102d860048036038101906102d39190612085565b610806565b005b6102f460048036038101906102ef91906120e9565b610869565b005b610310600480360381019061030b91906120e9565b6108a0565b005b61031a6108d7565b60405161032791906121cb565b60405180910390f35b61034a60048036038101906103459190612226565b6108e8565b6040516103579190611f1b565b60405180910390f35b610368610904565b60405161037591906122c1565b60405180910390f35b610398600480360381019061039391906120e9565b610941565b6040516103a59190611f1b565b60405180910390f35b6103c860048036038101906103c391906122e1565b61097f565b005b6103d26109df565b6040516103df919061232e565b60405180910390f35b61040260048036038101906103fd9190612085565b610a13565b60405161040f9190611f1b565b60405180910390f35b610420610a44565b60405161042d919061232e565b60405180910390f35b610450600480360381019061044b919061237d565b610a6b565b60405161045d91906122c1565b60405180910390f35b610480600480360381019061047b91906123a8565b610be1565b005b61049c600480360381019061049791906122e1565b610c42565b005b6104b860048036038101906104b39190612014565b610ca2565b6040516104c59190611f1b565b60405180910390f35b6104e860048036038101906104e391906120e9565b610cd0565b6040516104f59190611f1b565b60405180910390f35b610506610cec565b6040516105139190611f4c565b60405180910390f35b610524610d10565b6040516105319190611f4c565b60405180910390f35b610542610d16565b005b61055e60048036038101906105599190612459565b610d4b565b005b610568610ef7565b60405161057591906124b3565b60405180910390f35b61059860048036038101906105939190612085565b610f07565b6040516105a591906124db565b60405180910390f35b6105c860048036038101906105c391906123a8565b610feb565b6040516105d591906124db565b60405180910390f35b6105f860048036038101906105f39190612014565b6110cc565b005b610614600480360381019061060f91906124f4565b6110ee565b604051610621919061232e565b60405180910390f35b610644600480360381019061063f9190612226565b611124565b005b610660600480360381019061065b9190612226565b6111a5565b005b61067c600480360381019061067791906123a8565b611269565b6040516106899190611f1b565b60405180910390f35b61069a611298565b6040516106a791906121cb565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107225750610721826112a9565b5b9050919050565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b5f5f5f8381526020019081526020015f20600101549050919050565b6107728261074d565b61077b81611312565b6107858383611326565b50505050565b61079361140f565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146107f7576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610801828261141d565b505050565b61082161081161140f565b600361150690919063ffffffff16565b610857576040517fe39b3c8f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61086384848484611533565b50505050565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856861089381611312565b61089c826115df565b5050565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede6000285686108ca81611312565b6108d382611713565b5050565b60606108e360016117e1565b905090565b5f6108fd82600161150690919063ffffffff16565b9050919050565b60606040518060400160405280600581526020017f332e302e30000000000000000000000000000000000000000000000000000000815250905090565b5f61094a610a44565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b61099a61098a61140f565b600361150690919063ffffffff16565b6109d0576040517fe39b3c8f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109db5f8383611800565b5050565b5f5f6109eb60036118a9565b1115610a0c57610a055f60036118bc90919063ffffffff16565b9050610a10565b5f90505b90565b5f5f6006811115610a2757610a2661251f565b5b60ff16610a3686868686610f07565b60ff16149050949350505050565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b60605f610a76610ef7565b90505f5f90505b81811015610ba157610a8e816110ee565b73ffffffffffffffffffffffffffffffffffffffff16637d045df6856040518263ffffffff1660e01b8152600401610ac691906124db565b602060405180830381865afa158015610ae1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b059190612576565b15610b9657610b13816110ee565b73ffffffffffffffffffffffffffffffffffffffff16637f4ab1dd856040518263ffffffff1660e01b8152600401610b4b91906124db565b5f60405180830381865afa158015610b65573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610b8d91906126bb565b92505050610bdc565b806001019050610a7d565b506040518060400160405280601881526020017f556e6b6e6f776e207265737472696374696f6e20636f646500000000000000008152509150505b919050565b610bfc610bec61140f565b600361150690919063ffffffff16565b610c32576040517fe39b3c8f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c3d838383611800565b505050565b610c5d610c4d61140f565b600361150690919063ffffffff16565b610c93576040517fe39b3c8f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c9e825f83611800565b5050565b5f610caf5f5f1b836118d3565b15610cbd5760019050610cca565b610cc783836118d3565b90505b92915050565b5f610ce582600361150690919063ffffffff16565b9050919050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b5f5f1b81565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e610d4081611312565b610d48611936565b50565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e610d7581611312565b5f8383905003610db1576040517f59203cb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610dbc60016118a9565b1115610dcb57610dca611936565b5b5f5f90505b83839050811015610ef157610e0b848483818110610df157610df0612702565b5b9050602002016020810190610e069190612226565b61196e565b610e46848483818110610e2157610e20612702565b5b9050602002016020810190610e369190612226565b6001611a2190919063ffffffff16565b610e7c576040517ff280d16100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838382818110610e8f57610e8e612702565b5b9050602002016020810190610ea49190612226565b73ffffffffffffffffffffffffffffffffffffffff167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a2806001019050610dd0565b50505050565b5f610f0260016118a9565b905090565b5f5f610f11610ef7565b90505f5f90505b81811015610fcb575f610f2a826110ee565b73ffffffffffffffffffffffffffffffffffffffff1663d32c7bb5898989896040518563ffffffff1660e01b8152600401610f68949392919061272f565b602060405180830381865afa158015610f83573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fa79190612786565b90505f8160ff161115610fbf57809350505050610fe3565b50806001019050610f18565b505f6006811115610fdf57610fde61251f565b5b9150505b949350505050565b5f5f610ff5610ef7565b90505f5f90505b818110156110ad575f61100e826110ee565b73ffffffffffffffffffffffffffffffffffffffff1663d4ce14158888886040518463ffffffff1660e01b815260040161104a939291906127b1565b602060405180830381865afa158015611065573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110899190612786565b90505f8160ff1611156110a1578093505050506110c5565b50806001019050610ffc565b505f60068111156110c1576110c061251f565b5b9150505b9392505050565b6110d58261074d565b6110de81611312565b6110e8838361141d565b50505050565b5f6110f960016118a9565b82101561111b576111148260016118bc90919063ffffffff16565b905061111f565b5f90505b919050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e61114e81611312565b61116282600161150690919063ffffffff16565b611198576040517fb370e90400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111a182611a4e565b5050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e6111cf81611312565b6111d88261196e565b6111ec826001611a2190919063ffffffff16565b611222576040517ff280d16100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a25050565b5f5f600681111561127d5761127c61251f565b5b60ff1661128b858585610feb565b60ff161490509392505050565b60606112a460036117e1565b905090565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6113238161131e61140f565b611ade565b50565b5f6113318383610ca2565b6114055760015f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506113a261140f565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611409565b5f90505b92915050565b5f611418611b2f565b905090565b5f6114288383610ca2565b156114fc575f5f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555061149961140f565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050611500565b5f90505b92915050565b5f61152b835f018373ffffffffffffffffffffffffffffffffffffffff165f1b611b97565b905092915050565b5f61153e60016118a9565b90505f5f90505b818110156115d7576115618160016118bc90919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff16633e5af4ca878787876040518563ffffffff1660e01b815260040161159f949392919061272f565b5f604051808303815f87803b1580156115b6575f5ffd5b505af11580156115c8573d5f5f3e3d5ffd5b50505050806001019050611545565b505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611644576040517fdc418b8000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61165881600361150690919063ffffffff16565b1561168f576040517ff423354700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116a3816003611a2190919063ffffffff16565b6116d9576040517f369bb9e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b81604051611708919061232e565b60405180910390a150565b61172781600361150690919063ffffffff16565b61175d576040517fd456910600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611771816003611bb790919063ffffffff16565b6117a7576040517f369bb9e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a816040516117d6919061232e565b60405180910390a150565b60605f6117ef835f01611be4565b905060608190508092505050919050565b5f61180b60016118a9565b90505f5f90505b818110156118a25761182e8160016118bc90919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff16638baf29b48686866040518463ffffffff1660e01b815260040161186a939291906127b1565b5f604051808303815f87803b158015611881575f5ffd5b505af1158015611893573d5f5f3e3d5ffd5b50505050806001019050611812565b5050505050565b5f6118b5825f01611c3d565b9050919050565b5f6118c9835f0183611c4c565b5f1c905092915050565b5f5f5f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b7fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b260405160405180910390a161196c6001611c73565b565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036119d3576040517ff9d152fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119e781600161150690919063ffffffff16565b15611a1e576040517fcc790a4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f611a46835f018373ffffffffffffffffffffffffffffffffffffffff165f1b611c81565b905092915050565b611a62816001611bb790919063ffffffff16565b611a98576040517ff280d16100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc460405160405180910390a250565b611ae88282610ca2565b611b2b5780826040517fe2517d3f000000000000000000000000000000000000000000000000000000008152600401611b229291906127e6565b60405180910390fd5b5050565b5f5f5f36905090505f611b40611ce8565b9050808210158015611b575750611b5633610941565b5b15611b87575f36828403908092611b7093929190612815565b90611b7b9190612890565b60601c92505050611b94565b611b8f611cf6565b925050505b90565b5f5f836001015f8481526020019081526020015f20541415905092915050565b5f611bdc835f018373ffffffffffffffffffffffffffffffffffffffff165f1b611cfd565b905092915050565b6060815f01805480602002602001604051908101604052809291908181526020018280548015611c3157602002820191905f5260205f20905b815481526020019060010190808311611c1d575b50505050509050919050565b5f815f01805490509050919050565b5f825f018281548110611c6257611c61612702565b5b905f5260205f200154905092915050565b611c7e815f01611df9565b50565b5f611c8c8383611b97565b611cde57825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f208190555060019050611ce2565b5f90505b92915050565b5f611cf1611e61565b905090565b5f33905090565b5f5f836001015f8481526020019081526020015f205490505f8114611dee575f600182611d2a919061291b565b90505f6001865f0180549050611d40919061291b565b9050808214611da6575f865f018281548110611d5f57611d5e612702565b5b905f5260205f200154905080875f018481548110611d8057611d7f612702565b5b905f5260205f20018190555083876001015f8381526020019081526020015f2081905550505b855f01805480611db957611db861294e565b5b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050611df3565b5f9150505b92915050565b5f611e0382611c3d565b90505f5f90505b81811015611e5057826001015f845f018381548110611e2c57611e2b612702565b5b905f5260205f20015481526020019081526020015f205f9055806001019050611e0a565b50611e5d825f015f611e69565b5050565b5f6014905090565b8082555050565b5f604051905090565b5f5ffd5b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611eb581611e81565b8114611ebf575f5ffd5b50565b5f81359050611ed081611eac565b92915050565b5f60208284031215611eeb57611eea611e79565b5b5f611ef884828501611ec2565b91505092915050565b5f8115159050919050565b611f1581611f01565b82525050565b5f602082019050611f2e5f830184611f0c565b92915050565b5f819050919050565b611f4681611f34565b82525050565b5f602082019050611f5f5f830184611f3d565b92915050565b611f6e81611f34565b8114611f78575f5ffd5b50565b5f81359050611f8981611f65565b92915050565b5f60208284031215611fa457611fa3611e79565b5b5f611fb184828501611f7b565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611fe382611fba565b9050919050565b611ff381611fd9565b8114611ffd575f5ffd5b50565b5f8135905061200e81611fea565b92915050565b5f5f6040838503121561202a57612029611e79565b5b5f61203785828601611f7b565b925050602061204885828601612000565b9150509250929050565b5f819050919050565b61206481612052565b811461206e575f5ffd5b50565b5f8135905061207f8161205b565b92915050565b5f5f5f5f6080858703121561209d5761209c611e79565b5b5f6120aa87828801612000565b94505060206120bb87828801612000565b93505060406120cc87828801612000565b92505060606120dd87828801612071565b91505092959194509250565b5f602082840312156120fe576120fd611e79565b5b5f61210b84828501612000565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61214681611fd9565b82525050565b5f612157838361213d565b60208301905092915050565b5f602082019050919050565b5f61217982612114565b612183818561211e565b935061218e8361212e565b805f5b838110156121be5781516121a5888261214c565b97506121b083612163565b925050600181019050612191565b5085935050505092915050565b5f6020820190508181035f8301526121e3818461216f565b905092915050565b5f6121f582611fd9565b9050919050565b612205816121eb565b811461220f575f5ffd5b50565b5f81359050612220816121fc565b92915050565b5f6020828403121561223b5761223a611e79565b5b5f61224884828501612212565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61229382612251565b61229d818561225b565b93506122ad81856020860161226b565b6122b681612279565b840191505092915050565b5f6020820190508181035f8301526122d98184612289565b905092915050565b5f5f604083850312156122f7576122f6611e79565b5b5f61230485828601612000565b925050602061231585828601612071565b9150509250929050565b61232881611fd9565b82525050565b5f6020820190506123415f83018461231f565b92915050565b5f60ff82169050919050565b61235c81612347565b8114612366575f5ffd5b50565b5f8135905061237781612353565b92915050565b5f6020828403121561239257612391611e79565b5b5f61239f84828501612369565b91505092915050565b5f5f5f606084860312156123bf576123be611e79565b5b5f6123cc86828701612000565b93505060206123dd86828701612000565b92505060406123ee86828701612071565b9150509250925092565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f840112612419576124186123f8565b5b8235905067ffffffffffffffff811115612436576124356123fc565b5b60208301915083602082028301111561245257612451612400565b5b9250929050565b5f5f6020838503121561246f5761246e611e79565b5b5f83013567ffffffffffffffff81111561248c5761248b611e7d565b5b61249885828601612404565b92509250509250929050565b6124ad81612052565b82525050565b5f6020820190506124c65f8301846124a4565b92915050565b6124d581612347565b82525050565b5f6020820190506124ee5f8301846124cc565b92915050565b5f6020828403121561250957612508611e79565b5b5f61251684828501612071565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b61255581611f01565b811461255f575f5ffd5b50565b5f815190506125708161254c565b92915050565b5f6020828403121561258b5761258a611e79565b5b5f61259884828501612562565b91505092915050565b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6125db82612279565b810181811067ffffffffffffffff821117156125fa576125f96125a5565b5b80604052505050565b5f61260c611e70565b905061261882826125d2565b919050565b5f67ffffffffffffffff821115612637576126366125a5565b5b61264082612279565b9050602081019050919050565b5f61265f61265a8461261d565b612603565b90508281526020810184848401111561267b5761267a6125a1565b5b61268684828561226b565b509392505050565b5f82601f8301126126a2576126a16123f8565b5b81516126b284826020860161264d565b91505092915050565b5f602082840312156126d0576126cf611e79565b5b5f82015167ffffffffffffffff8111156126ed576126ec611e7d565b5b6126f98482850161268e565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6080820190506127425f83018761231f565b61274f602083018661231f565b61275c604083018561231f565b61276960608301846124a4565b95945050505050565b5f8151905061278081612353565b92915050565b5f6020828403121561279b5761279a611e79565b5b5f6127a884828501612772565b91505092915050565b5f6060820190506127c45f83018661231f565b6127d1602083018561231f565b6127de60408301846124a4565b949350505050565b5f6040820190506127f95f83018561231f565b6128066020830184611f3d565b9392505050565b5f5ffd5b5f5ffd5b5f5f858511156128285761282761280d565b5b8386111561283957612838612811565b5b6001850283019150848603905094509492505050565b5f82905092915050565b5f7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b5f82821b905092915050565b5f61289b838361284f565b826128a68135612859565b925060148210156128e6576128e17fffffffffffffffffffffffffffffffffffffffff00000000000000000000000083601403600802612884565b831692505b505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61292582612052565b915061293083612052565b9250828203905081811115612948576129476128ee565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfea2646970667358221220424f0794bba77302c7f954fbeba7cfe1f1e71aaf9ccfb51c88b7fc8c64e5082264736f6c634300081e0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610204575f3560e01c80638baf29b411610118578063bc13eacc116100ab578063db18af6c1161007a578063db18af6c146105fa578063df21950f1461062a578063e3c4602c14610646578063e46638e614610662578063e54621d21461069257610204565b8063bc13eacc14610560578063d32c7bb51461057e578063d4ce1415146105ae578063d547741f146105de57610204565b80639b11c115116100e75780639b11c115146104fe578063a217fddf1461051c578063b043572e1461053a578063b27aef3a1461054457610204565b80638baf29b4146104665780638d2ea7721461048257806391d148541461049e578063993e8b95146104ce57610204565b806352f6747a1161019b5780635f8dead31161016a5780635f8dead3146103ae5780636a3edf28146103ca5780637157797f146103e85780637da0a877146104185780637f4ab1dd1461043657610204565b806352f6747a1461031257806354e4b9451461033057806354fd4d5014610360578063572b6c051461037e57610204565b806336568abe116101d757806336568abe146102a25780633e5af4ca146102be5780633ff5aa02146102da57806340db3b50146102f657610204565b806301ffc9a71461020857806303c26bcd14610238578063248a9ca3146102565780632f2ff15d14610286575b5f5ffd5b610222600480360381019061021d9190611ed6565b6106b0565b60405161022f9190611f1b565b60405180910390f35b610240610729565b60405161024d9190611f4c565b60405180910390f35b610270600480360381019061026b9190611f8f565b61074d565b60405161027d9190611f4c565b60405180910390f35b6102a0600480360381019061029b9190612014565b610769565b005b6102bc60048036038101906102b79190612014565b61078b565b005b6102d860048036038101906102d39190612085565b610806565b005b6102f460048036038101906102ef91906120e9565b610869565b005b610310600480360381019061030b91906120e9565b6108a0565b005b61031a6108d7565b60405161032791906121cb565b60405180910390f35b61034a60048036038101906103459190612226565b6108e8565b6040516103579190611f1b565b60405180910390f35b610368610904565b60405161037591906122c1565b60405180910390f35b610398600480360381019061039391906120e9565b610941565b6040516103a59190611f1b565b60405180910390f35b6103c860048036038101906103c391906122e1565b61097f565b005b6103d26109df565b6040516103df919061232e565b60405180910390f35b61040260048036038101906103fd9190612085565b610a13565b60405161040f9190611f1b565b60405180910390f35b610420610a44565b60405161042d919061232e565b60405180910390f35b610450600480360381019061044b919061237d565b610a6b565b60405161045d91906122c1565b60405180910390f35b610480600480360381019061047b91906123a8565b610be1565b005b61049c600480360381019061049791906122e1565b610c42565b005b6104b860048036038101906104b39190612014565b610ca2565b6040516104c59190611f1b565b60405180910390f35b6104e860048036038101906104e391906120e9565b610cd0565b6040516104f59190611f1b565b60405180910390f35b610506610cec565b6040516105139190611f4c565b60405180910390f35b610524610d10565b6040516105319190611f4c565b60405180910390f35b610542610d16565b005b61055e60048036038101906105599190612459565b610d4b565b005b610568610ef7565b60405161057591906124b3565b60405180910390f35b61059860048036038101906105939190612085565b610f07565b6040516105a591906124db565b60405180910390f35b6105c860048036038101906105c391906123a8565b610feb565b6040516105d591906124db565b60405180910390f35b6105f860048036038101906105f39190612014565b6110cc565b005b610614600480360381019061060f91906124f4565b6110ee565b604051610621919061232e565b60405180910390f35b610644600480360381019061063f9190612226565b611124565b005b610660600480360381019061065b9190612226565b6111a5565b005b61067c600480360381019061067791906123a8565b611269565b6040516106899190611f1b565b60405180910390f35b61069a611298565b6040516106a791906121cb565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107225750610721826112a9565b5b9050919050565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b5f5f5f8381526020019081526020015f20600101549050919050565b6107728261074d565b61077b81611312565b6107858383611326565b50505050565b61079361140f565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146107f7576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610801828261141d565b505050565b61082161081161140f565b600361150690919063ffffffff16565b610857576040517fe39b3c8f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61086384848484611533565b50505050565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856861089381611312565b61089c826115df565b5050565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede6000285686108ca81611312565b6108d382611713565b5050565b60606108e360016117e1565b905090565b5f6108fd82600161150690919063ffffffff16565b9050919050565b60606040518060400160405280600581526020017f332e302e30000000000000000000000000000000000000000000000000000000815250905090565b5f61094a610a44565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b61099a61098a61140f565b600361150690919063ffffffff16565b6109d0576040517fe39b3c8f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109db5f8383611800565b5050565b5f5f6109eb60036118a9565b1115610a0c57610a055f60036118bc90919063ffffffff16565b9050610a10565b5f90505b90565b5f5f6006811115610a2757610a2661251f565b5b60ff16610a3686868686610f07565b60ff16149050949350505050565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b60605f610a76610ef7565b90505f5f90505b81811015610ba157610a8e816110ee565b73ffffffffffffffffffffffffffffffffffffffff16637d045df6856040518263ffffffff1660e01b8152600401610ac691906124db565b602060405180830381865afa158015610ae1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b059190612576565b15610b9657610b13816110ee565b73ffffffffffffffffffffffffffffffffffffffff16637f4ab1dd856040518263ffffffff1660e01b8152600401610b4b91906124db565b5f60405180830381865afa158015610b65573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610b8d91906126bb565b92505050610bdc565b806001019050610a7d565b506040518060400160405280601881526020017f556e6b6e6f776e207265737472696374696f6e20636f646500000000000000008152509150505b919050565b610bfc610bec61140f565b600361150690919063ffffffff16565b610c32576040517fe39b3c8f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c3d838383611800565b505050565b610c5d610c4d61140f565b600361150690919063ffffffff16565b610c93576040517fe39b3c8f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c9e825f83611800565b5050565b5f610caf5f5f1b836118d3565b15610cbd5760019050610cca565b610cc783836118d3565b90505b92915050565b5f610ce582600361150690919063ffffffff16565b9050919050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b5f5f1b81565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e610d4081611312565b610d48611936565b50565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e610d7581611312565b5f8383905003610db1576040517f59203cb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610dbc60016118a9565b1115610dcb57610dca611936565b5b5f5f90505b83839050811015610ef157610e0b848483818110610df157610df0612702565b5b9050602002016020810190610e069190612226565b61196e565b610e46848483818110610e2157610e20612702565b5b9050602002016020810190610e369190612226565b6001611a2190919063ffffffff16565b610e7c576040517ff280d16100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838382818110610e8f57610e8e612702565b5b9050602002016020810190610ea49190612226565b73ffffffffffffffffffffffffffffffffffffffff167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a2806001019050610dd0565b50505050565b5f610f0260016118a9565b905090565b5f5f610f11610ef7565b90505f5f90505b81811015610fcb575f610f2a826110ee565b73ffffffffffffffffffffffffffffffffffffffff1663d32c7bb5898989896040518563ffffffff1660e01b8152600401610f68949392919061272f565b602060405180830381865afa158015610f83573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fa79190612786565b90505f8160ff161115610fbf57809350505050610fe3565b50806001019050610f18565b505f6006811115610fdf57610fde61251f565b5b9150505b949350505050565b5f5f610ff5610ef7565b90505f5f90505b818110156110ad575f61100e826110ee565b73ffffffffffffffffffffffffffffffffffffffff1663d4ce14158888886040518463ffffffff1660e01b815260040161104a939291906127b1565b602060405180830381865afa158015611065573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110899190612786565b90505f8160ff1611156110a1578093505050506110c5565b50806001019050610ffc565b505f60068111156110c1576110c061251f565b5b9150505b9392505050565b6110d58261074d565b6110de81611312565b6110e8838361141d565b50505050565b5f6110f960016118a9565b82101561111b576111148260016118bc90919063ffffffff16565b905061111f565b5f90505b919050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e61114e81611312565b61116282600161150690919063ffffffff16565b611198576040517fb370e90400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111a182611a4e565b5050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e6111cf81611312565b6111d88261196e565b6111ec826001611a2190919063ffffffff16565b611222576040517ff280d16100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a25050565b5f5f600681111561127d5761127c61251f565b5b60ff1661128b858585610feb565b60ff161490509392505050565b60606112a460036117e1565b905090565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6113238161131e61140f565b611ade565b50565b5f6113318383610ca2565b6114055760015f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506113a261140f565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611409565b5f90505b92915050565b5f611418611b2f565b905090565b5f6114288383610ca2565b156114fc575f5f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555061149961140f565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050611500565b5f90505b92915050565b5f61152b835f018373ffffffffffffffffffffffffffffffffffffffff165f1b611b97565b905092915050565b5f61153e60016118a9565b90505f5f90505b818110156115d7576115618160016118bc90919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff16633e5af4ca878787876040518563ffffffff1660e01b815260040161159f949392919061272f565b5f604051808303815f87803b1580156115b6575f5ffd5b505af11580156115c8573d5f5f3e3d5ffd5b50505050806001019050611545565b505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611644576040517fdc418b8000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61165881600361150690919063ffffffff16565b1561168f576040517ff423354700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116a3816003611a2190919063ffffffff16565b6116d9576040517f369bb9e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b81604051611708919061232e565b60405180910390a150565b61172781600361150690919063ffffffff16565b61175d576040517fd456910600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611771816003611bb790919063ffffffff16565b6117a7576040517f369bb9e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a816040516117d6919061232e565b60405180910390a150565b60605f6117ef835f01611be4565b905060608190508092505050919050565b5f61180b60016118a9565b90505f5f90505b818110156118a25761182e8160016118bc90919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff16638baf29b48686866040518463ffffffff1660e01b815260040161186a939291906127b1565b5f604051808303815f87803b158015611881575f5ffd5b505af1158015611893573d5f5f3e3d5ffd5b50505050806001019050611812565b5050505050565b5f6118b5825f01611c3d565b9050919050565b5f6118c9835f0183611c4c565b5f1c905092915050565b5f5f5f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b7fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b260405160405180910390a161196c6001611c73565b565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036119d3576040517ff9d152fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119e781600161150690919063ffffffff16565b15611a1e576040517fcc790a4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f611a46835f018373ffffffffffffffffffffffffffffffffffffffff165f1b611c81565b905092915050565b611a62816001611bb790919063ffffffff16565b611a98576040517ff280d16100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc460405160405180910390a250565b611ae88282610ca2565b611b2b5780826040517fe2517d3f000000000000000000000000000000000000000000000000000000008152600401611b229291906127e6565b60405180910390fd5b5050565b5f5f5f36905090505f611b40611ce8565b9050808210158015611b575750611b5633610941565b5b15611b87575f36828403908092611b7093929190612815565b90611b7b9190612890565b60601c92505050611b94565b611b8f611cf6565b925050505b90565b5f5f836001015f8481526020019081526020015f20541415905092915050565b5f611bdc835f018373ffffffffffffffffffffffffffffffffffffffff165f1b611cfd565b905092915050565b6060815f01805480602002602001604051908101604052809291908181526020018280548015611c3157602002820191905f5260205f20905b815481526020019060010190808311611c1d575b50505050509050919050565b5f815f01805490509050919050565b5f825f018281548110611c6257611c61612702565b5b905f5260205f200154905092915050565b611c7e815f01611df9565b50565b5f611c8c8383611b97565b611cde57825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f208190555060019050611ce2565b5f90505b92915050565b5f611cf1611e61565b905090565b5f33905090565b5f5f836001015f8481526020019081526020015f205490505f8114611dee575f600182611d2a919061291b565b90505f6001865f0180549050611d40919061291b565b9050808214611da6575f865f018281548110611d5f57611d5e612702565b5b905f5260205f200154905080875f018481548110611d8057611d7f612702565b5b905f5260205f20018190555083876001015f8381526020019081526020015f2081905550505b855f01805480611db957611db861294e565b5b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050611df3565b5f9150505b92915050565b5f611e0382611c3d565b90505f5f90505b81811015611e5057826001015f845f018381548110611e2c57611e2b612702565b5b905f5260205f20015481526020019081526020015f205f9055806001019050611e0a565b50611e5d825f015f611e69565b5050565b5f6014905090565b8082555050565b5f604051905090565b5f5ffd5b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611eb581611e81565b8114611ebf575f5ffd5b50565b5f81359050611ed081611eac565b92915050565b5f60208284031215611eeb57611eea611e79565b5b5f611ef884828501611ec2565b91505092915050565b5f8115159050919050565b611f1581611f01565b82525050565b5f602082019050611f2e5f830184611f0c565b92915050565b5f819050919050565b611f4681611f34565b82525050565b5f602082019050611f5f5f830184611f3d565b92915050565b611f6e81611f34565b8114611f78575f5ffd5b50565b5f81359050611f8981611f65565b92915050565b5f60208284031215611fa457611fa3611e79565b5b5f611fb184828501611f7b565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611fe382611fba565b9050919050565b611ff381611fd9565b8114611ffd575f5ffd5b50565b5f8135905061200e81611fea565b92915050565b5f5f6040838503121561202a57612029611e79565b5b5f61203785828601611f7b565b925050602061204885828601612000565b9150509250929050565b5f819050919050565b61206481612052565b811461206e575f5ffd5b50565b5f8135905061207f8161205b565b92915050565b5f5f5f5f6080858703121561209d5761209c611e79565b5b5f6120aa87828801612000565b94505060206120bb87828801612000565b93505060406120cc87828801612000565b92505060606120dd87828801612071565b91505092959194509250565b5f602082840312156120fe576120fd611e79565b5b5f61210b84828501612000565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61214681611fd9565b82525050565b5f612157838361213d565b60208301905092915050565b5f602082019050919050565b5f61217982612114565b612183818561211e565b935061218e8361212e565b805f5b838110156121be5781516121a5888261214c565b97506121b083612163565b925050600181019050612191565b5085935050505092915050565b5f6020820190508181035f8301526121e3818461216f565b905092915050565b5f6121f582611fd9565b9050919050565b612205816121eb565b811461220f575f5ffd5b50565b5f81359050612220816121fc565b92915050565b5f6020828403121561223b5761223a611e79565b5b5f61224884828501612212565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61229382612251565b61229d818561225b565b93506122ad81856020860161226b565b6122b681612279565b840191505092915050565b5f6020820190508181035f8301526122d98184612289565b905092915050565b5f5f604083850312156122f7576122f6611e79565b5b5f61230485828601612000565b925050602061231585828601612071565b9150509250929050565b61232881611fd9565b82525050565b5f6020820190506123415f83018461231f565b92915050565b5f60ff82169050919050565b61235c81612347565b8114612366575f5ffd5b50565b5f8135905061237781612353565b92915050565b5f6020828403121561239257612391611e79565b5b5f61239f84828501612369565b91505092915050565b5f5f5f606084860312156123bf576123be611e79565b5b5f6123cc86828701612000565b93505060206123dd86828701612000565b92505060406123ee86828701612071565b9150509250925092565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f840112612419576124186123f8565b5b8235905067ffffffffffffffff811115612436576124356123fc565b5b60208301915083602082028301111561245257612451612400565b5b9250929050565b5f5f6020838503121561246f5761246e611e79565b5b5f83013567ffffffffffffffff81111561248c5761248b611e7d565b5b61249885828601612404565b92509250509250929050565b6124ad81612052565b82525050565b5f6020820190506124c65f8301846124a4565b92915050565b6124d581612347565b82525050565b5f6020820190506124ee5f8301846124cc565b92915050565b5f6020828403121561250957612508611e79565b5b5f61251684828501612071565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b61255581611f01565b811461255f575f5ffd5b50565b5f815190506125708161254c565b92915050565b5f6020828403121561258b5761258a611e79565b5b5f61259884828501612562565b91505092915050565b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6125db82612279565b810181811067ffffffffffffffff821117156125fa576125f96125a5565b5b80604052505050565b5f61260c611e70565b905061261882826125d2565b919050565b5f67ffffffffffffffff821115612637576126366125a5565b5b61264082612279565b9050602081019050919050565b5f61265f61265a8461261d565b612603565b90508281526020810184848401111561267b5761267a6125a1565b5b61268684828561226b565b509392505050565b5f82601f8301126126a2576126a16123f8565b5b81516126b284826020860161264d565b91505092915050565b5f602082840312156126d0576126cf611e79565b5b5f82015167ffffffffffffffff8111156126ed576126ec611e7d565b5b6126f98482850161268e565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6080820190506127425f83018761231f565b61274f602083018661231f565b61275c604083018561231f565b61276960608301846124a4565b95945050505050565b5f8151905061278081612353565b92915050565b5f6020828403121561279b5761279a611e79565b5b5f6127a884828501612772565b91505092915050565b5f6060820190506127c45f83018661231f565b6127d1602083018561231f565b6127de60408301846124a4565b949350505050565b5f6040820190506127f95f83018561231f565b6128066020830184611f3d565b9392505050565b5f5ffd5b5f5ffd5b5f5f858511156128285761282761280d565b5b8386111561283957612838612811565b5b6001850283019150848603905094509492505050565b5f82905092915050565b5f7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b5f82821b905092915050565b5f61289b838361284f565b826128a68135612859565b925060148210156128e6576128e17fffffffffffffffffffffffffffffffffffffffff00000000000000000000000083601403600802612884565b831692505b505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61292582612052565b915061293083612052565b9250828203905081811115612948576129476128ee565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfea2646970667358221220424f0794bba77302c7f954fbeba7cfe1f1e71aaf9ccfb51c88b7fc8c64e5082264736f6c634300081e0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/RuleEngineBase.sol/RuleEngineBase.dbg.json b/doc/compilation/hardhat/src/RuleEngineBase.sol/RuleEngineBase.dbg.json new file mode 100644 index 0000000..4d68568 --- /dev/null +++ b/doc/compilation/hardhat/src/RuleEngineBase.sol/RuleEngineBase.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/RuleEngineBase.sol/RuleEngineBase.json b/doc/compilation/hardhat/src/RuleEngineBase.sol/RuleEngineBase.json new file mode 100644 index 0000000..2c66cc2 --- /dev/null +++ b/doc/compilation/hardhat/src/RuleEngineBase.sol/RuleEngineBase.json @@ -0,0 +1,801 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleEngineBase", + "sourceName": "src/RuleEngineBase.sol", + "abi": [ + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_AdminWithAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_ERC3643Compliance_InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_ERC3643Compliance_OperationNotSuccessful", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_ERC3643Compliance_TokenAlreadyBound", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_ERC3643Compliance_TokenNotBound", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_ERC3643Compliance_UnauthorizedCaller", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_ArrayIsEmpty", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_OperationNotSuccessful", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleDoNotMatch", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "AddRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ClearRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "RemoveRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenBound", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenUnbound", + "type": "event" + }, + { + "inputs": [], + "name": "COMPLIANCE_MANAGER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RULES_MANAGEMENT_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "addRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "bindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clearRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "containsRule", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "created", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "destroyed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestriction", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestrictionFrom", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBound", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBounds", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenBound", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "messageForTransferRestriction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "removeRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "ruleId", + "type": "uint256" + } + ], + "name": "rule", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rules", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rulesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule[]", + "name": "rules_", + "type": "address[]" + } + ], + "name": "setRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unbindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "version_", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/interfaces/IERC3643Compliance.sol/IERC3643Compliance.dbg.json b/doc/compilation/hardhat/src/interfaces/IERC3643Compliance.sol/IERC3643Compliance.dbg.json new file mode 100644 index 0000000..30bf738 --- /dev/null +++ b/doc/compilation/hardhat/src/interfaces/IERC3643Compliance.sol/IERC3643Compliance.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/interfaces/IERC3643Compliance.sol/IERC3643Compliance.json b/doc/compilation/hardhat/src/interfaces/IERC3643Compliance.sol/IERC3643Compliance.json new file mode 100644 index 0000000..120674e --- /dev/null +++ b/doc/compilation/hardhat/src/interfaces/IERC3643Compliance.sol/IERC3643Compliance.json @@ -0,0 +1,196 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC3643Compliance", + "sourceName": "src/interfaces/IERC3643Compliance.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenBound", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenUnbound", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "bindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "created", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "destroyed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBound", + "outputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBounds", + "outputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenBound", + "outputs": [ + { + "internalType": "bool", + "name": "isBound", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unbindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/interfaces/IRule.sol/IRule.dbg.json b/doc/compilation/hardhat/src/interfaces/IRule.sol/IRule.dbg.json new file mode 100644 index 0000000..30bf738 --- /dev/null +++ b/doc/compilation/hardhat/src/interfaces/IRule.sol/IRule.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/interfaces/IRule.sol/IRule.json b/doc/compilation/hardhat/src/interfaces/IRule.sol/IRule.json new file mode 100644 index 0000000..6af72d9 --- /dev/null +++ b/doc/compilation/hardhat/src/interfaces/IRule.sol/IRule.json @@ -0,0 +1,226 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IRule", + "sourceName": "src/interfaces/IRule.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "canReturnTransferRestrictionCode", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestriction", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestrictionFrom", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "messageForTransferRestriction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/interfaces/IRulesManagementModule.sol/IRulesManagementModule.dbg.json b/doc/compilation/hardhat/src/interfaces/IRulesManagementModule.sol/IRulesManagementModule.dbg.json new file mode 100644 index 0000000..30bf738 --- /dev/null +++ b/doc/compilation/hardhat/src/interfaces/IRulesManagementModule.sol/IRulesManagementModule.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/interfaces/IRulesManagementModule.sol/IRulesManagementModule.json b/doc/compilation/hardhat/src/interfaces/IRulesManagementModule.sol/IRulesManagementModule.json new file mode 100644 index 0000000..0d1057e --- /dev/null +++ b/doc/compilation/hardhat/src/interfaces/IRulesManagementModule.sol/IRulesManagementModule.json @@ -0,0 +1,121 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IRulesManagementModule", + "sourceName": "src/interfaces/IRulesManagementModule.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "addRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clearRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "containsRule", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "removeRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "ruleId", + "type": "uint256" + } + ], + "name": "rule", + "outputs": [ + { + "internalType": "address", + "name": "ruleAddress", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rules", + "outputs": [ + { + "internalType": "address[]", + "name": "ruleAddresses", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rulesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "numberOfrules", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule[]", + "name": "rules_", + "type": "address[]" + } + ], + "name": "setRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/mocks/rules/operation/RuleConditionalTransferLight.sol/RuleConditionalTransferLight.dbg.json b/doc/compilation/hardhat/src/mocks/rules/operation/RuleConditionalTransferLight.sol/RuleConditionalTransferLight.dbg.json new file mode 100644 index 0000000..603ee8f --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/operation/RuleConditionalTransferLight.sol/RuleConditionalTransferLight.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/mocks/rules/operation/RuleConditionalTransferLight.sol/RuleConditionalTransferLight.json b/doc/compilation/hardhat/src/mocks/rules/operation/RuleConditionalTransferLight.sol/RuleConditionalTransferLight.json new file mode 100644 index 0000000..926f9f6 --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/operation/RuleConditionalTransferLight.sol/RuleConditionalTransferLight.json @@ -0,0 +1,644 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleConditionalTransferLight", + "sourceName": "src/mocks/rules/operation/RuleConditionalTransferLight.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "contract IRuleEngine", + "name": "ruleEngineContract", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "TransferNotApproved", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "count", + "type": "uint256" + } + ], + "name": "TransferApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remaining", + "type": "uint256" + } + ], + "name": "TransferExecuted", + "type": "event" + }, + { + "inputs": [], + "name": "CODE_TRANSFER_REQUEST_NOT_APPROVED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "OPERATOR_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RULE_ENGINE_CONTRACT_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "approvalCounts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approveTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approvedCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "canReturnTransferRestrictionCode", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "canTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestriction", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestrictionFrom", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "messageForTransferRestriction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561000f575f5ffd5b5060405161174138038061174183398181016040528101906100319190610347565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361009f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610096906103df565b60405180910390fd5b6100b15f5f1b3361014f60201b60201c565b506100e27f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b9298361014f60201b60201c565b505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610148576101467f5007339590b47d4786f4ab2ef7ffa0ec54bc5fe7244dd97bc6efa6ab3799807b8261014f60201b60201c565b505b50506103fd565b5f610160838361024460201b60201c565b61023a5760015f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506101d76102a760201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001905061023e565b5f90505b92915050565b5f5f5f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f33905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6102db826102b2565b9050919050565b6102eb816102d1565b81146102f5575f5ffd5b50565b5f81519050610306816102e2565b92915050565b5f610316826102d1565b9050919050565b6103268161030c565b8114610330575f5ffd5b50565b5f815190506103418161031d565b92915050565b5f5f6040838503121561035d5761035c6102ae565b5b5f61036a858286016102f8565b925050602061037b85828601610333565b9150509250929050565b5f82825260208201905092915050565b7f496e76616c6964206f70657261746f72000000000000000000000000000000005f82015250565b5f6103c9601083610385565b91506103d482610395565b602082019050919050565b5f6020820190508181035f8301526103f6816103bd565b9050919050565b6113378061040a5f395ff3fe608060405234801561000f575f5ffd5b5060043610610135575f3560e01c80638abed32b116100b6578063d4ce14151161007a578063d4ce141514610393578063d547741f146103c3578063dfdc49b9146103df578063e46638e6146103fd578063f02322f01461042d578063f5b541a61461044b57610135565b80638abed32b146102c95780638baf29b4146102f957806391d1485414610315578063a217fddf14610345578063d32c7bb51461036357610135565b80633e5af4ca116100fd5780633e5af4ca146102015780637157797f1461021d5780637d045df61461024d5780637f4ab1dd1461027d57806382580805146102ad57610135565b806301ffc9a714610139578063248a9ca31461016957806325005a41146101995780632f2ff15d146101c957806336568abe146101e5575b5f5ffd5b610153600480360381019061014e9190610d6a565b610469565b6040516101609190610daf565b60405180910390f35b610183600480360381019061017e9190610dfb565b6104e2565b6040516101909190610e35565b60405180910390f35b6101b360048036038101906101ae9190610edb565b6104fe565b6040516101c09190610f3a565b60405180910390f35b6101e360048036038101906101de9190610f53565b610549565b005b6101ff60048036038101906101fa9190610f53565b61056b565b005b61021b60048036038101906102169190610f91565b6105e6565b005b61023760048036038101906102329190610f91565b6105f7565b6040516102449190610daf565b60405180910390f35b6102676004803603810190610262919061102b565b610628565b6040516102749190610daf565b60405180910390f35b6102976004803603810190610292919061102b565b61063a565b6040516102a491906110c6565b60405180910390f35b6102c760048036038101906102c29190610edb565b6106a8565b005b6102e360048036038101906102de9190610dfb565b6107a6565b6040516102f09190610f3a565b60405180910390f35b610313600480360381019061030e9190610edb565b6107bb565b005b61032f600480360381019061032a9190610f53565b6108d8565b60405161033c9190610daf565b60405180910390f35b61034d61093b565b60405161035a9190610e35565b60405180910390f35b61037d60048036038101906103789190610f91565b610941565b60405161038a91906110f5565b60405180910390f35b6103ad60048036038101906103a89190610edb565b610957565b6040516103ba91906110f5565b60405180910390f35b6103dd60048036038101906103d89190610f53565b6109cc565b005b6103e76109ee565b6040516103f491906110f5565b60405180910390f35b61041760048036038101906104129190610edb565b6109f3565b6040516104249190610daf565b60405180910390f35b610435610a22565b6040516104429190610e35565b60405180910390f35b610453610a46565b6040516104609190610e35565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806104db57506104da82610a6a565b5b9050919050565b5f5f5f8381526020019081526020015f20600101549050919050565b5f5f84848460405160200161051593929190611173565b60405160208183030381529060405280519060200120905060015f8281526020019081526020015f20549150509392505050565b610552826104e2565b61055b81610ad3565b6105658383610ae7565b50505050565b610573610bd0565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146105d7576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105e18282610bd7565b505050565b6105f18383836107bb565b50505050565b5f5f600681111561060b5761060a6111af565b5b60ff1661061a86868686610941565b60ff16149050949350505050565b5f604760ff168260ff16149050919050565b6060604760ff168260ff160361066a576040518060600160405280603581526020016112cd6035913990506106a3565b6040518060400160405280601881526020017f556e6b6e6f776e207265737472696374696f6e20636f6465000000000000000081525090505b919050565b7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b9296106d281610ad3565b5f8484846040516020016106e893929190611173565b6040516020818303038152906040528051906020012090506001805f8381526020019081526020015f205f8282546107209190611209565b925050819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167feccbdf7c486b88cbffbd8100b22951057ab0de2b73f27f625cc468ccabc3d08a8560015f8681526020019081526020015f205460405161079792919061123c565b60405180910390a35050505050565b6001602052805f5260405f205f915090505481565b5f8383836040516020016107d193929190611173565b6040516020818303038152906040528051906020012090505f60015f8381526020019081526020015f205490505f8103610837576040517ff82ba75a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001816108449190611263565b60015f8481526020019081526020015f20819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f8e386ea29f37964fdbdb87193d773dea74e258b0f6108461c88c712051fb27bc8560015f8781526020019081526020015f20546040516108c992919061123c565b60405180910390a35050505050565b5f5f5f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f5f1b81565b5f61094d848484610957565b9050949350505050565b5f5f84848460405160200161096e93929190611173565b6040516020818303038152906040528051906020012090505f60015f8381526020019081526020015f205490505f81036109ad576047925050506109c5565b5f60068111156109c0576109bf6111af565b5b925050505b9392505050565b6109d5826104e2565b6109de81610ad3565b6109e88383610bd7565b50505050565b604781565b5f5f6006811115610a0757610a066111af565b5b60ff16610a15858585610957565b60ff161490509392505050565b7f5007339590b47d4786f4ab2ef7ffa0ec54bc5fe7244dd97bc6efa6ab3799807b81565b7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b92981565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b610ae481610adf610bd0565b610cc0565b50565b5f610af283836108d8565b610bc65760015f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550610b63610bd0565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050610bca565b5f90505b92915050565b5f33905090565b5f610be283836108d8565b15610cb6575f5f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550610c53610bd0565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050610cba565b5f90505b92915050565b610cca82826108d8565b610d0d5780826040517fe2517d3f000000000000000000000000000000000000000000000000000000008152600401610d049291906112a5565b60405180910390fd5b5050565b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610d4981610d15565b8114610d53575f5ffd5b50565b5f81359050610d6481610d40565b92915050565b5f60208284031215610d7f57610d7e610d11565b5b5f610d8c84828501610d56565b91505092915050565b5f8115159050919050565b610da981610d95565b82525050565b5f602082019050610dc25f830184610da0565b92915050565b5f819050919050565b610dda81610dc8565b8114610de4575f5ffd5b50565b5f81359050610df581610dd1565b92915050565b5f60208284031215610e1057610e0f610d11565b5b5f610e1d84828501610de7565b91505092915050565b610e2f81610dc8565b82525050565b5f602082019050610e485f830184610e26565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610e7782610e4e565b9050919050565b610e8781610e6d565b8114610e91575f5ffd5b50565b5f81359050610ea281610e7e565b92915050565b5f819050919050565b610eba81610ea8565b8114610ec4575f5ffd5b50565b5f81359050610ed581610eb1565b92915050565b5f5f5f60608486031215610ef257610ef1610d11565b5b5f610eff86828701610e94565b9350506020610f1086828701610e94565b9250506040610f2186828701610ec7565b9150509250925092565b610f3481610ea8565b82525050565b5f602082019050610f4d5f830184610f2b565b92915050565b5f5f60408385031215610f6957610f68610d11565b5b5f610f7685828601610de7565b9250506020610f8785828601610e94565b9150509250929050565b5f5f5f5f60808587031215610fa957610fa8610d11565b5b5f610fb687828801610e94565b9450506020610fc787828801610e94565b9350506040610fd887828801610e94565b9250506060610fe987828801610ec7565b91505092959194509250565b5f60ff82169050919050565b61100a81610ff5565b8114611014575f5ffd5b50565b5f8135905061102581611001565b92915050565b5f602082840312156110405761103f610d11565b5b5f61104d84828501611017565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61109882611056565b6110a28185611060565b93506110b2818560208601611070565b6110bb8161107e565b840191505092915050565b5f6020820190508181035f8301526110de818461108e565b905092915050565b6110ef81610ff5565b82525050565b5f6020820190506111085f8301846110e6565b92915050565b5f8160601b9050919050565b5f6111248261110e565b9050919050565b5f6111358261111a565b9050919050565b61114d61114882610e6d565b61112b565b82525050565b5f819050919050565b61116d61116882610ea8565b611153565b82525050565b5f61117e828661113c565b60148201915061118e828561113c565b60148201915061119e828461115c565b602082019150819050949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61121382610ea8565b915061121e83610ea8565b9250828201905080821115611236576112356111dc565b5b92915050565b5f60408201905061124f5f830185610f2b565b61125c6020830184610f2b565b9392505050565b5f61126d82610ea8565b915061127883610ea8565b92508282039050818111156112905761128f6111dc565b5b92915050565b61129f81610e6d565b82525050565b5f6040820190506112b85f830185611296565b6112c56020830184610e26565b939250505056fe436f6e646974696f6e616c5472616e736665724c696768743a205468652072657175657374206973206e6f7420617070726f766564a264697066735822122037b97360116ec69b2e625d68757383c571efc8b26affda74da34e99c87ee96d864736f6c634300081e0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610135575f3560e01c80638abed32b116100b6578063d4ce14151161007a578063d4ce141514610393578063d547741f146103c3578063dfdc49b9146103df578063e46638e6146103fd578063f02322f01461042d578063f5b541a61461044b57610135565b80638abed32b146102c95780638baf29b4146102f957806391d1485414610315578063a217fddf14610345578063d32c7bb51461036357610135565b80633e5af4ca116100fd5780633e5af4ca146102015780637157797f1461021d5780637d045df61461024d5780637f4ab1dd1461027d57806382580805146102ad57610135565b806301ffc9a714610139578063248a9ca31461016957806325005a41146101995780632f2ff15d146101c957806336568abe146101e5575b5f5ffd5b610153600480360381019061014e9190610d6a565b610469565b6040516101609190610daf565b60405180910390f35b610183600480360381019061017e9190610dfb565b6104e2565b6040516101909190610e35565b60405180910390f35b6101b360048036038101906101ae9190610edb565b6104fe565b6040516101c09190610f3a565b60405180910390f35b6101e360048036038101906101de9190610f53565b610549565b005b6101ff60048036038101906101fa9190610f53565b61056b565b005b61021b60048036038101906102169190610f91565b6105e6565b005b61023760048036038101906102329190610f91565b6105f7565b6040516102449190610daf565b60405180910390f35b6102676004803603810190610262919061102b565b610628565b6040516102749190610daf565b60405180910390f35b6102976004803603810190610292919061102b565b61063a565b6040516102a491906110c6565b60405180910390f35b6102c760048036038101906102c29190610edb565b6106a8565b005b6102e360048036038101906102de9190610dfb565b6107a6565b6040516102f09190610f3a565b60405180910390f35b610313600480360381019061030e9190610edb565b6107bb565b005b61032f600480360381019061032a9190610f53565b6108d8565b60405161033c9190610daf565b60405180910390f35b61034d61093b565b60405161035a9190610e35565b60405180910390f35b61037d60048036038101906103789190610f91565b610941565b60405161038a91906110f5565b60405180910390f35b6103ad60048036038101906103a89190610edb565b610957565b6040516103ba91906110f5565b60405180910390f35b6103dd60048036038101906103d89190610f53565b6109cc565b005b6103e76109ee565b6040516103f491906110f5565b60405180910390f35b61041760048036038101906104129190610edb565b6109f3565b6040516104249190610daf565b60405180910390f35b610435610a22565b6040516104429190610e35565b60405180910390f35b610453610a46565b6040516104609190610e35565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806104db57506104da82610a6a565b5b9050919050565b5f5f5f8381526020019081526020015f20600101549050919050565b5f5f84848460405160200161051593929190611173565b60405160208183030381529060405280519060200120905060015f8281526020019081526020015f20549150509392505050565b610552826104e2565b61055b81610ad3565b6105658383610ae7565b50505050565b610573610bd0565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146105d7576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105e18282610bd7565b505050565b6105f18383836107bb565b50505050565b5f5f600681111561060b5761060a6111af565b5b60ff1661061a86868686610941565b60ff16149050949350505050565b5f604760ff168260ff16149050919050565b6060604760ff168260ff160361066a576040518060600160405280603581526020016112cd6035913990506106a3565b6040518060400160405280601881526020017f556e6b6e6f776e207265737472696374696f6e20636f6465000000000000000081525090505b919050565b7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b9296106d281610ad3565b5f8484846040516020016106e893929190611173565b6040516020818303038152906040528051906020012090506001805f8381526020019081526020015f205f8282546107209190611209565b925050819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167feccbdf7c486b88cbffbd8100b22951057ab0de2b73f27f625cc468ccabc3d08a8560015f8681526020019081526020015f205460405161079792919061123c565b60405180910390a35050505050565b6001602052805f5260405f205f915090505481565b5f8383836040516020016107d193929190611173565b6040516020818303038152906040528051906020012090505f60015f8381526020019081526020015f205490505f8103610837576040517ff82ba75a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001816108449190611263565b60015f8481526020019081526020015f20819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f8e386ea29f37964fdbdb87193d773dea74e258b0f6108461c88c712051fb27bc8560015f8781526020019081526020015f20546040516108c992919061123c565b60405180910390a35050505050565b5f5f5f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f5f1b81565b5f61094d848484610957565b9050949350505050565b5f5f84848460405160200161096e93929190611173565b6040516020818303038152906040528051906020012090505f60015f8381526020019081526020015f205490505f81036109ad576047925050506109c5565b5f60068111156109c0576109bf6111af565b5b925050505b9392505050565b6109d5826104e2565b6109de81610ad3565b6109e88383610bd7565b50505050565b604781565b5f5f6006811115610a0757610a066111af565b5b60ff16610a15858585610957565b60ff161490509392505050565b7f5007339590b47d4786f4ab2ef7ffa0ec54bc5fe7244dd97bc6efa6ab3799807b81565b7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b92981565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b610ae481610adf610bd0565b610cc0565b50565b5f610af283836108d8565b610bc65760015f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550610b63610bd0565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050610bca565b5f90505b92915050565b5f33905090565b5f610be283836108d8565b15610cb6575f5f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550610c53610bd0565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050610cba565b5f90505b92915050565b610cca82826108d8565b610d0d5780826040517fe2517d3f000000000000000000000000000000000000000000000000000000008152600401610d049291906112a5565b60405180910390fd5b5050565b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610d4981610d15565b8114610d53575f5ffd5b50565b5f81359050610d6481610d40565b92915050565b5f60208284031215610d7f57610d7e610d11565b5b5f610d8c84828501610d56565b91505092915050565b5f8115159050919050565b610da981610d95565b82525050565b5f602082019050610dc25f830184610da0565b92915050565b5f819050919050565b610dda81610dc8565b8114610de4575f5ffd5b50565b5f81359050610df581610dd1565b92915050565b5f60208284031215610e1057610e0f610d11565b5b5f610e1d84828501610de7565b91505092915050565b610e2f81610dc8565b82525050565b5f602082019050610e485f830184610e26565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610e7782610e4e565b9050919050565b610e8781610e6d565b8114610e91575f5ffd5b50565b5f81359050610ea281610e7e565b92915050565b5f819050919050565b610eba81610ea8565b8114610ec4575f5ffd5b50565b5f81359050610ed581610eb1565b92915050565b5f5f5f60608486031215610ef257610ef1610d11565b5b5f610eff86828701610e94565b9350506020610f1086828701610e94565b9250506040610f2186828701610ec7565b9150509250925092565b610f3481610ea8565b82525050565b5f602082019050610f4d5f830184610f2b565b92915050565b5f5f60408385031215610f6957610f68610d11565b5b5f610f7685828601610de7565b9250506020610f8785828601610e94565b9150509250929050565b5f5f5f5f60808587031215610fa957610fa8610d11565b5b5f610fb687828801610e94565b9450506020610fc787828801610e94565b9350506040610fd887828801610e94565b9250506060610fe987828801610ec7565b91505092959194509250565b5f60ff82169050919050565b61100a81610ff5565b8114611014575f5ffd5b50565b5f8135905061102581611001565b92915050565b5f602082840312156110405761103f610d11565b5b5f61104d84828501611017565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61109882611056565b6110a28185611060565b93506110b2818560208601611070565b6110bb8161107e565b840191505092915050565b5f6020820190508181035f8301526110de818461108e565b905092915050565b6110ef81610ff5565b82525050565b5f6020820190506111085f8301846110e6565b92915050565b5f8160601b9050919050565b5f6111248261110e565b9050919050565b5f6111358261111a565b9050919050565b61114d61114882610e6d565b61112b565b82525050565b5f819050919050565b61116d61116882610ea8565b611153565b82525050565b5f61117e828661113c565b60148201915061118e828561113c565b60148201915061119e828461115c565b602082019150819050949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61121382610ea8565b915061121e83610ea8565b9250828201905080821115611236576112356111dc565b5b92915050565b5f60408201905061124f5f830185610f2b565b61125c6020830184610f2b565b9392505050565b5f61126d82610ea8565b915061127883610ea8565b92508282039050818111156112905761128f6111dc565b5b92915050565b61129f81610e6d565b82525050565b5f6040820190506112b85f830185611296565b6112c56020830184610e26565b939250505056fe436f6e646974696f6e616c5472616e736665724c696768743a205468652072657175657374206973206e6f7420617070726f766564a264697066735822122037b97360116ec69b2e625d68757383c571efc8b26affda74da34e99c87ee96d864736f6c634300081e0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/mocks/rules/operation/RuleOperationRevert.sol/RuleOperationRevert.dbg.json b/doc/compilation/hardhat/src/mocks/rules/operation/RuleOperationRevert.sol/RuleOperationRevert.dbg.json new file mode 100644 index 0000000..603ee8f --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/operation/RuleOperationRevert.sol/RuleOperationRevert.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/mocks/rules/operation/RuleOperationRevert.sol/RuleOperationRevert.json b/doc/compilation/hardhat/src/mocks/rules/operation/RuleOperationRevert.sol/RuleOperationRevert.json new file mode 100644 index 0000000..3dd23aa --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/operation/RuleOperationRevert.sol/RuleOperationRevert.json @@ -0,0 +1,469 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleOperationRevert", + "sourceName": "src/mocks/rules/operation/RuleOperationRevert.sol", + "abi": [ + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "RuleConditionalTransferLight_InvalidTransfer", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "CODE_TRANSFER_REQUEST_NOT_APPROVED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "canReturnTransferRestrictionCode", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "canTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "detectTransferRestriction", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestrictionFrom", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "name": "messageForTransferRestriction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "pure", + "type": "function" + } + ], + "bytecode": "0x6080604052348015600e575f5ffd5b50610d998061001c5f395ff3fe608060405234801561000f575f5ffd5b50600436106100fe575f3560e01c80638baf29b411610095578063d4ce141511610064578063d4ce1415146102e0578063d547741f14610310578063dfdc49b91461032c578063e46638e61461034a576100fe565b80638baf29b41461024657806391d1485414610262578063a217fddf14610292578063d32c7bb5146102b0576100fe565b80633e5af4ca116100d15780633e5af4ca1461019a5780637157797f146101b65780637d045df6146101e65780637f4ab1dd14610216576100fe565b806301ffc9a714610102578063248a9ca3146101325780632f2ff15d1461016257806336568abe1461017e575b5f5ffd5b61011c60048036038101906101179190610984565b61037a565b60405161012991906109c9565b60405180910390f35b61014c60048036038101906101479190610a15565b6103f3565b6040516101599190610a4f565b60405180910390f35b61017c60048036038101906101779190610ac2565b61040f565b005b61019860048036038101906101939190610ac2565b610431565b005b6101b460048036038101906101af9190610b33565b6104ac565b005b6101d060048036038101906101cb9190610b33565b6104de565b6040516101dd91906109c9565b60405180910390f35b61020060048036038101906101fb9190610bcd565b61050f565b60405161020d91906109c9565b60405180910390f35b610230600480360381019061022b9190610bcd565b610521565b60405161023d9190610c68565b60405180910390f35b610260600480360381019061025b9190610c88565b610560565b005b61027c60048036038101906102779190610ac2565b610592565b60405161028991906109c9565b60405180910390f35b61029a6105f5565b6040516102a79190610a4f565b60405180910390f35b6102ca60048036038101906102c59190610b33565b6105fb565b6040516102d79190610ce7565b60405180910390f35b6102fa60048036038101906102f59190610c88565b610611565b6040516103079190610ce7565b60405180910390f35b61032a60048036038101906103259190610ac2565b61062e565b005b610334610650565b6040516103419190610ce7565b60405180910390f35b610364600480360381019061035f9190610c88565b610655565b60405161037191906109c9565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806103ec57506103eb82610684565b5b9050919050565b5f5f5f8381526020019081526020015f20600101549050919050565b610418826103f3565b610421816106ed565b61042b8383610701565b50505050565b6104396107ea565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461049d576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104a782826107f1565b505050565b6040517f15ec568600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f60068111156104f2576104f1610d00565b5b60ff16610501868686866105fb565b60ff16149050949350505050565b5f604760ff168260ff16149050919050565b60606040518060400160405280601881526020017f556e6b6e6f776e207265737472696374696f6e20636f646500000000000000008152509050919050565b6040517f15ec568600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f5f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f5f1b81565b5f610607848484610611565b9050949350505050565b5f5f600681111561062557610624610d00565b5b90509392505050565b610637826103f3565b610640816106ed565b61064a83836107f1565b50505050565b604781565b5f5f600681111561066957610668610d00565b5b60ff16610677858585610611565b60ff161490509392505050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6106fe816106f96107ea565b6108da565b50565b5f61070c8383610592565b6107e05760015f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555061077d6107ea565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600190506107e4565b5f90505b92915050565b5f33905090565b5f6107fc8383610592565b156108d0575f5f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555061086d6107ea565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a4600190506108d4565b5f90505b92915050565b6108e48282610592565b6109275780826040517fe2517d3f00000000000000000000000000000000000000000000000000000000815260040161091e929190610d3c565b60405180910390fd5b5050565b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6109638161092f565b811461096d575f5ffd5b50565b5f8135905061097e8161095a565b92915050565b5f602082840312156109995761099861092b565b5b5f6109a684828501610970565b91505092915050565b5f8115159050919050565b6109c3816109af565b82525050565b5f6020820190506109dc5f8301846109ba565b92915050565b5f819050919050565b6109f4816109e2565b81146109fe575f5ffd5b50565b5f81359050610a0f816109eb565b92915050565b5f60208284031215610a2a57610a2961092b565b5b5f610a3784828501610a01565b91505092915050565b610a49816109e2565b82525050565b5f602082019050610a625f830184610a40565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610a9182610a68565b9050919050565b610aa181610a87565b8114610aab575f5ffd5b50565b5f81359050610abc81610a98565b92915050565b5f5f60408385031215610ad857610ad761092b565b5b5f610ae585828601610a01565b9250506020610af685828601610aae565b9150509250929050565b5f819050919050565b610b1281610b00565b8114610b1c575f5ffd5b50565b5f81359050610b2d81610b09565b92915050565b5f5f5f5f60808587031215610b4b57610b4a61092b565b5b5f610b5887828801610aae565b9450506020610b6987828801610aae565b9350506040610b7a87828801610aae565b9250506060610b8b87828801610b1f565b91505092959194509250565b5f60ff82169050919050565b610bac81610b97565b8114610bb6575f5ffd5b50565b5f81359050610bc781610ba3565b92915050565b5f60208284031215610be257610be161092b565b5b5f610bef84828501610bb9565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f610c3a82610bf8565b610c448185610c02565b9350610c54818560208601610c12565b610c5d81610c20565b840191505092915050565b5f6020820190508181035f830152610c808184610c30565b905092915050565b5f5f5f60608486031215610c9f57610c9e61092b565b5b5f610cac86828701610aae565b9350506020610cbd86828701610aae565b9250506040610cce86828701610b1f565b9150509250925092565b610ce181610b97565b82525050565b5f602082019050610cfa5f830184610cd8565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b610d3681610a87565b82525050565b5f604082019050610d4f5f830185610d2d565b610d5c6020830184610a40565b939250505056fea26469706673582212209e6a01fafca16b63fb72447553c976985562ee8379b4b404c7ec81afe6659d5264736f6c634300081e0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106100fe575f3560e01c80638baf29b411610095578063d4ce141511610064578063d4ce1415146102e0578063d547741f14610310578063dfdc49b91461032c578063e46638e61461034a576100fe565b80638baf29b41461024657806391d1485414610262578063a217fddf14610292578063d32c7bb5146102b0576100fe565b80633e5af4ca116100d15780633e5af4ca1461019a5780637157797f146101b65780637d045df6146101e65780637f4ab1dd14610216576100fe565b806301ffc9a714610102578063248a9ca3146101325780632f2ff15d1461016257806336568abe1461017e575b5f5ffd5b61011c60048036038101906101179190610984565b61037a565b60405161012991906109c9565b60405180910390f35b61014c60048036038101906101479190610a15565b6103f3565b6040516101599190610a4f565b60405180910390f35b61017c60048036038101906101779190610ac2565b61040f565b005b61019860048036038101906101939190610ac2565b610431565b005b6101b460048036038101906101af9190610b33565b6104ac565b005b6101d060048036038101906101cb9190610b33565b6104de565b6040516101dd91906109c9565b60405180910390f35b61020060048036038101906101fb9190610bcd565b61050f565b60405161020d91906109c9565b60405180910390f35b610230600480360381019061022b9190610bcd565b610521565b60405161023d9190610c68565b60405180910390f35b610260600480360381019061025b9190610c88565b610560565b005b61027c60048036038101906102779190610ac2565b610592565b60405161028991906109c9565b60405180910390f35b61029a6105f5565b6040516102a79190610a4f565b60405180910390f35b6102ca60048036038101906102c59190610b33565b6105fb565b6040516102d79190610ce7565b60405180910390f35b6102fa60048036038101906102f59190610c88565b610611565b6040516103079190610ce7565b60405180910390f35b61032a60048036038101906103259190610ac2565b61062e565b005b610334610650565b6040516103419190610ce7565b60405180910390f35b610364600480360381019061035f9190610c88565b610655565b60405161037191906109c9565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806103ec57506103eb82610684565b5b9050919050565b5f5f5f8381526020019081526020015f20600101549050919050565b610418826103f3565b610421816106ed565b61042b8383610701565b50505050565b6104396107ea565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461049d576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104a782826107f1565b505050565b6040517f15ec568600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f60068111156104f2576104f1610d00565b5b60ff16610501868686866105fb565b60ff16149050949350505050565b5f604760ff168260ff16149050919050565b60606040518060400160405280601881526020017f556e6b6e6f776e207265737472696374696f6e20636f646500000000000000008152509050919050565b6040517f15ec568600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f5f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f5f1b81565b5f610607848484610611565b9050949350505050565b5f5f600681111561062557610624610d00565b5b90509392505050565b610637826103f3565b610640816106ed565b61064a83836107f1565b50505050565b604781565b5f5f600681111561066957610668610d00565b5b60ff16610677858585610611565b60ff161490509392505050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6106fe816106f96107ea565b6108da565b50565b5f61070c8383610592565b6107e05760015f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555061077d6107ea565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600190506107e4565b5f90505b92915050565b5f33905090565b5f6107fc8383610592565b156108d0575f5f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555061086d6107ea565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a4600190506108d4565b5f90505b92915050565b6108e48282610592565b6109275780826040517fe2517d3f00000000000000000000000000000000000000000000000000000000815260040161091e929190610d3c565b60405180910390fd5b5050565b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6109638161092f565b811461096d575f5ffd5b50565b5f8135905061097e8161095a565b92915050565b5f602082840312156109995761099861092b565b5b5f6109a684828501610970565b91505092915050565b5f8115159050919050565b6109c3816109af565b82525050565b5f6020820190506109dc5f8301846109ba565b92915050565b5f819050919050565b6109f4816109e2565b81146109fe575f5ffd5b50565b5f81359050610a0f816109eb565b92915050565b5f60208284031215610a2a57610a2961092b565b5b5f610a3784828501610a01565b91505092915050565b610a49816109e2565b82525050565b5f602082019050610a625f830184610a40565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610a9182610a68565b9050919050565b610aa181610a87565b8114610aab575f5ffd5b50565b5f81359050610abc81610a98565b92915050565b5f5f60408385031215610ad857610ad761092b565b5b5f610ae585828601610a01565b9250506020610af685828601610aae565b9150509250929050565b5f819050919050565b610b1281610b00565b8114610b1c575f5ffd5b50565b5f81359050610b2d81610b09565b92915050565b5f5f5f5f60808587031215610b4b57610b4a61092b565b5b5f610b5887828801610aae565b9450506020610b6987828801610aae565b9350506040610b7a87828801610aae565b9250506060610b8b87828801610b1f565b91505092959194509250565b5f60ff82169050919050565b610bac81610b97565b8114610bb6575f5ffd5b50565b5f81359050610bc781610ba3565b92915050565b5f60208284031215610be257610be161092b565b5b5f610bef84828501610bb9565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f610c3a82610bf8565b610c448185610c02565b9350610c54818560208601610c12565b610c5d81610c20565b840191505092915050565b5f6020820190508181035f830152610c808184610c30565b905092915050565b5f5f5f60608486031215610c9f57610c9e61092b565b5b5f610cac86828701610aae565b9350506020610cbd86828701610aae565b9250506040610cce86828701610b1f565b9150509250925092565b610ce181610b97565b82525050565b5f602082019050610cfa5f830184610cd8565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b610d3681610a87565b82525050565b5f604082019050610d4f5f830185610d2d565b610d5c6020830184610a40565b939250505056fea26469706673582212209e6a01fafca16b63fb72447553c976985562ee8379b4b404c7ec81afe6659d5264736f6c634300081e0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol/RuleConditionalTransferLightInvariantStorage.dbg.json b/doc/compilation/hardhat/src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol/RuleConditionalTransferLightInvariantStorage.dbg.json new file mode 100644 index 0000000..00f772e --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol/RuleConditionalTransferLightInvariantStorage.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol/RuleConditionalTransferLightInvariantStorage.json b/doc/compilation/hardhat/src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol/RuleConditionalTransferLightInvariantStorage.json new file mode 100644 index 0000000..249f8f6 --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol/RuleConditionalTransferLightInvariantStorage.json @@ -0,0 +1,117 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleConditionalTransferLightInvariantStorage", + "sourceName": "src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol", + "abi": [ + { + "inputs": [], + "name": "TransferNotApproved", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "count", + "type": "uint256" + } + ], + "name": "TransferApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remaining", + "type": "uint256" + } + ], + "name": "TransferExecuted", + "type": "event" + }, + { + "inputs": [], + "name": "CODE_TRANSFER_REQUEST_NOT_APPROVED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "OPERATOR_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RULE_ENGINE_CONTRACT_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/RuleWhitelist.sol/RuleWhitelist.dbg.json b/doc/compilation/hardhat/src/mocks/rules/validation/RuleWhitelist.sol/RuleWhitelist.dbg.json new file mode 100644 index 0000000..603ee8f --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/RuleWhitelist.sol/RuleWhitelist.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/RuleWhitelist.sol/RuleWhitelist.json b/doc/compilation/hardhat/src/mocks/rules/validation/RuleWhitelist.sol/RuleWhitelist.json new file mode 100644 index 0000000..6a8e028 --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/RuleWhitelist.sol/RuleWhitelist.json @@ -0,0 +1,760 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleWhitelist", + "sourceName": "src/mocks/rules/validation/RuleWhitelist.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "address", + "name": "forwarderIrrevocable", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "RuleAddressList_AdminWithAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "code", + "type": "uint8" + } + ], + "name": "RuleWhitelist_InvalidTransfer", + "type": "error" + }, + { + "inputs": [], + "name": "Rulelist_AddressAlreadylisted", + "type": "error" + }, + { + "inputs": [], + "name": "Rulelist_AddressNotPresent", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "AddAddressToTheList", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "listTargetAddresses", + "type": "address[]" + } + ], + "name": "AddAddressesToTheList", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "RemoveAddressFromTheList", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "listTargetAddresses", + "type": "address[]" + } + ], + "name": "RemoveAddressesFromTheList", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "ADDRESS_LIST_ADD_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ADDRESS_LIST_REMOVE_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_ADDRESS_FROM_NOT_WHITELISTED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_ADDRESS_SPENDER_NOT_WHITELISTED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_ADDRESS_TO_NOT_WHITELISTED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "addAddressToTheList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "listTargetAddresses", + "type": "address[]" + } + ], + "name": "addAddressesToTheList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_targetAddress", + "type": "address" + } + ], + "name": "addressIsListed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_targetAddresses", + "type": "address[]" + } + ], + "name": "addressIsListedBatch", + "outputs": [ + { + "internalType": "bool[]", + "name": "", + "type": "bool[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "canReturnTransferRestrictionCode", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "canTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "detectTransferRestriction", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestrictionFrom", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isTrustedForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "messageForTransferRestriction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "numberListedAddress", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "removeAddressFromTheList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "listTargetAddresses", + "type": "address[]" + } + ], + "name": "removeAddressesFromTheList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "trustedForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60a060405234801561000f575f5ffd5b506040516125fc3803806125fc833981810160405281019061003191906103da565b818180808073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff168152505050505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036100d0576040517f5f1a6c0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6100e25f5f1b836100ec60201b60201c565b50505050506104f9565b5f6100fd83836101e160201b60201c565b6101d75760015f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555061017461021b60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600190506101db565b5f90505b92915050565b5f6101f45f5f1b8361022f60201b60201c565b156102025760019050610215565b610212838361022f60201b60201c565b90505b92915050565b5f61022a61029260201b60201c565b905090565b5f5f5f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f5f5f36905090505f6102a961030c60201b60201c565b90508082101580156102c657506102c53361032060201b60201c565b5b156102f6575f368284039080926102df93929190610420565b906102ea919061049b565b60601c92505050610309565b61030461036460201b60201c565b925050505b90565b5f61031b61036b60201b60201c565b905090565b5f61032f61037360201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b5f33905090565b5f6014905090565b5f608051905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6103a982610380565b9050919050565b6103b98161039f565b81146103c3575f5ffd5b50565b5f815190506103d4816103b0565b92915050565b5f5f604083850312156103f0576103ef61037c565b5b5f6103fd858286016103c6565b925050602061040e858286016103c6565b9150509250929050565b5f5ffd5b5f5ffd5b5f5f8585111561043357610432610418565b5b838611156104445761044361041c565b5b6001850283019150848603905094509492505050565b5f82905092915050565b5f7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b5f82821b905092915050565b5f6104a6838361045a565b826104b18135610464565b925060148210156104f1576104ec7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008360140360080261048f565b831692505b505092915050565b6080516120eb6105115f395f610a1c01526120eb5ff3fe608060405234801561000f575f5ffd5b50600436106101cd575f3560e01c80637d045df611610102578063a217fddf116100a0578063daafd1c71161006f578063daafd1c714610575578063db136dad14610591578063e46638e6146105af578063fa83a2da146105df576101cd565b8063a217fddf146104db578063d32c7bb5146104f9578063d4ce141514610529578063d547741f14610559576101cd565b8063893c1440116100dc578063893c1440146104555780638baf29b41461047157806391d148541461048d578063948b851e146104bd576101cd565b80637d045df6146103d75780637da0a877146104075780637f4ab1dd14610425576101cd565b806336568abe1161016f578063572b6c0511610149578063572b6c05146103295780635b119c0a146103595780635b577f66146103775780637157797f146103a7576101cd565b806336568abe146102d35780633e5af4ca146102ef578063421069171461030b576101cd565b806313be3212116101ab57806313be32121461024d578063248a9ca31461026b5780632f2ff15d1461029b5780633630e2ea146102b7576101cd565b806301ffc9a7146101d15780630a3640d21461020157806311d1c5ca14610231575b5f5ffd5b6101eb60048036038101906101e69190611634565b6105fd565b6040516101f89190611679565b60405180910390f35b61021b6004803603810190610216919061183c565b610676565b604051610228919061193a565b60405180910390f35b61024b600480360381019061024691906119b3565b610730565b005b6102556107a2565b6040516102629190611a16565b60405180910390f35b61028560048036038101906102809190611a62565b6107b0565b6040516102929190611a9c565b60405180910390f35b6102b560048036038101906102b09190611ab5565b6107cc565b005b6102d160048036038101906102cc91906119b3565b6107ee565b005b6102ed60048036038101906102e89190611ab5565b610860565b005b61030960048036038101906103049190611b1d565b6108db565b005b61031361095b565b6040516103209190611b9c565b60405180910390f35b610343600480360381019061033e9190611bb5565b610960565b6040516103509190611679565b60405180910390f35b61036161099e565b60405161036e9190611b9c565b60405180910390f35b610391600480360381019061038c9190611bb5565b6109a3565b60405161039e9190611679565b60405180910390f35b6103c160048036038101906103bc9190611b1d565b6109b4565b6040516103ce9190611679565b60405180910390f35b6103f160048036038101906103ec9190611c0a565b6109e5565b6040516103fe9190611679565b60405180910390f35b61040f610a19565b60405161041c9190611c44565b60405180910390f35b61043f600480360381019061043a9190611c0a565b610a40565b60405161044c9190611cbd565b60405180910390f35b61046f600480360381019061046a9190611bb5565b610b0a565b005b61048b60048036038101906104869190611cdd565b610b78565b005b6104a760048036038101906104a29190611ab5565b610bf6565b6040516104b49190611679565b60405180910390f35b6104c5610c24565b6040516104d29190611a9c565b60405180910390f35b6104e3610c48565b6040516104f09190611a9c565b60405180910390f35b610513600480360381019061050e9190611b1d565b610c4e565b6040516105209190611b9c565b60405180910390f35b610543600480360381019061053e9190611cdd565b610c7b565b6040516105509190611b9c565b60405180910390f35b610573600480360381019061056e9190611ab5565b610cc5565b005b61058f600480360381019061058a9190611bb5565b610ce7565b005b610599610d55565b6040516105a69190611b9c565b60405180910390f35b6105c960048036038101906105c49190611cdd565b610d5a565b6040516105d69190611679565b60405180910390f35b6105e7610d89565b6040516105f49190611a9c565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061066f575061066e82610dad565b5b9050919050565b60605f825167ffffffffffffffff811115610694576106936116a6565b5b6040519080825280602002602001820160405280156106c25781602001602082028036833780820191505090505b5090505f5f90505b8351811015610726576106f68482815181106106e9576106e8611d2d565b5b6020026020010151610e16565b82828151811061070957610708611d2d565b5b6020026020010190151590811515815250508060010190506106ca565b5080915050919050565b7f1b03c849816e077359373cf0a8d6d8f741d643bc1e95273ffe11515f83bebf6161075a81610e68565b6107648383610e7c565b7f9f3dfa145deb5071c94eb9a1393634e982a46367c42dce9622f49213d8f427bd8383604051610795929190611e16565b60405180910390a1505050565b5f6107ab610fa7565b905090565b5f5f5f8381526020019081526020015f20600101549050919050565b6107d5826107b0565b6107de81610e68565b6107e88383610fb0565b50505050565b7f1b94c92b564251ed6b49246d9a82eb7a486b6490f3b3a3bf3b28d2e99801f3ec61081881610e68565b6108228383611099565b7f3be9b663c544556a256ca6ed9f2f6875dba1b09a6eee2571196227f7ec8c621c8383604051610853929190611e16565b60405180910390a1505050565b6108686111c5565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146108cc576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108d682826111d3565b505050565b5f6108e885858585610c4e565b90505f60068111156108fd576108fc611e38565b5b60ff168160ff16148484848490919293610950576040517fd9ead46f0000000000000000000000000000000000000000000000000000000081526004016109479493929190611e65565b60405180910390fd5b505050505050505050565b601781565b5f610969610a19565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b601581565b5f6109ad82610e16565b9050919050565b5f5f60068111156109c8576109c7611e38565b5b60ff166109d786868686610c4e565b60ff16149050949350505050565b5f601560ff168260ff161480610a015750601660ff168260ff16145b80610a125750601760ff168260ff16145b9050919050565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b6060601560ff168260ff1603610a7057604051806060016040528060228152602001612094602291399050610b05565b601660ff168260ff1603610a9e5760405180606001604052806025815260200161206f602591399050610b05565b601760ff168260ff1603610acc5760405180606001604052806023815260200161204c602391399050610b05565b6040518060400160405280601881526020017f556e6b6e6f776e207265737472696374696f6e20636f6465000000000000000081525090505b919050565b7f1b94c92b564251ed6b49246d9a82eb7a486b6490f3b3a3bf3b28d2e99801f3ec610b3481610e68565b610b3d826112bc565b7fe46e95d98efc7b1a5d9359155b9137734ac3be3f4b32eab0f697558c27f2d99c82604051610b6c9190611c44565b60405180910390a15050565b5f610b84848484610c7b565b90505f6006811115610b9957610b98611e38565b5b60ff168160ff16148484848490919293610bec576040517fd9ead46f000000000000000000000000000000000000000000000000000000008152600401610be39493929190611e65565b60405180910390fd5b5050505050505050565b5f610c035f5f1b836113a8565b15610c115760019050610c1e565b610c1b83836113a8565b90505b92915050565b7f1b03c849816e077359373cf0a8d6d8f741d643bc1e95273ffe11515f83bebf6181565b5f5f1b81565b5f610c58856109a3565b610c655760179050610c73565b610c70848484610c7b565b90505b949350505050565b5f610c85846109a3565b610c925760159050610cbe565b610c9b836109a3565b610ca85760169050610cbe565b5f6006811115610cbb57610cba611e38565b5b90505b9392505050565b610cce826107b0565b610cd781610e68565b610ce183836111d3565b50505050565b7f1b03c849816e077359373cf0a8d6d8f741d643bc1e95273ffe11515f83bebf61610d1181610e68565b610d1a8261140b565b7f7802fa8b90d406b2eb85b620cecde734206f390fa73c61e824384474b734cd9382604051610d499190611c44565b60405180910390a15050565b601681565b5f5f6006811115610d6e57610d6d611e38565b5b60ff16610d7c858585610c7b565b60ff161490509392505050565b7f1b94c92b564251ed6b49246d9a82eb7a486b6490f3b3a3bf3b28d2e99801f3ec81565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f60015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b610e7981610e746111c5565b6114f8565b50565b5f60025490505f5f90505b83839050811015610f9a5760015f858584818110610ea857610ea7611d2d565b5b9050602002016020810190610ebd9190611bb5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16610f8f576001805f868685818110610f1e57610f1d611d2d565b5b9050602002016020810190610f339190611bb5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555081610f8c90611ed5565b91505b806001019050610e87565b5080600281905550505050565b5f600254905090565b5f610fbb8383610bf6565b61108f5760015f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555061102c6111c5565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611093565b5f90505b92915050565b5f60025490505f5f90505b838390508110156111b85760015f8585848181106110c5576110c4611d2d565b5b90506020020160208101906110da9190611bb5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16156111ad575f60015f86868581811061113c5761113b611d2d565b5b90506020020160208101906111519190611bb5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550816111aa90611f1c565b91505b8060010190506110a4565b5080600281905550505050565b5f6111ce611549565b905090565b5f6111de8383610bf6565b156112b2575f5f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555061124f6111c5565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a4600190506112b6565b5f90505b92915050565b60015f8273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1661133c576040517fcfc5cc9500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555060025f815461139e90611f1c565b9190508190555050565b5f5f5f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b60015f8273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff161561148c576040517f57845b8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555060025f81546114ee90611ed5565b9190508190555050565b6115028282610bf6565b6115455780826040517fe2517d3f00000000000000000000000000000000000000000000000000000000815260040161153c929190611f43565b60405180910390fd5b5050565b5f5f5f36905090505f61155a6115b1565b9050808210158015611571575061157033610960565b5b156115a1575f3682840390809261158a93929190611f72565b906115959190611fed565b60601c925050506115ae565b6115a96115bf565b925050505b90565b5f6115ba6115c6565b905090565b5f33905090565b5f6014905090565b5f604051905090565b5f5ffd5b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611613816115df565b811461161d575f5ffd5b50565b5f8135905061162e8161160a565b92915050565b5f60208284031215611649576116486115d7565b5b5f61165684828501611620565b91505092915050565b5f8115159050919050565b6116738161165f565b82525050565b5f60208201905061168c5f83018461166a565b92915050565b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6116dc82611696565b810181811067ffffffffffffffff821117156116fb576116fa6116a6565b5b80604052505050565b5f61170d6115ce565b905061171982826116d3565b919050565b5f67ffffffffffffffff821115611738576117376116a6565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6117768261174d565b9050919050565b6117868161176c565b8114611790575f5ffd5b50565b5f813590506117a18161177d565b92915050565b5f6117b96117b48461171e565b611704565b905080838252602082019050602084028301858111156117dc576117db611749565b5b835b8181101561180557806117f18882611793565b8452602084019350506020810190506117de565b5050509392505050565b5f82601f83011261182357611822611692565b5b81356118338482602086016117a7565b91505092915050565b5f60208284031215611851576118506115d7565b5b5f82013567ffffffffffffffff81111561186e5761186d6115db565b5b61187a8482850161180f565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6118b58161165f565b82525050565b5f6118c683836118ac565b60208301905092915050565b5f602082019050919050565b5f6118e882611883565b6118f2818561188d565b93506118fd8361189d565b805f5b8381101561192d57815161191488826118bb565b975061191f836118d2565b925050600181019050611900565b5085935050505092915050565b5f6020820190508181035f83015261195281846118de565b905092915050565b5f5ffd5b5f5f83601f84011261197357611972611692565b5b8235905067ffffffffffffffff8111156119905761198f61195a565b5b6020830191508360208202830111156119ac576119ab611749565b5b9250929050565b5f5f602083850312156119c9576119c86115d7565b5b5f83013567ffffffffffffffff8111156119e6576119e56115db565b5b6119f28582860161195e565b92509250509250929050565b5f819050919050565b611a10816119fe565b82525050565b5f602082019050611a295f830184611a07565b92915050565b5f819050919050565b611a4181611a2f565b8114611a4b575f5ffd5b50565b5f81359050611a5c81611a38565b92915050565b5f60208284031215611a7757611a766115d7565b5b5f611a8484828501611a4e565b91505092915050565b611a9681611a2f565b82525050565b5f602082019050611aaf5f830184611a8d565b92915050565b5f5f60408385031215611acb57611aca6115d7565b5b5f611ad885828601611a4e565b9250506020611ae985828601611793565b9150509250929050565b611afc816119fe565b8114611b06575f5ffd5b50565b5f81359050611b1781611af3565b92915050565b5f5f5f5f60808587031215611b3557611b346115d7565b5b5f611b4287828801611793565b9450506020611b5387828801611793565b9350506040611b6487828801611793565b9250506060611b7587828801611b09565b91505092959194509250565b5f60ff82169050919050565b611b9681611b81565b82525050565b5f602082019050611baf5f830184611b8d565b92915050565b5f60208284031215611bca57611bc96115d7565b5b5f611bd784828501611793565b91505092915050565b611be981611b81565b8114611bf3575f5ffd5b50565b5f81359050611c0481611be0565b92915050565b5f60208284031215611c1f57611c1e6115d7565b5b5f611c2c84828501611bf6565b91505092915050565b611c3e8161176c565b82525050565b5f602082019050611c575f830184611c35565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f611c8f82611c5d565b611c998185611c67565b9350611ca9818560208601611c77565b611cb281611696565b840191505092915050565b5f6020820190508181035f830152611cd58184611c85565b905092915050565b5f5f5f60608486031215611cf457611cf36115d7565b5b5f611d0186828701611793565b9350506020611d1286828701611793565b9250506040611d2386828701611b09565b9150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82825260208201905092915050565b5f819050919050565b611d7c8161176c565b82525050565b5f611d8d8383611d73565b60208301905092915050565b5f611da76020840184611793565b905092915050565b5f602082019050919050565b5f611dc68385611d5a565b9350611dd182611d6a565b805f5b85811015611e0957611de68284611d99565b611df08882611d82565b9750611dfb83611daf565b925050600181019050611dd4565b5085925050509392505050565b5f6020820190508181035f830152611e2f818486611dbb565b90509392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f608082019050611e785f830187611c35565b611e856020830186611c35565b611e926040830185611a07565b611e9f6060830184611b8d565b95945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f611edf826119fe565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611f1157611f10611ea8565b5b600182019050919050565b5f611f26826119fe565b91505f8203611f3857611f37611ea8565b5b600182039050919050565b5f604082019050611f565f830185611c35565b611f636020830184611a8d565b9392505050565b5f5ffd5b5f5ffd5b5f5f85851115611f8557611f84611f6a565b5b83861115611f9657611f95611f6e565b5b6001850283019150848603905094509492505050565b5f82905092915050565b5f7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b5f82821b905092915050565b5f611ff88383611fac565b826120038135611fb6565b925060148210156120435761203e7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000083601403600802611fe1565b831692505b50509291505056fe546865207370656e646572206973206e6f7420696e207468652077686974656c69737454686520726563697069656e74206973206e6f7420696e207468652077686974656c6973745468652073656e646572206973206e6f7420696e207468652077686974656c697374a2646970667358221220c5d9366742fb111255ac42ea02b6428161121fb7b40f452a8bf8a4365b3f041364736f6c634300081e0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106101cd575f3560e01c80637d045df611610102578063a217fddf116100a0578063daafd1c71161006f578063daafd1c714610575578063db136dad14610591578063e46638e6146105af578063fa83a2da146105df576101cd565b8063a217fddf146104db578063d32c7bb5146104f9578063d4ce141514610529578063d547741f14610559576101cd565b8063893c1440116100dc578063893c1440146104555780638baf29b41461047157806391d148541461048d578063948b851e146104bd576101cd565b80637d045df6146103d75780637da0a877146104075780637f4ab1dd14610425576101cd565b806336568abe1161016f578063572b6c0511610149578063572b6c05146103295780635b119c0a146103595780635b577f66146103775780637157797f146103a7576101cd565b806336568abe146102d35780633e5af4ca146102ef578063421069171461030b576101cd565b806313be3212116101ab57806313be32121461024d578063248a9ca31461026b5780632f2ff15d1461029b5780633630e2ea146102b7576101cd565b806301ffc9a7146101d15780630a3640d21461020157806311d1c5ca14610231575b5f5ffd5b6101eb60048036038101906101e69190611634565b6105fd565b6040516101f89190611679565b60405180910390f35b61021b6004803603810190610216919061183c565b610676565b604051610228919061193a565b60405180910390f35b61024b600480360381019061024691906119b3565b610730565b005b6102556107a2565b6040516102629190611a16565b60405180910390f35b61028560048036038101906102809190611a62565b6107b0565b6040516102929190611a9c565b60405180910390f35b6102b560048036038101906102b09190611ab5565b6107cc565b005b6102d160048036038101906102cc91906119b3565b6107ee565b005b6102ed60048036038101906102e89190611ab5565b610860565b005b61030960048036038101906103049190611b1d565b6108db565b005b61031361095b565b6040516103209190611b9c565b60405180910390f35b610343600480360381019061033e9190611bb5565b610960565b6040516103509190611679565b60405180910390f35b61036161099e565b60405161036e9190611b9c565b60405180910390f35b610391600480360381019061038c9190611bb5565b6109a3565b60405161039e9190611679565b60405180910390f35b6103c160048036038101906103bc9190611b1d565b6109b4565b6040516103ce9190611679565b60405180910390f35b6103f160048036038101906103ec9190611c0a565b6109e5565b6040516103fe9190611679565b60405180910390f35b61040f610a19565b60405161041c9190611c44565b60405180910390f35b61043f600480360381019061043a9190611c0a565b610a40565b60405161044c9190611cbd565b60405180910390f35b61046f600480360381019061046a9190611bb5565b610b0a565b005b61048b60048036038101906104869190611cdd565b610b78565b005b6104a760048036038101906104a29190611ab5565b610bf6565b6040516104b49190611679565b60405180910390f35b6104c5610c24565b6040516104d29190611a9c565b60405180910390f35b6104e3610c48565b6040516104f09190611a9c565b60405180910390f35b610513600480360381019061050e9190611b1d565b610c4e565b6040516105209190611b9c565b60405180910390f35b610543600480360381019061053e9190611cdd565b610c7b565b6040516105509190611b9c565b60405180910390f35b610573600480360381019061056e9190611ab5565b610cc5565b005b61058f600480360381019061058a9190611bb5565b610ce7565b005b610599610d55565b6040516105a69190611b9c565b60405180910390f35b6105c960048036038101906105c49190611cdd565b610d5a565b6040516105d69190611679565b60405180910390f35b6105e7610d89565b6040516105f49190611a9c565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061066f575061066e82610dad565b5b9050919050565b60605f825167ffffffffffffffff811115610694576106936116a6565b5b6040519080825280602002602001820160405280156106c25781602001602082028036833780820191505090505b5090505f5f90505b8351811015610726576106f68482815181106106e9576106e8611d2d565b5b6020026020010151610e16565b82828151811061070957610708611d2d565b5b6020026020010190151590811515815250508060010190506106ca565b5080915050919050565b7f1b03c849816e077359373cf0a8d6d8f741d643bc1e95273ffe11515f83bebf6161075a81610e68565b6107648383610e7c565b7f9f3dfa145deb5071c94eb9a1393634e982a46367c42dce9622f49213d8f427bd8383604051610795929190611e16565b60405180910390a1505050565b5f6107ab610fa7565b905090565b5f5f5f8381526020019081526020015f20600101549050919050565b6107d5826107b0565b6107de81610e68565b6107e88383610fb0565b50505050565b7f1b94c92b564251ed6b49246d9a82eb7a486b6490f3b3a3bf3b28d2e99801f3ec61081881610e68565b6108228383611099565b7f3be9b663c544556a256ca6ed9f2f6875dba1b09a6eee2571196227f7ec8c621c8383604051610853929190611e16565b60405180910390a1505050565b6108686111c5565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146108cc576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108d682826111d3565b505050565b5f6108e885858585610c4e565b90505f60068111156108fd576108fc611e38565b5b60ff168160ff16148484848490919293610950576040517fd9ead46f0000000000000000000000000000000000000000000000000000000081526004016109479493929190611e65565b60405180910390fd5b505050505050505050565b601781565b5f610969610a19565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050919050565b601581565b5f6109ad82610e16565b9050919050565b5f5f60068111156109c8576109c7611e38565b5b60ff166109d786868686610c4e565b60ff16149050949350505050565b5f601560ff168260ff161480610a015750601660ff168260ff16145b80610a125750601760ff168260ff16145b9050919050565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b6060601560ff168260ff1603610a7057604051806060016040528060228152602001612094602291399050610b05565b601660ff168260ff1603610a9e5760405180606001604052806025815260200161206f602591399050610b05565b601760ff168260ff1603610acc5760405180606001604052806023815260200161204c602391399050610b05565b6040518060400160405280601881526020017f556e6b6e6f776e207265737472696374696f6e20636f6465000000000000000081525090505b919050565b7f1b94c92b564251ed6b49246d9a82eb7a486b6490f3b3a3bf3b28d2e99801f3ec610b3481610e68565b610b3d826112bc565b7fe46e95d98efc7b1a5d9359155b9137734ac3be3f4b32eab0f697558c27f2d99c82604051610b6c9190611c44565b60405180910390a15050565b5f610b84848484610c7b565b90505f6006811115610b9957610b98611e38565b5b60ff168160ff16148484848490919293610bec576040517fd9ead46f000000000000000000000000000000000000000000000000000000008152600401610be39493929190611e65565b60405180910390fd5b5050505050505050565b5f610c035f5f1b836113a8565b15610c115760019050610c1e565b610c1b83836113a8565b90505b92915050565b7f1b03c849816e077359373cf0a8d6d8f741d643bc1e95273ffe11515f83bebf6181565b5f5f1b81565b5f610c58856109a3565b610c655760179050610c73565b610c70848484610c7b565b90505b949350505050565b5f610c85846109a3565b610c925760159050610cbe565b610c9b836109a3565b610ca85760169050610cbe565b5f6006811115610cbb57610cba611e38565b5b90505b9392505050565b610cce826107b0565b610cd781610e68565b610ce183836111d3565b50505050565b7f1b03c849816e077359373cf0a8d6d8f741d643bc1e95273ffe11515f83bebf61610d1181610e68565b610d1a8261140b565b7f7802fa8b90d406b2eb85b620cecde734206f390fa73c61e824384474b734cd9382604051610d499190611c44565b60405180910390a15050565b601681565b5f5f6006811115610d6e57610d6d611e38565b5b60ff16610d7c858585610c7b565b60ff161490509392505050565b7f1b94c92b564251ed6b49246d9a82eb7a486b6490f3b3a3bf3b28d2e99801f3ec81565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f60015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b610e7981610e746111c5565b6114f8565b50565b5f60025490505f5f90505b83839050811015610f9a5760015f858584818110610ea857610ea7611d2d565b5b9050602002016020810190610ebd9190611bb5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16610f8f576001805f868685818110610f1e57610f1d611d2d565b5b9050602002016020810190610f339190611bb5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555081610f8c90611ed5565b91505b806001019050610e87565b5080600281905550505050565b5f600254905090565b5f610fbb8383610bf6565b61108f5760015f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555061102c6111c5565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611093565b5f90505b92915050565b5f60025490505f5f90505b838390508110156111b85760015f8585848181106110c5576110c4611d2d565b5b90506020020160208101906110da9190611bb5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16156111ad575f60015f86868581811061113c5761113b611d2d565b5b90506020020160208101906111519190611bb5565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550816111aa90611f1c565b91505b8060010190506110a4565b5080600281905550505050565b5f6111ce611549565b905090565b5f6111de8383610bf6565b156112b2575f5f5f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555061124f6111c5565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a4600190506112b6565b5f90505b92915050565b60015f8273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1661133c576040517fcfc5cc9500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555060025f815461139e90611f1c565b9190508190555050565b5f5f5f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b60015f8273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff161561148c576040517f57845b8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555060025f81546114ee90611ed5565b9190508190555050565b6115028282610bf6565b6115455780826040517fe2517d3f00000000000000000000000000000000000000000000000000000000815260040161153c929190611f43565b60405180910390fd5b5050565b5f5f5f36905090505f61155a6115b1565b9050808210158015611571575061157033610960565b5b156115a1575f3682840390809261158a93929190611f72565b906115959190611fed565b60601c925050506115ae565b6115a96115bf565b925050505b90565b5f6115ba6115c6565b905090565b5f33905090565b5f6014905090565b5f604051905090565b5f5ffd5b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611613816115df565b811461161d575f5ffd5b50565b5f8135905061162e8161160a565b92915050565b5f60208284031215611649576116486115d7565b5b5f61165684828501611620565b91505092915050565b5f8115159050919050565b6116738161165f565b82525050565b5f60208201905061168c5f83018461166a565b92915050565b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6116dc82611696565b810181811067ffffffffffffffff821117156116fb576116fa6116a6565b5b80604052505050565b5f61170d6115ce565b905061171982826116d3565b919050565b5f67ffffffffffffffff821115611738576117376116a6565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6117768261174d565b9050919050565b6117868161176c565b8114611790575f5ffd5b50565b5f813590506117a18161177d565b92915050565b5f6117b96117b48461171e565b611704565b905080838252602082019050602084028301858111156117dc576117db611749565b5b835b8181101561180557806117f18882611793565b8452602084019350506020810190506117de565b5050509392505050565b5f82601f83011261182357611822611692565b5b81356118338482602086016117a7565b91505092915050565b5f60208284031215611851576118506115d7565b5b5f82013567ffffffffffffffff81111561186e5761186d6115db565b5b61187a8482850161180f565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6118b58161165f565b82525050565b5f6118c683836118ac565b60208301905092915050565b5f602082019050919050565b5f6118e882611883565b6118f2818561188d565b93506118fd8361189d565b805f5b8381101561192d57815161191488826118bb565b975061191f836118d2565b925050600181019050611900565b5085935050505092915050565b5f6020820190508181035f83015261195281846118de565b905092915050565b5f5ffd5b5f5f83601f84011261197357611972611692565b5b8235905067ffffffffffffffff8111156119905761198f61195a565b5b6020830191508360208202830111156119ac576119ab611749565b5b9250929050565b5f5f602083850312156119c9576119c86115d7565b5b5f83013567ffffffffffffffff8111156119e6576119e56115db565b5b6119f28582860161195e565b92509250509250929050565b5f819050919050565b611a10816119fe565b82525050565b5f602082019050611a295f830184611a07565b92915050565b5f819050919050565b611a4181611a2f565b8114611a4b575f5ffd5b50565b5f81359050611a5c81611a38565b92915050565b5f60208284031215611a7757611a766115d7565b5b5f611a8484828501611a4e565b91505092915050565b611a9681611a2f565b82525050565b5f602082019050611aaf5f830184611a8d565b92915050565b5f5f60408385031215611acb57611aca6115d7565b5b5f611ad885828601611a4e565b9250506020611ae985828601611793565b9150509250929050565b611afc816119fe565b8114611b06575f5ffd5b50565b5f81359050611b1781611af3565b92915050565b5f5f5f5f60808587031215611b3557611b346115d7565b5b5f611b4287828801611793565b9450506020611b5387828801611793565b9350506040611b6487828801611793565b9250506060611b7587828801611b09565b91505092959194509250565b5f60ff82169050919050565b611b9681611b81565b82525050565b5f602082019050611baf5f830184611b8d565b92915050565b5f60208284031215611bca57611bc96115d7565b5b5f611bd784828501611793565b91505092915050565b611be981611b81565b8114611bf3575f5ffd5b50565b5f81359050611c0481611be0565b92915050565b5f60208284031215611c1f57611c1e6115d7565b5b5f611c2c84828501611bf6565b91505092915050565b611c3e8161176c565b82525050565b5f602082019050611c575f830184611c35565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f611c8f82611c5d565b611c998185611c67565b9350611ca9818560208601611c77565b611cb281611696565b840191505092915050565b5f6020820190508181035f830152611cd58184611c85565b905092915050565b5f5f5f60608486031215611cf457611cf36115d7565b5b5f611d0186828701611793565b9350506020611d1286828701611793565b9250506040611d2386828701611b09565b9150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82825260208201905092915050565b5f819050919050565b611d7c8161176c565b82525050565b5f611d8d8383611d73565b60208301905092915050565b5f611da76020840184611793565b905092915050565b5f602082019050919050565b5f611dc68385611d5a565b9350611dd182611d6a565b805f5b85811015611e0957611de68284611d99565b611df08882611d82565b9750611dfb83611daf565b925050600181019050611dd4565b5085925050509392505050565b5f6020820190508181035f830152611e2f818486611dbb565b90509392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f608082019050611e785f830187611c35565b611e856020830186611c35565b611e926040830185611a07565b611e9f6060830184611b8d565b95945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f611edf826119fe565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611f1157611f10611ea8565b5b600182019050919050565b5f611f26826119fe565b91505f8203611f3857611f37611ea8565b5b600182039050919050565b5f604082019050611f565f830185611c35565b611f636020830184611a8d565b9392505050565b5f5ffd5b5f5ffd5b5f5f85851115611f8557611f84611f6a565b5b83861115611f9657611f95611f6e565b5b6001850283019150848603905094509492505050565b5f82905092915050565b5f7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b5f82821b905092915050565b5f611ff88383611fac565b826120038135611fb6565b925060148210156120435761203e7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000083601403600802611fe1565b831692505b50509291505056fe546865207370656e646572206973206e6f7420696e207468652077686974656c69737454686520726563697069656e74206973206e6f7420696e207468652077686974656c6973745468652073656e646572206973206e6f7420696e207468652077686974656c697374a2646970667358221220c5d9366742fb111255ac42ea02b6428161121fb7b40f452a8bf8a4365b3f041364736f6c634300081e0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol/RuleAddressList.dbg.json b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol/RuleAddressList.dbg.json new file mode 100644 index 0000000..c4bdbe7 --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol/RuleAddressList.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol/RuleAddressList.json b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol/RuleAddressList.json new file mode 100644 index 0000000..22e00ec --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol/RuleAddressList.json @@ -0,0 +1,464 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleAddressList", + "sourceName": "src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol", + "abi": [ + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "RuleAddressList_AdminWithAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "Rulelist_AddressAlreadylisted", + "type": "error" + }, + { + "inputs": [], + "name": "Rulelist_AddressNotPresent", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "AddAddressToTheList", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "listTargetAddresses", + "type": "address[]" + } + ], + "name": "AddAddressesToTheList", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "RemoveAddressFromTheList", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "listTargetAddresses", + "type": "address[]" + } + ], + "name": "RemoveAddressesFromTheList", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "ADDRESS_LIST_ADD_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ADDRESS_LIST_REMOVE_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "addAddressToTheList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "listTargetAddresses", + "type": "address[]" + } + ], + "name": "addAddressesToTheList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_targetAddress", + "type": "address" + } + ], + "name": "addressIsListed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_targetAddresses", + "type": "address[]" + } + ], + "name": "addressIsListedBatch", + "outputs": [ + { + "internalType": "bool[]", + "name": "", + "type": "bool[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isTrustedForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numberListedAddress", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "removeAddressFromTheList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "listTargetAddresses", + "type": "address[]" + } + ], + "name": "removeAddressesFromTheList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "trustedForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol/RuleAddressListInternal.dbg.json b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol/RuleAddressListInternal.dbg.json new file mode 100644 index 0000000..c4bdbe7 --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol/RuleAddressListInternal.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol/RuleAddressListInternal.json b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol/RuleAddressListInternal.json new file mode 100644 index 0000000..85304d6 --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol/RuleAddressListInternal.json @@ -0,0 +1,21 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleAddressListInternal", + "sourceName": "src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol", + "abi": [ + { + "inputs": [], + "name": "Rulelist_AddressAlreadylisted", + "type": "error" + }, + { + "inputs": [], + "name": "Rulelist_AddressNotPresent", + "type": "error" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol/RuleAddressListInvariantStorage.dbg.json b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol/RuleAddressListInvariantStorage.dbg.json new file mode 100644 index 0000000..26657ff --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol/RuleAddressListInvariantStorage.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../../../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol/RuleAddressListInvariantStorage.json b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol/RuleAddressListInvariantStorage.json new file mode 100644 index 0000000..4d9250d --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol/RuleAddressListInvariantStorage.json @@ -0,0 +1,94 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleAddressListInvariantStorage", + "sourceName": "src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol", + "abi": [ + { + "inputs": [], + "name": "RuleAddressList_AdminWithAddressZeroNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "AddAddressToTheList", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "listTargetAddresses", + "type": "address[]" + } + ], + "name": "AddAddressesToTheList", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "RemoveAddressFromTheList", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "listTargetAddresses", + "type": "address[]" + } + ], + "name": "RemoveAddressesFromTheList", + "type": "event" + }, + { + "inputs": [], + "name": "ADDRESS_LIST_ADD_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ADDRESS_LIST_REMOVE_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol/RuleBlacklistInvariantStorage.dbg.json b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol/RuleBlacklistInvariantStorage.dbg.json new file mode 100644 index 0000000..26657ff --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol/RuleBlacklistInvariantStorage.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../../../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol/RuleBlacklistInvariantStorage.json b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol/RuleBlacklistInvariantStorage.json new file mode 100644 index 0000000..4f1de1f --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol/RuleBlacklistInvariantStorage.json @@ -0,0 +1,50 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleBlacklistInvariantStorage", + "sourceName": "src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol", + "abi": [ + { + "inputs": [], + "name": "CODE_ADDRESS_FROM_IS_BLACKLISTED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_ADDRESS_SPENDER_IS_BLACKLISTED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_ADDRESS_TO_IS_BLACKLISTED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol/RuleWhitelistInvariantStorage.dbg.json b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol/RuleWhitelistInvariantStorage.dbg.json new file mode 100644 index 0000000..26657ff --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol/RuleWhitelistInvariantStorage.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../../../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol/RuleWhitelistInvariantStorage.json b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol/RuleWhitelistInvariantStorage.json new file mode 100644 index 0000000..3c24ddf --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol/RuleWhitelistInvariantStorage.json @@ -0,0 +1,50 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleWhitelistInvariantStorage", + "sourceName": "src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol", + "abi": [ + { + "inputs": [], + "name": "CODE_ADDRESS_FROM_NOT_WHITELISTED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_ADDRESS_SPENDER_NOT_WHITELISTED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_ADDRESS_TO_NOT_WHITELISTED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol/RuleCommonInvariantStorage.dbg.json b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol/RuleCommonInvariantStorage.dbg.json new file mode 100644 index 0000000..00f772e --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol/RuleCommonInvariantStorage.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol/RuleCommonInvariantStorage.json b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol/RuleCommonInvariantStorage.json new file mode 100644 index 0000000..6ba6397 --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol/RuleCommonInvariantStorage.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleCommonInvariantStorage", + "sourceName": "src/mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol", + "abi": [], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleWhitelistCommon.sol/RuleWhitelistCommon.dbg.json b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleWhitelistCommon.sol/RuleWhitelistCommon.dbg.json new file mode 100644 index 0000000..00f772e --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleWhitelistCommon.sol/RuleWhitelistCommon.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleWhitelistCommon.sol/RuleWhitelistCommon.json b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleWhitelistCommon.sol/RuleWhitelistCommon.json new file mode 100644 index 0000000..43733dd --- /dev/null +++ b/doc/compilation/hardhat/src/mocks/rules/validation/abstract/RuleWhitelistCommon.sol/RuleWhitelistCommon.json @@ -0,0 +1,265 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleWhitelistCommon", + "sourceName": "src/mocks/rules/validation/abstract/RuleWhitelistCommon.sol", + "abi": [ + { + "inputs": [], + "name": "CODE_ADDRESS_FROM_NOT_WHITELISTED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_ADDRESS_SPENDER_NOT_WHITELISTED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_ADDRESS_TO_NOT_WHITELISTED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "canReturnTransferRestrictionCode", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestriction", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestrictionFrom", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "messageForTransferRestriction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/modules/ERC2771ModuleStandalone.sol/ERC2771ModuleStandalone.dbg.json b/doc/compilation/hardhat/src/modules/ERC2771ModuleStandalone.sol/ERC2771ModuleStandalone.dbg.json new file mode 100644 index 0000000..30bf738 --- /dev/null +++ b/doc/compilation/hardhat/src/modules/ERC2771ModuleStandalone.sol/ERC2771ModuleStandalone.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/modules/ERC2771ModuleStandalone.sol/ERC2771ModuleStandalone.json b/doc/compilation/hardhat/src/modules/ERC2771ModuleStandalone.sol/ERC2771ModuleStandalone.json new file mode 100644 index 0000000..3db37a7 --- /dev/null +++ b/doc/compilation/hardhat/src/modules/ERC2771ModuleStandalone.sol/ERC2771ModuleStandalone.json @@ -0,0 +1,43 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC2771ModuleStandalone", + "sourceName": "src/modules/ERC2771ModuleStandalone.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isTrustedForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "trustedForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/modules/ERC3643ComplianceModule.sol/ERC3643ComplianceModule.dbg.json b/doc/compilation/hardhat/src/modules/ERC3643ComplianceModule.sol/ERC3643ComplianceModule.dbg.json new file mode 100644 index 0000000..30bf738 --- /dev/null +++ b/doc/compilation/hardhat/src/modules/ERC3643ComplianceModule.sol/ERC3643ComplianceModule.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/modules/ERC3643ComplianceModule.sol/ERC3643ComplianceModule.json b/doc/compilation/hardhat/src/modules/ERC3643ComplianceModule.sol/ERC3643ComplianceModule.json new file mode 100644 index 0000000..021c6e0 --- /dev/null +++ b/doc/compilation/hardhat/src/modules/ERC3643ComplianceModule.sol/ERC3643ComplianceModule.json @@ -0,0 +1,459 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC3643ComplianceModule", + "sourceName": "src/modules/ERC3643ComplianceModule.sol", + "abi": [ + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_ERC3643Compliance_InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_ERC3643Compliance_OperationNotSuccessful", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_ERC3643Compliance_TokenAlreadyBound", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_ERC3643Compliance_TokenNotBound", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_ERC3643Compliance_UnauthorizedCaller", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenBound", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenUnbound", + "type": "event" + }, + { + "inputs": [], + "name": "COMPLIANCE_MANAGER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "bindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "created", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "destroyed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBound", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBounds", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenBound", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unbindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/modules/RulesManagementModule.sol/RulesManagementModule.dbg.json b/doc/compilation/hardhat/src/modules/RulesManagementModule.sol/RulesManagementModule.dbg.json new file mode 100644 index 0000000..30bf738 --- /dev/null +++ b/doc/compilation/hardhat/src/modules/RulesManagementModule.sol/RulesManagementModule.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/modules/RulesManagementModule.sol/RulesManagementModule.json b/doc/compilation/hardhat/src/modules/RulesManagementModule.sol/RulesManagementModule.json new file mode 100644 index 0000000..3e54488 --- /dev/null +++ b/doc/compilation/hardhat/src/modules/RulesManagementModule.sol/RulesManagementModule.json @@ -0,0 +1,416 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RulesManagementModule", + "sourceName": "src/modules/RulesManagementModule.sol", + "abi": [ + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_ArrayIsEmpty", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_OperationNotSuccessful", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleDoNotMatch", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "AddRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ClearRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "RemoveRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RULES_MANAGEMENT_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "addRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clearRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "containsRule", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "removeRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "ruleId", + "type": "uint256" + } + ], + "name": "rule", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rules", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rulesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule[]", + "name": "rules_", + "type": "address[]" + } + ], + "name": "setRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/modules/VersionModule.sol/VersionModule.dbg.json b/doc/compilation/hardhat/src/modules/VersionModule.sol/VersionModule.dbg.json new file mode 100644 index 0000000..30bf738 --- /dev/null +++ b/doc/compilation/hardhat/src/modules/VersionModule.sol/VersionModule.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/modules/VersionModule.sol/VersionModule.json b/doc/compilation/hardhat/src/modules/VersionModule.sol/VersionModule.json new file mode 100644 index 0000000..dfa523f --- /dev/null +++ b/doc/compilation/hardhat/src/modules/VersionModule.sol/VersionModule.json @@ -0,0 +1,24 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "VersionModule", + "sourceName": "src/modules/VersionModule.sol", + "abi": [ + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "version_", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/modules/library/RuleEngineInvariantStorage.sol/RuleEngineInvariantStorage.dbg.json b/doc/compilation/hardhat/src/modules/library/RuleEngineInvariantStorage.sol/RuleEngineInvariantStorage.dbg.json new file mode 100644 index 0000000..cb2dc52 --- /dev/null +++ b/doc/compilation/hardhat/src/modules/library/RuleEngineInvariantStorage.sol/RuleEngineInvariantStorage.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/modules/library/RuleEngineInvariantStorage.sol/RuleEngineInvariantStorage.json b/doc/compilation/hardhat/src/modules/library/RuleEngineInvariantStorage.sol/RuleEngineInvariantStorage.json new file mode 100644 index 0000000..6162b92 --- /dev/null +++ b/doc/compilation/hardhat/src/modules/library/RuleEngineInvariantStorage.sol/RuleEngineInvariantStorage.json @@ -0,0 +1,16 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleEngineInvariantStorage", + "sourceName": "src/modules/library/RuleEngineInvariantStorage.sol", + "abi": [ + { + "inputs": [], + "name": "RuleEngine_AdminWithAddressZeroNotAllowed", + "type": "error" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/hardhat/src/modules/library/RulesManagementModuleInvariantStorage.sol/RulesManagementModuleInvariantStorage.dbg.json b/doc/compilation/hardhat/src/modules/library/RulesManagementModuleInvariantStorage.sol/RulesManagementModuleInvariantStorage.dbg.json new file mode 100644 index 0000000..cb2dc52 --- /dev/null +++ b/doc/compilation/hardhat/src/modules/library/RulesManagementModuleInvariantStorage.sol/RulesManagementModuleInvariantStorage.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../build-info/0d8630f2c04bc3d6d290fc92cebd01e5.json" +} diff --git a/doc/compilation/hardhat/src/modules/library/RulesManagementModuleInvariantStorage.sol/RulesManagementModuleInvariantStorage.json b/doc/compilation/hardhat/src/modules/library/RulesManagementModuleInvariantStorage.sol/RulesManagementModuleInvariantStorage.json new file mode 100644 index 0000000..74d32fe --- /dev/null +++ b/doc/compilation/hardhat/src/modules/library/RulesManagementModuleInvariantStorage.sol/RulesManagementModuleInvariantStorage.json @@ -0,0 +1,81 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RulesManagementModuleInvariantStorage", + "sourceName": "src/modules/library/RulesManagementModuleInvariantStorage.sol", + "abi": [ + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_ArrayIsEmpty", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_OperationNotSuccessful", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleDoNotMatch", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "AddRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ClearRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "RemoveRule", + "type": "event" + }, + { + "inputs": [], + "name": "RULES_MANAGEMENT_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/coverage/code-coverage.png b/doc/coverage/code-coverage.png new file mode 100644 index 0000000..198329f Binary files /dev/null and b/doc/coverage/code-coverage.png differ diff --git a/doc/coverage/coverage/index-sort-b.html b/doc/coverage/coverage/index-sort-b.html index 79c22e9..840a305 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 % + 123 + 125 + 98.4 % Date: - 2024-12-20 10:41:14 + 2025-08-15 12:12:38 Functions: - 117 - 125 - 93.6 % + 33 + 34 + 97.1 % Branches: - 126 - 128 - 98.4 % + 29 + 34 + 85.3 % @@ -81,125 +81,29 @@ Functions Sort by function coverage Branches Sort by branch coverage - - script - -
0.0%
- - 0.0 % - 0 / 26 - 0.0 % - 0 / 2 - 0.0 % - 0 / 2 - - - 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 - - - src/rules/validation/abstract - -
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 - 100.0 % - 12 / 12 - - - src/rules/operation/abstract - -
100.0%
- - 100.0 % - 113 / 113 - 100.0 % - 20 / 20 + 73 / 73 100.0 % - 31 / 31 + 21 / 21 + 81.5 % + 22 / 27 - src/rules/validation - -
97.3%97.3%
- - 97.3 % - 72 / 74 - 90.9 % - 20 / 22 - 100.0 % - 32 / 32 - - - src/rules/operation + src -
99.1%99.1%
+
96.2%96.2%
- 99.1 % - 105 / 106 - 94.4 % - 17 / 18 + 96.2 % + 50 / 52 + 92.3 % + 12 / 13 100.0 % - 33 / 33 + 7 / 7 diff --git a/doc/coverage/coverage/index-sort-f.html b/doc/coverage/coverage/index-sort-f.html index 4c104bd..15b6e4d 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 % + 123 + 125 + 98.4 % Date: - 2024-12-20 10:41:14 + 2025-08-15 12:12:38 Functions: - 117 - 125 - 93.6 % + 33 + 34 + 97.1 % Branches: - 126 - 128 - 98.4 % + 29 + 34 + 85.3 % @@ -81,113 +81,17 @@ Functions Sort by function coverage Branches Sort by branch coverage - - script - -
0.0%
- - 0.0 % - 0 / 26 - 0.0 % - 0 / 2 - 0.0 % - 0 / 2 - - - test/utils - -
85.7%85.7%
- - 85.7 % - 6 / 7 - 80.0 % - 4 / 5 - - - 0 / 0 - src -
97.4%97.4%
- - 97.4 % - 38 / 39 - 88.9 % - 8 / 9 - 100.0 % - 8 / 8 - - - src/rules/validation - -
97.3%97.3%
+
96.2%96.2%
- 97.3 % - 72 / 74 - 90.9 % - 20 / 22 + 96.2 % + 50 / 52 + 92.3 % + 12 / 13 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%
- - 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 - -
100.0%
- - 100.0 % - 113 / 113 - 100.0 % - 20 / 20 - 100.0 % - 31 / 31 + 7 / 7 src/modules @@ -195,11 +99,11 @@
100.0%
100.0 % - 81 / 81 - 100.0 % - 27 / 27 + 73 / 73 100.0 % - 12 / 12 + 21 / 21 + 81.5 % + 22 / 27 diff --git a/doc/coverage/coverage/index-sort-l.html b/doc/coverage/coverage/index-sort-l.html index f352c82..4273893 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 % + 123 + 125 + 98.4 % Date: - 2024-12-20 10:41:14 + 2025-08-15 12:12:38 Functions: - 117 - 125 - 93.6 % + 33 + 34 + 97.1 % Branches: - 126 - 128 - 98.4 % + 29 + 34 + 85.3 % @@ -81,101 +81,17 @@ Functions Sort by function coverage Branches Sort by branch coverage - - script - -
0.0%
- - 0.0 % - 0 / 26 - 0.0 % - 0 / 2 - 0.0 % - 0 / 2 - - - test/utils - -
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%
+
96.2%96.2%
- 97.4 % - 38 / 39 - 88.9 % - 8 / 9 + 96.2 % + 50 / 52 + 92.3 % + 12 / 13 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%
- - 100.0 % - 10 / 10 - 100.0 % - 3 / 3 - 100.0 % - 4 / 4 - - - test/RuleConditionalTransfer/utils - -
100.0%
- - 100.0 % - 10 / 10 - 100.0 % - 1 / 1 - - - 0 / 0 + 7 / 7 src/modules @@ -183,23 +99,11 @@
100.0%
100.0 % - 81 / 81 - 100.0 % - 27 / 27 - 100.0 % - 12 / 12 - - - src/rules/operation/abstract - -
100.0%
- - 100.0 % - 113 / 113 - 100.0 % - 20 / 20 + 73 / 73 100.0 % - 31 / 31 + 21 / 21 + 81.5 % + 22 / 27 diff --git a/doc/coverage/coverage/index.html b/doc/coverage/coverage/index.html index 92f429f..41a2530 100644 --- a/doc/coverage/coverage/index.html +++ b/doc/coverage/coverage/index.html @@ -31,27 +31,27 @@ lcov.info Lines: - 479 - 511 - 93.7 % + 123 + 125 + 98.4 % Date: - 2024-12-20 10:41:14 + 2025-08-15 12:12:38 Functions: - 117 - 125 - 93.6 % + 33 + 34 + 97.1 % Branches: - 126 - 128 - 98.4 % + 29 + 34 + 85.3 % @@ -81,29 +81,17 @@ Functions Sort by function coverage 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%
+
96.2%96.2%
- 97.4 % - 38 / 39 - 88.9 % - 8 / 9 + 96.2 % + 50 / 52 + 92.3 % + 12 / 13 100.0 % - 8 / 8 + 7 / 7 src/modules @@ -111,95 +99,11 @@
100.0%
100.0 % - 81 / 81 - 100.0 % - 27 / 27 - 100.0 % - 12 / 12 - - - src/rules/operation - -
99.1%99.1%
- - 99.1 % - 105 / 106 - 94.4 % - 17 / 18 - 100.0 % - 33 / 33 - - - src/rules/operation/abstract - -
100.0%
- - 100.0 % - 113 / 113 - 100.0 % - 20 / 20 + 73 / 73 100.0 % - 31 / 31 - - - src/rules/validation - -
97.3%97.3%
- - 97.3 % - 72 / 74 - 90.9 % - 20 / 22 - 100.0 % - 32 / 32 - - - src/rules/validation/abstract - -
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 - - - 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 + 21 / 21 + 81.5 % + 22 / 27 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/RuleEngine.sol.func-sort-c.html b/doc/coverage/coverage/src/RuleEngine.sol.func-sort-c.html index eabf2d9..75b792f 100644 --- a/doc/coverage/coverage/src/RuleEngine.sol.func-sort-c.html +++ b/doc/coverage/coverage/src/RuleEngine.sol.func-sort-c.html @@ -31,26 +31,26 @@ lcov.info Lines: - 38 - 39 - 97.4 % + 10 + 12 + 83.3 % Date: - 2024-12-20 10:41:14 + 2025-08-15 12:12:38 Functions: - 8 - 9 - 88.9 % + 3 + 4 + 75.0 % Branches: - 8 - 8 + 2 + 2 100.0 % @@ -69,40 +69,20 @@ Hit count Sort by hit count - RuleEngine._msgData + RuleEngine._msgData 0 - RuleEngine.validateTransfer - 12 + RuleEngine.constructor + 90 - RuleEngine.messageForTransferRestriction - 18 + RuleEngine._contextSuffixLength + 300 - RuleEngine.detectTransferRestriction - 20 - - - RuleEngine.operateOnTransfer - 69 - - - RuleEngine. - 205 - - - RuleEngine.hasRole - 299 - - - RuleEngine._contextSuffixLength - 588 - - - RuleEngine._msgSender - 588 + RuleEngine._msgSender + 300
diff --git a/doc/coverage/coverage/src/RuleEngine.sol.func.html b/doc/coverage/coverage/src/RuleEngine.sol.func.html index f12d35b..20dc8f4 100644 --- a/doc/coverage/coverage/src/RuleEngine.sol.func.html +++ b/doc/coverage/coverage/src/RuleEngine.sol.func.html @@ -31,26 +31,26 @@ lcov.info Lines: - 38 - 39 - 97.4 % + 10 + 12 + 83.3 % Date: - 2024-12-20 10:41:14 + 2025-08-15 12:12:38 Functions: - 8 - 9 - 88.9 % + 3 + 4 + 75.0 % Branches: - 8 - 8 + 2 + 2 100.0 % @@ -69,40 +69,20 @@ Hit count Sort by hit count - RuleEngine. - 205 + RuleEngine._contextSuffixLength + 300 - RuleEngine._contextSuffixLength - 588 - - - RuleEngine._msgData + RuleEngine._msgData 0 - RuleEngine._msgSender - 588 - - - RuleEngine.detectTransferRestriction - 20 - - - RuleEngine.hasRole - 299 - - - RuleEngine.messageForTransferRestriction - 18 - - - RuleEngine.operateOnTransfer - 69 + RuleEngine._msgSender + 300 - RuleEngine.validateTransfer - 12 + RuleEngine.constructor + 90
diff --git a/doc/coverage/coverage/src/RuleEngine.sol.gcov.html b/doc/coverage/coverage/src/RuleEngine.sol.gcov.html index b32d492..3ef64f3 100644 --- a/doc/coverage/coverage/src/RuleEngine.sol.gcov.html +++ b/doc/coverage/coverage/src/RuleEngine.sol.gcov.html @@ -31,26 +31,26 @@ lcov.info Lines: - 38 - 39 - 97.4 % + 10 + 12 + 83.3 % Date: - 2024-12-20 10:41:14 + 2025-08-15 12:12:38 Functions: - 8 - 9 - 88.9 % + 3 + 4 + 75.0 % Branches: - 8 - 8 + 2 + 2 100.0 % @@ -73,204 +73,80 @@ 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 : : } - 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 : : } + 5 : : /* ==== OpenZeppelin === */ + 6 : : import {Context} from "OZ/utils/Context.sol"; + 7 : : /* ==== Modules === */ + 8 : : import {ERC2771ModuleStandalone, ERC2771Context} from "./modules/ERC2771ModuleStandalone.sol"; + 9 : : /* ==== Base contract === */ + 10 : : import {RuleEngineBase} from "./RuleEngineBase.sol"; + 11 : : /** + 12 : : * @title Implementation of a ruleEngine as defined by the CMTAT + 13 : : */ + 14 : : contract RuleEngine is + 15 : : ERC2771ModuleStandalone, + 16 : : RuleEngineBase + 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 : 90 : constructor( + 23 : : address admin, + 24 : : address forwarderIrrevocable, + 25 : : address tokenContract + 26 : : ) ERC2771ModuleStandalone(forwarderIrrevocable) { + 27 [ + ]: 90 : if (admin == address(0)) { + 28 : 1 : revert RuleEngine_AdminWithAddressZeroNotAllowed(); + 29 : : } + 30 [ + ]: 89 : if (tokenContract != address(0)) { + 31 : 15 : _bindToken(tokenContract); + 32 : : } + 33 : 89 : _grantRole(DEFAULT_ADMIN_ROLE, admin); + 34 : : } + 35 : : + 36 : : /*////////////////////////////////////////////////////////////// + 37 : : ERC-2771 + 38 : : //////////////////////////////////////////////////////////////*/ + 39 : : + 40 : : /** + 41 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 42 : : */ + 43 : 300 : function _msgSender() + 44 : : internal + 45 : : view + 46 : : virtual + 47 : : override(ERC2771Context, Context) + 48 : : returns (address sender) + 49 : : { + 50 : 300 : return ERC2771Context._msgSender(); + 51 : : } + 52 : : + 53 : : /** + 54 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 55 : : */ + 56 : 0 : function _msgData() + 57 : : internal + 58 : : view + 59 : : virtual + 60 : : override(ERC2771Context, Context) + 61 : : returns (bytes calldata) + 62 : : { + 63 : 0 : return ERC2771Context._msgData(); + 64 : : } + 65 : : + 66 : : /** + 67 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 68 : : */ + 69 : 300 : function _contextSuffixLength() + 70 : : internal + 71 : : view + 72 : : virtual + 73 : : override(ERC2771Context, Context) + 74 : : returns (uint256) + 75 : : { + 76 : 300 : return ERC2771Context._contextSuffixLength(); + 77 : : } + 78 : : } diff --git a/doc/coverage/coverage/src/RuleEngineBase.sol.func-sort-c.html b/doc/coverage/coverage/src/RuleEngineBase.sol.func-sort-c.html new file mode 100644 index 0000000..e98ecbd --- /dev/null +++ b/doc/coverage/coverage/src/RuleEngineBase.sol.func-sort-c.html @@ -0,0 +1,117 @@ + + + + + + + LCOV - lcov.info - src/RuleEngineBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src - RuleEngineBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:4040100.0 %
Date:2025-08-15 12:12:38Functions:99100.0 %
Branches:55100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleEngineBase.created2
RuleEngineBase.destroyed2
RuleEngineBase.detectTransferRestrictionFrom11
RuleEngineBase.transferred12
RuleEngineBase.messageForTransferRestriction13
RuleEngineBase.canTransferFrom14
RuleEngineBase.canTransfer18
RuleEngineBase.detectTransferRestriction21
RuleEngineBase.hasRole98
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/src/RuleEngineBase.sol.func.html b/doc/coverage/coverage/src/RuleEngineBase.sol.func.html new file mode 100644 index 0000000..8a30502 --- /dev/null +++ b/doc/coverage/coverage/src/RuleEngineBase.sol.func.html @@ -0,0 +1,117 @@ + + + + + + + LCOV - lcov.info - src/RuleEngineBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src - RuleEngineBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:4040100.0 %
Date:2025-08-15 12:12:38Functions:99100.0 %
Branches:55100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleEngineBase.canTransfer18
RuleEngineBase.canTransferFrom14
RuleEngineBase.created2
RuleEngineBase.destroyed2
RuleEngineBase.detectTransferRestriction21
RuleEngineBase.detectTransferRestrictionFrom11
RuleEngineBase.hasRole98
RuleEngineBase.messageForTransferRestriction13
RuleEngineBase.transferred12
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html b/doc/coverage/coverage/src/RuleEngineBase.sol.gcov.html similarity index 55% rename from doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html rename to doc/coverage/coverage/src/RuleEngineBase.sol.gcov.html index 2cd242c..bdd45c3 100644 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html +++ b/doc/coverage/coverage/src/RuleEngineBase.sol.gcov.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol - + LCOV - lcov.info - src/RuleEngineBase.sol + - + - +
LCOV - code coverage report
- + @@ -31,34 +31,34 @@ - - - + + + - + - - - + + + - - + + - +
Current view:top level - src/rules/validation/abstract/RuleAddressList - RuleAddressList.sol (source / functions)top level - src - RuleEngineBase.sol (source / functions) Hitlcov.info Lines:222395.7 %4040100.0 %
Date:2024-12-20 10:41:142025-08-15 12:12:38 Functions:111291.7 %99100.0 %
Branches:2255 100.0 %
@@ -73,176 +73,176 @@ 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 : : * - 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(); + 5 : : /* ==== OpenZeppelin === */ + 6 : : import {AccessControl} from "OZ/access/AccessControl.sol"; + 7 : : /* ==== CMTAT === */ + 8 : : import {IRuleEngine}from "CMTAT/interfaces/engine/IRuleEngine.sol"; + 9 : : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; + 10 : : import {IERC3643ComplianceRead, IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; + 11 : : import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol"; + 12 : : + 13 : : /* ==== Modules === */ + 14 : : import {ERC3643ComplianceModule, IERC3643Compliance} from "./modules/ERC3643ComplianceModule.sol"; + 15 : : import {VersionModule} from "./modules/VersionModule.sol"; + 16 : : import {RulesManagementModule} from "./modules/RulesManagementModule.sol"; + 17 : : + 18 : : /* ==== Interface and other library === */ + 19 : : import {IRule} from "./interfaces/IRule.sol"; + 20 : : import {RuleEngineInvariantStorage} from "./modules/library/RuleEngineInvariantStorage.sol"; + 21 : : /** + 22 : : * @title Implementation of a ruleEngine as defined by the CMTAT + 23 : : */ + 24 : : abstract contract RuleEngineBase is + 25 : : VersionModule, + 26 : : RulesManagementModule, + 27 : : ERC3643ComplianceModule, + 28 : : RuleEngineInvariantStorage, + 29 : : IRuleEngine + 30 : : { + 31 : : /* ============ State functions ============ */ + 32 : : /* + 33 : : * @inheritdoc IRuleEngine + 34 : : */ + 35 : 3 : function transferred( + 36 : : address spender, + 37 : : address from, + 38 : : address to, + 39 : : uint256 value + 40 : : ) public virtual override(IRuleEngine) onlyBoundToken { + 41 : : // Apply on RuleEngine + 42 : 2 : RulesManagementModule._transferred(spender, from, to, value); + 43 : : } + 44 : : + 45 : : /** + 46 : : * @inheritdoc IERC3643IComplianceContract + 47 : : */ + 48 : 9 : function transferred( + 49 : : address from, + 50 : : address to, + 51 : : uint256 value + 52 : : ) public virtual override(IERC3643IComplianceContract) onlyBoundToken { + 53 : 8 : _transferred(from, to, value); + 54 : : } + 55 : : + 56 : : /// @inheritdoc IERC3643Compliance + 57 : 2 : function created(address to, uint256 value) public virtual override(IERC3643Compliance) onlyBoundToken{ + 58 : 1 : _transferred(address(0), to, value); + 59 : : } + 60 : : + 61 : : /// @inheritdoc IERC3643Compliance + 62 : 2 : function destroyed(address from, uint256 value) public virtual override(IERC3643Compliance) onlyBoundToken { + 63 : 1 : _transferred(from, address(0), value); + 64 : : } + 65 : : + 66 : : + 67 : : + 68 : : /* ============ View functions ============ */ + 69 : : /** + 70 : : * @notice Go through all the rule to know if a restriction exists on the transfer + 71 : : * @param from the origin address + 72 : : * @param to the destination address + 73 : : * @param value to transfer + 74 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid + 75 : : **/ + 76 : 21 : function detectTransferRestriction( + 77 : : address from, + 78 : : address to, + 79 : : uint256 value + 80 : : ) public view virtual override returns (uint8) { + 81 : 39 : uint256 rulesLength = rulesCount(); + 82 : 39 : for (uint256 i = 0; i < rulesLength; ++i) { + 83 : 39 : uint8 restriction = IRule(rule(i)) + 84 : : .detectTransferRestriction(from, to, value); + 85 [ + ]: 39 : if (restriction > 0) { + 86 : 28 : return restriction; + 87 : : } + 88 : : } + 89 : 11 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 90 : : } + 91 : : + 92 : : /** + 93 : : * @inheritdoc IERC1404Extend + 94 : : */ + 95 : 11 : function detectTransferRestrictionFrom( + 96 : : address spender, + 97 : : address from, + 98 : : address to, + 99 : : uint256 value + 100 : : ) public view virtual override(IERC1404Extend) returns (uint8) { + 101 : 25 : uint256 rulesLength = rulesCount(); + 102 : 25 : for (uint256 i = 0; i < rulesLength; ++i) { + 103 : 25 : uint8 restriction = IRule(rule(i)) + 104 : : .detectTransferRestrictionFrom(spender,from, to, value); + 105 [ + ]: 25 : if (restriction > 0) { + 106 : 19 : return restriction; + 107 : : } + 108 : : } + 109 : : + 110 : 6 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 111 : : } + 112 : : + 113 : : /** + 114 : : * @inheritdoc IERC1404 + 115 : : */ + 116 : 13 : function messageForTransferRestriction( + 117 : : uint8 restrictionCode + 118 : : ) public virtual view override(IERC1404) returns (string memory) { + 119 : : // + 120 : 13 : uint256 rulesLength = rulesCount(); + 121 : 13 : for (uint256 i = 0; i < rulesLength; ++i) { + 122 : : if ( + 123 : 10 : IRule(rule(i)) + 124 : : .canReturnTransferRestrictionCode(restrictionCode) + 125 [ + ]: 8 : ) { + 126 : 8 : return + 127 : 8 : IRule(rule(i)) + 128 : : .messageForTransferRestriction(restrictionCode); + 129 : : } + 130 : : } + 131 : 5 : return "Unknown restriction code"; + 132 : : } + 133 : : + 134 : : /** + 135 : : * @inheritdoc IERC3643ComplianceRead + 136 : : */ + 137 : 18 : function canTransfer( + 138 : : address from, + 139 : : address to, + 140 : : uint256 value + 141 : : ) public virtual view override(IERC3643ComplianceRead) returns (bool) { + 142 : 18 : return + 143 : 18 : detectTransferRestriction(from, to, value) == + 144 : : uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 145 : : } + 146 : : + 147 : : /** + 148 : : * @inheritdoc IERC7551Compliance + 149 : : */ + 150 : 14 : function canTransferFrom( + 151 : : address spender, + 152 : : address from, + 153 : : address to, + 154 : : uint256 value + 155 : : ) public virtual view override(IERC7551Compliance) returns (bool) { + 156 : 14 : return + 157 : 14 : detectTransferRestrictionFrom(spender, from, to, value) == + 158 : : uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 159 : : } + 160 : : + 161 : : /* ============ ACCESS CONTROL ============ */ + 162 : : /** + 163 : : * @notice Returns `true` if `account` has been granted `role`. + 164 : : * @dev The Default Admin has all roles + 165 : : */ + 166 : 98 : function hasRole( + 167 : : bytes32 role, + 168 : : address account + 169 : : ) public view virtual override(AccessControl) returns (bool) { + 170 [ + + ]: 293 : if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { + 171 : 165 : return true; + 172 : : } else { + 173 : 128 : return AccessControl.hasRole(role, account); + 174 : : } 175 : : } 176 : : } @@ -252,7 +252,7 @@
- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/src/index-sort-b.html b/doc/coverage/coverage/src/index-sort-b.html index 576ca6d..0f079e8 100644 --- a/doc/coverage/coverage/src/index-sort-b.html +++ b/doc/coverage/coverage/src/index-sort-b.html @@ -31,26 +31,26 @@ lcov.info Lines: - 38 - 39 - 97.4 % + 50 + 52 + 96.2 % Date: - 2024-12-20 10:41:14 + 2025-08-15 12:12:38 Functions: - 8 - 9 - 88.9 % + 12 + 13 + 92.3 % Branches: - 8 - 8 + 7 + 7 100.0 % @@ -84,14 +84,26 @@ RuleEngine.sol -
97.4%97.4%
+
83.3%83.3%
- 97.4 % - 38 / 39 - 88.9 % - 8 / 9 + 83.3 % + 10 / 12 + 75.0 % + 3 / 4 100.0 % - 8 / 8 + 2 / 2 + + + RuleEngineBase.sol + +
100.0%
+ + 100.0 % + 40 / 40 + 100.0 % + 9 / 9 + 100.0 % + 5 / 5 diff --git a/doc/coverage/coverage/src/index-sort-f.html b/doc/coverage/coverage/src/index-sort-f.html index 8962246..ae9a17d 100644 --- a/doc/coverage/coverage/src/index-sort-f.html +++ b/doc/coverage/coverage/src/index-sort-f.html @@ -31,26 +31,26 @@ lcov.info Lines: - 38 - 39 - 97.4 % + 50 + 52 + 96.2 % Date: - 2024-12-20 10:41:14 + 2025-08-15 12:12:38 Functions: - 8 - 9 - 88.9 % + 12 + 13 + 92.3 % Branches: - 8 - 8 + 7 + 7 100.0 % @@ -84,14 +84,26 @@ RuleEngine.sol -
97.4%97.4%
+
83.3%83.3%
- 97.4 % - 38 / 39 - 88.9 % - 8 / 9 + 83.3 % + 10 / 12 + 75.0 % + 3 / 4 100.0 % - 8 / 8 + 2 / 2 + + + RuleEngineBase.sol + +
100.0%
+ + 100.0 % + 40 / 40 + 100.0 % + 9 / 9 + 100.0 % + 5 / 5 diff --git a/doc/coverage/coverage/src/index-sort-l.html b/doc/coverage/coverage/src/index-sort-l.html index f6e4883..cb7432b 100644 --- a/doc/coverage/coverage/src/index-sort-l.html +++ b/doc/coverage/coverage/src/index-sort-l.html @@ -31,26 +31,26 @@ lcov.info Lines: - 38 - 39 - 97.4 % + 50 + 52 + 96.2 % Date: - 2024-12-20 10:41:14 + 2025-08-15 12:12:38 Functions: - 8 - 9 - 88.9 % + 12 + 13 + 92.3 % Branches: - 8 - 8 + 7 + 7 100.0 % @@ -84,14 +84,26 @@ RuleEngine.sol -
97.4%97.4%
+
83.3%83.3%
- 97.4 % - 38 / 39 - 88.9 % - 8 / 9 + 83.3 % + 10 / 12 + 75.0 % + 3 / 4 100.0 % - 8 / 8 + 2 / 2 + + + RuleEngineBase.sol + +
100.0%
+ + 100.0 % + 40 / 40 + 100.0 % + 9 / 9 + 100.0 % + 5 / 5 diff --git a/doc/coverage/coverage/src/index.html b/doc/coverage/coverage/src/index.html index 0762168..2129358 100644 --- a/doc/coverage/coverage/src/index.html +++ b/doc/coverage/coverage/src/index.html @@ -31,26 +31,26 @@ lcov.info Lines: - 38 - 39 - 97.4 % + 50 + 52 + 96.2 % Date: - 2024-12-20 10:41:14 + 2025-08-15 12:12:38 Functions: - 8 - 9 - 88.9 % + 12 + 13 + 92.3 % Branches: - 8 - 8 + 7 + 7 100.0 % @@ -84,14 +84,26 @@ RuleEngine.sol -
97.4%97.4%
+
83.3%83.3%
- 97.4 % - 38 / 39 - 88.9 % - 8 / 9 + 83.3 % + 10 / 12 + 75.0 % + 3 / 4 100.0 % - 8 / 8 + 2 / 2 + + + RuleEngineBase.sol + +
100.0%
+ + 100.0 % + 40 / 40 + 100.0 % + 9 / 9 + 100.0 % + 5 / 5 diff --git a/doc/coverage/coverage/src/modules/RuleInternal.sol.func-sort-c.html b/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func-sort-c.html similarity index 56% rename from doc/coverage/coverage/src/modules/RuleInternal.sol.func-sort-c.html rename to doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func-sort-c.html index 7456c15..5bda21a 100644 --- a/doc/coverage/coverage/src/modules/RuleInternal.sol.func-sort-c.html +++ b/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func-sort-c.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src/modules/RuleInternal.sol - functions + LCOV - lcov.info - src/modules/ERC3643ComplianceModule.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,17 +31,17 @@ - - + + - + - - + + @@ -49,9 +49,9 @@ - - - + + +
Current view:top level - src/modules - RuleInternal.sol (source / functions)top level - src/modules - ERC3643ComplianceModule.sol (source / functions) Hitlcov.info Lines:29292424 100.0 %
Date:2024-12-20 10:41:142025-08-15 12:12:38 Functions:4488 100.0 %
Branches:88100.0 %111384.6 %
@@ -65,24 +65,40 @@ - + - - + + + + + + - - + + + + + + + + + + + + + + - - + + - - + +

Function Name Sort by function nameFunction Name Sort by function name Hit count Sort by hit count
RuleInternal._getRuleIndex6ERC3643ComplianceModule.getTokenBound2
ERC3643ComplianceModule.getTokenBounds2
RuleInternal._setRules32ERC3643ComplianceModule.onlyBoundToken3
ERC3643ComplianceModule._unbindToken4
ERC3643ComplianceModule.unbindToken4
ERC3643ComplianceModule.isTokenBound6
RuleInternal._removeRule55ERC3643ComplianceModule.bindToken11
RuleInternal._addRule203ERC3643ComplianceModule._bindToken26

diff --git a/doc/coverage/coverage/src/modules/RuleInternal.sol.func.html b/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func.html similarity index 56% rename from doc/coverage/coverage/src/modules/RuleInternal.sol.func.html rename to doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func.html index 239df15..cc97af1 100644 --- a/doc/coverage/coverage/src/modules/RuleInternal.sol.func.html +++ b/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src/modules/RuleInternal.sol - functions + LCOV - lcov.info - src/modules/ERC3643ComplianceModule.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,17 +31,17 @@ - - + + - + - - + + @@ -49,9 +49,9 @@ - - - + + +
Current view:top level - src/modules - RuleInternal.sol (source / functions)top level - src/modules - ERC3643ComplianceModule.sol (source / functions) Hitlcov.info Lines:29292424 100.0 %
Date:2024-12-20 10:41:142025-08-15 12:12:38 Functions:4488 100.0 %
Branches:88100.0 %111384.6 %
@@ -66,23 +66,39 @@
Function Name Sort by function name - Hit count Sort by hit count + Hit count Sort by hit count - RuleInternal._addRule - 203 + ERC3643ComplianceModule._bindToken + 26 + + + ERC3643ComplianceModule._unbindToken + 4 + + + ERC3643ComplianceModule.bindToken + 11 + + + ERC3643ComplianceModule.getTokenBound + 2 + + + ERC3643ComplianceModule.getTokenBounds + 2 - RuleInternal._getRuleIndex + ERC3643ComplianceModule.isTokenBound 6 - RuleInternal._removeRule - 55 + ERC3643ComplianceModule.onlyBoundToken + 3 - RuleInternal._setRules - 32 + ERC3643ComplianceModule.unbindToken + 4
diff --git a/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.gcov.html b/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.gcov.html new file mode 100644 index 0000000..9f5027e --- /dev/null +++ b/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.gcov.html @@ -0,0 +1,175 @@ + + + + + + + LCOV - lcov.info - src/modules/ERC3643ComplianceModule.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/modules - ERC3643ComplianceModule.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2424100.0 %
Date:2025-08-15 12:12:38Functions:88100.0 %
Branches:111384.6 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : //SPDX-License-Identifier: MPL-2.0
+       2                 :            : 
+       3                 :            : pragma solidity ^0.8.20;
+       4                 :            : 
+       5                 :            : /* ==== OpenZeppelin === */
+       6                 :            : import {AccessControl}  from "OZ/access/AccessControl.sol";
+       7                 :            : import {EnumerableSet} from "OZ/utils/structs/EnumerableSet.sol";
+       8                 :            : /* ==== Interface and other library === */
+       9                 :            : import {IERC3643Compliance} from "../interfaces/IERC3643Compliance.sol";
+      10                 :            : abstract contract ERC3643ComplianceModule is IERC3643Compliance, AccessControl {
+      11                 :            :     /* ==== Type declaration === */
+      12                 :            :     using EnumerableSet for EnumerableSet.AddressSet;
+      13                 :            :     /* ==== State Variables === */
+      14                 :            :     // Token binding tracking
+      15                 :            :     EnumerableSet.AddressSet private _boundTokens;
+      16                 :            :     // Access Control
+      17                 :            :     bytes32 public constant COMPLIANCE_MANAGER_ROLE = keccak256("COMPLIANCE_MANAGER_ROLE");
+      18                 :            : 
+      19                 :            :     /* ==== Errors === */
+      20                 :            :     error RuleEngine_ERC3643Compliance_InvalidTokenAddress();
+      21                 :            :     error RuleEngine_ERC3643Compliance_TokenAlreadyBound();
+      22                 :            :     error RuleEngine_ERC3643Compliance_TokenNotBound();
+      23                 :            :     error RuleEngine_ERC3643Compliance_UnauthorizedCaller();
+      24                 :            :     error RuleEngine_ERC3643Compliance_OperationNotSuccessful();
+      25                 :            : 
+      26                 :            :     /* ==== Modifier === */
+      27                 :          3 :     modifier onlyBoundToken() {
+      28            [ + ]:          3 :     if (!_boundTokens.contains(_msgSender())) {
+      29                 :          1 :         revert RuleEngine_ERC3643Compliance_UnauthorizedCaller();
+      30                 :            :     }
+      31                 :            :     _;
+      32                 :            :     }
+      33                 :            : 
+      34                 :            :     /*//////////////////////////////////////////////////////////////
+      35                 :            :                             PUBLIC/public FUNCTIONS
+      36                 :            :     //////////////////////////////////////////////////////////////*/
+      37                 :            : 
+      38                 :            :     /* ============ State functions ============ */
+      39                 :            :     /// @inheritdoc IERC3643Compliance
+      40                 :         11 :     function bindToken(address token) public override virtual onlyRole(COMPLIANCE_MANAGER_ROLE) {
+      41                 :         11 :        _bindToken(token);
+      42                 :            :     }
+      43                 :            : 
+      44                 :            :     /// @inheritdoc IERC3643Compliance
+      45                 :          4 :     function unbindToken(address token) public override virtual onlyRole(COMPLIANCE_MANAGER_ROLE) {
+      46                 :          4 :         _unbindToken(token);
+      47                 :            :     }
+      48                 :            : 
+      49                 :            :     /// @inheritdoc IERC3643Compliance
+      50                 :          6 :     function isTokenBound(address token) public view virtual override returns (bool) {
+      51                 :          6 :         return _boundTokens.contains(token);
+      52                 :            :     }
+      53                 :            : 
+      54                 :            :     /// @inheritdoc IERC3643Compliance
+      55                 :          2 :     function getTokenBound() public view virtual override returns (address) {
+      56         [ +  + ]:          2 :         if(_boundTokens.length() > 0){
+      57                 :            :             // Note that there are no guarantees on the ordering of values inside the array, 
+      58                 :            :             // and it may change when more values are added or removed.
+      59                 :          1 :             return _boundTokens.at(0);
+      60                 :            :         } else {
+      61                 :          1 :             return address(0);
+      62                 :            :         }
+      63                 :            :     }
+      64                 :            : 
+      65                 :            :     /// @inheritdoc IERC3643Compliance
+      66                 :          2 :     function getTokenBounds() public view override returns (address[] memory) {
+      67                 :          2 :         return _boundTokens.values();
+      68                 :            :     }
+      69                 :            : 
+      70                 :            : 
+      71                 :            : 
+      72                 :            :     /*//////////////////////////////////////////////////////////////
+      73                 :            :                             INTERNAL/PRIVATE FUNCTIONS
+      74                 :            :     //////////////////////////////////////////////////////////////*/
+      75                 :            : 
+      76                 :          4 :     function _unbindToken(address token)  internal {
+      77         [ +  + ]:          4 :         require (_boundTokens.contains(token), RuleEngine_ERC3643Compliance_TokenNotBound()); 
+      78                 :            :         // Should never revert because we check if the token address is already set before
+      79         [ #  + ]:          3 :         require(_boundTokens.remove(token), RuleEngine_ERC3643Compliance_OperationNotSuccessful());
+      80                 :            : 
+      81                 :          3 :         emit TokenUnbound(token);
+      82                 :            :     }
+      83                 :         26 :     function _bindToken(address token) internal{
+      84         [ +  + ]:         26 :         require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress());
+      85         [ +  + ]:         25 :         require(!_boundTokens.contains(token), RuleEngine_ERC3643Compliance_TokenAlreadyBound());
+      86                 :            :         // Should never revert because we check if the token address is already set before
+      87         [ #  + ]:         24 :         require(_boundTokens.add(token), RuleEngine_ERC3643Compliance_OperationNotSuccessful());
+      88                 :         24 :         emit TokenBound(token);
+      89                 :            :     }
+      90                 :            : }
+
+
+
+ + + + +
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/RuleEngineValidationCommon.sol.gcov.html b/doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.gcov.html deleted file mode 100644 index 1c29fc2..0000000 --- a/doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.gcov.html +++ /dev/null @@ -1,237 +0,0 @@ - - - - - - - LCOV - lcov.info - src/modules/RuleEngineValidationCommon.sol - - - - - - - - - - - - - - -
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 %
-
- - - - - - - - -

-
           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                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/modules/RuleInternal.sol.gcov.html b/doc/coverage/coverage/src/modules/RuleInternal.sol.gcov.html deleted file mode 100644 index cd50bce..0000000 --- a/doc/coverage/coverage/src/modules/RuleInternal.sol.gcov.html +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - - LCOV - lcov.info - src/modules/RuleInternal.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modules - RuleInternal.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2929100.0 %
Date:2024-12-20 10:41:14Functions:44100.0 %
Branches:88100.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       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                 :            : }
-
-
-
- - - - -
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/RulesManagementModule.sol.func-sort-c.html similarity index 52% rename from doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html rename to doc/coverage/coverage/src/modules/RulesManagementModule.sol.func-sort-c.html index 260f236..ddc2799 100644 --- a/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html +++ b/doc/coverage/coverage/src/modules/RulesManagementModule.sol.func-sort-c.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src/modules/RuleEngineOperation.sol - functions + LCOV - lcov.info - src/modules/RulesManagementModule.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,17 +31,17 @@ - - + + - + - - + + @@ -49,9 +49,9 @@ - - - + + +
Current view:top level - src/modules - RuleEngineOperation.sol (source / functions)top level - src/modules - RulesManagementModule.sol (source / functions) Hitlcov.info Lines:25254747 100.0 %
Date:2024-12-20 10:41:142025-08-15 12:12:38 Functions:11111212 100.0 %
Branches:22100.0 %111478.6 %
@@ -65,52 +65,56 @@ - + - - - - - + - - + + - - + + - - + + - + - - + + + + + + + + + + - - + + - - + + - - + + - - + +

Function Name Sort by function nameFunction Name Sort by function name Hit count Sort by hit count
RuleEngineOperation.ruleOperation1
RuleEngineOperation.getRuleIndexOperationRulesManagementModule.rule 3
RuleEngineOperation.clearRulesOperation4RulesManagementModule._removeRule8
RuleEngineOperation.removeRuleOperation5RulesManagementModule.clearRules10
RuleEngineOperation.rulesOperation5RulesManagementModule.rules10
RuleEngineOperation.setRulesOperationRulesManagementModule.removeRule 11
RuleEngineOperation._clearRulesOperation14RulesManagementModule._transferred12
RulesManagementModule.setRules34
RulesManagementModule.containsRule35
RuleEngineOperation._removeRuleOperation22RulesManagementModule._clearRules36
RuleEngineOperation.rulesCountOperation41RulesManagementModule.addRule95
RuleEngineOperation._operateOnTransfer58RulesManagementModule.rulesCount115
RuleEngineOperation.addRuleOperation85RulesManagementModule._checkRule141

diff --git a/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func.html b/doc/coverage/coverage/src/modules/RulesManagementModule.sol.func.html similarity index 52% rename from doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func.html rename to doc/coverage/coverage/src/modules/RulesManagementModule.sol.func.html index 323d585..8aab7fe 100644 --- a/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func.html +++ b/doc/coverage/coverage/src/modules/RulesManagementModule.sol.func.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src/modules/RuleEngineOperation.sol - functions + LCOV - lcov.info - src/modules/RulesManagementModule.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,17 +31,17 @@ - - + + - + - - + + @@ -49,9 +49,9 @@ - - - + + +
Current view:top level - src/modules - RuleEngineOperation.sol (source / functions)top level - src/modules - RulesManagementModule.sol (source / functions) Hitlcov.info Lines:25254747 100.0 %
Date:2024-12-20 10:41:142025-08-15 12:12:38 Functions:11111212 100.0 %
Branches:22100.0 %111478.6 %
@@ -66,51 +66,55 @@
Function Name Sort by function name - Hit count Sort by hit count + Hit count Sort by hit count - RuleEngineOperation._clearRulesOperation - 14 + RulesManagementModule._checkRule + 141 - RuleEngineOperation._operateOnTransfer - 58 + RulesManagementModule._clearRules + 36 - RuleEngineOperation._removeRuleOperation - 22 + RulesManagementModule._removeRule + 8 - RuleEngineOperation.addRuleOperation - 85 + RulesManagementModule._transferred + 12 - RuleEngineOperation.clearRulesOperation - 4 + RulesManagementModule.addRule + 95 - RuleEngineOperation.getRuleIndexOperation - 3 + RulesManagementModule.clearRules + 10 - RuleEngineOperation.removeRuleOperation - 5 + RulesManagementModule.containsRule + 35 - RuleEngineOperation.ruleOperation - 1 + RulesManagementModule.removeRule + 11 - RuleEngineOperation.rulesCountOperation - 41 + RulesManagementModule.rule + 3 - RuleEngineOperation.rulesOperation - 5 + RulesManagementModule.rules + 10 - RuleEngineOperation.setRulesOperation - 11 + RulesManagementModule.rulesCount + 115 + + + RulesManagementModule.setRules + 34
diff --git a/doc/coverage/coverage/src/modules/RulesManagementModule.sol.gcov.html b/doc/coverage/coverage/src/modules/RulesManagementModule.sol.gcov.html new file mode 100644 index 0000000..6a77ef4 --- /dev/null +++ b/doc/coverage/coverage/src/modules/RulesManagementModule.sol.gcov.html @@ -0,0 +1,295 @@ + + + + + + + LCOV - lcov.info - src/modules/RulesManagementModule.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/modules - RulesManagementModule.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:4747100.0 %
Date:2025-08-15 12:12:38Functions:1212100.0 %
Branches:111478.6 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : 
+       3                 :            : pragma solidity ^0.8.20;
+       4                 :            : 
+       5                 :            : /* ==== OpenZeppelin === */
+       6                 :            : import {EnumerableSet} from "OZ/utils/structs/EnumerableSet.sol";
+       7                 :            : import {AccessControl}  from "OZ/access/AccessControl.sol";
+       8                 :            : /* ==== Interface and other library === */
+       9                 :            : import {IRulesManagementModule} from "../interfaces/IRulesManagementModule.sol";
+      10                 :            : import {IRule} from "../interfaces/IRule.sol";
+      11                 :            : import {RulesManagementModuleInvariantStorage} from "./library/RulesManagementModuleInvariantStorage.sol";
+      12                 :            : /**
+      13                 :            :  * @title RuleEngine -  part
+      14                 :            :  */
+      15                 :            : abstract contract RulesManagementModule is
+      16                 :            :     AccessControl,
+      17                 :            :     RulesManagementModuleInvariantStorage,
+      18                 :            :     IRulesManagementModule
+      19                 :            : {
+      20                 :            :     /* ==== Type declaration === */
+      21                 :            :     using EnumerableSet for EnumerableSet.AddressSet;
+      22                 :            : 
+      23                 :            :     /* ==== State Variables === */
+      24                 :            :     /// @dev Array of rules
+      25                 :            :     EnumerableSet.AddressSet internal _rules;
+      26                 :            : 
+      27                 :            :     /*//////////////////////////////////////////////////////////////
+      28                 :            :                             PUBLIC/EXTERNAL FUNCTIONS
+      29                 :            :     //////////////////////////////////////////////////////////////*/
+      30                 :            : 
+      31                 :            :     /* ============ State functions ============ */
+      32                 :            : 
+      33                 :            :     /**
+      34                 :            :     * @inheritdoc IRulesManagementModule
+      35                 :            :     */
+      36                 :         34 :     function setRules(
+      37                 :            :         IRule[] calldata rules_
+      38                 :            :     ) public virtual override(IRulesManagementModule) onlyRole(RULES_MANAGEMENT_ROLE) {
+      39            [ + ]:         33 :         if (rules_.length == 0) {
+      40                 :          4 :             revert RuleEngine_RulesManagementModule_ArrayIsEmpty();
+      41                 :            :         }
+      42            [ + ]:         29 :         if (_rules.length() > 0) {
+      43                 :         27 :             _clearRules();
+      44                 :            :         }
+      45                 :         29 :         for(uint256 i = 0; i < rules_.length; ++i){
+      46                 :         47 :            _checkRule(address(rules_[i]));
+      47                 :            :             // Should never revert because we check the presence of the rule before
+      48         [ #  + ]:         45 :             require(_rules.add(address(rules_[i])), RuleEngine_RulesManagementModule_OperationNotSuccessful());
+      49                 :         45 :             emit AddRule(rules_[i]);
+      50                 :            :         }
+      51                 :            :     }
+      52                 :            : 
+      53                 :            :     /**
+      54                 :            :     * @inheritdoc IRulesManagementModule
+      55                 :            :     */  
+      56                 :         10 :     function clearRules() public virtual override(IRulesManagementModule) onlyRole(RULES_MANAGEMENT_ROLE) {
+      57                 :          9 :         _clearRules();
+      58                 :            :     }
+      59                 :            : 
+      60                 :            :     /**
+      61                 :            :     * @inheritdoc IRulesManagementModule
+      62                 :            :     */
+      63                 :         95 :     function addRule(
+      64                 :            :         IRule rule_
+      65                 :            :     ) public virtual override(IRulesManagementModule) onlyRole(RULES_MANAGEMENT_ROLE) {
+      66                 :         94 :         _checkRule(address(rule_));
+      67         [ #  + ]:         90 :         require(_rules.add(address(rule_)), RuleEngine_RulesManagementModule_OperationNotSuccessful());
+      68                 :         90 :         emit AddRule(rule_);
+      69                 :            :     }
+      70                 :            : 
+      71                 :            :    /**
+      72                 :            :     * @inheritdoc IRulesManagementModule
+      73                 :            :     */
+      74                 :         11 :     function removeRule(
+      75                 :            :         IRule rule_
+      76                 :            :     ) public virtual override(IRulesManagementModule) onlyRole(RULES_MANAGEMENT_ROLE) {
+      77         [ +  + ]:         10 :         require(_rules.contains(address(rule_)), RuleEngine_RulesManagementModule_RuleDoNotMatch());
+      78                 :          8 :         _removeRule(rule_);
+      79                 :            :     }
+      80                 :            : 
+      81                 :            :     /* ============ View functions ============ */
+      82                 :            : 
+      83                 :            :    /**
+      84                 :            :     * @inheritdoc IRulesManagementModule
+      85                 :            :     */
+      86                 :        115 :     function rulesCount() public view virtual override(IRulesManagementModule) returns (uint256) {
+      87                 :        192 :         return _rules.length();
+      88                 :            :     }
+      89                 :            : 
+      90                 :            :     /**
+      91                 :            :     * @inheritdoc IRulesManagementModule
+      92                 :            :     */
+      93                 :         35 :     function containsRule(IRule rule_) public view virtual override(IRulesManagementModule) returns (bool){
+      94                 :         35 :         return _rules.contains(address(rule_));
+      95                 :            :     }
+      96                 :            : 
+      97                 :            : 
+      98                 :            :     /**
+      99                 :            :     * @inheritdoc IRulesManagementModule
+     100                 :            :     */
+     101                 :          3 :     function rule(
+     102                 :            :         uint256 ruleId
+     103                 :            :     ) public view virtual override(IRulesManagementModule) returns (address) {
+     104         [ +  + ]:         85 :         if(ruleId < _rules.length()){
+     105                 :            :             // Note that there are no guarantees on the ordering of values inside the array, 
+     106                 :            :             // and it may change when more values are added or removed.
+     107                 :         84 :             return _rules.at(ruleId);
+     108                 :            :         } else {
+     109                 :          1 :             return address(0);
+     110                 :            :         }
+     111                 :            :     }
+     112                 :            : 
+     113                 :            :     /**
+     114                 :            :     * @inheritdoc IRulesManagementModule
+     115                 :            :     */
+     116                 :         10 :     function rules()
+     117                 :            :         public
+     118                 :            :         view
+     119                 :            :         virtual
+     120                 :            :         override(IRulesManagementModule)
+     121                 :            :         returns (address[] memory)
+     122                 :            :     {
+     123                 :         10 :         return _rules.values();
+     124                 :            :     }
+     125                 :            : 
+     126                 :            :     /*//////////////////////////////////////////////////////////////
+     127                 :            :                             INTERNAL/PRIVATE FUNCTIONS
+     128                 :            :     //////////////////////////////////////////////////////////////*/
+     129                 :            :     /**
+     130                 :            :      * @notice Clear all the rules of the array of rules
+     131                 :            :      *
+     132                 :            :      */
+     133                 :         36 :     function _clearRules() internal virtual {
+     134                 :         36 :         emit ClearRules();
+     135                 :         36 :         _rules.clear();
+     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                 :            :      *
+     143                 :            :      *
+     144                 :            :      */
+     145                 :          8 :     function _removeRule(IRule rule_) internal virtual {
+     146                 :            :         // Should never revert because we check the presence of the rule before
+     147         [ #  + ]:          8 :         require(_rules.remove(address(rule_)), RuleEngine_RulesManagementModule_OperationNotSuccessful());
+     148                 :          8 :         emit RemoveRule(rule_);
+     149                 :            :     }
+     150                 :            : 
+     151                 :            :     /**
+     152                 :            :     * @dev check if a rule is valid, revert otherwise
+     153                 :            :     */
+     154                 :        141 :     function _checkRule(address rule_) internal view{
+     155            [ + ]:        141 :           if (rule_ == address(0x0)) {
+     156                 :          2 :                 revert RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed();
+     157                 :            :             }
+     158            [ + ]:        139 :         if (_rules.contains(rule_)) {
+     159                 :          4 :             revert RuleEngine_RulesManagementModule_RuleAlreadyExists();
+     160                 :            :         }
+     161                 :            :     }
+     162                 :            : 
+     163                 :            : 
+     164                 :            :     /* ============ Transferred functions ============ */
+     165                 :            : 
+     166                 :            :     /**
+     167                 :            :      * @notice Go through all the rule to know if a restriction exists on the transfer
+     168                 :            :      * @param from the origin address
+     169                 :            :      * @param to the destination address
+     170                 :            :      * @param value to transfer
+     171                 :            :      **/
+     172                 :         10 :     function _transferred(
+     173                 :            :         address from,
+     174                 :            :         address to,
+     175                 :            :         uint256 value
+     176                 :            :     ) internal virtual{
+     177                 :         10 :         uint256 rulesLength = _rules.length();
+     178                 :         10 :         for (uint256 i = 0; i < rulesLength; ++i) {
+     179                 :          7 :             IRule(_rules.at(i)).transferred(
+     180                 :            :                 from,
+     181                 :            :                 to,
+     182                 :            :                 value
+     183                 :            :             );
+     184                 :            :         }
+     185                 :            :     }
+     186                 :            : 
+     187                 :            :     /**
+     188                 :            :      * @notice Go through all the rule to know if a restriction exists on the transfer
+     189                 :            :      * @param spender the spender address (transferFrom)
+     190                 :            :      * @param from the origin address
+     191                 :            :      * @param to the destination address
+     192                 :            :      * @param value to transfer
+     193                 :            :      **/
+     194                 :          2 :     function _transferred(
+     195                 :            :         address spender,
+     196                 :            :         address from,
+     197                 :            :         address to,
+     198                 :            :         uint256 value
+     199                 :            :     ) internal virtual{
+     200                 :          2 :         uint256 rulesLength = _rules.length();
+     201                 :          2 :         for (uint256 i = 0; i < rulesLength; ++i) {
+     202                 :          2 :             IRule(_rules.at(i)).transferred(
+     203                 :            :                 spender,
+     204                 :            :                 from,
+     205                 :            :                 to,
+     206                 :            :                 value
+     207                 :            :             );
+     208                 :            :         }
+     209                 :            :     }
+     210                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func-sort-c.html b/doc/coverage/coverage/src/modules/VersionModule.sol.func-sort-c.html similarity index 78% rename from doc/coverage/coverage/test/utils/CMTATDeployment.sol.func-sort-c.html rename to doc/coverage/coverage/src/modules/VersionModule.sol.func-sort-c.html index a8ae820..72f73b9 100644 --- a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func-sort-c.html +++ b/doc/coverage/coverage/src/modules/VersionModule.sol.func-sort-c.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - test/utils/CMTATDeployment.sol - functions + LCOV - lcov.info - src/modules/VersionModule.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,13 +31,13 @@ - - + + - + @@ -65,12 +65,12 @@
Current view:top level - test/utils - CMTATDeployment.sol (source / functions)top level - src/modules - VersionModule.sol (source / functions) Hitlcov.info Lines:4422 100.0 %
Date:2024-12-20 10:41:142025-08-15 12:12:38 Functions: 1
- + - - + +

Function Name Sort by function nameFunction Name Sort by function name Hit count Sort by hit count
CMTATDeployment.86VersionModule.version1

diff --git a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func.html b/doc/coverage/coverage/src/modules/VersionModule.sol.func.html similarity index 78% rename from doc/coverage/coverage/test/utils/CMTATDeployment.sol.func.html rename to doc/coverage/coverage/src/modules/VersionModule.sol.func.html index a912669..5f5430e 100644 --- a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func.html +++ b/doc/coverage/coverage/src/modules/VersionModule.sol.func.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - test/utils/CMTATDeployment.sol - functions + LCOV - lcov.info - src/modules/VersionModule.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,13 +31,13 @@ - - + + - + @@ -66,11 +66,11 @@ - + - - + +
Current view:top level - test/utils - CMTATDeployment.sol (source / functions)top level - src/modules - VersionModule.sol (source / functions) Hitlcov.info Lines:4422 100.0 %
Date:2024-12-20 10:41:142025-08-15 12:12:38 Functions: 1

Function Name Sort by function nameHit count Sort by hit countHit count Sort by hit count
CMTATDeployment.86VersionModule.version1

diff --git a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.gcov.html b/doc/coverage/coverage/src/modules/VersionModule.sol.gcov.html similarity index 69% rename from doc/coverage/coverage/test/utils/SanctionListOracle.sol.gcov.html rename to doc/coverage/coverage/src/modules/VersionModule.sol.gcov.html index 6a45b5a..c87703d 100644 --- a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.gcov.html +++ b/doc/coverage/coverage/src/modules/VersionModule.sol.gcov.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - test/utils/SanctionListOracle.sol + LCOV - lcov.info - src/modules/VersionModule.sol @@ -19,7 +19,7 @@ - + @@ -32,17 +32,17 @@ - - + + - + - - - + + + @@ -70,27 +70,27 @@
           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;
+       2                 :            : 
+       3                 :            : pragma solidity ^0.8.20;
+       4                 :            : 
+       5                 :            : /* ==== CMTAT === */
+       6                 :            : import {IERC3643Base} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+       7                 :            : abstract contract VersionModule is IERC3643Base {
+       8                 :            :     /* ============ State Variables ============ */
+       9                 :            :     /** 
+      10                 :            :     * @dev 
+      11                 :            :     * Get the current version of the smart contract
+      12                 :            :     */
+      13                 :            :     string private constant VERSION = "3.0.0";
+      14                 :            :     /* ============ Events ============ */
+      15                 :            :     /*//////////////////////////////////////////////////////////////
+      16                 :            :                             PUBLIC/EXTERNAL FUNCTIONS
+      17                 :            :     //////////////////////////////////////////////////////////////*/
+      18                 :            :     /**
+      19                 :            :     * @inheritdoc IERC3643Base
+      20                 :            :     */
+      21                 :          1 :     function version() public view virtual override(IERC3643Base) returns (string memory version_) {
+      22                 :          1 :        return VERSION;
       23                 :            :     }
       24                 :            : }
 
diff --git a/doc/coverage/coverage/src/modules/index-sort-b.html b/doc/coverage/coverage/src/modules/index-sort-b.html index 1356192..8894d3d 100644 --- a/doc/coverage/coverage/src/modules/index-sort-b.html +++ b/doc/coverage/coverage/src/modules/index-sort-b.html @@ -31,17 +31,17 @@ - - + + - + - - + + @@ -49,9 +49,9 @@ - - - + + +
Current view:top level - test/utils - SanctionListOracle.sol (source / functions)top level - src/modules - VersionModule.sol (source / functions) Hit Lines: 2366.7 %2100.0 %
Date:2024-12-20 10:41:142025-08-15 12:12:38 Functions:3475.0 %11100.0 %
lcov.info Lines:81817373 100.0 %
Date:2024-12-20 10:41:142025-08-15 12:12:38 Functions:27272121 100.0 %
Branches:1212100.0 %222781.5 %
@@ -82,52 +82,40 @@ Branches Sort by branch coverage - RuleEngineValidationCommon.sol + RulesManagementModule.sol
100.0%
100.0 % - 19 / 19 - 100.0 % - 10 / 10 + 47 / 47 100.0 % - 1 / 1 + 12 / 12 + 78.6 % + 11 / 14 - RuleEngineValidation.sol + ERC3643ComplianceModule.sol
100.0%
100.0 % - 8 / 8 - 100.0 % - 2 / 2 + 24 / 24 100.0 % - 1 / 1 + 8 / 8 + 84.6 % + 11 / 13 - RuleEngineOperation.sol + VersionModule.sol
100.0%
100.0 % - 25 / 25 - 100.0 % - 11 / 11 - 100.0 % 2 / 2 - - - RuleInternal.sol - -
100.0%
- - 100.0 % - 29 / 29 - 100.0 % - 4 / 4 100.0 % - 8 / 8 + 1 / 1 + - + 0 / 0 diff --git a/doc/coverage/coverage/src/modules/index-sort-f.html b/doc/coverage/coverage/src/modules/index-sort-f.html index f0cc112..43cd97e 100644 --- a/doc/coverage/coverage/src/modules/index-sort-f.html +++ b/doc/coverage/coverage/src/modules/index-sort-f.html @@ -31,17 +31,17 @@ lcov.info Lines: - 81 - 81 + 73 + 73 100.0 % Date: - 2024-12-20 10:41:14 + 2025-08-15 12:12:38 Functions: - 27 - 27 + 21 + 21 100.0 % @@ -49,9 +49,9 @@ Branches: - 12 - 12 - 100.0 % + 22 + 27 + 81.5 % @@ -82,52 +82,40 @@ Branches Sort by branch coverage - RuleEngineValidation.sol + VersionModule.sol
100.0%
100.0 % - 8 / 8 - 100.0 % 2 / 2 100.0 % 1 / 1 + - + 0 / 0 - RuleInternal.sol + ERC3643ComplianceModule.sol
100.0%
100.0 % - 29 / 29 - 100.0 % - 4 / 4 + 24 / 24 100.0 % 8 / 8 + 84.6 % + 11 / 13 - RuleEngineValidationCommon.sol - -
100.0%
- - 100.0 % - 19 / 19 - 100.0 % - 10 / 10 - 100.0 % - 1 / 1 - - - RuleEngineOperation.sol + RulesManagementModule.sol
100.0%
100.0 % - 25 / 25 + 47 / 47 100.0 % - 11 / 11 - 100.0 % - 2 / 2 + 12 / 12 + 78.6 % + 11 / 14 diff --git a/doc/coverage/coverage/src/modules/index-sort-l.html b/doc/coverage/coverage/src/modules/index-sort-l.html index 7d113ca..fcde026 100644 --- a/doc/coverage/coverage/src/modules/index-sort-l.html +++ b/doc/coverage/coverage/src/modules/index-sort-l.html @@ -31,17 +31,17 @@ lcov.info Lines: - 81 - 81 + 73 + 73 100.0 % Date: - 2024-12-20 10:41:14 + 2025-08-15 12:12:38 Functions: - 27 - 27 + 21 + 21 100.0 % @@ -49,9 +49,9 @@ Branches: - 12 - 12 - 100.0 % + 22 + 27 + 81.5 % @@ -82,52 +82,40 @@ Branches Sort by branch coverage - RuleEngineValidation.sol + VersionModule.sol
100.0%
100.0 % - 8 / 8 - 100.0 % 2 / 2 100.0 % 1 / 1 + - + 0 / 0 - RuleEngineValidationCommon.sol - -
100.0%
- - 100.0 % - 19 / 19 - 100.0 % - 10 / 10 - 100.0 % - 1 / 1 - - - RuleEngineOperation.sol + ERC3643ComplianceModule.sol
100.0%
100.0 % - 25 / 25 + 24 / 24 100.0 % - 11 / 11 - 100.0 % - 2 / 2 + 8 / 8 + 84.6 % + 11 / 13 - RuleInternal.sol + RulesManagementModule.sol
100.0%
100.0 % - 29 / 29 + 47 / 47 100.0 % - 4 / 4 - 100.0 % - 8 / 8 + 12 / 12 + 78.6 % + 11 / 14 diff --git a/doc/coverage/coverage/src/modules/index.html b/doc/coverage/coverage/src/modules/index.html index 60ae93b..0beaa22 100644 --- a/doc/coverage/coverage/src/modules/index.html +++ b/doc/coverage/coverage/src/modules/index.html @@ -31,17 +31,17 @@ lcov.info Lines: - 81 - 81 + 73 + 73 100.0 % Date: - 2024-12-20 10:41:14 + 2025-08-15 12:12:38 Functions: - 27 - 27 + 21 + 21 100.0 % @@ -49,9 +49,9 @@ Branches: - 12 - 12 - 100.0 % + 22 + 27 + 81.5 % @@ -82,52 +82,40 @@ Branches Sort by branch coverage - RuleEngineOperation.sol + ERC3643ComplianceModule.sol
100.0%
100.0 % - 25 / 25 - 100.0 % - 11 / 11 - 100.0 % - 2 / 2 - - - RuleEngineValidation.sol - -
100.0%
- + 24 / 24 100.0 % 8 / 8 - 100.0 % - 2 / 2 - 100.0 % - 1 / 1 + 84.6 % + 11 / 13 - RuleEngineValidationCommon.sol + RulesManagementModule.sol
100.0%
100.0 % - 19 / 19 - 100.0 % - 10 / 10 + 47 / 47 100.0 % - 1 / 1 + 12 / 12 + 78.6 % + 11 / 14 - RuleInternal.sol + VersionModule.sol
100.0%
100.0 % - 29 / 29 - 100.0 % - 4 / 4 + 2 / 2 100.0 % - 8 / 8 + 1 / 1 + - + 0 / 0 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/abstract/index-sort-b.html b/doc/coverage/coverage/src/rules/operation/abstract/index-sort-b.html deleted file mode 100644 index e47a898..0000000 --- a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-b.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/operation/abstract - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation/abstractHitTotalCoverage
Test:lcov.infoLines:113113100.0 %
Date:2024-12-20 10:41:14Functions:2020100.0 %
Branches:3131100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransferOperator.sol -
100.0%
-
100.0 %113 / 113100.0 %20 / 20100.0 %31 / 31
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-f.html b/doc/coverage/coverage/src/rules/operation/abstract/index-sort-f.html deleted file mode 100644 index aaae3fc..0000000 --- a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-f.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/operation/abstract - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation/abstractHitTotalCoverage
Test:lcov.infoLines:113113100.0 %
Date:2024-12-20 10:41:14Functions:2020100.0 %
Branches:3131100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransferOperator.sol -
100.0%
-
100.0 %113 / 113100.0 %20 / 20100.0 %31 / 31
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-l.html b/doc/coverage/coverage/src/rules/operation/abstract/index-sort-l.html deleted file mode 100644 index 2ec5b2c..0000000 --- a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-l.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/operation/abstract - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation/abstractHitTotalCoverage
Test:lcov.infoLines:113113100.0 %
Date:2024-12-20 10:41:14Functions:2020100.0 %
Branches:3131100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransferOperator.sol -
100.0%
-
100.0 %113 / 113100.0 %20 / 20100.0 %31 / 31
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/operation/abstract/index.html b/doc/coverage/coverage/src/rules/operation/abstract/index.html deleted file mode 100644 index 1428f56..0000000 --- a/doc/coverage/coverage/src/rules/operation/abstract/index.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/operation/abstract - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation/abstractHitTotalCoverage
Test:lcov.infoLines:113113100.0 %
Date:2024-12-20 10:41:14Functions:2020100.0 %
Branches:3131100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransferOperator.sol -
100.0%
-
100.0 %113 / 113100.0 %20 / 20100.0 %31 / 31
-
-
- - - - -
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/RuleBlacklist.sol.gcov.html b/doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html deleted file mode 100644 index bea5e34..0000000 --- a/doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/RuleBlacklist.sol - - - - - - - - - - - - - - -
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 %
-
- - - - - - - - -

-
           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                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html deleted file mode 100644 index 76ad884..0000000 --- a/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/RuleSanctionList.sol - functions - - - - - - - - - - - - - - -
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 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleSanctionList._msgData0
RuleSanctionList.canReturnTransferRestrictionCode3
RuleSanctionList.messageForTransferRestriction3
RuleSanctionList.detectTransferRestriction7
RuleSanctionList._setSanctionListOracle11
RuleSanctionList.setSanctionListOracle11
RuleSanctionList.13
RuleSanctionList.hasRole13
RuleSanctionList._contextSuffixLength23
RuleSanctionList._msgSender23
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func.html b/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func.html deleted file mode 100644 index f3eefa0..0000000 --- a/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/RuleSanctionList.sol - functions - - - - - - - - - - - - - - -
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 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleSanctionList.13
RuleSanctionList._contextSuffixLength23
RuleSanctionList._msgData0
RuleSanctionList._msgSender23
RuleSanctionList._setSanctionListOracle11
RuleSanctionList.canReturnTransferRestrictionCode3
RuleSanctionList.detectTransferRestriction7
RuleSanctionList.hasRole13
RuleSanctionList.messageForTransferRestriction3
RuleSanctionList.setSanctionListOracle11
-
-
- - - -
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/RuleWhitelistWrapper.sol.gcov.html b/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.gcov.html deleted file mode 100644 index 497bf06..0000000 --- a/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.gcov.html +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/RuleWhitelistWrapper.sol - - - - - - - - - - - - - - -
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 %
-
- - - - - - - - -

-
           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                 :            : }
-
-
-
- - - - -
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/RuleWhitelistCommon.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html deleted file mode 100644 index d40fb06..0000000 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/abstract/RuleWhitelistCommon.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract - RuleWhitelistCommon.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:88100.0 %
Date:2024-12-20 10:41:14Functions:22100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistCommon.messageForTransferRestriction10
RuleWhitelistCommon.canReturnTransferRestrictionCode12
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func.html deleted file mode 100644 index b899bc1..0000000 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/abstract/RuleWhitelistCommon.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract - RuleWhitelistCommon.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:88100.0 %
Date:2024-12-20 10:41:14Functions:22100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistCommon.canReturnTransferRestrictionCode12
RuleWhitelistCommon.messageForTransferRestriction10
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.gcov.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.gcov.html deleted file mode 100644 index 20b596c..0000000 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.gcov.html +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/abstract/RuleWhitelistCommon.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract - RuleWhitelistCommon.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:88100.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 "./RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol";
-       6                 :            : import "./RuleValidateTransfer.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                 :            : }
-
-
-
- - - - -
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.func-sort-c.html b/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func-sort-c.html deleted file mode 100644 index 88c2a09..0000000 --- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func-sort-c.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - test/RuleConditionalTransfer/utils/RuleCTDeployment.sol - functions - - - - - - - - - - - - - - -
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-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleCTDeployment.13
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func.html b/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func.html deleted file mode 100644 index ead2a6c..0000000 --- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - test/RuleConditionalTransfer/utils/RuleCTDeployment.sol - functions - - - - - - - - - - - - - - -
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-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleCTDeployment.13
-
-
- - - -
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/RuleConditionalTransfer/utils/index-sort-b.html b/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-b.html deleted file mode 100644 index 273564b..0000000 --- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-b.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - test/RuleConditionalTransfer/utils - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/RuleConditionalTransfer/utilsHitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleCTDeployment.sol -
100.0%
-
100.0 %10 / 10100.0 %1 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-f.html b/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-f.html deleted file mode 100644 index cfa53fa..0000000 --- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-f.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - test/RuleConditionalTransfer/utils - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/RuleConditionalTransfer/utilsHitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleCTDeployment.sol -
100.0%
-
100.0 %10 / 10100.0 %1 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-l.html b/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-l.html deleted file mode 100644 index 8cfb2ca..0000000 --- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-l.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - test/RuleConditionalTransfer/utils - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/RuleConditionalTransfer/utilsHitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleCTDeployment.sol -
100.0%
-
100.0 %10 / 10100.0 %1 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index.html b/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index.html deleted file mode 100644 index 0fb4392..0000000 --- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - test/RuleConditionalTransfer/utils - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/RuleConditionalTransfer/utilsHitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleCTDeployment.sol -
100.0%
-
100.0 %10 / 10100.0 %1 / 1-0 / 0
-
-
- - - - -
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.func-sort-c.html b/doc/coverage/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html deleted file mode 100644 index 32ca64b..0000000 --- a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils/SanctionListOracle.sol - functions - - - - - - - - - - - - - - -
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-
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
SanctionListOracle.removeFromSanctionsList0
SanctionListOracle.addToSanctionsList10
SanctionListOracle.11
SanctionListOracle.isSanctioned12
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.func.html b/doc/coverage/coverage/test/utils/SanctionListOracle.sol.func.html deleted file mode 100644 index 12d4508..0000000 --- a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.func.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils/SanctionListOracle.sol - functions - - - - - - - - - - - - - - -
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-
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
SanctionListOracle.11
SanctionListOracle.addToSanctionsList10
SanctionListOracle.isSanctioned12
SanctionListOracle.removeFromSanctionsList0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/test/utils/index-sort-b.html b/doc/coverage/coverage/test/utils/index-sort-b.html deleted file mode 100644 index 500c424..0000000 --- a/doc/coverage/coverage/test/utils/index-sort-b.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utilsHitTotalCoverage
Test:lcov.infoLines:6785.7 %
Date:2024-12-20 10:41:14Functions:4580.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
CMTATDeployment.sol -
100.0%
-
100.0 %4 / 4100.0 %1 / 1-0 / 0
SanctionListOracle.sol -
66.7%66.7%
-
66.7 %2 / 375.0 %3 / 4-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/test/utils/index-sort-f.html b/doc/coverage/coverage/test/utils/index-sort-f.html deleted file mode 100644 index ff0b711..0000000 --- a/doc/coverage/coverage/test/utils/index-sort-f.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utilsHitTotalCoverage
Test:lcov.infoLines:6785.7 %
Date:2024-12-20 10:41:14Functions:4580.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
SanctionListOracle.sol -
66.7%66.7%
-
66.7 %2 / 375.0 %3 / 4-0 / 0
CMTATDeployment.sol -
100.0%
-
100.0 %4 / 4100.0 %1 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/test/utils/index-sort-l.html b/doc/coverage/coverage/test/utils/index-sort-l.html deleted file mode 100644 index b1f3e52..0000000 --- a/doc/coverage/coverage/test/utils/index-sort-l.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utilsHitTotalCoverage
Test:lcov.infoLines:6785.7 %
Date:2024-12-20 10:41:14Functions:4580.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
SanctionListOracle.sol -
66.7%66.7%
-
66.7 %2 / 375.0 %3 / 4-0 / 0
CMTATDeployment.sol -
100.0%
-
100.0 %4 / 4100.0 %1 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/test/utils/index.html b/doc/coverage/coverage/test/utils/index.html deleted file mode 100644 index 0cb6aec..0000000 --- a/doc/coverage/coverage/test/utils/index.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utilsHitTotalCoverage
Test:lcov.infoLines:6785.7 %
Date:2024-12-20 10:41:14Functions:4580.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
CMTATDeployment.sol -
100.0%
-
100.0 %4 / 4100.0 %1 / 1-0 / 0
SanctionListOracle.sol -
66.7%66.7%
-
66.7 %2 / 375.0 %3 / 4-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/lcov.info b/doc/coverage/lcov.info index a4e6aaf..9a34f35 100644 --- a/doc/coverage/lcov.info +++ b/doc/coverage/lcov.info @@ -1,995 +1,272 @@ 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 +DA:22,90 +FN:22,RuleEngine.constructor +FNDA:90,RuleEngine.constructor +DA:27,90 +BRDA:27,0,0,1 +DA:28,1 +DA:30,89 +BRDA:30,1,0,15 +DA:31,15 +DA:33,89 +DA:43,300 +FN:43,RuleEngine._msgSender +FNDA:300,RuleEngine._msgSender +DA:50,300 +DA:56,0 +FN:56,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 +DA:63,0 +DA:69,300 +FN:69,RuleEngine._contextSuffixLength +FNDA:300,RuleEngine._contextSuffixLength +DA:76,300 +FNF:4 +FNH:3 +LF:12 +LH:10 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 -FNF:2 -FNH:2 -LF:8 -LH:8 -BRF:1 -BRH:1 -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 +SF:src/RuleEngineBase.sol +DA:35,3 +FN:35,RuleEngineBase.transferred +FNDA:3,RuleEngineBase.transferred +DA:42,2 +DA:48,9 +FN:48,RuleEngineBase.transferred +FNDA:9,RuleEngineBase.transferred +DA:53,8 +DA:57,2 +FN:57,RuleEngineBase.created +FNDA:2,RuleEngineBase.created +DA:58,1 +DA:62,2 +FN:62,RuleEngineBase.destroyed +FNDA:2,RuleEngineBase.destroyed +DA:63,1 +DA:76,21 +FN:76,RuleEngineBase.detectTransferRestriction +FNDA:21,RuleEngineBase.detectTransferRestriction +DA:81,39 +DA:82,39 +DA:83,39 +DA:85,39 +BRDA:85,0,0,28 +DA:86,28 +DA:89,11 +DA:95,11 +FN:95,RuleEngineBase.detectTransferRestrictionFrom +FNDA:11,RuleEngineBase.detectTransferRestrictionFrom +DA:101,25 +DA:102,25 +DA:103,25 +DA:105,25 +BRDA:105,1,0,19 +DA:106,19 +DA:110,6 +DA:116,13 +FN:116,RuleEngineBase.messageForTransferRestriction +FNDA:13,RuleEngineBase.messageForTransferRestriction +DA:120,13 +DA:121,13 +DA:123,10 +DA:125,8 +BRDA:125,2,0,8 +DA:126,8 +DA:127,8 +DA:131,5 +DA:137,18 +FN:137,RuleEngineBase.canTransfer +FNDA:18,RuleEngineBase.canTransfer +DA:142,18 +DA:143,18 +DA:150,14 +FN:150,RuleEngineBase.canTransferFrom +FNDA:14,RuleEngineBase.canTransferFrom +DA:156,14 +DA:157,14 +DA:166,98 +FN:166,RuleEngineBase.hasRole +FNDA:98,RuleEngineBase.hasRole +DA:170,293 +BRDA:170,3,0,165 +BRDA:170,3,1,128 +DA:171,165 +DA:173,128 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 +LF:40 +LH:40 +BRF:5 +BRH:5 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 -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 -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 -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 +SF:src/modules/ERC3643ComplianceModule.sol +DA:27,3 +FN:27,ERC3643ComplianceModule.onlyBoundToken +FNDA:3,ERC3643ComplianceModule.onlyBoundToken +DA:28,3 +BRDA:28,0,0,1 +DA:29,1 +DA:40,11 +FN:40,ERC3643ComplianceModule.bindToken +FNDA:11,ERC3643ComplianceModule.bindToken +DA:41,11 +DA:45,4 +FN:45,ERC3643ComplianceModule.unbindToken +FNDA:4,ERC3643ComplianceModule.unbindToken +DA:46,4 +DA:50,6 +FN:50,ERC3643ComplianceModule.isTokenBound +FNDA:6,ERC3643ComplianceModule.isTokenBound +DA:51,6 +DA:55,2 +FN:55,ERC3643ComplianceModule.getTokenBound +FNDA:2,ERC3643ComplianceModule.getTokenBound +DA:56,2 +BRDA:56,1,0,1 +BRDA:56,1,1,1 +DA:59,1 +DA:61,1 DA:66,2 -DA:69,3 -FN:77,RuleSanctionList.canReturnTransferRestrictionCode -FNDA:3,RuleSanctionList.canReturnTransferRestrictionCode -DA:80,3 +FN:66,ERC3643ComplianceModule.getTokenBounds +FNDA:2,ERC3643ComplianceModule.getTokenBounds +DA:67,2 +DA:76,4 +FN:76,ERC3643ComplianceModule._unbindToken +FNDA:4,ERC3643ComplianceModule._unbindToken +DA:77,4 +BRDA:77,2,0,1 +BRDA:77,2,1,3 +DA:79,3 +BRDA:79,3,0,- +BRDA:79,3,1,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 +DA:83,26 +FN:83,ERC3643ComplianceModule._bindToken +FNDA:26,ERC3643ComplianceModule._bindToken +DA:84,26 +BRDA:84,4,0,1 +BRDA:84,4,1,25 +DA:85,25 +BRDA:85,5,0,1 +BRDA:85,5,1,24 +DA:87,24 +BRDA:87,6,0,- +BRDA:87,6,1,24 +DA:88,24 +FNF:8 +FNH:8 +LF:24 +LH:24 +BRF:13 BRH:11 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 -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: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 -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 -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 -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 -FNF:6 -FNH:6 -LF:22 -LH:22 -BRF:4 -BRH:4 +SF:src/modules/RulesManagementModule.sol +DA:36,34 +FN:36,RulesManagementModule.setRules +FNDA:34,RulesManagementModule.setRules +DA:39,33 +BRDA:39,0,0,4 +DA:40,4 +DA:42,29 +BRDA:42,1,0,27 +DA:43,27 +DA:45,29 +DA:46,47 +DA:48,45 +BRDA:48,2,0,- +BRDA:48,2,1,45 +DA:49,45 +DA:56,10 +FN:56,RulesManagementModule.clearRules +FNDA:10,RulesManagementModule.clearRules +DA:57,9 +DA:63,95 +FN:63,RulesManagementModule.addRule +FNDA:95,RulesManagementModule.addRule +DA:66,94 +DA:67,90 +BRDA:67,3,0,- +BRDA:67,3,1,90 +DA:68,90 +DA:74,11 +FN:74,RulesManagementModule.removeRule +FNDA:11,RulesManagementModule.removeRule +DA:77,10 +BRDA:77,4,0,2 +BRDA:77,4,1,8 +DA:78,8 +DA:86,115 +FN:86,RulesManagementModule.rulesCount +FNDA:115,RulesManagementModule.rulesCount +DA:87,192 +DA:93,35 +FN:93,RulesManagementModule.containsRule +FNDA:35,RulesManagementModule.containsRule +DA:94,35 +DA:101,3 +FN:101,RulesManagementModule.rule +FNDA:3,RulesManagementModule.rule +DA:104,85 +BRDA:104,5,0,84 +BRDA:104,5,1,1 +DA:107,84 +DA:109,1 +DA:116,10 +FN:116,RulesManagementModule.rules +FNDA:10,RulesManagementModule.rules +DA:123,10 +DA:133,36 +FN:133,RulesManagementModule._clearRules +FNDA:36,RulesManagementModule._clearRules +DA:134,36 +DA:135,36 +DA:145,8 +FN:145,RulesManagementModule._removeRule +FNDA:8,RulesManagementModule._removeRule +DA:147,8 +BRDA:147,6,0,- +BRDA:147,6,1,8 +DA:148,8 +DA:154,141 +FN:154,RulesManagementModule._checkRule +FNDA:141,RulesManagementModule._checkRule +DA:155,141 +BRDA:155,7,0,2 +DA:156,2 +DA:158,139 +BRDA:158,8,0,4 +DA:159,4 +DA:172,10 +FN:172,RulesManagementModule._transferred +FNDA:10,RulesManagementModule._transferred +DA:177,10 +DA:178,10 +DA:179,7 +DA:194,2 +FN:194,RulesManagementModule._transferred +FNDA:2,RulesManagementModule._transferred +DA:200,2 +DA:201,2 +DA:202,2 +FNF:13 +FNH:13 +LF:47 +LH:47 +BRF:14 +BRH:11 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 +SF:src/modules/VersionModule.sol +DA:21,1 +FN:21,VersionModule.version +FNDA:1,VersionModule.version +DA:22,1 FNF:1 FNH:1 LF:2 @@ -997,95 +274,3 @@ 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 -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 -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 -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 -end_of_record diff --git a/doc/functionalities.odt b/doc/functionalities.odt deleted file mode 100644 index 3ff1fd4..0000000 Binary files a/doc/functionalities.odt and /dev/null differ diff --git a/doc/functionalities.pdf b/doc/functionalities.pdf deleted file mode 100644 index 7c5cf1c..0000000 Binary files a/doc/functionalities.pdf and /dev/null differ diff --git a/doc/other/CMTAT/checkTransferred.png b/doc/other/CMTAT/checkTransferred.png new file mode 100644 index 0000000..317ff56 Binary files /dev/null and b/doc/other/CMTAT/checkTransferred.png differ diff --git a/doc/other/CMTAT/transferred.png b/doc/other/CMTAT/transferred.png new file mode 100644 index 0000000..f378b43 Binary files /dev/null and b/doc/other/CMTAT/transferred.png differ diff --git a/doc/schema/Engine-RuleEngine.drawio.png b/doc/schema/Engine-RuleEngine.drawio.png deleted file mode 100644 index ceccf1e..0000000 Binary files a/doc/schema/Engine-RuleEngine.drawio.png and /dev/null differ diff --git a/doc/schema/RuleEngine b/doc/schema/RuleEngine deleted file mode 100644 index e908186..0000000 --- a/doc/schema/RuleEngine +++ /dev/null @@ -1 +0,0 @@ -1VpLc+I4EP41VO0e4rIkP/AxkMzMYac2NWEnm70JW4AqxqJkMcD8+pWxbCzJBEIwIblEar3s7q+/7hbuoeF8/ZXjxew7S0jag26y7qG7HoQA+VD+KySbUuL3+6VgymmiJu0Ej/Q3UUJXSZc0Ibk2UTCWCrrQhTHLMhILTYY5Zyt92oSl+qkLPCWW4DHGqS19oomYlVKIULAb+EbodFYdHfheOTLH1Wz1KvkMJ2zVEKH7HhpyxkTZmq+HJC20VymmXPdlz2j9ZJxk4pgF3og/hzzA5Gnz9/PLqj/65+d/N2qXXzhdqjcefh/djtQTi02lh9WMCvK4wHHRX0lb99BgJuap7AHZxPmi1P6Erok8b2A/XHUS4YKsGyL1sF8JmxPBN3KKGoWhUpyCDvD9sr/aGQJUc2ZNG1RCrIw/rffeqUc2lIbeoC1oaQs4guMsnxD+h2A9OKxG/7Q0SLLktgCk7MUpznMa6yrkbJklhe7uXNmTauObf2XnxnVcACvJczHseCisBHfr5oK7TbP3QDiV7024Eu61icB8SsRhlJBEcxbbcg3L+C2GqWScpFjQX7qLtRlLnfDAqHziGhgA6sCAyLB3zpY8JmpV0yOMjWBgICwyNioVY220xU792qfDCVlwGrEXkhVakzwl7WZiSFLIomgu5+ltLJg07KDwJyr56i88JukDy6mgLJNTxkwINm9MuE3ptBgQzPBdthQpzciwZtBXsXK8//qGlSpKb4AEtYAk6Mp5PUvb5/JRV3dP/4Bz7tVtidvDfnjQX/2r8tcA6UhA7on+GkQGpEysdOyvgYUg6MgOTbAgIxUGbExJI2yd04iYyh1jCQLCW/x0TpOk2GPASU5/4/F2vwI+i+L1ti/sD3r+XSugXnUA04Pr7EkdouUnbZ7tOqgfIt0UZ0HKDQy1XW/6+g5sMslJJ6b1LdP+WKbkPptKZrRM+gHJkN+/umQo7IxPgc6n4cmE+skSG9PIsI9OJErP3OiyRNm3oCG4bEFXpiyyCMNpbjvV9fBkBewz8KQXeUBnNPA+pHTPhJFlO4SdRJYRsahi3A+SC07jbab5MSkUWVNRM4VsPzfkuyVF5/1Jl38sl7hXRSaBb0UMx238GRseSy1916AWeFlqqbRsRGopqa5ZdljUsXYgap8hSEeGbiK74qlr14uUPMC+sFDKAlenLOi2ZDSX1ZZdj3sXp77uUh14VfQUmtcD3olFYWgWhf6FCelt9woZy4pkJcH5bAsFoGOkkD9gIVOdbCuBLpJSiTn2Ul9AQxtLKhyqwNlxQARHR8TrglzkehpSUFVDvRVykZleB8ZGXUOuvVqVEpuUPprWkffhtN5WqAapPHYwlo1p0SDO1JFTngr1pDQvbM23Gi3nyXPrqZaGpWKErsbSXYcsLW5oK4+f0DQ1RMfXNm120y17BtMBFxzOX7wW03X3e4sdkf3LFyPwlGoEdES+R3Pvdd0Bh4EVpc9RjUTmT0Heq0VOx7wM7VTAGzt8B9AhS1ouPi5zSVbnCM0MQS3rIkmARwL1unEKgrNUzZHBrMD8yXIPMiUw8KYxTd1p7X18qzoPtW8CZKPc8bywtwOs3xnsm0h/brrBG2DfFTcfnRhfF+YtEg3Ows0W5UfQOS5P3o/6szO2fVONxl0RtuMCXydt4KEuWPttX38chrX7OWENPg2s95A5NGPRu8hcdncfm5XTd9/sofv/AQ== \ No newline at end of file diff --git a/doc/schema/RuleEngine.drawio b/doc/schema/RuleEngine.drawio new file mode 100644 index 0000000..dfe33f6 --- /dev/null +++ b/doc/schema/RuleEngine.drawio @@ -0,0 +1 @@ +5VpNk+I2EP01VG0OULbkD3zkY7I5ZGtmdyaZmdwMFqBaYxFZLLC/PpItY8sS4CEYSIULVlu07NdPr9USHThabj/TcLX4QiIUd4AVbTtw3AHA9nzIv4Rll1u8AOSGOcWR7FQanvFPJI2WtK5xhFKlIyMkZnilGqckSdCUKbaQUrJRu81IrI66CudIMzxPw1i3vuKILXIrgNArb/yG8HxRDO25Tn5nGRa95aukizAim4oJPnTgiBLC8qvldoRigV4BTP67Xw/c3T8ZRQlr8gPnhb771AvR6+7x/fum//LHn391pZcfYbyWbzz68jJ4kU/MdgUOmwVm6HkVTkV7w2PdgcMFW8a8ZfPLMF3l6M/wFvHxhjOSMBlN2+Vt/WGLkRFlaFsxyYf/jMgSMbrjXeRd4AS9oPrxcw+SWbYvcd6UcbKhtC2qISqMoeTGfD9UiR6/kAB+AEyogflCvqNEjM95h6iGKqfESlyul/FgygjlQAk8MOff7+EExU8kxQyThHeZEMbIstJhEOO5uMFILRZkzWKcoNF+RljtxMOzFPyB5Wr4m+D32kLf0dDX8EZJNBCiwFvTOExTPFWho2SdRIK/GWZoi9mbuNOzrL5sv4t7PRcW7fG20nm8qzSeEMX8xXjUzRHgwNPdW/ED0ZC+i2bpOmsVvg9GLiVrOkWn5zoL6RyxI/1kHFGkSKPOg0qgXUOgCxtFccjwD1VQTdGXIzwRzN+spBnk+AOVar6reslfXf6wKoE1X65f46xTI2OOjeYo4+P+zc+nqKdRFPQYDZN0hijlvAPWpxnlsxyMsjyXf2e9f9G5zMOTiURNiaUsTDk9EDXoxRJHkfAxpCjFP8NJ5k8QayXeOsPBHXbccSPRODoR60qyz9JyUCUPmhTG6sF+sYAoInYRTnWh6rVr91UXZDZLUSsUcDUKfFvH6CGZc8m+x6zrWeqUsV1d5vepV0mzfltCH2gQwlCdRv9O9s8U5n26qKaKo2micbhOSrvbUNqLZfW9aLuvkYvn2vJTc9hU5vugJvPgujJfoFyb5NxSlAIlN1XunZjwLczvoIZVYFhFg2su42xwCDz77sEzrYGvjJ5eg8BJT0jDzfWxMf6nVQzclYr5p1aVjXXLrjlyr6xbHyuhEpKIdWQUpouMHLbKGmF/ChlfhSaZBViQW1NGeU1c7KWAg0WX5NOV86jdOJHeFwUD4CjMge6ZFVJQr+q9mqO2KWheH3NLcvfqD52bq79vmMBezIcdThTsvL/XYtsxQ6WbZrAMRIZ1V9sMm+I+v5qLb9SbiyTyKjCOcSoIQ7Ow5M75w06KrlqYOJpMjUWuASMSix2vQkZmOI5rpua1rCn4Kj1aiL9tOf2TayfHEP/WKiNgyP7T62R/cE55ZF9J1hur+n1tffl9bT1wifIocOrrlaNV1+UUfzbZvD0uif01XbtfHzeDYDFeGE4gWmLoeevTGhXO4x9syr9bss0G+kYrPHMZYfuaL7vf2krCyCu9jLSrSsgvP93rDmvjnVOVjYen18EU1rV6ju0FatAvwibgKk73helFd1iNb6znwIdvoy70HCjCLw7kUi3Ul9loNcRNU4tzjzehZ1hctHa8aQT28gdsV1fqqgIfJs/NqrhaXj5XfUGgK7lzXfXVyzjwf1Rf59rqK704bZxnGd/QVHHeRBSMxy/7TaSPVBgfXfIdy0LNDttvJTgOn5WWW8k5atLOUhKs3HbO0yPXD3oQlAVGXZrsntc/PErLStU3KNV/7kz+kprlH9Ws9s7kgbrg6V5Awniz/H9d3r38myJ8+Ac= \ No newline at end of file diff --git a/doc/schema/RuleEngine.drawio.png b/doc/schema/RuleEngine.drawio.png new file mode 100644 index 0000000..0004966 Binary files /dev/null and b/doc/schema/RuleEngine.drawio.png differ diff --git a/doc/schema/RuleEngine.png b/doc/schema/RuleEngine.png deleted file mode 100644 index 3e891c6..0000000 Binary files a/doc/schema/RuleEngine.png and /dev/null differ diff --git a/doc/schema/RuleEngine.svg b/doc/schema/RuleEngine.svg deleted file mode 100644 index f597ee9..0000000 --- a/doc/schema/RuleEngine.svg +++ /dev/null @@ -1,596 +0,0 @@ - - - - - - -UmlClassDiagram - - - -0 - -<<Interface>> -IERC1404 -RuleEngine.sol - -External: -     detectTransferRestriction(_from: address, _to: address, _amount: uint256): uint8 -     messageForTransferRestriction(_restrictionCode: uint8): string - - - -1 - -<<Interface>> -IERC1404EnumCode -RuleEngine.sol - - - -2 - -<<Enum>> -REJECTED_CODE_BASE -RuleEngine.sol - -TRANSFER_OK: 0 -TRANSFER_REJECTED_PAUSED: 1 -TRANSFER_REJECTED_FROM_FROZEN: 2 -TRANSFER_REJECTED_TO_FROZEN: 3 - - - -2->1 - - - - - -3 - -<<Interface>> -IAccessControl -RuleEngine.sol - -External: -     hasRole(role: bytes32, account: address): bool -     getRoleAdmin(role: bytes32): bytes32 -     grantRole(role: bytes32, account: address) -     revokeRole(role: bytes32, account: address) -     renounceRole(role: bytes32, callerConfirmation: address) -Public: -    <<event>> RoleAdminChanged(role: bytes32, previousAdminRole: bytes32, newAdminRole: bytes32) -    <<event>> RoleGranted(role: bytes32, account: address, sender: address) -    <<event>> RoleRevoked(role: bytes32, account: address, sender: address) - - - -4 - -<<Abstract>> -Context -RuleEngine.sol - -Internal: -    _msgSender(): address -    _msgData(): bytes -    _contextSuffixLength(): uint256 - - - -5 - -<<Interface>> -IERC165 -RuleEngine.sol - -External: -     supportsInterface(interfaceId: bytes4): bool - - - -6 - -<<Interface>> -IRuleEngineOperation -RuleEngine.sol - -External: -     setRulesOperation(rules_: address[]) -     rulesCountOperation(): uint256 -     ruleOperation(ruleId: uint256): address -     rulesOperation(): address[] - - - -7 - -<<Interface>> -IRuleEngineValidation -RuleEngine.sol - -External: -     detectTransferRestrictionValidation(_from: address, _to: address, _amount: uint256): uint8 -     validateTransferValidation(_from: address, _to: address, _amount: uint256): (isValid: bool) - - - -8 - -<<Interface>> -IRuleEngineValidationCommon -RuleEngine.sol - -External: -     setRulesValidation(rules_: address[]) -     rulesCountValidation(): uint256 -     ruleValidation(ruleId: uint256): address -     rulesValidation(): address[] - - - -9 - -<<Interface>> -IRuleOperation -RuleEngine.sol - -External: -     operateOnTransfer(_from: address, _to: address, _amount: uint256): (isValid: bool) - - - -10 - -<<Abstract>> -RuleEngineInvariantStorage -RuleEngine.sol - -Public: -   RULE_ENGINE_OPERATOR_ROLE: bytes32 -   TOKEN_CONTRACT_ROLE: bytes32 - -Public: -    <<event>> AddRule(rule: address) -    <<event>> RemoveRule(rule: address) -    <<event>> ClearRules(rulesRemoved: address[]) - - - -11 - -<<Abstract>> -ERC2771Context -RuleEngine.sol - -Private: -   _trustedForwarder: address - -Internal: -    _msgSender(): address -    _msgData(): bytes -    _contextSuffixLength(): uint256 -Public: -    constructor(trustedForwarder_: address) -    trustedForwarder(): address -    isTrustedForwarder(forwarder: address): bool - - - -11->4 - - - - - -12 - -<<Abstract>> -ERC165 -RuleEngine.sol - -Public: -    supportsInterface(interfaceId: bytes4): bool - - - -12->5 - - - - - -13 - -<<Abstract>> -RuleInternal -RuleEngine.sol - -Public: -   _ruleIsPresent: mapping(address=>bool) - -Internal: -    _setRules(rules_: address[]) -    _addRule(_rules: address[], rule_: address) -    _removeRule(_rules: address[], rule_: address, index: uint256) -    _getRuleIndex(_rules: address[], rule_: address): (index: uint256) - - - -13->10 - - - - - -14 - -<<Interface>> -IERC1404Wrapper -RuleEngine.sol - -External: -     validateTransfer(_from: address, _to: address, _amount: uint256): (isValid: bool) - - - -14->0 - - - - - -14->1 - - - - - -15 - -<<Abstract>> -MetaTxModuleStandalone -RuleEngine.sol - -Public: -    constructor(trustedForwarder: address) - - - -15->11 - - - - - -16 - -<<Interface>> -IRuleEngine -RuleEngine.sol - -External: -     operateOnTransfer(_from: address, _to: address, _amount: uint256): (isValid: bool) - - - -16->14 - - - - - -17 - -<<Interface>> -IRuleValidation -RuleEngine.sol - -External: -     canReturnTransferRestrictionCode(_restrictionCode: uint8): bool - - - -17->14 - - - - - -18 - -<<Abstract>> -AccessControl -RuleEngine.sol - -Private: -   _roles: mapping(bytes32=>RoleData) -Public: -   DEFAULT_ADMIN_ROLE: bytes32 - -Internal: -    _checkRole(role: bytes32) -    _checkRole(role: bytes32, account: address) -    _setRoleAdmin(role: bytes32, adminRole: bytes32) -    _grantRole(role: bytes32, account: address): bool -    _revokeRole(role: bytes32, account: address): bool -Public: -    <<modifier>> onlyRole(role: bytes32) -    supportsInterface(interfaceId: bytes4): bool -    hasRole(role: bytes32, account: address): bool -    getRoleAdmin(role: bytes32): bytes32 -    grantRole(role: bytes32, account: address) <<onlyRole>> -    revokeRole(role: bytes32, account: address) <<onlyRole>> -    renounceRole(role: bytes32, callerConfirmation: address) - - - -18->3 - - - - - -18->4 - - - - - -18->12 - - - - - -19 - -<<Struct>> -RoleData -RuleEngine.sol - -hasRole: mapping(address=>bool) -adminRole: bytes32 - - - -18->19 - - - - - -19->18 - - - - - -20 - -<<Abstract>> -RuleEngineOperation -RuleEngine.sol - -Internal: -   _rulesOperation: address[] - -Internal: -    _clearRulesOperation() -    _removeRuleOperation(rule_: address, index: uint256) -    _operateOnTransfer(_from: address, _to: address, _amount: uint256): (isValid: bool) -External: -    rulesCountOperation(): uint256 -    getRuleIndexOperation(rule_: IRuleOperation): (index: uint256) -    ruleOperation(ruleId: uint256): address -    rulesOperation(): address[] -Public: -    setRulesOperation(rules_: address[]) <<onlyRole>> -    clearRulesOperation() <<onlyRole>> -    addRuleOperation(rule_: IRuleOperation) <<onlyRole>> -    removeRuleOperation(rule_: IRuleOperation, index: uint256) <<onlyRole>> - - - -20->6 - - - - - -20->9 - - - - - -20->13 - - - - - -20->18 - - - - - -21 - -<<Abstract>> -RuleEngineValidationCommon -RuleEngine.sol - -Internal: -   _rulesValidation: address[] - -Internal: -    _clearRulesValidation() -    _removeRuleValidation(rule_: address, index: uint256) -External: -    rulesCountValidation(): uint256 -    getRuleIndexValidation(rule_: IRuleValidation): (index: uint256) -    ruleValidation(ruleId: uint256): address -    rulesValidation(): address[] -Public: -    setRulesValidation(rules_: address[]) <<onlyRole>> -    clearRulesValidation() <<onlyRole>> -    addRuleValidation(rule_: IRuleValidation) <<onlyRole>> -    removeRuleValidation(rule_: IRuleValidation, index: uint256) <<onlyRole>> - - - -21->8 - - - - - -21->13 - - - - - -21->17 - - - - - -21->18 - - - - - -22 - -<<Abstract>> -RuleEngineValidation -RuleEngine.sol - -Public: -    detectTransferRestrictionValidation(_from: address, _to: address, _amount: uint256): uint8 -    validateTransferValidation(_from: address, _to: address, _amount: uint256): bool - - - -22->1 - - - - - -22->2 - - - - - -22->7 - - - - - -22->13 - - - - - -22->17 - - - - - -22->18 - - - - - -22->21 - - - - - -23 - -RuleEngine -RuleEngine.sol - -Public: -   VERSION: string - -Internal: -    _msgSender(): (sender: address) -    _msgData(): bytes -    _contextSuffixLength(): uint256 -External: -    messageForTransferRestriction(_restrictionCode: uint8): string -    operateOnTransfer(from: address, to: address, amount: uint256): (isValid: bool) <<onlyRole>> -Public: -    constructor(admin: address, forwarderIrrevocable: address, tokenContract: address) -    detectTransferRestriction(_from: address, _to: address, _amount: uint256): uint8 -    validateTransfer(_from: address, _to: address, _amount: uint256): bool -    hasRole(role: bytes32, account: address): bool - - - -23->2 - - - - - -23->11 - - - - - -23->15 - - - - - -23->16 - - - - - -23->17 - - - - - -23->18 - - - - - -23->20 - - - - - -23->22 - - - - - diff --git a/doc/schema/classDiagram.svg b/doc/schema/classDiagram.svg index f407eb7..d3a0e65 100644 --- a/doc/schema/classDiagram.svg +++ b/doc/schema/classDiagram.svg @@ -4,1005 +4,1539 @@ - - + + UmlClassDiagram - + 0 - -RuleEngine -src/RuleEngine.sol - -Internal: -    _msgSender(): (sender: address) -    _msgData(): bytes -    _contextSuffixLength(): uint256 -External: -    messageForTransferRestriction(_restrictionCode: uint8): string -    operateOnTransfer(from: address, to: address, amount: uint256): (isValid: bool) <<onlyRole>> -Public: -    constructor(admin: address, forwarderIrrevocable: address, tokenContract: address) -    detectTransferRestriction(_from: address, _to: address, _amount: uint256): uint8 -    validateTransfer(_from: address, _to: address, _amount: uint256): bool - - - -5 - -<<Interface>> -IRuleValidation -src/interfaces/IRuleValidation.sol - -External: -     canReturnTransferRestrictionCode(_restrictionCode: uint8): bool - - - -0->5 - - - - - -6 - -<<Abstract>> -MetaTxModuleStandalone -src/modules/MetaTxModuleStandalone.sol - -Public: -    constructor(trustedForwarder: address) - - - -0->6 - - - - - -8 - -<<Abstract>> -RuleEngineOperation -src/modules/RuleEngineOperation.sol - -Internal: -   _rulesOperation: address[] - -Internal: -    _clearRulesOperation() -    _removeRuleOperation(rule_: address, index: uint256) -    _operateOnTransfer(_from: address, _to: address, _amount: uint256): (isValid: bool) -External: -    rulesCountOperation(): uint256 -    getRuleIndexOperation(rule_: IRuleOperation): (index: uint256) -    ruleOperation(ruleId: uint256): address -    rulesOperation(): address[] -Public: -    setRulesOperation(rules_: address[]) <<onlyRole>> -    clearRulesOperation() <<onlyRole>> -    addRuleOperation(rule_: IRuleOperation) <<onlyRole>> -    removeRuleOperation(rule_: IRuleOperation, index: uint256) <<onlyRole>> - - - -0->8 - - - - - -9 - -<<Abstract>> -RuleEngineValidation -src/modules/RuleEngineValidation.sol - -Public: -    detectTransferRestrictionValidation(_from: address, _to: address, _amount: uint256): uint8 -    validateTransferValidation(_from: address, _to: address, _amount: uint256): bool - - - -0->9 - - + +<<Interface>> +IERC3643Pause +RuleEngineFlatten.sol + +External: +     paused(): bool +     pause() +     unpause() 1 - -<<Interface>> -IRuleEngineOperation -src/interfaces/IRuleEngineOperation.sol - -External: -     setRulesOperation(rules_: address[]) -     rulesCountOperation(): uint256 -     ruleOperation(ruleId: uint256): address -     rulesOperation(): address[] + +<<Interface>> +IERC3643ERC20Base +RuleEngineFlatten.sol + +External: +     setName(name: string) +     setSymbol(symbol: string) 2 - -<<Interface>> -IRuleEngineValidation -src/interfaces/IRuleEngineValidation.sol - -External: -     detectTransferRestrictionValidation(_from: address, _to: address, _amount: uint256): uint8 -     validateTransferValidation(_from: address, _to: address, _amount: uint256): (isValid: bool) + +<<Interface>> +IERC3643BatchTransfer +RuleEngineFlatten.sol + +External: +     batchTransfer(tos: address[], values: uint256[]): (success_: bool) 3 - -<<Interface>> -IRuleEngineValidationCommon -src/interfaces/IRuleEngineValidation.sol - -External: -     setRulesValidation(rules_: address[]) -     rulesCountValidation(): uint256 -     ruleValidation(ruleId: uint256): address -     rulesValidation(): address[] + +<<Interface>> +IERC3643Base +RuleEngineFlatten.sol + +External: +     version(): (version_: string) 4 - -<<Interface>> -IRuleOperation -src/interfaces/IRuleOperation.sol - -External: -     operateOnTransfer(_from: address, _to: address, _amount: uint256): (isValid: bool) + +<<Interface>> +IERC3643EnforcementEvent +RuleEngineFlatten.sol + +Public: +    <<event>> AddressFrozen(account: address, isFrozen: bool, enforcer: address, data: bytes) + + + +5 + +<<Interface>> +IERC3643Enforcement +RuleEngineFlatten.sol + +External: +     isFrozen(account: address): (isFrozen_: bool) +     setAddressFrozen(account: address, freeze: bool) +     batchSetAddressFrozen(accounts: address[], freeze: bool[]) + + + +6 + +<<Interface>> +IERC3643ERC20Enforcement +RuleEngineFlatten.sol + +External: +     getFrozenTokens(account: address): (frozenBalance_: uint256) +     freezePartialTokens(account: address, value: uint256) +     unfreezePartialTokens(account: address, value: uint256) +     forcedTransfer(from: address, to: address, value: uint256): (success_: bool) 7 - -<<Abstract>> -RuleEngineInvariantStorage -src/modules/RuleEngineInvariantStorage.sol - -Public: -   RULE_ENGINE_OPERATOR_ROLE: bytes32 -   TOKEN_CONTRACT_ROLE: bytes32 - -Public: -    <<event>> AddRule(rule: address) -    <<event>> RemoveRule(rule: address) -    <<event>> ClearRules(rulesRemoved: address[]) - - - -8->1 - - + +<<Interface>> +IERC3643Mint +RuleEngineFlatten.sol + +External: +     mint(account: address, value: uint256) +     batchMint(accounts: address[], values: uint256[]) - - -8->4 - - + + +8 + +<<Interface>> +IERC3643Burn +RuleEngineFlatten.sol + +External: +     burn(account: address, value: uint256) +     batchBurn(accounts: address[], values: uint256[]) + + + +9 + +<<Interface>> +IERC3643ComplianceRead +RuleEngineFlatten.sol + +External: +     canTransfer(from: address, to: address, value: uint256): (isValid: bool) + + + +10 + +<<Interface>> +IERC3643IComplianceContract +RuleEngineFlatten.sol + +External: +     transferred(from: address, to: address, value: uint256) 11 - -<<Abstract>> -RuleInternal -src/modules/RuleInternal.sol - -Public: -   _ruleIsPresent: mapping(address=>bool) - -Internal: -    _setRules(rules_: address[]) -    _addRule(_rules: address[], rule_: address) -    _removeRule(_rules: address[], rule_: address, index: uint256) -    _getRuleIndex(_rules: address[], rule_: address): (index: uint256) - - - -8->11 - - + +<<Interface>> +IERC1404 +RuleEngineFlatten.sol + +External: +     detectTransferRestriction(from: address, to: address, value: uint256): uint8 +     messageForTransferRestriction(restrictionCode: uint8): string - - -9->2 - - + + +12 + +<<Interface>> +IERC1404Extend +RuleEngineFlatten.sol + +External: +     detectTransferRestrictionFrom(spender: address, from: address, to: address, value: uint256): uint8 + + + +12->11 + + - - -9->5 - - + + +13 + +<<Enum>> +REJECTED_CODE_BASE +RuleEngineFlatten.sol + +TRANSFER_OK: 0 +TRANSFER_REJECTED_DEACTIVATED: 1 +TRANSFER_REJECTED_PAUSED: 2 +TRANSFER_REJECTED_FROM_FROZEN: 3 +TRANSFER_REJECTED_TO_FROZEN: 4 +TRANSFER_REJECTED_SPENDER_FROZEN: 5 +TRANSFER_REJECTED_FROM_INSUFFICIENT_ACTIVE_BALANCE: 6 + + + +13->12 + + - - -10 - -<<Abstract>> -RuleEngineValidationCommon -src/modules/RuleEngineValidationCommon.sol - -Internal: -   _rulesValidation: address[] - -Internal: -    _clearRulesValidation() -    _removeRuleValidation(rule_: address, index: uint256) -External: -    rulesCountValidation(): uint256 -    getRuleIndexValidation(rule_: IRuleValidation): (index: uint256) -    ruleValidation(ruleId: uint256): address -    rulesValidation(): address[] -Public: -    setRulesValidation(rules_: address[]) <<onlyRole>> -    clearRulesValidation() <<onlyRole>> -    addRuleValidation(rule_: IRuleValidation) <<onlyRole>> -    removeRuleValidation(rule_: IRuleValidation, index: uint256) <<onlyRole>> - - - -9->10 - - + + +14 + +<<Interface>> +IAccessControl +RuleEngineFlatten.sol + +External: +     hasRole(role: bytes32, account: address): bool +     getRoleAdmin(role: bytes32): bytes32 +     grantRole(role: bytes32, account: address) +     revokeRole(role: bytes32, account: address) +     renounceRole(role: bytes32, callerConfirmation: address) +Public: +    <<event>> RoleAdminChanged(role: bytes32, previousAdminRole: bytes32, newAdminRole: bytes32) +    <<event>> RoleGranted(role: bytes32, account: address, sender: address) +    <<event>> RoleRevoked(role: bytes32, account: address, sender: address) - - -9->11 - - + + +15 + +<<Library>> +Comparators +RuleEngineFlatten.sol + +Internal: +    lt(a: uint256, b: uint256): bool +    gt(a: uint256, b: uint256): bool - - -10->3 - - + + +16 + +<<Abstract>> +Context +RuleEngineFlatten.sol + +Internal: +    _msgSender(): address +    _msgData(): bytes +    _contextSuffixLength(): uint256 - - -10->5 - - + + +17 + +<<Library>> +Panic +RuleEngineFlatten.sol + +Internal: +   GENERIC: uint256 +   ASSERT: uint256 +   UNDER_OVERFLOW: uint256 +   DIVISION_BY_ZERO: uint256 +   ENUM_CONVERSION_ERROR: uint256 +   STORAGE_ENCODING_ERROR: uint256 +   EMPTY_ARRAY_POP: uint256 +   ARRAY_OUT_OF_BOUNDS: uint256 +   RESOURCE_ERROR: uint256 +   INVALID_INTERNAL_FUNCTION: uint256 + +Internal: +    panic(code: uint256) - - -10->11 - - + + +18 + +<<Library>> +SlotDerivation +RuleEngineFlatten.sol + +Internal: +    erc7201Slot(namespace: string): (slot: bytes32) +    offset(slot: bytes32, pos: uint256): (result: bytes32) +    deriveArray(slot: bytes32): (result: bytes32) +    deriveMapping(slot: bytes32, key: address): (result: bytes32) +    deriveMapping(slot: bytes32, key: bool): (result: bytes32) +    deriveMapping(slot: bytes32, key: bytes32): (result: bytes32) +    deriveMapping(slot: bytes32, key: uint256): (result: bytes32) +    deriveMapping(slot: bytes32, key: int256): (result: bytes32) +    deriveMapping(slot: bytes32, key: string): (result: bytes32) +    deriveMapping(slot: bytes32, key: bytes): (result: bytes32) - - -11->7 - - + + +19 + +<<Library>> +StorageSlot +RuleEngineFlatten.sol + +Internal: +    getAddressSlot(slot: bytes32): (r: AddressSlot) +    getBooleanSlot(slot: bytes32): (r: BooleanSlot) +    getBytes32Slot(slot: bytes32): (r: Bytes32Slot) +    getUint256Slot(slot: bytes32): (r: Uint256Slot) +    getInt256Slot(slot: bytes32): (r: Int256Slot) +    getStringSlot(slot: bytes32): (r: StringSlot) +    getStringSlot(store: string): (r: StringSlot) +    getBytesSlot(slot: bytes32): (r: BytesSlot) +    getBytesSlot(store: bytes): (r: BytesSlot) - - -12 - -RuleConditionalTransfer -src/rules/operation/RuleConditionalTransfer.sol - -Internal: -    _cancelTransferRequest(requestId_: uint256) -    _validateBurnMint(_from: address, _to: address): (isValid: bool) -    _validateApproval(key: bytes32): (isValid: bool) -    _msgSender(): (sender: address) -    _msgData(): bytes -    _contextSuffixLength(): uint256 -External: -    canReturnTransferRestrictionCode(_restrictionCode: uint8): bool -    messageForTransferRestriction(_restrictionCode: uint8): string -Public: -    constructor(admin: address, forwarderIrrevocable: address, ruleEngineContract: IRuleEngine, options_: OPTION) -    operateOnTransfer(_from: address, _to: address, _amount: uint256): (isValid: bool) <<onlyRole>> -    createTransferRequest(to: address, value: uint256) -    createTransferRequestBatch(tos: address[], values: uint256[]) -    cancelTransferRequest(requestId_: uint256) -    cancelTransferRequestBatch(requestIds: uint256[]) -    getRequestTrade(from: address, to: address, value: uint256): TransferRequest -    getRequestByStatus(_targetStatus: STATUS): TransferRequest[] -    detectTransferRestriction(_from: address, _to: address, _amount: uint256): uint8 - - - -12->4 - - + + +20 + +<<Struct>> +AddressSlot +RuleEngineFlatten.sol + +value: address + + + +19->20 + + - - -12->6 - - + + +21 + +<<Struct>> +BooleanSlot +RuleEngineFlatten.sol + +value: bool + + + +19->21 + + + + + +22 + +<<Struct>> +Bytes32Slot +RuleEngineFlatten.sol + +value: bytes32 + + + +19->22 + + - + 23 - -<<Struct>> -OPTION -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol - -issuance: ISSUANCE -timeLimit: TIME_LIMIT -automaticApproval: AUTOMATIC_APPROVAL -automaticTransfer: AUTOMATIC_TRANSFER - - - -12->23 - - + +<<Struct>> +Uint256Slot +RuleEngineFlatten.sol + +value: uint256 + + + +19->23 + + - + 24 - -<<Struct>> -TransferRequestKeyElement -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol - -from: address -to: address -value: uint256 - - - -12->24 - - + +<<Struct>> +Int256Slot +RuleEngineFlatten.sol + +value: int256 + + + +19->24 + + - + 25 - -<<Struct>> -TransferRequest -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol - -key: bytes32 -id: uint256 -keyElement: TransferRequestKeyElement -askTime: uint256 -maxTime: uint256 -status: STATUS - - - -12->25 - - + +<<Struct>> +StringSlot +RuleEngineFlatten.sol + +value: string + + + +19->25 + + - + 26 - -<<Enum>> -STATUS -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol - -NONE: 0 -WAIT: 1 -APPROVED: 2 -DENIED: 3 -EXECUTED: 4 - - - -12->26 - - - - - -27 - -<<Abstract>> -RuleConditionalTransferOperator -src/rules/operation/abstract/RuleConditionalTransferOperator.sol - -Public: -   options: OPTION -   requestId: uint256 -   IdToKey: mapping(uint256=>bytes32) -   transferRequests: mapping(bytes32=>TransferRequest) -   whitelistConditionalTransfer: RuleWhitelist - -Internal: -    _approveTransferRequestKeyElement(keyElement: TransferRequestKeyElement, partialValue: uint256, isApproved: bool) -    _resetRequestStatus(key: bytes32) -    _checkRequestStatus(key: bytes32): bool -    _approveRequest(transferRequest: TransferRequest, isApproved: bool) -    _updateProcessedTransfer(key: bytes32) -Public: -    setConditionalWhitelist(newWhitelistConditionalTransfer: RuleWhitelist) <<onlyRole>> -    setIssuanceOptions(issuance_: ISSUANCE) <<onlyRole>> -    setAutomaticTransfer(automaticTransfer_: AUTOMATIC_TRANSFER) <<onlyRole>> -    setTimeLimit(timeLimit_: TIME_LIMIT) <<onlyRole>> -    setAutomaticApproval(automaticApproval_: AUTOMATIC_APPROVAL) <<onlyRole>> -    createTransferRequestWithApproval(keyElement: TransferRequestKeyElement) <<onlyRole>> -    approveTransferRequest(keyElement: TransferRequestKeyElement, partialValue: uint256, isApproved: bool) <<onlyRole>> -    approveTransferRequestWithId(requestId_: uint256, isApproved: bool) <<onlyRole>> -    resetRequestStatus(requestId_: uint256) <<onlyRole>> -    approveTransferRequestBatchWithId(requestId_: uint256[], isApproved: bool[]) <<onlyRole>> -    approveTransferRequestBatch(keyElements: TransferRequestKeyElement[], partialValues: uint256[], isApproved: bool[]) <<onlyRole>> -    createTransferRequestWithApprovalBatch(keyElements: TransferRequestKeyElement[]) <<onlyRole>> -    resetRequestStatusBatch(requestIds: uint256[]) <<onlyRole>> -    _createTransferRequestWithApproval(keyElement_: TransferRequestKeyElement) <<onlyRole>> - - - -12->27 - - - - - -30 - -<<Abstract>> -RuleValidateTransfer -src/rules/validation/abstract/RuleValidateTransfer.sol - -Public: -    validateTransfer(_from: address, _to: address, _amount: uint256): (isValid: bool) - - + +<<Struct>> +BytesSlot +RuleEngineFlatten.sol + +value: bytes + + -12->30 - - +19->26 + + - - -19 - -<<Struct>> -AUTOMATIC_TRANSFER -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol - -isActivate: bool -cmtat: IERC20 - - - -18 - -<<Abstract>> -RuleConditionalTransferInvariantStorage -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol - -Public: -   RULE_ENGINE_CONTRACT_ROLE: bytes32 -   RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE: bytes32 -   TEXT_TRANSFER_REQUEST_NOT_APPROVED: string -   CODE_TRANSFER_REQUEST_NOT_APPROVED: uint8 - -Public: -    <<event>> transferProcessed(key: bytes32, from: address, to: address, value: uint256, id: uint256) -    <<event>> transferWaiting(key: bytes32, from: address, to: address, value: uint256, id: uint256) -    <<event>> transferApproved(key: bytes32, from: address, to: address, value: uint256, id: uint256) -    <<event>> transferDenied(key: bytes32, from: address, to: address, value: uint256, id: uint256) -    <<event>> transferReset(key: bytes32, from: address, to: address, value: uint256, id: uint256) -    <<event>> WhitelistConditionalTransfer(whitelistConditionalTransfer: RuleWhitelist) - - - -19->18 - - - - - -20 - -<<Struct>> -ISSUANCE -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol - -authorizedMintWithoutApproval: bool -authorizedBurnWithoutApproval: bool - - - -20->18 - - + + +20->19 + + - - -21 - -<<Struct>> -TIME_LIMIT -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol - -timeLimitToApprove: uint256 -timeLimitToTransfer: uint256 - - - -21->18 - - + + +21->19 + + - - -22 - -<<Struct>> -AUTOMATIC_APPROVAL -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol - -isActivate: bool -timeLimitBeforeAutomaticApproval: uint256 - - - -22->18 - - + + +22->19 + + - + 23->19 - - + + - - -23->20 - - + + +24->19 + + - - -23->21 - - + + +25->19 + + - - -23->22 - - + + +26->19 + + - - -23->18 - - + + +27 + +<<Interface>> +IERC165 +RuleEngineFlatten.sol + +External: +     supportsInterface(interfaceId: bytes4): bool - - -24->18 - - + + +28 + +<<Library>> +SafeCast +RuleEngineFlatten.sol + +Internal: +    toUint248(value: uint256): uint248 +    toUint240(value: uint256): uint240 +    toUint232(value: uint256): uint232 +    toUint224(value: uint256): uint224 +    toUint216(value: uint256): uint216 +    toUint208(value: uint256): uint208 +    toUint200(value: uint256): uint200 +    toUint192(value: uint256): uint192 +    toUint184(value: uint256): uint184 +    toUint176(value: uint256): uint176 +    toUint168(value: uint256): uint168 +    toUint160(value: uint256): uint160 +    toUint152(value: uint256): uint152 +    toUint144(value: uint256): uint144 +    toUint136(value: uint256): uint136 +    toUint128(value: uint256): uint128 +    toUint120(value: uint256): uint120 +    toUint112(value: uint256): uint112 +    toUint104(value: uint256): uint104 +    toUint96(value: uint256): uint96 +    toUint88(value: uint256): uint88 +    toUint80(value: uint256): uint80 +    toUint72(value: uint256): uint72 +    toUint64(value: uint256): uint64 +    toUint56(value: uint256): uint56 +    toUint48(value: uint256): uint48 +    toUint40(value: uint256): uint40 +    toUint32(value: uint256): uint32 +    toUint24(value: uint256): uint24 +    toUint16(value: uint256): uint16 +    toUint8(value: uint256): uint8 +    toUint256(value: int256): uint256 +    toInt248(value: int256): (downcasted: int248) +    toInt240(value: int256): (downcasted: int240) +    toInt232(value: int256): (downcasted: int232) +    toInt224(value: int256): (downcasted: int224) +    toInt216(value: int256): (downcasted: int216) +    toInt208(value: int256): (downcasted: int208) +    toInt200(value: int256): (downcasted: int200) +    toInt192(value: int256): (downcasted: int192) +    toInt184(value: int256): (downcasted: int184) +    toInt176(value: int256): (downcasted: int176) +    toInt168(value: int256): (downcasted: int168) +    toInt160(value: int256): (downcasted: int160) +    toInt152(value: int256): (downcasted: int152) +    toInt144(value: int256): (downcasted: int144) +    toInt136(value: int256): (downcasted: int136) +    toInt128(value: int256): (downcasted: int128) +    toInt120(value: int256): (downcasted: int120) +    toInt112(value: int256): (downcasted: int112) +    toInt104(value: int256): (downcasted: int104) +    toInt96(value: int256): (downcasted: int96) +    toInt88(value: int256): (downcasted: int88) +    toInt80(value: int256): (downcasted: int80) +    toInt72(value: int256): (downcasted: int72) +    toInt64(value: int256): (downcasted: int64) +    toInt56(value: int256): (downcasted: int56) +    toInt48(value: int256): (downcasted: int48) +    toInt40(value: int256): (downcasted: int40) +    toInt32(value: int256): (downcasted: int32) +    toInt24(value: int256): (downcasted: int24) +    toInt16(value: int256): (downcasted: int16) +    toInt8(value: int256): (downcasted: int8) +    toInt256(value: uint256): int256 +    toUint(b: bool): (u: uint256) - - -25->24 - - + + +29 + +<<Abstract>> +RuleEngineInvariantStorage +RuleEngineFlatten.sol - - -25->26 - - + + +30 + +<<Interface>> +IERC7551Mint +RuleEngineFlatten.sol + +External: +     mint(account: address, value: uint256, data: bytes) +Public: +    <<event>> Mint(minter: address, account: address, value: uint256, data: bytes) - - -25->18 - - + + +31 + +<<Interface>> +IERC7551Burn +RuleEngineFlatten.sol + +External: +     burn(account: address, amount: uint256, data: bytes) +Public: +    <<event>> Burn(burner: address, account: address, value: uint256, data: bytes) - - -26->18 - - + + +32 + +<<Interface>> +IERC7551Pause +RuleEngineFlatten.sol + +External: +     paused(): bool +     pause() +     unpause() - + -28 - -<<Abstract>> -RuleCommonInvariantStorage -src/rules/validation/abstract/RuleCommonInvariantStorage.sol - -Public: -   TEXT_CODE_NOT_FOUND: string - - - -18->28 - - +33 + +<<Interface>> +IERC7551ERC20EnforcementEvent +RuleEngineFlatten.sol + +Public: +    <<event>> Enforcement(enforcer: address, account: address, amount: uint256, data: bytes) - - -27->19 - - + + +34 + +<<Interface>> +IERC7551ERC20EnforcementTokenFrozenEvent +RuleEngineFlatten.sol + +Public: +    <<event>> TokensFrozen(account: address, value: uint256, data: bytes) +    <<event>> TokensUnfrozen(account: address, value: uint256, data: bytes) - - -27->20 - - + + +35 + +<<Interface>> +IERC7551ERC20Enforcement +RuleEngineFlatten.sol + +External: +     getActiveBalanceOf(account: address): (activeBalance_: uint256) +     getFrozenTokens(account: address): (frozenBalance_: uint256) +     freezePartialTokens(account: address, amount: uint256, data: bytes) +     unfreezePartialTokens(account: address, amount: uint256, data: bytes) +     forcedTransfer(account: address, to: address, value: uint256, data: bytes): (success_: bool) - - -27->21 - - + + +36 + +<<Interface>> +IERC7551Compliance +RuleEngineFlatten.sol + +External: +     canTransferFrom(spender: address, from: address, to: address, value: uint256): bool + + + +36->9 + + + + + +37 + +<<Interface>> +IERC7551Document +RuleEngineFlatten.sol + +External: +     termsHash(): (hash_: bytes32) +     setTerms(_hash: bytes32, _uri: string) +     metaData(): (metadata_: string) +     setMetaData(metaData_: string) + + + +38 + +<<Abstract>> +ERC2771Context +RuleEngineFlatten.sol + +Private: +   _trustedForwarder: address + +Internal: +    _msgSender(): address +    _msgData(): bytes +    _contextSuffixLength(): uint256 +Public: +    constructor(trustedForwarder_: address) +    trustedForwarder(): address +    isTrustedForwarder(forwarder: address): bool + + + +38->16 + + + + + +39 + +<<Abstract>> +ERC165 +RuleEngineFlatten.sol + +Public: +    supportsInterface(interfaceId: bytes4): bool + + + +39->27 + + + + + +40 + +<<Interface>> +IERC3643Compliance +RuleEngineFlatten.sol + +External: +     bindToken(token: address) +     unbindToken(token: address) +     isTokenBound(token: address): (isBound: bool) +     getTokenBound(): (token: address) +     getTokenBounds(): (tokens: address[]) +     created(to: address, value: uint256) +     destroyed(from: address, value: uint256) +Public: +    <<event>> TokenBound(token: address) +    <<event>> TokenUnbound(token: address) + + + +40->9 + + - - -27->22 - - + + +40->10 + + + + + +41 + +<<Abstract>> +VersionModule +RuleEngineFlatten.sol + +Private: +   VERSION: string + +Public: +    version(): (version_: string) + + + +41->3 + + + + + +42 + +<<Library>> +Math +RuleEngineFlatten.sol + +Private: +    _zeroBytes(byteArray: bytes): bool +Internal: +    add512(a: uint256, b: uint256): (high: uint256, low: uint256) +    mul512(a: uint256, b: uint256): (high: uint256, low: uint256) +    tryAdd(a: uint256, b: uint256): (success: bool, result: uint256) +    trySub(a: uint256, b: uint256): (success: bool, result: uint256) +    tryMul(a: uint256, b: uint256): (success: bool, result: uint256) +    tryDiv(a: uint256, b: uint256): (success: bool, result: uint256) +    tryMod(a: uint256, b: uint256): (success: bool, result: uint256) +    saturatingAdd(a: uint256, b: uint256): uint256 +    saturatingSub(a: uint256, b: uint256): uint256 +    saturatingMul(a: uint256, b: uint256): uint256 +    ternary(condition: bool, a: uint256, b: uint256): uint256 +    max(a: uint256, b: uint256): uint256 +    min(a: uint256, b: uint256): uint256 +    average(a: uint256, b: uint256): uint256 +    ceilDiv(a: uint256, b: uint256): uint256 +    mulDiv(x: uint256, y: uint256, denominator: uint256): (result: uint256) +    mulDiv(x: uint256, y: uint256, denominator: uint256, rounding: Rounding): uint256 +    mulShr(x: uint256, y: uint256, n: uint8): (result: uint256) +    mulShr(x: uint256, y: uint256, n: uint8, rounding: Rounding): uint256 +    invMod(a: uint256, n: uint256): uint256 +    invModPrime(a: uint256, p: uint256): uint256 +    modExp(b: uint256, e: uint256, m: uint256): uint256 +    tryModExp(b: uint256, e: uint256, m: uint256): (success: bool, result: uint256) +    modExp(b: bytes, e: bytes, m: bytes): bytes +    tryModExp(b: bytes, e: bytes, m: bytes): (success: bool, result: bytes) +    sqrt(a: uint256): uint256 +    sqrt(a: uint256, rounding: Rounding): uint256 +    log2(x: uint256): (r: uint256) +    log2(value: uint256, rounding: Rounding): uint256 +    log10(value: uint256): uint256 +    log10(value: uint256, rounding: Rounding): uint256 +    log256(x: uint256): (r: uint256) +    log256(value: uint256, rounding: Rounding): uint256 +    unsignedRoundsUp(rounding: Rounding): bool + + + +42->17 + + - - -27->23 - - + + +42->28 + + + + + +43 + +<<Enum>> +Rounding +RuleEngineFlatten.sol + +Floor: 0 +Ceil: 1 +Trunc: 2 +Expand: 3 + + + +42->43 + + - - -27->24 - - + + +43->42 + + + + + +44 + +<<Abstract>> +ERC2771ModuleStandalone +RuleEngineFlatten.sol + +Public: +    constructor(trustedForwarder: address) + + + +44->38 + + + + + +45 + +<<Interface>> +IRuleEngine +RuleEngineFlatten.sol + +External: +     transferred(spender: address, from: address, to: address, value: uint256) + + + +45->10 + + - - -27->25 - - + + +45->12 + + - - -27->26 - - + + +45->36 + + + + + +46 + +<<Abstract>> +AccessControl +RuleEngineFlatten.sol + +Private: +   _roles: mapping(bytes32=>RoleData) +Public: +   DEFAULT_ADMIN_ROLE: bytes32 + +Internal: +    _checkRole(role: bytes32) +    _checkRole(role: bytes32, account: address) +    _setRoleAdmin(role: bytes32, adminRole: bytes32) +    _grantRole(role: bytes32, account: address): bool +    _revokeRole(role: bytes32, account: address): bool +Public: +    <<modifier>> onlyRole(role: bytes32) +    supportsInterface(interfaceId: bytes4): bool +    hasRole(role: bytes32, account: address): bool +    getRoleAdmin(role: bytes32): bytes32 +    grantRole(role: bytes32, account: address) <<onlyRole>> +    revokeRole(role: bytes32, account: address) <<onlyRole>> +    renounceRole(role: bytes32, callerConfirmation: address) + + + +46->14 + + - - -27->18 - - + + +46->16 + + - - -13 - -RuleBlacklist -src/rules/validation/RuleBlacklist.sol - -External: -    canReturnTransferRestrictionCode(_restrictionCode: uint8): bool -    messageForTransferRestriction(_restrictionCode: uint8): string -Public: -    constructor(admin: address, forwarderIrrevocable: address) -    detectTransferRestriction(_from: address, _to: address, uint256): uint8 + + +46->39 + + + + + +47 + +<<Struct>> +RoleData +RuleEngineFlatten.sol + +hasRole: mapping(address=>bool) +adminRole: bytes32 + + + +46->47 + + - - -32 - -<<Abstract>> -RuleAddressList -src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol - -Private: -   numAddressesWhitelisted: uint256 - -Internal: -    _msgSender(): (sender: address) -    _msgData(): bytes -    _contextSuffixLength(): uint256 -Public: -    constructor(admin: address, forwarderIrrevocable: address) -    addAddressesToTheList(listWhitelistedAddress: address[]) <<onlyRole>> -    removeAddressesFromTheList(listWhitelistedAddress: address[]) <<onlyRole>> -    addAddressToTheList(_newWhitelistAddress: address) <<onlyRole>> -    removeAddressFromTheList(_removeWhitelistAddress: address) <<onlyRole>> -    numberListedAddress(): uint256 -    addressIsListed(_targetAddress: address): bool -    addressIsListedBatch(_targetAddresses: address[]): bool[] - - - -13->32 - - + + +47->46 + + + + + +48 + +<<Interface>> +IRule +RuleEngineFlatten.sol + +External: +     canReturnTransferRestrictionCode(restrictionCode: uint8): bool + + + +48->45 + + + + + +49 + +<<Interface>> +IRulesManagementModule +RuleEngineFlatten.sol + +External: +     setRules(rules_: IRule[]) +     rulesCount(): (numberOfrules: uint256) +     rule(ruleId: uint256): (ruleAddress: address) +     rules(): (ruleAddresses: address[]) +     clearRules() +     addRule(rule_: IRule) +     removeRule(rule_: IRule) +     containsRule(rule_: IRule): (exists: bool) + + + +49->48 + + + + + +50 + +<<Abstract>> +RulesManagementModuleInvariantStorage +RuleEngineFlatten.sol + +Public: +   RULES_MANAGEMENT_ROLE: bytes32 + +Public: +    <<event>> AddRule(rule: IRule) +    <<event>> RemoveRule(rule: IRule) +    <<event>> ClearRules() + + + +50->48 + + + + + +51 + +<<Library>> +Arrays +RuleEngineFlatten.sol + +Private: +    _quickSort(begin: uint256, end: uint256, comp: FunctionTypeName()) +    _begin(array: uint256[]): (ptr: uint256) +    _end(array: uint256[]): (ptr: uint256) +    _mload(ptr: uint256): (value: uint256) +    _swap(ptr1: uint256, ptr2: uint256) +    _castToUint256Array(input: address[]): (output: uint256[]) +    _castToUint256Array(input: bytes32[]): (output: uint256[]) +    _castToUint256Comp(input: FunctionTypeName()): (output: FunctionTypeName()) +    _castToUint256Comp(input: FunctionTypeName()): (output: FunctionTypeName()) +Internal: +    sort(array: uint256[], comp: FunctionTypeName()): uint256[] +    sort(array: uint256[]): uint256[] +    sort(array: address[], comp: FunctionTypeName()): address[] +    sort(array: address[]): address[] +    sort(array: bytes32[], comp: FunctionTypeName()): bytes32[] +    sort(array: bytes32[]): bytes32[] +    findUpperBound(array: uint256[], element: uint256): uint256 +    lowerBound(array: uint256[], element: uint256): uint256 +    upperBound(array: uint256[], element: uint256): uint256 +    lowerBoundMemory(array: uint256[], element: uint256): uint256 +    upperBoundMemory(array: uint256[], element: uint256): uint256 +    unsafeAccess(arr: address[], pos: uint256): StorageSlot.AddressSlot +    unsafeAccess(arr: bytes32[], pos: uint256): StorageSlot.Bytes32Slot +    unsafeAccess(arr: uint256[], pos: uint256): StorageSlot.Uint256Slot +    unsafeAccess(arr: bytes[], pos: uint256): StorageSlot.BytesSlot +    unsafeAccess(arr: string[], pos: uint256): StorageSlot.StringSlot +    unsafeMemoryAccess(arr: address[], pos: uint256): (res: address) +    unsafeMemoryAccess(arr: bytes32[], pos: uint256): (res: bytes32) +    unsafeMemoryAccess(arr: uint256[], pos: uint256): (res: uint256) +    unsafeMemoryAccess(arr: bytes[], pos: uint256): (res: bytes) +    unsafeMemoryAccess(arr: string[], pos: uint256): (res: string) +    unsafeSetLength(array: address[], len: uint256) +    unsafeSetLength(array: bytes32[], len: uint256) +    unsafeSetLength(array: uint256[], len: uint256) +    unsafeSetLength(array: bytes[], len: uint256) +    unsafeSetLength(array: string[], len: uint256) + + + +51->15 + + - - -35 - -<<Abstract>> -RuleBlacklistInvariantStorage -src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol - -Public: -   TEXT_ADDRESS_FROM_IS_BLACKLISTED: string -   TEXT_ADDRESS_TO_IS_BLACKLISTED: string -   CODE_ADDRESS_FROM_IS_BLACKLISTED: uint8 -   CODE_ADDRESS_TO_IS_BLACKLISTED: uint8 - - - -13->35 - - + + +51->18 + + - - -13->30 - - + + +51->19 + + - - -14 - -<<Interface>> -SanctionsList -src/rules/validation/RuleSanctionList.sol - -External: -     isSanctioned(addr: address): bool + + +51->20 + + - - -15 - -RuleSanctionList -src/rules/validation/RuleSanctionList.sol - -Public: -   sanctionsList: SanctionsList - -Internal: -    _msgSender(): (sender: address) -    _msgData(): bytes -    _contextSuffixLength(): uint256 -External: -    canReturnTransferRestrictionCode(_restrictionCode: uint8): bool -    messageForTransferRestriction(_restrictionCode: uint8): string -Public: -    constructor(admin: address, forwarderIrrevocable: address) -    setSanctionListOracle(sanctionContractOracle_: address) <<onlyRole>> -    detectTransferRestriction(_from: address, _to: address, uint256): uint8 - - - -15->6 - - + + +51->22 + + - - -15->14 - - + + +51->23 + + - - -29 - -<<Abstract>> -RuleSanctionlistInvariantStorage -src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol - -Public: -   SANCTIONLIST_ROLE: bytes32 -   TEXT_ADDRESS_FROM_IS_SANCTIONED: string -   TEXT_ADDRESS_TO_IS_SANCTIONED: string -   CODE_ADDRESS_FROM_IS_SANCTIONED: uint8 -   CODE_ADDRESS_TO_IS_SANCTIONED: uint8 - - - -15->29 - - + + +51->25 + + - - -15->30 - - + + +51->26 + + - - -16 - -RuleWhitelist -src/rules/validation/RuleWhitelist.sol - -Public: -    constructor(admin: address, forwarderIrrevocable: address) -    detectTransferRestriction(_from: address, _to: address, uint256): uint8 - - + + +51->42 + + + + + +52 + +<<Library>> +EnumerableSet +RuleEngineFlatten.sol + +Private: +    _add(set: Set, value: bytes32): bool +    _remove(set: Set, value: bytes32): bool +    _clear(set: Set) +    _contains(set: Set, value: bytes32): bool +    _length(set: Set): uint256 +    _at(set: Set, index: uint256): bytes32 +    _values(set: Set): bytes32[] +    _values(set: Set, start: uint256, end: uint256): bytes32[] +Internal: +    add(set: Bytes32Set, value: bytes32): bool +    remove(set: Bytes32Set, value: bytes32): bool +    clear(set: Bytes32Set) +    contains(set: Bytes32Set, value: bytes32): bool +    length(set: Bytes32Set): uint256 +    at(set: Bytes32Set, index: uint256): bytes32 +    values(set: Bytes32Set): bytes32[] +    values(set: Bytes32Set, start: uint256, end: uint256): bytes32[] +    add(set: AddressSet, value: address): bool +    remove(set: AddressSet, value: address): bool +    clear(set: AddressSet) +    contains(set: AddressSet, value: address): bool +    length(set: AddressSet): uint256 +    at(set: AddressSet, index: uint256): address +    values(set: AddressSet): address[] +    values(set: AddressSet, start: uint256, end: uint256): address[] +    add(set: UintSet, value: uint256): bool +    remove(set: UintSet, value: uint256): bool +    clear(set: UintSet) +    contains(set: UintSet, value: uint256): bool +    length(set: UintSet): uint256 +    at(set: UintSet, index: uint256): uint256 +    values(set: UintSet): uint256[] +    values(set: UintSet, start: uint256, end: uint256): uint256[] +    add(set: StringSet, value: string): bool +    remove(set: StringSet, value: string): bool +    clear(set: StringSet) +    contains(set: StringSet, value: string): bool +    length(set: StringSet): uint256 +    at(set: StringSet, index: uint256): string +    values(set: StringSet): string[] +    values(set: StringSet, start: uint256, end: uint256): string[] +    add(set: BytesSet, value: bytes): bool +    remove(set: BytesSet, value: bytes): bool +    clear(set: BytesSet) +    contains(set: BytesSet, value: bytes): bool +    length(set: BytesSet): uint256 +    at(set: BytesSet, index: uint256): bytes +    values(set: BytesSet): bytes[] +    values(set: BytesSet, start: uint256, end: uint256): bytes[] + + -16->32 - - - - - -31 - -<<Abstract>> -RuleWhitelistCommon -src/rules/validation/abstract/RuleWhitelistCommon.sol - -External: -    canReturnTransferRestrictionCode(_restrictionCode: uint8): bool -    messageForTransferRestriction(_restrictionCode: uint8): string - - +52->51 + + + + + +53 + +<<Struct>> +Set +RuleEngineFlatten.sol + +_values: bytes32[] +_positions: mapping(bytes32=>uint256) + + + +52->53 + + + + + +54 + +<<Struct>> +Bytes32Set +RuleEngineFlatten.sol + +_inner: Set + + -16->31 - - - - - -17 - -RuleWhitelistWrapper -src/rules/validation/RuleWhitelistWrapper.sol - -Internal: -    _msgSender(): (sender: address) -    _msgData(): bytes -    _contextSuffixLength(): uint256 -Public: -    constructor(admin: address, forwarderIrrevocable: address) -    detectTransferRestriction(_from: address, _to: address, uint256): uint8 - - - -17->6 - - - - +52->54 + + + + + +55 + +<<Struct>> +AddressSet +RuleEngineFlatten.sol + +_inner: Set + + -17->10 - - - - +52->55 + + + + + +56 + +<<Struct>> +UintSet +RuleEngineFlatten.sol + +_inner: Set + + + +52->56 + + + + + +57 + +<<Struct>> +StringSet +RuleEngineFlatten.sol + +_values: string[] +_positions: mapping(string=>uint256) + + + +52->57 + + + + + +58 + +<<Struct>> +BytesSet +RuleEngineFlatten.sol + +_values: bytes[] +_positions: mapping(bytes=>uint256) + + -17->32 - - +52->58 + + - - -17->31 - - + + +53->52 + + - + + +54->52 + + + + -32->6 - - +54->53 + + - - -33 - -<<Abstract>> -RuleAddressListInternal -src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol - -Private: -   list: mapping(address=>bool) -   numAddressesList: uint256 - -Internal: -    _addAddressesToThelist(listAddresses: address[]) -    _removeAddressesFromThelist(listAddresses: address[]) -    _addAddressToThelist(_newlistAddress: address) -    _removeAddressFromThelist(_removelistAddress: address) -    _numberListedAddress(): uint256 -    _addressIsListed(_targetAddress: address): bool - - + + +55->52 + + + + -32->33 - - +55->53 + + - - -34 - -<<Abstract>> -RuleAddressListInvariantStorage -src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol - -Public: -   ADDRESS_LIST_REMOVE_ROLE: bytes32 -   ADDRESS_LIST_ADD_ROLE: bytes32 - - + + +56->52 + + + + -32->34 - - +56->53 + + + + + +57->52 + + - + + +58->52 + + + + + +59 + +<<Abstract>> +ERC3643ComplianceModule +RuleEngineFlatten.sol + +Private: +   _boundTokens: EnumerableSet.AddressSet +Public: +   COMPLIANCE_MANAGER_ROLE: bytes32 + +Internal: +    _unbindToken(token: address) +    _bindToken(token: address) +Public: +    <<modifier>> onlyBoundToken() +    bindToken(token: address) <<onlyRole>> +    unbindToken(token: address) <<onlyRole>> +    isTokenBound(token: address): bool +    getTokenBound(): address +    getTokenBounds(): address[] + + -35->28 - - +59->40 + + - - -36 - -<<Abstract>> -RuleWhitelistInvariantStorage -src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol - -Public: -   TEXT_ADDRESS_FROM_NOT_WHITELISTED: string -   TEXT_ADDRESS_TO_NOT_WHITELISTED: string -   CODE_ADDRESS_FROM_NOT_WHITELISTED: uint8 -   CODE_ADDRESS_TO_NOT_WHITELISTED: uint8 - - + -36->28 - - +59->46 + + - + -29->28 - - +59->52 + + - + -30->5 - - - - - -31->36 - - - - +59->55 + + + + + +60 + +<<Abstract>> +RulesManagementModule +RuleEngineFlatten.sol + +Internal: +   _rules: EnumerableSet.AddressSet + +Internal: +    _clearRules() +    _removeRule(rule_: IRule) +    _checkRule(rule_: address) +    _transferred(from: address, to: address, value: uint256) +    _transferred(spender: address, from: address, to: address, value: uint256) +Public: +    setRules(rules_: IRule[]) <<onlyRole>> +    clearRules() <<onlyRole>> +    addRule(rule_: IRule) <<onlyRole>> +    removeRule(rule_: IRule) <<onlyRole>> +    rulesCount(): uint256 +    containsRule(rule_: IRule): bool +    rule(ruleId: uint256): address +    rules(): address[] + + -31->30 - - +60->46 + + + + + +60->48 + + + + + +60->49 + + + + + +60->50 + + + + + +60->52 + + + + + +60->55 + + + + + +61 + +<<Abstract>> +RuleEngineBase +RuleEngineFlatten.sol + +Public: +    transferred(spender: address, from: address, to: address, value: uint256) <<onlyBoundToken>> +    transferred(from: address, to: address, value: uint256) <<onlyBoundToken>> +    created(to: address, value: uint256) <<onlyBoundToken>> +    destroyed(from: address, value: uint256) <<onlyBoundToken>> +    detectTransferRestriction(from: address, to: address, value: uint256): uint8 +    detectTransferRestrictionFrom(spender: address, from: address, to: address, value: uint256): uint8 +    messageForTransferRestriction(restrictionCode: uint8): string +    canTransfer(from: address, to: address, value: uint256): bool +    canTransferFrom(spender: address, from: address, to: address, value: uint256): bool +    hasRole(role: bytes32, account: address): bool + + + +61->13 + + + + + +61->29 + + + + + +61->41 + + + + + +61->45 + + + + + +61->46 + + + + + +61->48 + + + + + +61->59 + + + + + +61->60 + + + + + +62 + +RuleEngine +RuleEngineFlatten.sol + +Internal: +    _msgSender(): (sender: address) +    _msgData(): bytes +    _contextSuffixLength(): uint256 +Public: +    constructor(admin: address, forwarderIrrevocable: address, tokenContract: address) + + + +62->38 + + + + + +62->44 + + + + + +62->61 + + diff --git a/doc/schema/cmtat_surya_inheritance_IRuleEngine.sol.png b/doc/schema/cmtat_surya_inheritance_IRuleEngine.sol.png new file mode 100644 index 0000000..f7119f4 Binary files /dev/null and b/doc/schema/cmtat_surya_inheritance_IRuleEngine.sol.png differ diff --git a/doc/schema/rule/IncomeVault-claimDividend.drawio.png b/doc/schema/rule/IncomeVault-claimDividend.drawio.png deleted file mode 100644 index 3056bfe..0000000 Binary files a/doc/schema/rule/IncomeVault-claimDividend.drawio.png and /dev/null differ diff --git a/doc/schema/rule/conditionalTransfer-Storage.drawio.png b/doc/schema/rule/conditionalTransfer-Storage.drawio.png deleted file mode 100644 index 6fa3d10..0000000 Binary files a/doc/schema/rule/conditionalTransfer-Storage.drawio.png and /dev/null differ diff --git a/doc/schema/rule/conditionalTransfer-automaticTransfer.drawio.png b/doc/schema/rule/conditionalTransfer-automaticTransfer.drawio.png deleted file mode 100644 index 2a97df8..0000000 Binary files a/doc/schema/rule/conditionalTransfer-automaticTransfer.drawio.png and /dev/null differ diff --git a/doc/schema/rule/conditionalTransfer-state machine.drawio.png b/doc/schema/rule/conditionalTransfer-state machine.drawio.png deleted file mode 100644 index ff4388e..0000000 Binary files a/doc/schema/rule/conditionalTransfer-state machine.drawio.png and /dev/null differ diff --git a/doc/schema/rule/conditionalTransfer.drawio b/doc/schema/rule/conditionalTransfer.drawio deleted file mode 100644 index 9f632cc..0000000 --- a/doc/schema/rule/conditionalTransfer.drawio +++ /dev/null @@ -1 +0,0 @@ -7VvbcuI4EP0aqrIPoWzJNx4TkrnsTDaZJLPJzsuUwQJcMRYjiwTm61ey5ZtkwBAbSHZTUzV2Y2Tcffr0UUvuwP508ZG4s8kV9lDQAZq36MCLDgC6AUCH/9O8ZWqBTmIZE98Tttxw5/9GwqgJ69z3UFS6kGIcUH9WNg5xGKIhLdlcQvBL+bIRDsp3nbljpBjuhm6gWh98j06EVde0/INPyB9PxK0dU3wwddOLhSGauB5+KZjgZQf2CcY0OZou+ijg3kv9knzvw4pPsx9GUEjrfOHHT9z78vcXf0xurxD03UfPHJ+KUZ7dYC4e+B4/oZCZJsxTiIifTpepP9hTzPjhfBqcDSkmHXj+jAj1mce+ugMU3ODIpz4O2SUDTCmeFi44C/wx/4DiGbNO6DRgJzo7xHMa+CHqZzHUmHGEQyrwoBvsXH3e9Mez4dGiYBLP/xHhKaJkyS5JP01jIdB4CsX5Sx7a1DQpBNUSNleAaZyNnPubHQiXb+F+oLj/ds48DTTmCi/2oxvcEzeMRhWhIHgeesgT7nqZ+BTdzdwh//SFZWPZxS14E/Y2e1O3K9zZnj+h4k+q+g2F3hlnBnY2DNwo8odlV5X9yvxDlo/8pKvpemr4JzbolpUaLhbF6y+WxbMbRHz2fCyEWyKbumSM6Gb8IK9EYmrEChExKwKS2ggKXOo/l6mvKkjiDjfYZ784Ty+zDAhdCnOE52SIxJeKTCWNIwMLSOMkblHGiRGTPfTuIDIUEOldXmEIcilKs/EW/ZqjiJ5Q3AH99Oo/VKyxyMS8WIaYK5hwyCKOSAVFTn3P42OcExT5v91BPB7Hzow/dewH87xjXtRC09pUkdM9K6XipqVqVUUDpywPgAnKVKC/DlDpJXg0ilArQTZXMK8VMKedD0gpjNavOa/SsatPo9jXZ+wC3ZgtYoenn7OjMf//jhVGritWFc/hkpU7Vl3hZt4eJGT0dZAZ3OHTOKao66RqCnskIGC2Q/aOLuUk6Joq21eRi26aLbG9pSbqIEtUdoB5FOczLzkjScY2Vg5KpWBNGYgjUlkH0MKnj+Iu/DgpKsAUp/lY/CStKLVjm7Dt5uKxsciYR1VkbCgVGVlM1K0ytiMNJJerlstMb5X2u54h4nJp/b609yp3H0p7p/cvBOC13CDyWeuapYxen9D8ZGeFuDHJe0eVvKCp5JUlom7sN3l1VT+ArjubEfwsS8QHn04+X5yI8vPZe0siMcuRV6tEVteMVAi8GZGo241TRGE2qWWTx4QmDPPQs8njIosspwVeTHNXspAGMpw9k4WjwAjyGSUVRPF2J5FZgjQxi7Q0aJfiBBqBkTT7aI8tgMoWTMmNMJkWYq0E99BdPFOqpBZQdVnWN91PU1RVxv2r+7P7o3OdoUm8cgQNUKBSjcu4xnKn3B/hIJolfYq4zRHNXN7qj+tWp9jomAWnT8W2xit6ITiezaDrMO9jJzdnz5fcP7nuZETYhCWmwU10uJsoL0ry9YK8eorfzebxK6pzgzPznlqxH89/O3TS//b99sP85/mnq8sv8M9UQW0s2DnJAkfiWBWyLZZ0A4KuBXv5X+m3QMvp2lrhT6LuuvXekPvHvXr1fp/SEqpLFZBP/k8oYecx/EduELUCf70e/MuLHW2Afx2m35palUEHd139MG1pIHu/ahWq6x+5eNHEHNdjhx34QS3JEzwdzKODlGNbWt01q5SMVoGAzNh8OVZb1GMUxgWR344XX8Ry+fhUoSNNmSy9ottfpQrlOVpzrlTV9V+4IXIsN+A3tOvyGbzZOkGuTdCNDJmi70gY0pHzU56G12XInqS7TTl/VzAkQ4a7LFwmpsErf7ByH7u0w4YdJCM2S79qs2CJohZUwDsCejrzPhagy7iBOwLdMqsB2DTQV92nVaCnFaaogEfrcB5ivthdg827ml5egIEG2HoJ5vDwr5oFrs2TI4G/3FFS6Lk2/OW+rSwu2t4IpDZTauDTc6NJjEm9DFZuv3EpQ1gYW4DGt39ElOCnbGspUEDdXHe/bq/gjTX3dWm61OIy/rrpqrSMfxmO+dacY5P1tkT0ME3NoqzvVURd7qDsIusr3aemGBx0lZ5h683BLl97yEvGKV+e275mNN4EOZJkVTZ/7SpoTEsaKGXUPSWr2nR7LYBylWBvJROqp572Afd+vQEcWtIMEsh6uLaysGUc7rdoqC026HVqNX+PYSl4bWo1shJsAqdc1F8Hn0bb+b+08Kx3cx8svjvgx8PgOlxcPVSogOtbJXjMMbQct0T99XHAN/OlAnLkB4Fkqh/fKk2xo6KsLyuAvLfPcBRZYVXQglxGdlEVleHYTrhvw/OxMrDLC4OODjax/X/pNRAgiUx91z6fvG9HGag5lq5EkcrSq/b41den75cDJGmXTSMOxQHq0gvgbwfs532AjZsFtngh4P/3AdZ2myQpZ+y4aUBenTDsrjRSy2yjrm/BYZt4ZXUMljFrO/arUMtGdErItaxDbn1/H3hW+lm7Arq5xhg7zV9bTy7P3/6Hl/8C7Vtdc9o4FP01zGQfYCz5k8cE0m6z202mzW7bR4EFeGos1xYJ9NdXsuUPSaYYB7Nk2kxmYl1kGV8dnXPvlTIwJ+vt2wTFq/fEx+EAGv52YE4HEAILwgH/NfxdbrE9Lzcsk8AXnSrDx+A7FkZDWDeBj1OpIyUkpEEsG+ckivCcSjaUJORZ7rYgofzUGC2xZvg4R6Fu/RT4dCWswDCqD/7EwXIlHu3Z4oM1KjoLQ7pCPnmumczbgTlJCKH51Xo7wSF3XuEX+j3ZzSbI/2Tehfffhnd3/63fDvPB3hxzS/kKCY7oaYcWk/uEwo3w1yP5iiNmWjFH40S8Od0V7mROiPnlZh1ezylJBubNE05owBz+N5rh8IGkAQ1IxLrMCKVkXetwHQZL/gElMbOu6DpkDcAuyYaGQYQnJQQMZlyQiAo4AZu1WzpBOIs/E29rEBBOeYvJGtNkx7psSyjktwiAm6L5XKGlMK1qOHGEDQl8LsuBqzlgF2IajpgSU5uSDxvmfWgw9/iZb1H4mKAoXTRMT0I2kY994cLnVUDxxxjN+afPbH3Lbj+Xhy140MPAa3Bxfz62NB9T3Zc48q85AbHWPERpGsxl98m+Zj5Ldp95Y2QAUBi+ZAbgOIVhuq33n+7qrQecBOz92LSeYgVQlCzxz/oJoGFfIlB9FmvTZDfMUmFLcIho8CTTbtPMiSc8kIC9RrUMbRkkrjL3KdkkcyxuqtOcMo45lsfxlHFyt2jjZDAqX7o7smwNWWDE1S3BiOJi2X7A3zY4pVeUDOCk6P2HDkA2MxmpyrhDgkbnDAY4aeDXdeD7fIybBKfBdzTLxuOAivlbZ36wbwb2tDvEivWjUkAp4+KhklI2UcOQLQ5oQ2nGCgB3BVTRhSwWKe5lkr19FH0f4wRxVfwFZNOT1xlw/2fdHGuT8lJG3wY0J3RbtL5IrYrKeWNXaxwi8lIrhlwsZK1wHNhFK46b5pxMDyP8lWlICTiByTJ0f6mIQOO8KlKEpDUwwxGK44Q8qSLyKaCrd9OrJG+981+TjBRL9sUyYoygZdsnVZFCoCwgD+tAeYj+VAYADQQvZbQyRpU5xz7AOD0HosC6KBYBSrriqpLVmkUUOrLVgfpmET27N3kwSgWDvN74E+wLV7oEoI5hujLbnwRG9tl4Qq8YsDB0QZJ1ba61yb3ISoGjLD2voIZ6qQCeM6oEeqlg8v7x+vF1+FOtvDhNpRe3wZ89OlTPkE3EWMlBa+6kaJbGmUOckH2VmzRGvBiZaVvW2fm24fXWmzgcfq1a0lQURu7kYZp5+Zp1AHa8zUcub3KW/C/JkjZ8H1VVtfzh7P3y5+f9rhYJy8sywjxEnB3zDDCGtUyDJwfGy5ON47B1MDNoLdZlaGZ4Y0dC4djUQNijnFuKCjtw3E3OLduU5dxqJ+fnrEwAR19dPmtf0YS1M8wuUJi+HLNFJClnr7/jyHoAoCSRGl7aAs9W40hLQXDfcaSrgaoKKwyRlnKUDcw3ui6uyHq2SS9HEx2lcFW265roNMCi3Cg6vSbqBcUljjJV4o/jCojZ2nwlQZyrONiDLYM4uzf/6rXBf8iJVBscURvcWwespeBtePTUku62JVjvogjWU7aMPKOjsnuWMpC6+bSHYBlc0K7WTeS3+7+w+hwobdmzi3zEk7J3sdJq4N/h9EToN45Af1e09x3Qtkb/ZRW7PUMGkzvuiH5HXUZmu/DiWPSrwuuBc6BfL6Ka+Gfgj0iEW/F+sc1foh+Mz4P/pqTv1GvCarsm3ItaE2rI7RpKFa71mlCY2gXnDbkh1GDbArQ+SlcZUIGMYG5/QJTBJcos0DB5bYUm5Gt5KA5qSO85W4MXhRyt6G92TNbKclqxL65mDX0jp/n82G20DCKd+C4ygVCrlpbdkKE1HRgb95VAwIai5by3mooxco8SiKqA6NZPKoCfqlHPUZXZlgUuK6hylKDKdK2OAqLQgKVWHfumAb1mc/9BAyhbkFSGZC4KExLyM0qFriyCMFRM7TcBm0jllELTnldYxDkqdLzY6mvYEGmq/ahqcDpm0Us/L6SRpnAxZwfYnh2kE0qGI7HRaGxYhxjpDEeUYNu87bIYBto6CNUzJa13JJSj69qh2b5JRq+r7Tum1H7z7BfjJGvPFJ6BkG5n27+i6d3nqfGw+PfmDQrgJhrq1SJz9nt7NuM9IBEoZ0ZoHVfv7T9zbx1PVedfoKkcwAYG0DDY5watDUeOOa5+pC9jO97I7UiP6tpS84ODG7a7xlfqsn3LmtV/iuXdq/+3M29/AA==5VvbcuI4EP0aqjIPuCz5gnkkJJlNzaQym2ST3X0ztgDXGMsjywnM168E8kWSCTdDmFkqVbHaomV3t053H5uONZzNPxM/nd7hEMUdaIbzjnXVgRDYEHb4nxkuConlrSQTEoVCVgkeo59ICE0hzaMQZdJEinFMo1QWBjhJUEAlmU8IfpOnjXEsr5r6E6QJHgM/1qUvUUinQgpMszrxB4omU7G054gTM7+YLATZ1A/xW01kXXesIcGYro5m8yGKufUKuwwf/nr+cnU7GIBRF3r38+evQdBdKbvZ5SvlLRCU0HZVC++++nEu7IXfEkTEDdNFYUV27yk/zGfxIKCYdKzLV0RoxOz81R+h+BvOIhrhhE0ZYUrxrDZhEEcTfoLilEmndBazAWCHOKdxlKBh6XmTCcc4oSKKgMPGW967sBFfE81rnhe2+IzwDFGyYFPE2b7wqojrLigC9q2KEkuIprX4cIXMF3E5KTVXtmcHwvw7uMLSXPGQM/NDk9knXBrXj5+In2TjBv8QnCchCoUN36YRRY+pH/Czb2xjy3Y/lYltKNvY0i0MvAYTH8/GtmZjqtsSJeGAAw8bBbGfZVEgm0+29WHGRKGEXropa7ZyGkxVyAiKfRq9ypjXZD6xwjccscsrPQVsZTc4igcynJMAiW/VQUZRpLq8p+ihPpkgqulZOrO86/3962j+BSODJxeCfIqK3fOAfuQooxcUd+CwmP5JjwPmmyW4ye73BZwFzMGINODcLApDruOSoCz66Y+W+niopPy2l4ZwLjvO1f7BU4SxuhPLLCoWlRJV0w7tmgaADlSQsJ2QkpXaUFaAx+MMHSUG3HU4ep8i4vPc9fsnt7K6Kaq23gcnt57mlANhF80j+jc/Nhwx+kcaXc1rE68WtcE3RCJ2U3zrNvqEuYIsuGq2OUxQCFbaXRcWgmqB5WhRH6lL7ObmFdZujvAVlm6uKM4kx5QBJ2KyrKt3zTGWUrpB87RJxtNiGQ4MP00JflVTzEtEp7dXF2Q1ug1/pSRTbNmDk4xpQNtxjpFjuvaHZZl+24CmwVAJcD0J4d7HtwK7im8V0AU2wNY4iuMhjnnuY5duhT7yxvxyM0rwd1Q74wYeGo3bxzRrS0wD8KxAreeobaQKRtuimqPC4ZFRrGh36zC2rJWpgLAbgmcXfhgygMku6DTKPq2qZUEQDJdEzi9aQBe7t40C2jWtnpyPWoks51RIVuyoWiAM754GT5o7z5NjUKqKrgUbWIbeSVmGwtlKC3KdTFhD8GuY1VPNCpvM2kTe9I9mVT1OYcAAy/Vn3EjJKEuXBnFjyhNX6id8O/PEu5zs/sg5UXuZxt3v1YgdTfh/vOwN0X1SMWwrPexSV6pW8y7GDBW3A7/d2pkyccsNh7Mpb6+pGoDUFPXe74o+PPkXELQx+8Pzos08pc329sz9bk/WY8P+SWsBqHPP9w9aRDPooHIMywGS4AQp0SRE22f8Jvhrk2/dgUJRmEzY8HygMa9YRwNAnb0+EHXW9xyw3nOAd9FD4ktMV8avvmmfAWECt+0uzowxcYAB+nIUukqHuzUxD5RwPjEzD3VqHl6uYU22T7L/L0iC9hof1sLRPSki6Vz7oXVQiUBAgiCOLdB+v4ppADMVV0qsUnhduLHO+ugSqXx3ojWCpPYIyIIyynQdWwusI+Kc7UDDtfrVR7oYx/WM3p6gp24YtTlZA3qVolbb7y8LhP+1b4Obx2c7uLt7ISRcNDz2h2PjieR6o3hiOsXePohLHGiBK7b6tis77bAYO74H9W4fjA6FwTXt4Gac2pJFNjbUdA3Y2TagtY1nJ3pTwpUhBZi86q0+QNG4NVRZwOh7imrLYMtVH+9YFVtjWOt0C/A5PyxqtguSx+g5Sr7ncYRInkzOnwp+d/ee5bsUxwcvvaeEIfeyRogdjfnap+fcvRzbM7O1Xp5t22GW+dD0lHqo5AFO9IRL4UHAvq+G9Xoacp5dMaY3qS1F90587O//FPfceFxPfT1h33dTXIVm6XuG3bfYnnE9/t86WgoPv9y8zAEM/3QGXzM4zJK7DDaBO+Lgfr7txbu7so0UDR2lvSjqnI9I0WxY/XxgNb36FYZ1/R8=3Vpbc9o6EP41PCZjWbYxjxDoZaYnzcnlNHk6o2ABbo1FhQjQX18ZyxdJBgwxttuZTMZaryV599tPu4s78Ga++UjRYvYP8XDQMQ1v04HDjmkCyzQ70Z/hbWOJ7bqxYEp9Tyhlggf/FxZCQ0hXvoeXkiIjJGD+QhaOSRjiMZNkiFKyltUmJJBXXaAp1gQPYxTo0m++x2ax1ITQyW58wv50lizt2FZ8Z44SbfEqyxnyyDongqMOvKGEsPhqvrnBQWS9xDDxcx/23E13RnHIyjzw6RaN+1NGB4sNotPp0+I7fbkSs7yhYCXe+Fv/86PYMNsmZuAzcYvzwWA98xl+WKBxdGfNnc5lMzYP+AjwS31TyQqYMrzJicQmP2Iyx4xuuYq4axnCYAIywBbjdeYAkBh1lrO9K2RI+HyaTp1ZhV8Iw5xgJFszElosKHnDHpe+RlsnC0wRI1Q3XOj1Ixjy0ThAy6U/lu1FySr0cLS4wUd447NncSe6fonk17YYDTc5teFWDPZafElWdIyP+x57UgjofsnZ3S4weyKjOEDMf5MDp8gXYoU74vMdp263u7LbUwpIpojfRzyVx7kykeMq+OkpEzFuAsy0iXbQSF/7fLQ4Glr6d3f3X/8bDRsNK8dpW1h1NUM1ED7coHT7nB/knoqG2WO70fvDTuAjRuEBPbdV4QktGT5QhUXZ8HS7zYZnT0MdoyhcTjDd0Tne4PGKZczOyA8cRiblmQMu4HfunS/olWc9Ei5R4E/DCLQcHfwpOIji1OdpRV/cmPueF80xoHjp/0Kvu/kiXC2i995Zwh507GEh0g5Gk0oIaW4kFpGyjyKiuDKuoeSh5KB4L4KAPCtUZiCTyRJfxOWu5vLR8+jm6bFhRu7ZbWPk5MitkJIL6RUcIddK86CjROu0imjNnkK0wD6PaC2FaFMGr4logV5beD7lRBRExhxTjGKaReHuf+mMujWMm0ZLFZQLelZP5kfrfXC6PK0CvS46xBbco+Eu0r0PfpC4jY9E0Q/MMqldxgIveRKoJ7U7yiRnVFTAqYg2urYc7caZ+RlU6gSzZH7G3Yy2OTURVvs3rJRpUG1fHNFP8sYM1PEOKoW4CTWIx8TFZY8ibeSX9/jnCi9Zm7kqidVKuMo2e60nJ70Mr5mcQElyyvioTGq0l5yO1p1uSRI7o+6sisRcqHBPVUUmhDXnPqf1NipBH2juYCzbajx+gDYIPlsBH1Dz5XMbkE7N2NM7HB4O/T8rta6sm2FcW9CyZDJo/dmlNyyGo9vPTTeQlQ5g490KU+9W3JIQN2qk9FcLJatt0EpWjUdRltR0bVc+XHq2c6zrE43uMPX5i0c8U39bp6qjBBgKDEw1/yjdxDHqqca0HUNwuBzr2uCQ/oXKMb3j8He1lNJgreDcg4bTlVx0ZVYCbuU0TU+ry5+LZuM1Xdm8Wq7pjCPEt5fjKqvpGmxMuXvShlOZEBjG4YkuxYTWMSI8Sd1yDqlfiDb1avTP7GKlBFDJj5zAkTvu76THGvhPrwsuxn97OakJDlFLDzUJKsshWnZesjQ/ubcNCvdbdlugDlJIMtIcmO5xAtyWhn+C/yqyI1POYtoU/P7Xf//Hs6enB2v0vftK3NvZzy8FX2peLPYnJGSJopXPa0Cnpn5h2W+kkkq6DaSkkUnpZrVRDyt1zeJ1qqKZQtiaGmwpnvOqLK3PUNAE46gQ16F6MAgrICBD+b22Of7hw+wr9Fg9+5gfjn4DzVdLj9owEP41OVIlcRLocXl0e9iqaEFtOa3cZCAuTswah0d/fW3ihDiGLkVlBeLgeXic+ebz2HbQINs9crxKv7AEqOO7yc5BQ8f3vcD3HfV3k32p8f1AaxacJNrrqJiQ36CVrtYWJIG14SgYo4KsTGXM8hxiYegw52xrus0ZNVdd4QVYikmMqa39ThKR6jQQio6Gz0AWabV0FAalJcOVt05lneKEbRsqNHLQgDMmylG2GwBV8FXAlPM+nbHWX8YhF5dMYC9k+Dr4VWyG7tNr2psul0Gno6NsMC10xkMswFGhIpytHNSnMnj/YHKnJIMnkhExZVOO8/UcuE5N7CvAeMqyn4VEvb9NiYDJCsfKspX8kLpUZFRKnhzOWS50vb1QLWGlU30bcAG7hkqn9wgsA8H30kVbg0BDrdnmIS1vG6WrfNJG1eoaYU2XRR37CKgcaEz/AV/fwncisJD4yBWleID1YTx+/vptNLwvLLuhgWXH82wwve4JML3wVmAiC0wLMsiTB7XtpRRTvF6T2ESKsyJPQC3insBNwsX3P5TxQy3OtO9BGO4MaV9JOyIa06Q00+up8XGSEqo5Z2u0ZgWP4S8w9HQfxHwB4m3uQWK0OLvijYKGJ+pZ6ThQLMjGbIynaqxXGDMiM6sJFUZui1BBiydl4npas5G1I3ntSKgVqYTGinQgXZ349TwMLB7O5Bn1n6n4rpTyL6SUd1eUilr9vnsloaKPZpz2aXBjOoU3b2tXcOnaVng9B6vr3VscjO6Lg6HJnaBNnou7Wqs/Bu1j9MYsjCwWPoMoeK5KwqXKupwYlHv/C0rongG+eT/xTxQ+utX1pHfBPqZUvlzABEc+DFbKLje5uhwq65xQOmCU8cM05B5+ylVwtoSGZT7XllsgHLSvgD0bYnQC4fZxfAHCUjy+hEpKH1+UaPQHzVhZc9owEP41nmkfwtiSLx7J1XammR40SfPUEbbAmtiWR5YD9NdXsmV8CBpgIM4Dg7Ta1fHtt7uSDXiVrD4xlEV3NMSxAcxwZcBrAwALOkD8Scm6kji+XwkWjIRKqRFMyV+shKaSFiTEeUeRUxpzknWFAU1THPCODDFGl121OY27q2ZogTXBNECxLn0kIY8qKYDQbQY+Y7KI6qVdx65GElRrq6PkEQrpsiWCNwa8YpTyqpWsrnAs0auBqexud4xudsZwyvcxKH78eXjMp/j+FpFJ9pCy2Ty7ULO8oLhQJ54WiRDQuQSwtC/HcnkATkpBTINnHKpD8XUNFaNFGmK5mGXAy2VEOJ5mKJCjS0EOIYt4EqthtSxmHK92nsfaoCT4hWmCOVsLFWUAXQVsTS3VXTZ+ssZKFrVdVHMLKW4sNlM36ImGAvAAMIEGpgYSTsOJpKXoBTHKcxJ0cWlANEVPIMHWv2Vn5NTdp/bY9arTW9e9FeEtM9F7UvPLdmMkO7VNtVUcavHQ84c4Di1YgF8nFUdsgfl/9Ozt/m050Nniv1rGcIw4eelud5tP1QrfKREH2dDHGXfpA0GPFtUxlVU7rnoTuU53IuD1Jqpw0CYqKbY59vGsgxrrfmJesFR6gAnR0HFq9YC2/T0D1TlXnNoaYpcoRqmAAJgX4jdJBETSwwZwUSIRWXCJhVQ1p/d3Hy6rFPhRxzaiyazI3yb/wR7vLB3XrQFk+ecC1jl5AqwTWSuNNUnt7InM3jORwSETmd2rg3B8ZCID/o5AfSWRCX+idUstkwr57g0D3+lu2OxcXESjmvGkWdI9FzWtA6h5bD0fgNLekJR2QY+JR9dmrxcbe9bmQyntmgNQ2ttd+Ocozoev/I713ir/WIPsi3zo/GrX+rip9TNZ50ecJDjn5eBEaJXjMyZa5a0gL99LBlAmqLw7fBV2XMNfvAAz2cwYDXC+xy1hhoLnRem1bwWPSYpP5xvP7vrG2uIbYG7xjXsu39RkGTZFnzDV7vsMsnZ46o1ybS9ILXhkrvXM7kT9a8iZn0GW/injljKj/oox2cTl+w7LXuVzvJGjx6W9hQ5j51xxqT+XThSXh3yeeAdXJ2vfgB4PGc++tyOxHxrPfu/dbplg1OPY0SEtus2Hz0q9+X4Mb/4B \ No newline at end of file diff --git a/doc/schema/rule/conditionalTransferCMTAT.drawio.png b/doc/schema/rule/conditionalTransferCMTAT.drawio.png deleted file mode 100644 index 83cf658..0000000 Binary files a/doc/schema/rule/conditionalTransferCMTAT.drawio.png and /dev/null differ diff --git a/doc/schema/rule/conditionalTransferTime.png b/doc/schema/rule/conditionalTransferTime.png deleted file mode 100644 index 52eefdc..0000000 Binary files a/doc/schema/rule/conditionalTransferTime.png and /dev/null differ diff --git a/doc/schema/rule/ruleWhitelistWrapper.drawio b/doc/schema/rule/ruleWhitelistWrapper.drawio deleted file mode 100644 index 70e72c6..0000000 --- a/doc/schema/rule/ruleWhitelistWrapper.drawio +++ /dev/null @@ -1 +0,0 @@ -7Vxbd5s4EP41Pmf7YB8kcfNjnEu7Z9uz2Xa3tzfFyDYtRi7IcZJfXwkERgLb2AV86ebF1iAGWfPNN6ORSA9dz59eR3gxe0c9EvSg4T310E0PQhsMh/xDSJ5TCbBdI5VMI9+TsrXgg/9CpDDrtvQ9EisdGaUB8xeqcEzDkIyZIsNRRFdqtwkN1Kcu8JSUBB/GOChLP/kem6VSiJC9vvCG+NNZ9mjbMtMrc5z1lj8lnmGPrgoidNtD1xGlLP02f7omgZi+bGLS++42XM1HFpGQ1bmB3b08vLY9I4b+18dbEDBnNuvDVMsjDpbyF/egHXB9ownlavmo2bOcC/vHkmYX+nFiqSveAQwX3Nyj9XX+bSo+3y8DchtO/ZBkKvnYUq1pBzkt+QNgvPLnAeb90Wg18xn5sMBjcWnFwcVlMzYPeAvIMUiwACdXVZwLOT2PJGLkqSCSc/Oa0Dlh0TPvIq/2AZKGklhFmeFWBcMbUjYr2DwXYgm2aa58bQ7+RVpkD+ug9qzzSUxw4MfsE5/cBYnOwkameXImMjswEe8UcWcSfc/CTEPdk45uJas9K63KVoLnaaXjO5PdqZnCszSTc3wzOSUzgYFI8gjjKdi/EQ7jCYnek5hF/pj5NPxjEtF5D14nyVv6ied0GbJXpakmoXcl0jbeGgc4jv2xOsERv80jYnAGb5Enn32WV8T3L0I+sGTr5qnQ7eY5a4R8Cj4XG4W7RHN9W9LK7qtt2pguozHZnXMxHE0J2x39iaekqJsTGGNgQGcX8VoVSMlkEQkw8x/V1LcKPXIM99RPvFIOANkqUk1LA2A6M/KuYqaqKTKBpkhHcjp1WxRlHelkEhOlTwL4fPIO9wG3gqpawDI8DMywOzSjmmg2a6K5G6w6GsSQeSBWHQ30cFgPqwfgkNx979/YX6/efvz4H/NH/Y9339CWBVy8wGGtkOlsCJkQC1bHnheROP4zfsuDJ/FGmI1nCqG/KoTR9Jkbwqgw/Vv8QALVDXDgT0PhIxx6fB2CRiI2+nwJfiUvzH3PEzpGfBz+C35I9AkQL8SkJtNsjXrWTS1Yb3VmPSjndQX50F5x5b6Bg6Fluip7NQLYPrQUrX04VFW0R3XDEsRQbWT8huG9LiFap0WIWppp6jxWmxBdTZHOrBsIkeMCPxe6SefePGBLe45a/uJfUo2NukIWNQq+YB7PF8CFeIJd0xOk5XmeC7IxSOPbnSa6tgY9Gx3qK4aqyHJPL9EFVRlGI1A2FFp3tvN6c6g8rUTU3lTS3BdLJUXtJaLVOCkXq+GDoMaeM2IRFyVEOMFBTHrOTRlCJ5sc5g7wy9mhMQCOq6ZxqBEQITXjBKaqoEVyqCp/d08OeagDaqhzuot1Vs1YV7eo0w37uFBbvR66DNZDYt2STWNALFf40WWwT+ZhJ8g+HfBL1Y5A4/xSN48u8El+WyfkYl8EuZh6dntoamOBjsmlvOFhXga5ZO71e5LLfjX8kCY7gB6OZwmbANWcQn6PGTdlmEiggUQRlkX0e350CG6mo7ys9aXIQbsI6cT56LRKXK6zY7Vdl4+GGrFZ+vq/bT4qV2QtSUeGuHeSXuM6oEEjYQAO4Shxao+0ED/PIT+vW4uCJwVZZO2IfLW3VLVKk2m3BtnKbar91ontUG3btHlmW6DA2HQAaF9wAUNP0NojxEp0lVcJfy9IhFlCeqCEtHiGF+Lrch5cjUWnde6V5Gn3NPbFuRXe5YEyRucVyRmj2tEfumSBH5Lr/CDyXtipfx4I5DvMWbUnc+0CbFAFbHSPP+Q4UOXsl7PjpmKMmhTt2vnjjXsS+fxHiXR6a+BpJe5sg+a5cQPUzkeAQwtDAGoHJDo+HwEyB1uj8x0Oxan/k1ymbXWwJo4ngGHmntlBgmZK0HkFLlPrqBoaWcZVzk45Gf5V+jmQNGIOZaalMLWJ5FQcH+mJYrbY2Nvx9fcpuKYB0FDRtvPDbYlBeOGJgTN0jpsYVGwJHsk1z94NXWg35IZcE3dDI//Txta2R5YXgmcXjnNYN3JcELnq5m2WMTYdj/XKQXsBuVxWLZBumQEui3TzYxdHI93ycqz4JqZBc1tckh36pgp3u+ItmW7N0Hhaqs/aQVsH29bIe9bFNlpt55o4g+iZF2PtQ9fEejHW6vqdgfIpVkER5VeCL5QsLO0svQ2OTBawXKT4nyw0sJ7Z4Qdr19HeumRh6VtA7dXWr344/zy/eN/CxVN0+9ebhzdjC/RPv35WOw+vAOCWxM4YDoZDFwHHtQ0AXPXNSk7hA8MwoevariiO2pvxsYEZeHP9vz9SY63/hwq6/Qk= \ No newline at end of file diff --git a/doc/schema/rule/ruleWhitelistWrapper.drawio.png b/doc/schema/rule/ruleWhitelistWrapper.drawio.png deleted file mode 100644 index 0cadf5d..0000000 Binary files a/doc/schema/rule/ruleWhitelistWrapper.drawio.png and /dev/null differ diff --git a/doc/schema/rule/ruleWhitelistWrapperV2.drawio.png b/doc/schema/rule/ruleWhitelistWrapperV2.drawio.png deleted file mode 100644 index b8295c7..0000000 Binary files a/doc/schema/rule/ruleWhitelistWrapperV2.drawio.png and /dev/null differ diff --git a/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceModule.sol.png b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceModule.sol.png new file mode 100644 index 0000000..bb44d1d Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceModule.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IERC3643Compliance.sol.png b/doc/schema/surya/surya_graph/surya_graph_IERC3643Compliance.sol.png new file mode 100644 index 0000000..49f8124 Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_IERC3643Compliance.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IRule.sol.png b/doc/schema/surya/surya_graph/surya_graph_IRule.sol.png new file mode 100644 index 0000000..b6381f2 Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_IRule.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IRulesManagementModule.sol.png b/doc/schema/surya/surya_graph/surya_graph_IRulesManagementModule.sol.png new file mode 100644 index 0000000..1c7a02c Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_IRulesManagementModule.sol.png differ diff --git a/doc/surya/surya_graph/surya_graph_MetaTxModuleStandalone.sol.png b/doc/schema/surya/surya_graph/surya_graph_MetaTxModuleStandalone.sol.png similarity index 100% rename from doc/surya/surya_graph/surya_graph_MetaTxModuleStandalone.sol.png rename to doc/schema/surya/surya_graph/surya_graph_MetaTxModuleStandalone.sol.png diff --git a/doc/surya/surya_graph/surya_graph_RuleAddressList.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleAddressList.sol.png similarity index 100% rename from doc/surya/surya_graph/surya_graph_RuleAddressList.sol.png rename to doc/schema/surya/surya_graph/surya_graph_RuleAddressList.sol.png diff --git a/doc/surya/surya_graph/surya_graph_RuleAddressListInternal.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleAddressListInternal.sol.png similarity index 100% rename from doc/surya/surya_graph/surya_graph_RuleAddressListInternal.sol.png rename to doc/schema/surya/surya_graph/surya_graph_RuleAddressListInternal.sol.png diff --git a/doc/surya/surya_graph/surya_graph_RuleAddressListInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleAddressListInvariantStorage.sol.png similarity index 100% rename from doc/surya/surya_graph/surya_graph_RuleAddressListInvariantStorage.sol.png rename to doc/schema/surya/surya_graph/surya_graph_RuleAddressListInvariantStorage.sol.png diff --git a/doc/surya/surya_graph/surya_graph_RuleBlacklistInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleBlacklistInvariantStorage.sol.png similarity index 100% rename from doc/surya/surya_graph/surya_graph_RuleBlacklistInvariantStorage.sol.png rename to doc/schema/surya/surya_graph/surya_graph_RuleBlacklistInvariantStorage.sol.png diff --git a/doc/surya/surya_graph/surya_graph_RuleCommonInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleCommonInvariantStorage.sol.png similarity index 100% rename from doc/surya/surya_graph/surya_graph_RuleCommonInvariantStorage.sol.png rename to doc/schema/surya/surya_graph/surya_graph_RuleCommonInvariantStorage.sol.png diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLight.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLight.sol.png new file mode 100644 index 0000000..e453d15 Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLight.sol.png differ diff --git a/doc/surya/surya_graph/surya_graph_RuleConditionalTransferInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLightInvariantStorage.sol.png similarity index 100% rename from doc/surya/surya_graph/surya_graph_RuleConditionalTransferInvariantStorage.sol.png rename to doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLightInvariantStorage.sol.png diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngine.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngine.sol.png new file mode 100644 index 0000000..3f479f7 Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_RuleEngine.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngineBase.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngineBase.sol.png new file mode 100644 index 0000000..c6dae24 Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_RuleEngineBase.sol.png differ diff --git a/doc/surya/surya_graph/surya_graph_RuleEngineInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngineInvariantStorage.sol.png similarity index 100% rename from doc/surya/surya_graph/surya_graph_RuleEngineInvariantStorage.sol.png rename to doc/schema/surya/surya_graph/surya_graph_RuleEngineInvariantStorage.sol.png diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleOperationRevert.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleOperationRevert.sol.png new file mode 100644 index 0000000..53fd6e7 Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_RuleOperationRevert.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleWhitelist.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleWhitelist.sol.png new file mode 100644 index 0000000..458926d Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_RuleWhitelist.sol.png differ diff --git a/doc/surya/surya_graph/surya_graph_RuleWhitelistCommon.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleWhitelistCommon.sol.png similarity index 100% rename from doc/surya/surya_graph/surya_graph_RuleWhitelistCommon.sol.png rename to doc/schema/surya/surya_graph/surya_graph_RuleWhitelistCommon.sol.png diff --git a/doc/surya/surya_graph/surya_graph_RuleWhitelistInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleWhitelistInvariantStorage.sol.png similarity index 100% rename from doc/surya/surya_graph/surya_graph_RuleWhitelistInvariantStorage.sol.png rename to doc/schema/surya/surya_graph/surya_graph_RuleWhitelistInvariantStorage.sol.png diff --git a/doc/schema/surya/surya_graph/surya_graph_RulesManagementModule.sol.png b/doc/schema/surya/surya_graph/surya_graph_RulesManagementModule.sol.png new file mode 100644 index 0000000..aee7803 Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_RulesManagementModule.sol.png differ diff --git a/doc/surya/surya_graph/surya_graph_RuleSanctionListInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RulesManagementModuleInvariantStorage.sol.png similarity index 100% rename from doc/surya/surya_graph/surya_graph_RuleSanctionListInvariantStorage.sol.png rename to doc/schema/surya/surya_graph/surya_graph_RulesManagementModuleInvariantStorage.sol.png diff --git a/doc/schema/surya/surya_graph/surya_graph_VersionModule.sol.png b/doc/schema/surya/surya_graph/surya_graph_VersionModule.sol.png new file mode 100644 index 0000000..6d3a741 Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_VersionModule.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceModule.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceModule.sol.png new file mode 100644 index 0000000..d4e67fd Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceModule.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643Compliance.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643Compliance.sol.png new file mode 100644 index 0000000..33880da Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643Compliance.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IRule.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IRule.sol.png new file mode 100644 index 0000000..1092c91 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_IRule.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IRulesManagementModule.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IRulesManagementModule.sol.png new file mode 100644 index 0000000..d27b5f3 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_IRulesManagementModule.sol.png differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_MetaTxModuleStandalone.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_MetaTxModuleStandalone.sol.png similarity index 100% rename from doc/surya/surya_inheritance/surya_inheritance_MetaTxModuleStandalone.sol.png rename to doc/schema/surya/surya_inheritance/surya_inheritance_MetaTxModuleStandalone.sol.png diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleAddressList.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressList.sol.png similarity index 100% rename from doc/surya/surya_inheritance/surya_inheritance_RuleAddressList.sol.png rename to doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressList.sol.png diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleAddressListInternal.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressListInternal.sol.png similarity index 100% rename from doc/surya/surya_inheritance/surya_inheritance_RuleAddressListInternal.sol.png rename to doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressListInternal.sol.png diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleAddressListInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressListInvariantStorage.sol.png similarity index 100% rename from doc/surya/surya_inheritance/surya_inheritance_RuleAddressListInvariantStorage.sol.png rename to doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressListInvariantStorage.sol.png diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleBlacklistInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleBlacklistInvariantStorage.sol.png similarity index 100% rename from doc/surya/surya_inheritance/surya_inheritance_RuleBlacklistInvariantStorage.sol.png rename to doc/schema/surya/surya_inheritance/surya_inheritance_RuleBlacklistInvariantStorage.sol.png diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleCommonInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleCommonInvariantStorage.sol.png similarity index 100% rename from doc/surya/surya_inheritance/surya_inheritance_RuleCommonInvariantStorage.sol.png rename to doc/schema/surya/surya_inheritance/surya_inheritance_RuleCommonInvariantStorage.sol.png diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferLight.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferLight.sol.png new file mode 100644 index 0000000..754a650 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferLight.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferLightInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferLightInvariantStorage.sol.png new file mode 100644 index 0000000..f54aa6c Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferLightInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngine.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngine.sol.png new file mode 100644 index 0000000..0ddc9a2 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngine.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineBase.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineBase.sol.png new file mode 100644 index 0000000..2d065b8 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineBase.sol.png differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleEngineInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineInvariantStorage.sol.png similarity index 100% rename from doc/surya/surya_inheritance/surya_inheritance_RuleEngineInvariantStorage.sol.png rename to doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineInvariantStorage.sol.png diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleOperationRevert.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleOperationRevert.sol.png new file mode 100644 index 0000000..6eefd3d Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleOperationRevert.sol.png differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleWhitelist.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelist.sol.png similarity index 100% rename from doc/surya/surya_inheritance/surya_inheritance_RuleWhitelist.sol.png rename to doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelist.sol.png diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistCommon.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistCommon.sol.png new file mode 100644 index 0000000..b4891fa Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistCommon.sol.png differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleWhitelistInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistInvariantStorage.sol.png similarity index 100% rename from doc/surya/surya_inheritance/surya_inheritance_RuleWhitelistInvariantStorage.sol.png rename to doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistInvariantStorage.sol.png diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModule.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModule.sol.png new file mode 100644 index 0000000..fa292e5 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModule.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModuleInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModuleInvariantStorage.sol.png new file mode 100644 index 0000000..3d5fb78 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModuleInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_VersionModule.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_VersionModule.sol.png new file mode 100644 index 0000000..0617153 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_VersionModule.sol.png differ diff --git a/doc/surya/surya_report/surya_report_IRuleEngineOperation.sol.md b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceModule.sol.md similarity index 52% rename from doc/surya/surya_report/surya_report_IRuleEngineOperation.sol.md rename to doc/schema/surya/surya_report/surya_report_ERC3643ComplianceModule.sol.md index eb41011..842c492 100644 --- a/doc/surya/surya_report/surya_report_IRuleEngineOperation.sol.md +++ b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceModule.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./interfaces/IRuleEngineOperation.sol | 4bb16cd4f36ba8ce8133f2313fcded0796fc67b3 | +| ./modules/ERC3643ComplianceModule.sol | 5d853a580045cc1107f0b4b00b012dd7a088b4be | ### Contracts Description Table @@ -15,11 +15,14 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **IRuleEngineOperation** | Interface | ||| -| └ | setRulesOperation | External ❗️ | 🛑 |NO❗️ | -| └ | rulesCountOperation | External ❗️ | |NO❗️ | -| └ | ruleOperation | External ❗️ | |NO❗️ | -| └ | rulesOperation | External ❗️ | |NO❗️ | +| **ERC3643ComplianceModule** | Implementation | IERC3643Compliance, AccessControl ||| +| └ | bindToken | Public ❗️ | 🛑 | onlyRole | +| └ | unbindToken | Public ❗️ | 🛑 | onlyRole | +| └ | isTokenBound | Public ❗️ | |NO❗️ | +| └ | getTokenBound | External ❗️ | |NO❗️ | +| └ | getTokenBounds | External ❗️ | |NO❗️ | +| └ | _unbindToken | Internal 🔒 | 🛑 | | +| └ | _bindToken | Internal 🔒 | 🛑 | | ### Legend diff --git a/doc/schema/surya/surya_report/surya_report_IERC3643Compliance.sol.md b/doc/schema/surya/surya_report/surya_report_IERC3643Compliance.sol.md new file mode 100644 index 0000000..adcb8be --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_IERC3643Compliance.sol.md @@ -0,0 +1,33 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./interfaces/IERC3643Compliance.sol | f636595955dd26c915cfd870f1b9c1a1c653cd19 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **IERC3643Compliance** | Interface | IERC3643ComplianceRead, IERC3643IComplianceContract ||| +| └ | bindToken | External ❗️ | 🛑 |NO❗️ | +| └ | unbindToken | External ❗️ | 🛑 |NO❗️ | +| └ | isTokenBound | External ❗️ | |NO❗️ | +| └ | getTokenBound | External ❗️ | |NO❗️ | +| └ | getTokenBounds | External ❗️ | |NO❗️ | +| └ | created | External ❗️ | 🛑 |NO❗️ | +| └ | destroyed | External ❗️ | 🛑 |NO❗️ | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/surya/surya_report/surya_report_IRuleValidation.sol.md b/doc/schema/surya/surya_report/surya_report_IRule.sol.md similarity index 83% rename from doc/surya/surya_report/surya_report_IRuleValidation.sol.md rename to doc/schema/surya/surya_report/surya_report_IRule.sol.md index cfbc4c3..ea64fff 100644 --- a/doc/surya/surya_report/surya_report_IRuleValidation.sol.md +++ b/doc/schema/surya/surya_report/surya_report_IRule.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./interfaces/IRuleValidation.sol | cb3247e70bb4dca270e109cc1f961436165e657b | +| ./interfaces/IRule.sol | a76399a324e73846f5ba41cdc0b0277a27f76aa5 | ### Contracts Description Table @@ -15,7 +15,7 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **IRuleValidation** | Interface | IERC1404Wrapper ||| +| **IRule** | Interface | IRuleEngine ||| | └ | canReturnTransferRestrictionCode | External ❗️ | |NO❗️ | diff --git a/doc/schema/surya/surya_report/surya_report_IRulesManagementModule.sol.md b/doc/schema/surya/surya_report/surya_report_IRulesManagementModule.sol.md new file mode 100644 index 0000000..6adb3c6 --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_IRulesManagementModule.sol.md @@ -0,0 +1,34 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./interfaces/IRulesManagementModule.sol | 4756338d2051398ca7d89e941296909aea5dc58d | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **IRulesManagementModule** | Interface | ||| +| └ | setRules | External ❗️ | 🛑 |NO❗️ | +| └ | rulesCount | External ❗️ | |NO❗️ | +| └ | rule | External ❗️ | |NO❗️ | +| └ | rules | External ❗️ | |NO❗️ | +| └ | clearRules | External ❗️ | 🛑 |NO❗️ | +| └ | addRule | External ❗️ | 🛑 |NO❗️ | +| └ | removeRule | External ❗️ | 🛑 |NO❗️ | +| └ | containsRule | External ❗️ | 🛑 |NO❗️ | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/surya/surya_report/surya_report_MetaTxModuleStandalone.sol.md b/doc/schema/surya/surya_report/surya_report_MetaTxModuleStandalone.sol.md similarity index 89% rename from doc/surya/surya_report/surya_report_MetaTxModuleStandalone.sol.md rename to doc/schema/surya/surya_report/surya_report_MetaTxModuleStandalone.sol.md index 96201b7..4079d57 100644 --- a/doc/surya/surya_report/surya_report_MetaTxModuleStandalone.sol.md +++ b/doc/schema/surya/surya_report/surya_report_MetaTxModuleStandalone.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/MetaTxModuleStandalone.sol | 9d622167d731e7457db63bcb5f9b070e30d62131 | +| ./modules/MetaTxModuleStandalone.sol | 7f61b75c585854e696ec011ef699a3016282bf9f | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleAddressList.sol.md b/doc/schema/surya/surya_report/surya_report_RuleAddressList.sol.md similarity index 92% rename from doc/surya/surya_report/surya_report_RuleAddressList.sol.md rename to doc/schema/surya/surya_report/surya_report_RuleAddressList.sol.md index 0479115..167da42 100644 --- a/doc/surya/surya_report/surya_report_RuleAddressList.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleAddressList.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/abstract/RuleAddressList/RuleAddressList.sol | a5490babb4ea88b10fd8d5adfceafb4f14fae5e3 | +| ./mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol | 75a87c2d2af981e5c3afefb70a9fbcc13e1ba26b | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleAddressListInternal.sol.md b/doc/schema/surya/surya_report/surya_report_RuleAddressListInternal.sol.md similarity index 88% rename from doc/surya/surya_report/surya_report_RuleAddressListInternal.sol.md rename to doc/schema/surya/surya_report/surya_report_RuleAddressListInternal.sol.md index 6c302c5..abdf691 100644 --- a/doc/surya/surya_report/surya_report_RuleAddressListInternal.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleAddressListInternal.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol | bbe6d63aba425456591b7f2fa12e8aaa81c12bbb | +| ./mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol | bbe6d63aba425456591b7f2fa12e8aaa81c12bbb | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleAddressListInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RuleAddressListInvariantStorage.sol.md similarity index 81% rename from doc/surya/surya_report/surya_report_RuleAddressListInvariantStorage.sol.md rename to doc/schema/surya/surya_report/surya_report_RuleAddressListInvariantStorage.sol.md index bbf441e..893ba96 100644 --- a/doc/surya/surya_report/surya_report_RuleAddressListInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleAddressListInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol | 992fb7e7916167eae37d614c6fc47413afebcd82 | +| ./mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol | 992fb7e7916167eae37d614c6fc47413afebcd82 | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleBlacklistInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RuleBlacklistInvariantStorage.sol.md similarity index 82% rename from doc/surya/surya_report/surya_report_RuleBlacklistInvariantStorage.sol.md rename to doc/schema/surya/surya_report/surya_report_RuleBlacklistInvariantStorage.sol.md index 641e318..6a7e411 100644 --- a/doc/surya/surya_report/surya_report_RuleBlacklistInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleBlacklistInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol | ba066cb426060eaca152daa5bb489970c2f9c539 | +| ./mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol | 463cf8b5eda9e536e9a1e541b193c2856d6b26af | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleCommonInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RuleCommonInvariantStorage.sol.md similarity index 85% rename from doc/surya/surya_report/surya_report_RuleCommonInvariantStorage.sol.md rename to doc/schema/surya/surya_report/surya_report_RuleCommonInvariantStorage.sol.md index df9fbc9..63a7037 100644 --- a/doc/surya/surya_report/surya_report_RuleCommonInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleCommonInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/abstract/RuleCommonInvariantStorage.sol | bd2bf75999a7920aa4d6be476762d747efa15515 | +| ./mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol | bd2bf75999a7920aa4d6be476762d747efa15515 | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleSanctionList.sol.md b/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLight.sol.md similarity index 53% rename from doc/surya/surya_report/surya_report_RuleSanctionList.sol.md rename to doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLight.sol.md index 0140d39..2113835 100644 --- a/doc/surya/surya_report/surya_report_RuleSanctionList.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLight.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/RuleSanctionList.sol | 9d4f8926804ab2569d4f0e26e73c348c831fee3f | +| ./mocks/rules/operation/RuleConditionalTransferLight.sol | 563d9f2f21be53c588c4605313e344de5b74bf36 | ### Contracts Description Table @@ -15,20 +15,18 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **SanctionsList** | Interface | ||| -| └ | isSanctioned | External ❗️ | |NO❗️ | -|||||| -| **RuleSanctionList** | Implementation | AccessControl, MetaTxModuleStandalone, RuleValidateTransfer, RuleSanctionlistInvariantStorage ||| -| └ | | Public ❗️ | 🛑 | MetaTxModuleStandalone | -| └ | setSanctionListOracle | Public ❗️ | 🛑 | onlyRole | +| **RuleConditionalTransferLight** | Implementation | AccessControl, RuleConditionalTransferLightInvariantStorage, IRule ||| +| └ | | Public ❗️ | 🛑 |NO❗️ | +| └ | approveTransfer | Public ❗️ | 🛑 | onlyRole | +| └ | approvedCount | Public ❗️ | |NO❗️ | +| └ | transferred | Public ❗️ | 🛑 |NO❗️ | +| └ | transferred | Public ❗️ | 🛑 |NO❗️ | | └ | detectTransferRestriction | Public ❗️ | |NO❗️ | +| └ | detectTransferRestrictionFrom | Public ❗️ | |NO❗️ | | └ | canReturnTransferRestrictionCode | External ❗️ | |NO❗️ | | └ | messageForTransferRestriction | External ❗️ | |NO❗️ | -| └ | hasRole | Public ❗️ | |NO❗️ | -| └ | _setSanctionListOracle | Internal 🔒 | 🛑 | | -| └ | _msgSender | Internal 🔒 | | | -| └ | _msgData | Internal 🔒 | | | -| └ | _contextSuffixLength | Internal 🔒 | | | +| └ | canTransfer | Public ❗️ | |NO❗️ | +| └ | canTransferFrom | Public ❗️ | |NO❗️ | ### Legend diff --git a/doc/surya/surya_report/surya_report_RuleConditionalTransferInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLightInvariantStorage.sol.md similarity index 72% rename from doc/surya/surya_report/surya_report_RuleConditionalTransferInvariantStorage.sol.md rename to doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLightInvariantStorage.sol.md index 944844d..7f453ad 100644 --- a/doc/surya/surya_report/surya_report_RuleConditionalTransferInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLightInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol | 71ed84800ef21f7f0964ed6dfa744eb444cded98 | +| ./mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol | 2a0e5c5a7a089bf50dc8de38b4a5641a77a58597 | ### Contracts Description Table @@ -15,7 +15,7 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleConditionalTransferInvariantStorage** | Implementation | RuleCommonInvariantStorage ||| +| **RuleConditionalTransferLightInvariantStorage** | Implementation | RuleCommonInvariantStorage ||| ### Legend diff --git a/doc/surya/surya_report/surya_report_RuleWhitelistWrapper.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngine.sol.md similarity index 71% rename from doc/surya/surya_report/surya_report_RuleWhitelistWrapper.sol.md rename to doc/schema/surya/surya_report/surya_report_RuleEngine.sol.md index 69ab3b3..f4f2d8f 100644 --- a/doc/surya/surya_report/surya_report_RuleWhitelistWrapper.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleEngine.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/RuleWhitelistWrapper.sol | b9e309a42544f758b4cfbe05e1739e2a828ce237 | +| ./RuleEngine.sol | b4007ac9e9f570b4e102d2f29ec30efdba328e37 | ### Contracts Description Table @@ -15,10 +15,8 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleWhitelistWrapper** | Implementation | RuleEngineValidationCommon, MetaTxModuleStandalone, RuleWhitelistCommon ||| +| **RuleEngine** | Implementation | MetaTxModuleStandalone, RuleEngineBase ||| | └ | | Public ❗️ | 🛑 | MetaTxModuleStandalone | -| └ | detectTransferRestriction | Public ❗️ | |NO❗️ | -| └ | hasRole | Public ❗️ | |NO❗️ | | └ | _msgSender | Internal 🔒 | | | | └ | _msgData | Internal 🔒 | | | | └ | _contextSuffixLength | Internal 🔒 | | | diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngineBase.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngineBase.sol.md new file mode 100644 index 0000000..cad5a96 --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_RuleEngineBase.sol.md @@ -0,0 +1,36 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./RuleEngineBase.sol | 214152435cd5b2ba8317fb4d2c163137b7ab0f6f | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **RuleEngineBase** | Implementation | VersionModule, RulesManagementModule, ERC3643ComplianceModule, RuleEngineInvariantStorage, IRuleEngine ||| +| └ | transferred | Public ❗️ | 🛑 | onlyBoundToken | +| └ | transferred | Public ❗️ | 🛑 | onlyBoundToken | +| └ | created | Public ❗️ | 🛑 | onlyBoundToken | +| └ | destroyed | Public ❗️ | 🛑 | onlyBoundToken | +| └ | detectTransferRestriction | Public ❗️ | |NO❗️ | +| └ | detectTransferRestrictionFrom | Public ❗️ | |NO❗️ | +| └ | canTransfer | Public ❗️ | |NO❗️ | +| └ | canTransferFrom | Public ❗️ | |NO❗️ | +| └ | messageForTransferRestriction | Public ❗️ | |NO❗️ | +| └ | hasRole | Public ❗️ | |NO❗️ | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/surya/surya_report/surya_report_RuleEngineInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngineInvariantStorage.sol.md similarity index 87% rename from doc/surya/surya_report/surya_report_RuleEngineInvariantStorage.sol.md rename to doc/schema/surya/surya_report/surya_report_RuleEngineInvariantStorage.sol.md index aca78d7..49b0db0 100644 --- a/doc/surya/surya_report/surya_report_RuleEngineInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleEngineInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/RuleEngineInvariantStorage.sol | ae8100bce2e00f37166e10c998d9747a0bdf5ef4 | +| ./modules/library/RuleEngineInvariantStorage.sol | 35d62b0de74e4fbefff915f07d7dc3abe3777e38 | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleBlacklist.sol.md b/doc/schema/surya/surya_report/surya_report_RuleOperationRevert.sol.md similarity index 62% rename from doc/surya/surya_report/surya_report_RuleBlacklist.sol.md rename to doc/schema/surya/surya_report/surya_report_RuleOperationRevert.sol.md index 0ae2161..4bf805c 100644 --- a/doc/surya/surya_report/surya_report_RuleBlacklist.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleOperationRevert.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/RuleBlacklist.sol | bc23ad3743afc27239d05d7787f6f48840373e20 | +| ./mocks/rules/operation/RuleOperationRevert.sol | 1d4329d1dce3a0b4c864ebd2991ef4717da067b6 | ### Contracts Description Table @@ -15,11 +15,15 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleBlacklist** | Implementation | RuleValidateTransfer, RuleAddressList, RuleBlacklistInvariantStorage ||| -| └ | | Public ❗️ | 🛑 | RuleAddressList | +| **RuleOperationRevert** | Implementation | AccessControl, IRule, RuleCommonInvariantStorage ||| +| └ | transferred | Public ❗️ | |NO❗️ | +| └ | transferred | Public ❗️ | |NO❗️ | | └ | detectTransferRestriction | Public ❗️ | |NO❗️ | +| └ | detectTransferRestrictionFrom | Public ❗️ | |NO❗️ | | └ | canReturnTransferRestrictionCode | External ❗️ | |NO❗️ | | └ | messageForTransferRestriction | External ❗️ | |NO❗️ | +| └ | canTransfer | Public ❗️ | |NO❗️ | +| └ | canTransferFrom | Public ❗️ | |NO❗️ | ### Legend diff --git a/doc/surya/surya_report/surya_report_RuleWhitelist.sol.md b/doc/schema/surya/surya_report/surya_report_RuleWhitelist.sol.md similarity index 68% rename from doc/surya/surya_report/surya_report_RuleWhitelist.sol.md rename to doc/schema/surya/surya_report/surya_report_RuleWhitelist.sol.md index 24eadcc..0ec9c8f 100644 --- a/doc/surya/surya_report/surya_report_RuleWhitelist.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleWhitelist.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/RuleWhitelist.sol | c2fba89995e430d0f0965b24bf853772f3a51184 | +| ./mocks/rules/validation/RuleWhitelist.sol | 785ab1e469e09646edb82e842b47237a3c60eab1 | ### Contracts Description Table @@ -17,7 +17,12 @@ |||||| | **RuleWhitelist** | Implementation | RuleAddressList, RuleWhitelistCommon ||| | └ | | Public ❗️ | 🛑 | RuleAddressList | +| └ | canTransfer | Public ❗️ | |NO❗️ | +| └ | canTransferFrom | Public ❗️ | |NO❗️ | | └ | detectTransferRestriction | Public ❗️ | |NO❗️ | +| └ | detectTransferRestrictionFrom | Public ❗️ | |NO❗️ | +| └ | transferred | Public ❗️ | |NO❗️ | +| └ | transferred | Public ❗️ | |NO❗️ | ### Legend diff --git a/doc/surya/surya_report/surya_report_RuleWhitelistCommon.sol.md b/doc/schema/surya/surya_report/surya_report_RuleWhitelistCommon.sol.md similarity index 78% rename from doc/surya/surya_report/surya_report_RuleWhitelistCommon.sol.md rename to doc/schema/surya/surya_report/surya_report_RuleWhitelistCommon.sol.md index 276b8be..88f009c 100644 --- a/doc/surya/surya_report/surya_report_RuleWhitelistCommon.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleWhitelistCommon.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/abstract/RuleWhitelistCommon.sol | 38cb316c3cba0fc3945d7b4ba1069ae4f3480bb0 | +| ./mocks/rules/validation/abstract/RuleWhitelistCommon.sol | acf9b06014d115beee2cad0cb0ee8485d97e7cb0 | ### Contracts Description Table @@ -15,7 +15,7 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleWhitelistCommon** | Implementation | RuleValidateTransfer, RuleWhitelistInvariantStorage ||| +| **RuleWhitelistCommon** | Implementation | RuleWhitelistInvariantStorage, IRule ||| | └ | canReturnTransferRestrictionCode | External ❗️ | |NO❗️ | | └ | messageForTransferRestriction | External ❗️ | |NO❗️ | diff --git a/doc/surya/surya_report/surya_report_RuleWhitelistInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RuleWhitelistInvariantStorage.sol.md similarity index 82% rename from doc/surya/surya_report/surya_report_RuleWhitelistInvariantStorage.sol.md rename to doc/schema/surya/surya_report/surya_report_RuleWhitelistInvariantStorage.sol.md index 8591a82..3ecf212 100644 --- a/doc/surya/surya_report/surya_report_RuleWhitelistInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleWhitelistInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol | a49ed4b2f4e846464b80004e3d79c797320b6e5b | +| ./mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol | 2d91bd8748d0f3b586193da37ce6f9aec5dd089c | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RulesManagementModule.sol.md b/doc/schema/surya/surya_report/surya_report_RulesManagementModule.sol.md new file mode 100644 index 0000000..222e5d4 --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_RulesManagementModule.sol.md @@ -0,0 +1,39 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./modules/RulesManagementModule.sol | 01d405489c52d6b0e2feac077bfe0b4a95078119 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **RulesManagementModule** | Implementation | AccessControl, RulesManagementModuleInvariantStorage, IRulesManagementModule ||| +| └ | setRules | Public ❗️ | 🛑 | onlyRole | +| └ | clearRules | Public ❗️ | 🛑 | onlyRole | +| └ | addRule | Public ❗️ | 🛑 | onlyRole | +| └ | removeRule | Public ❗️ | 🛑 | onlyRole | +| └ | rulesCount | Public ❗️ | |NO❗️ | +| └ | containsRule | Public ❗️ | |NO❗️ | +| └ | rule | Public ❗️ | |NO❗️ | +| └ | rules | Public ❗️ | |NO❗️ | +| └ | _clearRules | Internal 🔒 | 🛑 | | +| └ | _removeRule | Internal 🔒 | 🛑 | | +| └ | _checkRule | Internal 🔒 | | | +| └ | _transferred | Internal 🔒 | 🛑 | | +| └ | _transferred | Internal 🔒 | 🛑 | | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/surya/surya_report/surya_report_IRuleOperation.sol.md b/doc/schema/surya/surya_report/surya_report_RulesManagementModuleInvariantStorage.sol.md similarity index 76% rename from doc/surya/surya_report/surya_report_IRuleOperation.sol.md rename to doc/schema/surya/surya_report/surya_report_RulesManagementModuleInvariantStorage.sol.md index e6dfbb1..3f6ddf5 100644 --- a/doc/surya/surya_report/surya_report_IRuleOperation.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RulesManagementModuleInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./interfaces/IRuleOperation.sol | 0284e295bdd4e46766290c62aa04841ffba6e056 | +| ./modules/library/RulesManagementModuleInvariantStorage.sol | c749738db35c43ee0591fd7236ee94f923669143 | ### Contracts Description Table @@ -15,8 +15,7 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **IRuleOperation** | Interface | ||| -| └ | operateOnTransfer | External ❗️ | 🛑 |NO❗️ | +| **RulesManagementModuleInvariantStorage** | Implementation | ||| ### Legend diff --git a/doc/surya/surya_report/surya_report_RuleSanctionListInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_VersionModule.sol.md similarity index 74% rename from doc/surya/surya_report/surya_report_RuleSanctionListInvariantStorage.sol.md rename to doc/schema/surya/surya_report/surya_report_VersionModule.sol.md index 5126a0e..5dad684 100644 --- a/doc/surya/surya_report/surya_report_RuleSanctionListInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_VersionModule.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/abstract/RuleSanctionListInvariantStorage.sol | dfda2a2bbee5719c4820c0df23d78552fa08cc90 | +| ./modules/VersionModule.sol | c0afee6f633c5066a4436b6e61102b6cfbe0d5e9 | ### Contracts Description Table @@ -15,7 +15,8 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleSanctionlistInvariantStorage** | Implementation | RuleCommonInvariantStorage ||| +| **VersionModule** | Implementation | IERC3643Base ||| +| └ | version | Public ❗️ | |NO❗️ | ### Legend diff --git a/doc/schema/vscode-uml/ERC2771ModuleUML.png b/doc/schema/vscode-uml/ERC2771ModuleUML.png new file mode 100644 index 0000000..6b488ee Binary files /dev/null and b/doc/schema/vscode-uml/ERC2771ModuleUML.png differ diff --git a/doc/schema/vscode-uml/ERC3643ComplianceModuleUML.png b/doc/schema/vscode-uml/ERC3643ComplianceModuleUML.png new file mode 100644 index 0000000..47061fe Binary files /dev/null and b/doc/schema/vscode-uml/ERC3643ComplianceModuleUML.png differ diff --git a/doc/schema/vscode-uml/IERC1404ExtendUML.png b/doc/schema/vscode-uml/IERC1404ExtendUML.png new file mode 100644 index 0000000..ff2570c Binary files /dev/null and b/doc/schema/vscode-uml/IERC1404ExtendUML.png differ diff --git a/doc/schema/vscode-uml/IERC1404UML.png b/doc/schema/vscode-uml/IERC1404UML.png new file mode 100644 index 0000000..aec3f3b Binary files /dev/null and b/doc/schema/vscode-uml/IERC1404UML.png differ diff --git a/doc/schema/vscode-uml/IERC3643ComplianceReadUML.png b/doc/schema/vscode-uml/IERC3643ComplianceReadUML.png new file mode 100644 index 0000000..d8d9f49 Binary files /dev/null and b/doc/schema/vscode-uml/IERC3643ComplianceReadUML.png differ diff --git a/doc/schema/vscode-uml/IERC3643IComplianceContractUML.png b/doc/schema/vscode-uml/IERC3643IComplianceContractUML.png new file mode 100644 index 0000000..8eb9993 Binary files /dev/null and b/doc/schema/vscode-uml/IERC3643IComplianceContractUML.png differ diff --git a/doc/schema/vscode-uml/IERC7551ComplianceUML.png b/doc/schema/vscode-uml/IERC7551ComplianceUML.png new file mode 100644 index 0000000..cb4d836 Binary files /dev/null and b/doc/schema/vscode-uml/IERC7551ComplianceUML.png differ diff --git a/doc/schema/vscode-uml/IRuleEngineUML.png b/doc/schema/vscode-uml/IRuleEngineUML.png new file mode 100644 index 0000000..a72713e Binary files /dev/null and b/doc/schema/vscode-uml/IRuleEngineUML.png differ diff --git a/doc/schema/vscode-uml/RuleEngineBaseUML.png b/doc/schema/vscode-uml/RuleEngineBaseUML.png new file mode 100644 index 0000000..b42a06a Binary files /dev/null and b/doc/schema/vscode-uml/RuleEngineBaseUML.png differ diff --git a/doc/schema/vscode-uml/RuleEngineUML.png.png b/doc/schema/vscode-uml/RuleEngineUML.png.png new file mode 100644 index 0000000..d1088bf Binary files /dev/null and b/doc/schema/vscode-uml/RuleEngineUML.png.png differ diff --git a/doc/schema/vscode-uml/RuleManagementModuleUML.png b/doc/schema/vscode-uml/RuleManagementModuleUML.png new file mode 100644 index 0000000..7a66b04 Binary files /dev/null and b/doc/schema/vscode-uml/RuleManagementModuleUML.png differ diff --git a/doc/schema/vscode-uml/VersionModuleUML.png b/doc/schema/vscode-uml/VersionModuleUML.png new file mode 100644 index 0000000..b035d88 Binary files /dev/null and b/doc/schema/vscode-uml/VersionModuleUML.png differ diff --git a/doc/security/accessControl/access-control-RuleEngine.png b/doc/security/accessControl/access-control-RuleEngine.png index a711397..fc50a68 100644 Binary files a/doc/security/accessControl/access-control-RuleEngine.png and b/doc/security/accessControl/access-control-RuleEngine.png differ diff --git a/doc/security/accessControl/access-control-RuleSanctionList.drawio.png b/doc/security/accessControl/access-control-RuleSanctionList.drawio.png deleted file mode 100644 index 056590f..0000000 Binary files a/doc/security/accessControl/access-control-RuleSanctionList.drawio.png and /dev/null differ diff --git a/doc/security/accessControl/access-control-RuleWhitelist.png b/doc/security/accessControl/access-control-RuleWhitelist.png deleted file mode 100644 index 1c49edd..0000000 Binary files a/doc/security/accessControl/access-control-RuleWhitelist.png and /dev/null differ diff --git a/doc/security/accessControl/access-control.drawio b/doc/security/accessControl/access-control.drawio index 8cfbe0e..2aab1d2 100644 --- a/doc/security/accessControl/access-control.drawio +++ b/doc/security/accessControl/access-control.drawio @@ -1 +1 @@ -3ZjbcpswEIafhstkOBiwLx2bpJlxko7dTJurjAKy0QwgRsixydNXCuIgidZOEze0V2ZX0gr9+xmtZDizdH9FQB7f4Agmhm1Ge8OZG7ZtWa7NfrinrDyuOa4cG4Ii0al1rNALFE5TeLcogoXUkWKcUJTLzhBnGQyp5AOE4J3cbY0TedYcbKDmWIUg0b3fUUTjyjt2zdb/BaJNXM9smaIlBXVn4ShiEOFdx+UEhjMjGNPqKd3PYMLFq3Wpxl3+orV5MQIzesyAM3O9WoGnGb7LbbQL8uUc+GciyjNItmLB8+Byer/49jid31zfPi7vFoF4fVrWmrC4TH5mXOxiROEqByFv2TECmC+macIsiz2ucUZFSi2P2for1/NDQuG+4xJLuII4hZSUrItordUUOHnC3LW5adCJu3mpxwHBw6aJ3ErGHoRqb1BwpCm4vF8Ej8Ht1fVtMDz9RoqAvi6gNekT0DyVgK4mYAHpcpuwf70qHMHbLII8mPk58DmyeL3q2T3qeacSz9PECxMIyDDlG5lDk8/X5ANRxMUbnHauOzTtxpp2BKb4GQ5SPn9w6E00+fR9IoumvIRhVpiAokChrJMsKhOHlD+4ce7W5kO3bb6XrFJYR6td4C0J4eGtkAKygfTwFx9GUuml566TG7cnNbWPwARQ9CwXbH35EjN8xYitrEHDGSloqKVCtW4xqltgqYEmciDLVwJVwmiBXvFplv3nRNV1z8chpaIB94h2CGPWgxjHn1u+uFG+E8vTY+gNCkPvozD0PhtD/UxxIgyt/wBCf1AQ+srpoDlLvRVC31cgVPfRU0NofwaE7XfxX8NwPCgMPbXYVQ+fR2OolH2W+5cxdIaNoQRhy+SHY1jf3B3CcDQoDO3xgZ306MpQuTfQbqNOjaF+SZWCjN98ajAy5RfgCSYygyBBm4wDyjIPCXPwkxcKQTIVDSmKIh7jgsACvYCn13icmZyv6XWV7oXhzo86b/z+r6Se+Zq7XzGr0b1e7TsLmueWP568j5CydwBerwv4xgwys70Drrq3N+lO8BM=3ZjZUtswFIafJpcwXuIll4EEykxoOzgdyhUjLCVWa1sZWSExT18Zy4skl4QlwS03+PySjqxfX6xlYJ8n20sKVtE1gSgeWAbcDuzJwOJ/hsP/FUpeKs7IL4UlxbCUzEYI8BMSoiHUNYYokyoyQmKGV7IYkjRFIZM0QCnZyNUWJJZ7XYEl0oQgBLGu3mLIolL1HaPRvyC8jKqeTUOUJKCqLIQsApBsWpI9HdjnlBBWPiXbcxQX5lW+lO0u/lJavxhFKdunwSZ2Ll0z8FfMRb8SN4Xo9+hEZHkE8VoMeDK9GP+Yze/Hk+urr/c332ZT8fosrzzhebn9PDjbRJihYAXComTDCeBaxJKYRyZ/XJCUiSk1hzzWX7nqH1GGti1JDOESkQQxmvMqovSkJkoA5Qp7N83s1PBE7Zmp5gEIIpZ17sY0/iB8e4WHQ83D8WRyMw2C+9lVMO+fhZZvSA56uoPmqMtB41AOOpqDAMIxhBRlGcrmZB6hGc6Y5iIla56gyGwc10nhnG10wGd1WOceyjlXc46ihDyi2rwLSpLe2VeBOJRB7LTTOaad3gsg9hBDUeoYu33s/EUfzEf/ZSz7DKVn7gGlfUwzR5qZ+nKSwnGx2eFRGIMsw6Hsk2wqN4fmP4vg1KnCu3bZZCtFuYj2djsjaxqi3UsmA3SJ2O6FAUFpk6bPXWtuur4XlUZRDBh+lLd2XfMlevhOMB9ZjYatfK8sdUtRjlu0am/F1EQjOZHpKYlKY7REz/jUw347URXiH4eUigbaYtYijEd3ol3x3PBVBPk7sTw8hm6vMHQ/CkP3szHUTx8HwtD8DyD0egWhZykQmm+E0PMUCNV19NAQWp8BYfNd/Ncw9HuFoesoGKpn1L0xVPbQpnNkDO1+YyhB2DD54RhWd3y7MBz2CkP1SkVbSffeGdpKInVtPzSG+mVWAtLijlSDkTs/Aw8olhkEMV6mBaB85hHlQnHywiGIx6IgwRAWOc74QRA/gYfnfAUzq2JMz6N0zgbOZK/zxss/JfXMV98Si14H7YvYrrOgcWp6/uh9hOSdDchikaFXziAPm9visnpz525P/wA=1VfbctowEP0aP5LxBQd45JYmUwKdOpkmfckIW9iasS1XFgHn67vCso0sNwlNmbZPaI+kI/bsQSsMZ5rsPzGURbc0wLFhm8HecGaGbdvmwIQPgRQl4tqjEggZCUrIagCPvGAJyn3hlgQ4VxZySmNOMhX0aZpinysYYozu1GUbGqunZijEGuD5KNbRbyTgUYkOXbPBrzEJo+pky5QzCaoWSyCPUEB3R5AzN5wpo5SXo2Q/xbEQr9JlcM2t9XSSfvd+4FXe+5wF42WvJLs6ZUudAsMp/7PUdkn9jOKt1Gs2vxrfL+6exrPbm+XT19ViLrPnRSUp8EL1IJjsIsKxlyFfzOzAQIBFPIkhsmC4oSmXjrD6EMvDMON436rOG6lZtd5gVEwTzFkB+yRLzzbdkkia9FKWbNdUvDZkdFztqrZIuiysuRslYSDFPEFYRxPWGy+ndzer5eLGu/tPdLWHpiLrQJfVGnXJap5L1r4ma465h1KfE5ouSM5XDPmgZ1taRrdpgAWz+Q/Je6m61jE7bGt36Ht5LnmHmry6SdNgLK5liPwY5TnxVfFUpUEeVjyI4MKtwsfjudleiQoZdZcAB9pd/54CwPenW+bjt3+uHLEQv8bX7y7oUcHcjnpVGMMx4uRZzaGriPKEL5RAdrVfnL76c7Tbt1eZptx13AraRCOVyBq0iEodNKKDp+q0f99mlt52Puiztl/wnvAHuVKMHxsLQtSYTgSF5lXFqY1xf+HVc3vTfqc3nb/pzXar0Cz1bm86LaK2yc/tTb1zJygVj0zNoVDxBVrDe1kxJopJmArXQvUxA0A0DgIP0rGcSEgQCI4Jwzl5QesDnzBSJnI6ZOlODHd2SieSr2dJZtQ3w9smtF9tUeaFNRiOPuaQonMD3WygdZ9WQQib53a5vPnT4sx/Ag== \ No newline at end of file +7Zpbc6IwFMc/jY90uIOPVrG7s9putZ1tnzoRomYKxImxaj/9hhoEErysV2anM30gBziY//lxcnJozWhGizsCJuMuDmBY09VgUTNaNV3XTF2vJX9qsOQW23VXlhFBAbdlhj76hNyocusMBXBauJBiHFI0KRp9HMfQpwUbIATPi5cNcVh86gSMoGTo+yCUrX9QQMcrq2upmf0HRKNx+mRN5WcikF7MDdMxCPA8ZzK8mtEkGNPVUbRowjBRL9VldV97w9n1DyMwpvvcoKjDfh8MmvhhoqO5N+m1gKNwLx8gnPEJt7x247nz9NZodX/ev/UeOh7/+XSZasL8MvnZ4HY+RhT2J8BPzswZAsw2plHIRho7HOKY8pBqNhvLPzl9PiQULnImPoU7iCNIyZJdws+6mrW6hQOl6CbXd56FZ03POB+aNBCAIzFaO89UYwdcuH8Q0ZRE7D13vP5bt3HfuPO63v1T9XS0dEFHo0TGepmM6rlktCQZp5D2ZiF7/UXlCJ7FAUycqVdRz1CL6mmWrN6at7x69rnEsyXx/BACUk35zFSGysjnSPKBIEjEq5x2tlY17VxJOwIj/AErKZ9TOfTqknzyQhEHjaSWYSM/BNMp8os6FUVl4pDlSzK4sdLha/5ca1EYLflIVBsuEM25YaNX/rzkOHOSDFIfGyM0xTPiw92LKAVkBOnuVQIGhbpNjncunlZJOFMbgSGg6KNY7ZXFmD/hN0ZsZtlC4BRxWlcjqYvVvPld+epMcGTqApd1wdFKGMnRF3LraR9OYZpVTofhKXA6FOXzY2hXCkP7VBg618ZQ3pB8Y7i7bqkIho4lYGgciKGrChi6F8ZQPzuGByJVzUXZrRSGVl3YnYlJbO9saAgYOhfG0PjGMNel2omhWSkMXbNIjyK1Tvbl0LadG+uy5Mk9rQjESa9UbyO5oZAo3gEDGBbZAyEaxQmYLOKQMEOyT0M+CBv8RISCIPFxS+AUfYLBl7+ElUkysa+pWrc1q7XXXnD7KyTuENctY/7UWr4rW7ZzVG80x60fR8ay9AY8HE7hsWF06Lv/iB7bn91OPX75ZT4qZkeR84fXaxq2aTRxNAkRiH3YxUHZPv3I3mSJ3NKLv1HpulBGKGlRepHeZKmQ8utwZCK+fBkqZMWTZeLN4F0r8WqqJmXewxKvpgrtIkVsA23Iw4wEsMxdxvPZGV7xko17hTK1tS0jlCfgIpib38aN6UNRb9S6fmSmTtsyrgDSxVK3/DVkgOLgCb/DWArqCZqqxyXsQ5uqlrU5IEfla/lzyCyurn6aVjkB5Q8i//2Ct62C2rngWVdd8LRd/ZK9FzxNqL00sYVzuo1HqY7yx6Rv7rZxZ1+VO12kRSyP9ubOEAkWS7aDuWPD7J9sVpdn/6tkeH8B3ZjZUtswFIafJpcwXuIll4EEykxoOzgdyhUjLCVWa1sZWSExT18Zy4skl4QlwS03+PySjqxfX6xlYJ8n20sKVtE1gSgeWAbcDuzJwOJ/hsP/FUpeKs7IL4UlxbCUzEYI8BMSoiHUNYYokyoyQmKGV7IYkjRFIZM0QCnZyNUWJJZ7XYEl0oQgBLGu3mLIolL1HaPRvyC8jKqeTUOUJKCqLIQsApBsWpI9HdjnlBBWPiXbcxQX5lW+lO0u/lJavxhFKdunwSZ2Ll0z8FfMRb8SN4Xo9+hEZHkE8VoMeDK9GP+Yze/Hk+urr/c332ZT8fosrzzhebn9PDjbRJihYAXComTDCeBaxJKYRyZ/XJCUiSk1hzzWX7nqH1GGti1JDOESkQQxmvMqovSkJkoA5Qp7N83s1PBE7Zmp5gEIIpZ17sY0/iB8e4WHQ83D8WRyMw2C+9lVMO+fhZZvSA56uoPmqMtB41AOOpqDAMIxhBRlGcrmZB6hGc6Y5iIla56gyGwc10nhnG10wGd1WOceyjlXc46ihDyi2rwLSpLe2VeBOJRB7LTTOaad3gsg9hBDUeoYu33s/EUfzEf/ZSz7DKVn7gGlfUwzR5qZ+nKSwnGx2eFRGIMsw6Hsk2wqN4fmP4vg1KnCu3bZZCtFuYj2djsjaxqi3UsmA3SJ2O6FAUFpk6bPXWtuur4XlUZRDBh+lLd2XfMlevhOMB9ZjYatfK8sdUtRjlu0am/F1EQjOZHpKYlKY7REz/jUw347URXiH4eUigbaYtYijEd3ol3x3PBVBPk7sTw8hm6vMHQ/CkP3szHUTx8HwtD8DyD0egWhZykQmm+E0PMUCNV19NAQWp8BYfNd/Ncw9HuFoesoGKpn1L0xVPbQpnNkDO1+YyhB2DD54RhWd3y7MBz2CkP1SkVbSffeGdpKInVtPzSG+mVWAtLijlSDkTs/Aw8olhkEMV6mBaB85hHlQnHywiGIx6IgwRAWOc74QRA/gYfnfAUzq2JMz6N0zgbOZK/zxss/JfXMV98Si14H7YvYrrOgcWp6/uh9hOSdDchikaFXziAPm9visnpz525P/wA=1VfbctowEP0aP5LxBQd45JYmUwKdOpkmfckIW9iasS1XFgHn67vCso0sNwlNmbZPaI+kI/bsQSsMZ5rsPzGURbc0wLFhm8HecGaGbdvmwIQPgRQl4tqjEggZCUrIagCPvGAJyn3hlgQ4VxZySmNOMhX0aZpinysYYozu1GUbGqunZijEGuD5KNbRbyTgUYkOXbPBrzEJo+pky5QzCaoWSyCPUEB3R5AzN5wpo5SXo2Q/xbEQr9JlcM2t9XSSfvd+4FXe+5wF42WvJLs6ZUudAsMp/7PUdkn9jOKt1Gs2vxrfL+6exrPbm+XT19ViLrPnRSUp8EL1IJjsIsKxlyFfzOzAQIBFPIkhsmC4oSmXjrD6EMvDMON436rOG6lZtd5gVEwTzFkB+yRLzzbdkkia9FKWbNdUvDZkdFztqrZIuiysuRslYSDFPEFYRxPWGy+ndzer5eLGu/tPdLWHpiLrQJfVGnXJap5L1r4ma465h1KfE5ouSM5XDPmgZ1taRrdpgAWz+Q/Je6m61jE7bGt36Ht5LnmHmry6SdNgLK5liPwY5TnxVfFUpUEeVjyI4MKtwsfjudleiQoZdZcAB9pd/54CwPenW+bjt3+uHLEQv8bX7y7oUcHcjnpVGMMx4uRZzaGriPKEL5RAdrVfnL76c7Tbt1eZptx13AraRCOVyBq0iEodNKKDp+q0f99mlt52Puiztl/wnvAHuVKMHxsLQtSYTgSF5lXFqY1xf+HVc3vTfqc3nb/pzXar0Cz1bm86LaK2yc/tTb1zJygVj0zNoVDxBVrDe1kxJopJmArXQvUxA0A0DgIP0rGcSEgQCI4Jwzl5QesDnzBSJnI6ZOlODHd2SieSr2dJZtQ3w9smtF9tUeaFNRiOPuaQonMD3WygdZ9WQQib53a5vPnT4sx/Ag== \ No newline at end of file diff --git a/doc/security/audits/tools/aderyn-report.md b/doc/security/audits/tools/aderyn-report.md new file mode 100644 index 0000000..0d42edc --- /dev/null +++ b/doc/security/audits/tools/aderyn-report.md @@ -0,0 +1,299 @@ +# 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: PUSH0 Opcode](#l-3-push0-opcode) + - [L-4: Loop Contains `require`/`revert`](#l-4-loop-contains-requirerevert) + + +# Summary + +## Files Summary + +| Key | Value | +| --- | --- | +| .sol Files | 11 | +| Total nSLOC | 389 | + + +## Files Details + +| Filepath | nSLOC | +| --- | --- | +| src/RuleEngine.sol | 49 | +| src/RuleEngineBase.sol | 113 | +| src/interfaces/IERC3643Compliance.sol | 13 | +| src/interfaces/IRule.sol | 7 | +| src/interfaces/IRulesManagementModule.sol | 16 | +| src/modules/ERC3643ComplianceModule.sol | 49 | +| src/modules/MetaTxModuleStandalone.sol | 6 | +| src/modules/RulesManagementModule.sol | 111 | +| src/modules/VersionModule.sol | 8 | +| src/modules/library/RuleEngineInvariantStorage.sol | 4 | +| src/modules/library/RulesManagementModuleInvariantStorage.sol | 13 | +| **Total** | **389** | + + +## Issue Summary + +| Category | No. of Issues | +| --- | --- | +| High | 0 | +| Low | 4 | + + +# Low Issues + +## L-1: Centralization Risk + +> Acknowledge +> Admin and the different operators are considered as trusted. + +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/ERC3643ComplianceModule.sol [Line: 10](src/modules/ERC3643ComplianceModule.sol#L10) + + ```solidity + abstract contract ERC3643ComplianceModule is IERC3643Compliance, AccessControl { + ``` + +- Found in src/modules/ERC3643ComplianceModule.sol [Line: 39](src/modules/ERC3643ComplianceModule.sol#L39) + + ```solidity + function bindToken(address token) public override virtual onlyRole(COMPLIANCE_MANAGER_ROLE) { + ``` + +- Found in src/modules/ERC3643ComplianceModule.sol [Line: 44](src/modules/ERC3643ComplianceModule.sol#L44) + + ```solidity + function unbindToken(address token) public override virtual onlyRole(COMPLIANCE_MANAGER_ROLE) { + ``` + +- Found in src/modules/RulesManagementModule.sol [Line: 16](src/modules/RulesManagementModule.sol#L16) + + ```solidity + AccessControl, + ``` + +- Found in src/modules/RulesManagementModule.sol [Line: 38](src/modules/RulesManagementModule.sol#L38) + + ```solidity + ) public virtual override(IRulesManagementModule) onlyRole(RULE_ENGINE_OPERATOR_ROLE) { + ``` + +- Found in src/modules/RulesManagementModule.sol [Line: 56](src/modules/RulesManagementModule.sol#L56) + + ```solidity + function clearRules() public virtual override(IRulesManagementModule) onlyRole(RULE_ENGINE_OPERATOR_ROLE) { + ``` + +- Found in src/modules/RulesManagementModule.sol [Line: 65](src/modules/RulesManagementModule.sol#L65) + + ```solidity + ) public virtual override(IRulesManagementModule) onlyRole(RULE_ENGINE_OPERATOR_ROLE) { + ``` + +- Found in src/modules/RulesManagementModule.sol [Line: 76](src/modules/RulesManagementModule.sol#L76) + + ```solidity + ) public virtual override(IRulesManagementModule) onlyRole(RULE_ENGINE_OPERATOR_ROLE) { + ``` + +
+ + + +## L-2: Unspecific Solidity Pragma + +> One potential use of RuleEngine is to be used as a library, similar to OpenZeppelin library. +> +> In this sense, we use the same convention of OpenZeppelin which for the moment only imposes that the version is higher than 0.8.20: +> pragma solidity ^0.8.20; +> +> A fixed version is set in the config file (0.8.30). Users are free to use these or conduct their own research before switching to another. + +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;` + +
11 Found Instances + + +- Found in src/RuleEngine.sol [Line: 3](src/RuleEngine.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/RuleEngineBase.sol [Line: 3](src/RuleEngineBase.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/interfaces/IERC3643Compliance.sol [Line: 3](src/interfaces/IERC3643Compliance.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/interfaces/IRule.sol [Line: 3](src/interfaces/IRule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/interfaces/IRulesManagementModule.sol [Line: 3](src/interfaces/IRulesManagementModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/ERC3643ComplianceModule.sol [Line: 3](src/modules/ERC3643ComplianceModule.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/modules/RulesManagementModule.sol [Line: 3](src/modules/RulesManagementModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/VersionModule.sol [Line: 3](src/modules/VersionModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/RuleEngineInvariantStorage.sol [Line: 3](src/modules/library/RuleEngineInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/RulesManagementModuleInvariantStorage.sol [Line: 3](src/modules/library/RulesManagementModuleInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +
+ + + +## L-3: PUSH0 Opcode + +> Acknowledge + +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. + +
11 Found Instances + + +- Found in src/RuleEngine.sol [Line: 3](src/RuleEngine.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/RuleEngineBase.sol [Line: 3](src/RuleEngineBase.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/interfaces/IERC3643Compliance.sol [Line: 3](src/interfaces/IERC3643Compliance.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/interfaces/IRule.sol [Line: 3](src/interfaces/IRule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/interfaces/IRulesManagementModule.sol [Line: 3](src/interfaces/IRulesManagementModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/ERC3643ComplianceModule.sol [Line: 3](src/modules/ERC3643ComplianceModule.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/modules/RulesManagementModule.sol [Line: 3](src/modules/RulesManagementModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/VersionModule.sol [Line: 3](src/modules/VersionModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/RuleEngineInvariantStorage.sol [Line: 3](src/modules/library/RuleEngineInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/RulesManagementModuleInvariantStorage.sol [Line: 3](src/modules/library/RulesManagementModuleInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +
+ + + +## L-4: Loop Contains `require`/`revert` + +> Acknowledge +> The number + +Avoid `require` / `revert` statements in a loop because a single bad item can cause the whole transaction to fail. It's better to forgive on fail and return failed elements post processing of the loop + +
1 Found Instances + + +- Found in src/modules/RulesManagementModule.sol [Line: 45](src/modules/RulesManagementModule.sol#L45) + + ```solidity + for(uint256 i = 0; i < rules_.length; ++i){ + ``` + +
+ + + diff --git a/doc/security/audits/tools/slither-report.md b/doc/security/audits/tools/slither-report.md index fb021eb..d5eab1b 100644 --- a/doc/security/audits/tools/slither-report.md +++ b/doc/security/audits/tools/slither-report.md @@ -1,176 +1,36 @@ **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) - - [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 - -Impact: Medium -Confidence: High - - [ ] 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) - -src/rules/operation/RuleConditionalTransfer.sol#L177-L206 - - - - [ ] 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) - -src/rules/operation/RuleConditionalTransfer.sol#L329-L349 - - - - [ ] 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) - -src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L383-L388 - - - - [ ] 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) - -src/rules/operation/RuleConditionalTransfer.sol#L177-L206 - + - [calls-loop](#calls-loop) (4 results) (Low) + - [dead-code](#dead-code) (1 results) (Informational) ## calls-loop > Acknowledge +> Rule contracts are considered as trusted Impact: Low 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) - -src/rules/validation/RuleWhitelistWrapper.sol#L39-L74 - - - - [ ] 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) - -src/modules/RuleEngineValidation.sol#L29-L44 - - - - [ ] 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) - -src/RuleEngine.sol#L100-L128 - - - - [ ] 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) - -src/RuleEngine.sol#L100-L128 - - - - [ ] 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) - -src/RuleEngine.sol#L100-L128 - - - - [ ] 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) - -src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L390-L449 - - - - [ ] 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) - -src/RuleEngine.sol#L100-L128 - - - - [ ] 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) - -src/RuleEngine.sol#L50-L76 - -## 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) - -src/rules/operation/RuleConditionalTransfer.sol#L329-L349 - - - - [ ] 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) - -src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L383-L388 - - - - [ ] 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) - -src/rules/operation/RuleConditionalTransfer.sol#L177-L206 - - - - [ ] 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) - -src/rules/operation/RuleConditionalTransfer.sol#L281-L298 + - [ ] ID-0 +[RuleEngineBase.detectTransferRestriction(address,address,uint256)](src/RuleEngineBase.sol#L76-L90) has external calls inside a loop: [restriction = IRule(rule(i)).detectTransferRestriction(from,to,value)](src/RuleEngineBase.sol#L83-L84) +src/RuleEngineBase.sol#L76-L90 - - [ ] 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 + - [ ] ID-1 +[RuleEngineBase.messageForTransferRestriction(uint8)](src/RuleEngineBase.sol#L116-L132) has external calls inside a loop: [IRule(rule(i)).canReturnTransferRestrictionCode(restrictionCode)](src/RuleEngineBase.sol#L123-L124) -## costly-loop +src/RuleEngineBase.sol#L116-L132 -> 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) + - [ ] ID-2 +[RuleEngineBase.messageForTransferRestriction(uint8)](src/RuleEngineBase.sol#L116-L132) has external calls inside a loop: [IRule(rule(i)).messageForTransferRestriction(restrictionCode)](src/RuleEngineBase.sol#L126-L128) -src/rules/operation/RuleConditionalTransfer.sol#L79-L118 +src/RuleEngineBase.sol#L116-L132 - - [ ] 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) + - [ ] ID-3 +[RuleEngineBase.detectTransferRestrictionFrom(address,address,address,uint256)](src/RuleEngineBase.sol#L95-L111) has external calls inside a loop: [restriction = IRule(rule(i)).detectTransferRestrictionFrom(spender,from,to,value)](src/RuleEngineBase.sol#L103-L104) -src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L325-L370 +src/RuleEngineBase.sol#L95-L111 ## dead-code @@ -182,462 +42,8 @@ src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L325-L370 Impact: Informational Confidence: Medium + - [ ] ID-4 +[RuleEngine._msgData()](src/RuleEngine.sol#L56-L64) is never used and should be removed - - [ ] 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 - - - - [ ] 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#L15-L24 +src/RuleEngine.sol#L56-L64 diff --git a/doc/surya/surya_graph/surya_graph_IRuleEngineOperation.sol.png b/doc/surya/surya_graph/surya_graph_IRuleEngineOperation.sol.png deleted file mode 100644 index 1187e14..0000000 Binary files a/doc/surya/surya_graph/surya_graph_IRuleEngineOperation.sol.png and /dev/null differ diff --git a/doc/surya/surya_graph/surya_graph_IRuleEngineValidation.sol.png b/doc/surya/surya_graph/surya_graph_IRuleEngineValidation.sol.png deleted file mode 100644 index f24db03..0000000 Binary files a/doc/surya/surya_graph/surya_graph_IRuleEngineValidation.sol.png and /dev/null differ diff --git a/doc/surya/surya_graph/surya_graph_IRuleOperation.sol.png b/doc/surya/surya_graph/surya_graph_IRuleOperation.sol.png deleted file mode 100644 index efe8828..0000000 Binary files a/doc/surya/surya_graph/surya_graph_IRuleOperation.sol.png and /dev/null differ diff --git a/doc/surya/surya_graph/surya_graph_IRuleValidation.sol.png b/doc/surya/surya_graph/surya_graph_IRuleValidation.sol.png deleted file mode 100644 index a8f3fc6..0000000 Binary files a/doc/surya/surya_graph/surya_graph_IRuleValidation.sol.png and /dev/null differ diff --git a/doc/surya/surya_graph/surya_graph_RuleBlacklist.sol.png b/doc/surya/surya_graph/surya_graph_RuleBlacklist.sol.png deleted file mode 100644 index 46b034c..0000000 Binary files a/doc/surya/surya_graph/surya_graph_RuleBlacklist.sol.png and /dev/null differ diff --git a/doc/surya/surya_graph/surya_graph_RuleConditionalTransfer.sol.png b/doc/surya/surya_graph/surya_graph_RuleConditionalTransfer.sol.png deleted file mode 100644 index 47fb63b..0000000 Binary files a/doc/surya/surya_graph/surya_graph_RuleConditionalTransfer.sol.png and /dev/null differ diff --git a/doc/surya/surya_graph/surya_graph_RuleConditionalTransferOperator.sol.png b/doc/surya/surya_graph/surya_graph_RuleConditionalTransferOperator.sol.png deleted file mode 100644 index eef7ac6..0000000 Binary files a/doc/surya/surya_graph/surya_graph_RuleConditionalTransferOperator.sol.png and /dev/null differ diff --git a/doc/surya/surya_graph/surya_graph_RuleEngine.sol.png b/doc/surya/surya_graph/surya_graph_RuleEngine.sol.png deleted file mode 100644 index f3dbdf8..0000000 Binary files a/doc/surya/surya_graph/surya_graph_RuleEngine.sol.png and /dev/null differ diff --git a/doc/surya/surya_graph/surya_graph_RuleEngineOperation.sol.png b/doc/surya/surya_graph/surya_graph_RuleEngineOperation.sol.png deleted file mode 100644 index 2b42825..0000000 Binary files a/doc/surya/surya_graph/surya_graph_RuleEngineOperation.sol.png and /dev/null differ diff --git a/doc/surya/surya_graph/surya_graph_RuleEngineValidation.sol.png b/doc/surya/surya_graph/surya_graph_RuleEngineValidation.sol.png deleted file mode 100644 index 334417a..0000000 Binary files a/doc/surya/surya_graph/surya_graph_RuleEngineValidation.sol.png and /dev/null differ diff --git a/doc/surya/surya_graph/surya_graph_RuleEngineValidationCommon.sol.png b/doc/surya/surya_graph/surya_graph_RuleEngineValidationCommon.sol.png deleted file mode 100644 index 2987ded..0000000 Binary files a/doc/surya/surya_graph/surya_graph_RuleEngineValidationCommon.sol.png and /dev/null differ diff --git a/doc/surya/surya_graph/surya_graph_RuleInternal.sol.png b/doc/surya/surya_graph/surya_graph_RuleInternal.sol.png deleted file mode 100644 index c4af7de..0000000 Binary files a/doc/surya/surya_graph/surya_graph_RuleInternal.sol.png and /dev/null differ diff --git a/doc/surya/surya_graph/surya_graph_RuleSanctionList.sol.png b/doc/surya/surya_graph/surya_graph_RuleSanctionList.sol.png deleted file mode 100644 index b0d47f4..0000000 Binary files a/doc/surya/surya_graph/surya_graph_RuleSanctionList.sol.png and /dev/null differ diff --git a/doc/surya/surya_graph/surya_graph_RuleValidateTransfer.sol.png b/doc/surya/surya_graph/surya_graph_RuleValidateTransfer.sol.png deleted file mode 100644 index b1e50f7..0000000 Binary files a/doc/surya/surya_graph/surya_graph_RuleValidateTransfer.sol.png and /dev/null differ diff --git a/doc/surya/surya_graph/surya_graph_RuleWhitelist.sol.png b/doc/surya/surya_graph/surya_graph_RuleWhitelist.sol.png deleted file mode 100644 index 3dfa8a2..0000000 Binary files a/doc/surya/surya_graph/surya_graph_RuleWhitelist.sol.png and /dev/null differ diff --git a/doc/surya/surya_graph/surya_graph_RuleWhitelistWrapper.sol.png b/doc/surya/surya_graph/surya_graph_RuleWhitelistWrapper.sol.png deleted file mode 100644 index c3dae87..0000000 Binary files a/doc/surya/surya_graph/surya_graph_RuleWhitelistWrapper.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_IRuleEngineOperation.sol.png b/doc/surya/surya_inheritance/surya_inheritance_IRuleEngineOperation.sol.png deleted file mode 100644 index db1c0cb..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_IRuleEngineOperation.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_IRuleEngineValidation.sol.png b/doc/surya/surya_inheritance/surya_inheritance_IRuleEngineValidation.sol.png deleted file mode 100644 index d7954ab..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_IRuleEngineValidation.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_IRuleOperation.sol.png b/doc/surya/surya_inheritance/surya_inheritance_IRuleOperation.sol.png deleted file mode 100644 index 92be631..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_IRuleOperation.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_IRuleValidation.sol.png b/doc/surya/surya_inheritance/surya_inheritance_IRuleValidation.sol.png deleted file mode 100644 index 10cf331..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_IRuleValidation.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleBlacklist.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleBlacklist.sol.png deleted file mode 100644 index 4a82559..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_RuleBlacklist.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleConditionalTransfer.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleConditionalTransfer.sol.png deleted file mode 100644 index 26f7780..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_RuleConditionalTransfer.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferInvariantStorage.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferInvariantStorage.sol.png deleted file mode 100644 index 0491c0d..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferInvariantStorage.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferOperator.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferOperator.sol.png deleted file mode 100644 index 6635edc..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferOperator.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleEngine.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleEngine.sol.png deleted file mode 100644 index 891c5d1..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_RuleEngine.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleEngineOperation.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleEngineOperation.sol.png deleted file mode 100644 index 8dcb619..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_RuleEngineOperation.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleEngineValidation.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleEngineValidation.sol.png deleted file mode 100644 index 4ed4e87..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_RuleEngineValidation.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleEngineValidationCommon.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleEngineValidationCommon.sol.png deleted file mode 100644 index e2569bd..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_RuleEngineValidationCommon.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleInternal.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleInternal.sol.png deleted file mode 100644 index c0b07a2..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_RuleInternal.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleSanctionList.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleSanctionList.sol.png deleted file mode 100644 index 7e726fe..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_RuleSanctionList.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleSanctionListInvariantStorage.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleSanctionListInvariantStorage.sol.png deleted file mode 100644 index b084d73..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_RuleSanctionListInvariantStorage.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleValidateTransfer.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleValidateTransfer.sol.png deleted file mode 100644 index afdca02..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_RuleValidateTransfer.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleWhitelistCommon.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleWhitelistCommon.sol.png deleted file mode 100644 index f75664a..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_RuleWhitelistCommon.sol.png and /dev/null differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleWhitelistWrapper.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleWhitelistWrapper.sol.png deleted file mode 100644 index 73d3cb3..0000000 Binary files a/doc/surya/surya_inheritance/surya_inheritance_RuleWhitelistWrapper.sol.png and /dev/null differ diff --git a/doc/surya/surya_report/surya_report_IRuleEngineValidation.sol.md b/doc/surya/surya_report/surya_report_IRuleEngineValidation.sol.md deleted file mode 100644 index 0a34e51..0000000 --- a/doc/surya/surya_report/surya_report_IRuleEngineValidation.sol.md +++ /dev/null @@ -1,34 +0,0 @@ -## Sūrya's Description Report - -### Files Description Table - - -| File Name | SHA-1 Hash | -|-------------|--------------| -| ./interfaces/IRuleEngineValidation.sol | ae7c36b3a2c7805ef513f79b79bd6ce9d0357847 | - - -### Contracts Description Table - - -| Contract | Type | Bases | | | -|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| -| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | -|||||| -| **IRuleEngineValidation** | Interface | ||| -| └ | detectTransferRestrictionValidation | External ❗️ | |NO❗️ | -| └ | validateTransferValidation | External ❗️ | |NO❗️ | -|||||| -| **IRuleEngineValidationCommon** | Interface | ||| -| └ | setRulesValidation | External ❗️ | 🛑 |NO❗️ | -| └ | rulesCountValidation | External ❗️ | |NO❗️ | -| └ | ruleValidation | External ❗️ | |NO❗️ | -| └ | rulesValidation | External ❗️ | |NO❗️ | - - -### Legend - -| Symbol | Meaning | -|:--------:|-----------| -| 🛑 | Function can modify state | -| 💵 | Function is payable | diff --git a/doc/surya/surya_report/surya_report_RuleConditionalTransfer.sol.md b/doc/surya/surya_report/surya_report_RuleConditionalTransfer.sol.md deleted file mode 100644 index 2e44d15..0000000 --- a/doc/surya/surya_report/surya_report_RuleConditionalTransfer.sol.md +++ /dev/null @@ -1,44 +0,0 @@ -## Sūrya's Description Report - -### Files Description Table - - -| File Name | SHA-1 Hash | -|-------------|--------------| -| ./rules/operation/RuleConditionalTransfer.sol | d6c1c14a4196e7582019e913f409416d118edbd8 | - - -### Contracts Description Table - - -| Contract | Type | Bases | | | -|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| -| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | -|||||| -| **RuleConditionalTransfer** | Implementation | RuleValidateTransfer, IRuleOperation, RuleConditionalTransferOperator, MetaTxModuleStandalone ||| -| └ | | Public ❗️ | 🛑 | MetaTxModuleStandalone | -| └ | operateOnTransfer | Public ❗️ | 🛑 | onlyRole | -| └ | createTransferRequest | Public ❗️ | 🛑 |NO❗️ | -| └ | createTransferRequestBatch | Public ❗️ | 🛑 |NO❗️ | -| └ | cancelTransferRequest | Public ❗️ | 🛑 |NO❗️ | -| └ | cancelTransferRequestBatch | Public ❗️ | 🛑 |NO❗️ | -| └ | getRequestTrade | Public ❗️ | |NO❗️ | -| └ | getRequestByStatus | Public ❗️ | |NO❗️ | -| └ | detectTransferRestriction | Public ❗️ | |NO❗️ | -| └ | canReturnTransferRestrictionCode | External ❗️ | |NO❗️ | -| └ | messageForTransferRestriction | External ❗️ | |NO❗️ | -| └ | _validateTransfer | Internal 🔒 | | | -| └ | _cancelTransferRequest | Internal 🔒 | 🛑 | | -| └ | _validateBurnMint | Internal 🔒 | | | -| └ | _validateApproval | Internal 🔒 | | | -| └ | _msgSender | Internal 🔒 | | | -| └ | _msgData | Internal 🔒 | | | -| └ | _contextSuffixLength | Internal 🔒 | | | - - -### Legend - -| Symbol | Meaning | -|:--------:|-----------| -| 🛑 | Function can modify state | -| 💵 | Function is payable | diff --git a/doc/surya/surya_report/surya_report_RuleConditionalTransferOperator.sol.md b/doc/surya/surya_report/surya_report_RuleConditionalTransferOperator.sol.md deleted file mode 100644 index e426528..0000000 --- a/doc/surya/surya_report/surya_report_RuleConditionalTransferOperator.sol.md +++ /dev/null @@ -1,46 +0,0 @@ -## Sūrya's Description Report - -### Files Description Table - - -| File Name | SHA-1 Hash | -|-------------|--------------| -| ./rules/operation/abstract/RuleConditionalTransferOperator.sol | 51e02c78db77b0f0984e14cfad7a5def39bc1964 | - - -### Contracts Description Table - - -| Contract | Type | Bases | | | -|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| -| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | -|||||| -| **RuleConditionalTransferOperator** | Implementation | AccessControl, RuleConditionalTransferInvariantStorage ||| -| └ | setConditionalWhitelist | Public ❗️ | 🛑 | onlyRole | -| └ | setIssuanceOptions | Public ❗️ | 🛑 | onlyRole | -| └ | setAutomaticTransfer | Public ❗️ | 🛑 | onlyRole | -| └ | setTimeLimit | Public ❗️ | 🛑 | onlyRole | -| └ | setAutomaticApproval | Public ❗️ | 🛑 | onlyRole | -| └ | createTransferRequestWithApproval | Public ❗️ | 🛑 | onlyRole | -| └ | approveTransferRequest | Public ❗️ | 🛑 | onlyRole | -| └ | approveTransferRequestWithId | Public ❗️ | 🛑 | onlyRole | -| └ | resetRequestStatus | Public ❗️ | 🛑 | onlyRole | -| └ | approveTransferRequestBatchWithId | Public ❗️ | 🛑 | onlyRole | -| └ | approveTransferRequestBatch | Public ❗️ | 🛑 | onlyRole | -| └ | createTransferRequestWithApprovalBatch | Public ❗️ | 🛑 | onlyRole | -| └ | resetRequestStatusBatch | Public ❗️ | 🛑 | onlyRole | -| └ | hasRole | Public ❗️ | |NO❗️ | -| └ | _approveTransferRequestKeyElement | Internal 🔒 | 🛑 | | -| └ | _createTransferRequestWithApproval | Internal 🔒 | 🛑 | | -| └ | _resetRequestStatus | Internal 🔒 | 🛑 | | -| └ | _checkRequestStatus | Internal 🔒 | | | -| └ | _approveRequest | Internal 🔒 | 🛑 | | -| └ | _updateProcessedTransfer | Internal 🔒 | 🛑 | | - - -### Legend - -| Symbol | Meaning | -|:--------:|-----------| -| 🛑 | Function can modify state | -| 💵 | Function is payable | diff --git a/doc/surya/surya_report/surya_report_RuleEngine.sol.md b/doc/surya/surya_report/surya_report_RuleEngine.sol.md deleted file mode 100644 index 90cf24e..0000000 --- a/doc/surya/surya_report/surya_report_RuleEngine.sol.md +++ /dev/null @@ -1,35 +0,0 @@ -## Sūrya's Description Report - -### Files Description Table - - -| File Name | SHA-1 Hash | -|-------------|--------------| -| ./RuleEngine.sol | e13fc0c25fc199c56abd6dfbad3496431af1359f | - - -### Contracts Description Table - - -| Contract | Type | Bases | | | -|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| -| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | -|||||| -| **RuleEngine** | Implementation | IRuleEngine, RuleEngineOperation, RuleEngineValidation, MetaTxModuleStandalone ||| -| └ | | Public ❗️ | 🛑 | MetaTxModuleStandalone | -| └ | detectTransferRestriction | Public ❗️ | |NO❗️ | -| └ | validateTransfer | Public ❗️ | |NO❗️ | -| └ | messageForTransferRestriction | External ❗️ | |NO❗️ | -| └ | operateOnTransfer | External ❗️ | 🛑 | onlyRole | -| └ | hasRole | Public ❗️ | |NO❗️ | -| └ | _msgSender | Internal 🔒 | | | -| └ | _msgData | Internal 🔒 | | | -| └ | _contextSuffixLength | Internal 🔒 | | | - - -### Legend - -| Symbol | Meaning | -|:--------:|-----------| -| 🛑 | Function can modify state | -| 💵 | Function is payable | diff --git a/doc/surya/surya_report/surya_report_RuleEngineOperation.sol.md b/doc/surya/surya_report/surya_report_RuleEngineOperation.sol.md deleted file mode 100644 index 9083954..0000000 --- a/doc/surya/surya_report/surya_report_RuleEngineOperation.sol.md +++ /dev/null @@ -1,37 +0,0 @@ -## Sūrya's Description Report - -### Files Description Table - - -| File Name | SHA-1 Hash | -|-------------|--------------| -| ./modules/RuleEngineOperation.sol | 1e1185c6f479770d66aabb692a54d331cbaf8f4d | - - -### Contracts Description Table - - -| Contract | Type | Bases | | | -|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| -| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | -|||||| -| **RuleEngineOperation** | Implementation | AccessControl, RuleInternal, IRuleEngineOperation ||| -| └ | setRulesOperation | Public ❗️ | 🛑 | onlyRole | -| └ | clearRulesOperation | Public ❗️ | 🛑 | onlyRole | -| └ | _clearRulesOperation | Internal 🔒 | 🛑 | | -| └ | addRuleOperation | Public ❗️ | 🛑 | onlyRole | -| └ | removeRuleOperation | Public ❗️ | 🛑 | onlyRole | -| └ | _removeRuleOperation | Internal 🔒 | 🛑 | | -| └ | rulesCountOperation | External ❗️ | |NO❗️ | -| └ | getRuleIndexOperation | External ❗️ | |NO❗️ | -| └ | ruleOperation | External ❗️ | |NO❗️ | -| └ | rulesOperation | External ❗️ | |NO❗️ | -| └ | _operateOnTransfer | Internal 🔒 | 🛑 | | - - -### Legend - -| Symbol | Meaning | -|:--------:|-----------| -| 🛑 | Function can modify state | -| 💵 | Function is payable | diff --git a/doc/surya/surya_report/surya_report_RuleEngineValidation.sol.md b/doc/surya/surya_report/surya_report_RuleEngineValidation.sol.md deleted file mode 100644 index 01894ff..0000000 --- a/doc/surya/surya_report/surya_report_RuleEngineValidation.sol.md +++ /dev/null @@ -1,28 +0,0 @@ -## Sūrya's Description Report - -### Files Description Table - - -| File Name | SHA-1 Hash | -|-------------|--------------| -| ./modules/RuleEngineValidation.sol | 0f30ea71d3ce862e4bbb3083e0e45670a3393000 | - - -### Contracts Description Table - - -| Contract | Type | Bases | | | -|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| -| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | -|||||| -| **RuleEngineValidation** | Implementation | AccessControl, RuleInternal, RuleEngineValidationCommon, IRuleEngineValidation, IERC1404EnumCode ||| -| └ | detectTransferRestrictionValidation | Public ❗️ | |NO❗️ | -| └ | validateTransferValidation | Public ❗️ | |NO❗️ | - - -### Legend - -| Symbol | Meaning | -|:--------:|-----------| -| 🛑 | Function can modify state | -| 💵 | Function is payable | diff --git a/doc/surya/surya_report/surya_report_RuleEngineValidationCommon.sol.md b/doc/surya/surya_report/surya_report_RuleEngineValidationCommon.sol.md deleted file mode 100644 index c806888..0000000 --- a/doc/surya/surya_report/surya_report_RuleEngineValidationCommon.sol.md +++ /dev/null @@ -1,36 +0,0 @@ -## Sūrya's Description Report - -### Files Description Table - - -| File Name | SHA-1 Hash | -|-------------|--------------| -| ./modules/RuleEngineValidationCommon.sol | a942b2dc5791016dbf30c12b5778f1c65e167b0d | - - -### Contracts Description Table - - -| Contract | Type | Bases | | | -|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| -| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | -|||||| -| **RuleEngineValidationCommon** | Implementation | AccessControl, RuleInternal, IRuleEngineValidationCommon ||| -| └ | setRulesValidation | Public ❗️ | 🛑 | onlyRole | -| └ | clearRulesValidation | Public ❗️ | 🛑 | onlyRole | -| └ | addRuleValidation | Public ❗️ | 🛑 | onlyRole | -| └ | removeRuleValidation | Public ❗️ | 🛑 | onlyRole | -| └ | rulesCountValidation | External ❗️ | |NO❗️ | -| └ | getRuleIndexValidation | External ❗️ | |NO❗️ | -| └ | ruleValidation | External ❗️ | |NO❗️ | -| └ | rulesValidation | External ❗️ | |NO❗️ | -| └ | _clearRulesValidation | Internal 🔒 | 🛑 | | -| └ | _removeRuleValidation | Internal 🔒 | 🛑 | | - - -### Legend - -| Symbol | Meaning | -|:--------:|-----------| -| 🛑 | Function can modify state | -| 💵 | Function is payable | diff --git a/doc/surya/surya_report/surya_report_RuleInternal.sol.md b/doc/surya/surya_report/surya_report_RuleInternal.sol.md deleted file mode 100644 index 0eddb1f..0000000 --- a/doc/surya/surya_report/surya_report_RuleInternal.sol.md +++ /dev/null @@ -1,30 +0,0 @@ -## Sūrya's Description Report - -### Files Description Table - - -| File Name | SHA-1 Hash | -|-------------|--------------| -| ./modules/RuleInternal.sol | 7bad85bfbad52abc2ab9082628bf6bba2ee116f4 | - - -### Contracts Description Table - - -| Contract | Type | Bases | | | -|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| -| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | -|||||| -| **RuleInternal** | Implementation | RuleEngineInvariantStorage ||| -| └ | _setRules | Internal 🔒 | 🛑 | | -| └ | _addRule | Internal 🔒 | 🛑 | | -| └ | _removeRule | Internal 🔒 | 🛑 | | -| └ | _getRuleIndex | Internal 🔒 | | | - - -### Legend - -| Symbol | Meaning | -|:--------:|-----------| -| 🛑 | Function can modify state | -| 💵 | Function is payable | diff --git a/doc/surya/surya_report/surya_report_RuleValidateTransfer.sol.md b/doc/surya/surya_report/surya_report_RuleValidateTransfer.sol.md deleted file mode 100644 index 3b10ec8..0000000 --- a/doc/surya/surya_report/surya_report_RuleValidateTransfer.sol.md +++ /dev/null @@ -1,27 +0,0 @@ -## Sūrya's Description Report - -### Files Description Table - - -| File Name | SHA-1 Hash | -|-------------|--------------| -| ./rules/validation/abstract/RuleValidateTransfer.sol | bdc453d5afd57fde0c8ca1baffc05c6ed4cb6d20 | - - -### Contracts Description Table - - -| Contract | Type | Bases | | | -|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| -| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | -|||||| -| **RuleValidateTransfer** | Implementation | IRuleValidation ||| -| └ | validateTransfer | Public ❗️ | |NO❗️ | - - -### Legend - -| Symbol | Meaning | -|:--------:|-----------| -| 🛑 | Function can modify state | -| 💵 | Function is payable | diff --git a/doc/technical/RuleBlacklist.md b/doc/technical/RuleBlacklist.md deleted file mode 100644 index 59ebb3c..0000000 --- a/doc/technical/RuleBlacklist.md +++ /dev/null @@ -1,49 +0,0 @@ -# Rule Blacklist - -[TOC] - -This rule can be used to forbid transfer from/to addresses in the blacklist -A part of the code is shared with Rule Whitelist - -## Schema - -### Graph - -![surya_graph_Blacklist](../surya/surya_graph/surya_graph_RuleBlacklist.sol.png) - -### Inheritance - -![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/RuleConditionalTransfer.md b/doc/technical/RuleConditionalTransfer.md deleted file mode 100644 index fcea617..0000000 --- a/doc/technical/RuleConditionalTransfer.md +++ /dev/null @@ -1,191 +0,0 @@ -# Rule ConditionalTransfer - -[TOC] - -This page describes a Conditional Transfer implementation. This rule requires that transfers have to be approved before being executed by the token holders. - -In the Swiss law, this rule allows to implement a specific restriction called *Vinkulierung*. - - - -## Introduction - -The ConditionalTransfer rule has been implemented as an operation rule with the RuleEngine - -Why use a dedicated rule instead of directly implementing the solution directly in the CMTAT ? - -1. This feature is not a standard features common to all tokens. -2. The CMTAT is curently too “heavy” and its contract code size is close to the maximum size limit (if the snapshot module is included), it is not possible to include new features inside. -3. With the new version of the RuleEngine, it is now possible to update the storage of a rule during a transfer call from the CMTAT by using an operation rule. - -### Swiss Law requirement - -- The Swiss law defines that if the transfer is not approved or denied within three months, the request is considered as approved. - -This option can be activated by setting the option `AUTOMATIC_APPROVAL` in the rule - -- Not required by the Swiss Law, but upon request, we have also added the option to perform automatically a transfer if the transfer request is approved. - -This option can be activated by setting the option `AUTOMATIC_TRANSFER` in the rule. - -## Configuration - -### Options/Parameters - -At the rule issuance, the operator has different options to customize the behavior of the rule. - -All these parameters can be updated after deployment. - -| **Struct name** | **Parameter** | **Description** | -| :------------------- | :--------------------------------- | :----------------------------------------------------------- | -| `AUTOMATIC_TRANSFER` | | Manage automatic transfer | -| | `isActivate` | Activate automatic transfer | -| | cmtat | CMTAT token contract | -| `ISSUANCE` | | | -| | `authorizedMintWithoutApproval` | Authorize mint without the need of approval | -| | `authorizedBurnWithoutApproval` | Authorize burn without the need of approval | -| `TIME_LIMIT` | | | -| | `timeLimitToApprove` | Time to approve a request(e.g 7 days) | -| | `timeLimitToTransfer` | Time to perform a transfer after the approval (e.g 30 days) | -| `AUTOMATIC_APPROVAL` | | | -| | `isActivate` | Activate automatic approval | -| | `timeLimitBeforeAutomaticApproval` | Time limit before an approval is “automatically” approved. In this case, it is possible to perform the transfer with a status request to WAITING | - -### Conditional Whitelist - -There is the possibility to add a Rule whitelist. If `from`and `to` are in the whitelist, a CMTAT transfer will be authorized by the rule without an approved requestTransfer. - -The function to call is `setConditionalWhitelist`. - -### Automatic transfer after approval - -This option, if activated, will perform the transfer if the request is approved by the rule operator. - -To perform the transfer, the token holder has to `approve` the rule to spend tokens on his behalf (standard ERC-20 approval). If the allowance is not sufficient, the request will be approved, but without performing the transfer. - -![conditionalTransfer-automaticTransfer.drawio](../schema/rule/conditionalTransfer-automaticTransfer.drawio.png) - -## Schema - -### Graph - -![surya_graph_Blacklist](../surya/surya_graph/surya_graph_RuleConditionalTransfer.sol.png) - -### Inheritance - -![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleConditionalTransfer.sol.png) - -### Workflow - -#### Status - -Each request has a status, which changes regarding the decision of the operator - -The default status is `NONE`. - -![conditionalTransfer-state machine.drawio](../schema/rule/conditionalTransfer-state machine.drawio.png) - -#### With the CMTAT - -![conditionalTransfer - CMTAT](../schema/rule/conditionalTransferCMTAT.drawio.png) - -#### With Storage - -![conditionalTransfer-Storage](../schema/rule/conditionalTransfer-Storage.drawio.png) - -## Request - -- Each request has a status and a list of corresponding attributes. - -### Status - -| **Status** | **Description** | -| :--------- | :----------------------------------------------------------- | -| NONE | Default status \|\| the request has been reset by an operator \|\| the request has been cancelled by the token holder. | -| WAIT | The request is waiting for an approval | -| APPROVED | The request has been approved | -| DENIED | The request has been denied | -| EXECUTED | The request has been executed, which means a successful CMTAT transfer | - - - -### Attributes - -| Name | **Description** | -| :-------- | :----------------------------------------------------------- | -| `key` | Each request is identified with three elements: `from`, address `to` and `value`. From these three elements, a `key` is computed with the one-way hash function *Keccak-256.* | -| `id` | Each request has a unique identifier. Starts from zero | -| `from` | Token holder | -| `to` | Token receiver | -| `valu`e | `value` amount of tokens to transfer | -| `askTime` | Date where the request has been created by the token holder | -| `maxTime` | date limit to perform the transfer after approval | -| `status` | `request status` | - -### Initiate by the token holder(sender) - -1. The sender calls the contract rule to perform a request of transfer under the form of - -"to | value" - -=> Status Wait - -2. The rule operator has to validate the request - -"sender, recipient, amount, date" - -=> Status Approved - -3. The sender then makes the transfer by calling the corresponding function from the CMTAT. - -a. Before performing the transfer, the CMTAT calls the RuleEngine. The RuleEngine checks the request by calling the corresponding rule - - => if the request is valid, the transfer is valid and the ruleEngine will return True to the CMTAT AND the status of the transferRequest is set to `Exectuted`. - -The rest of the transaction is performed inside the CMTAT. - -=> Status Executed - -### Initiate by the operator - -1. The rule operator creates and validates the request : `from | to | value` - -=> Status Approved - -2. The token holder then makes the transfer by calling the corresponding function from the CMTAT - -=> Status Executed - -## Access Control - -The default admin is the address put in argument(`admin`) inside the constructor. It is set in the constructor when the contract is deployed. - -| Name | Description | -| --------------------------------------- | ------------------------------------------------------------ | -| DEFAULT_ADMIN_ROLE | Manage all the roles | -| RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE | Approve request and manage options. Functions defined in the contract RuleConditionalTransferOperator

setAutomaticTransfer
setIssuanceOptions
setTimeLimit
setAutomaticApproval
createTransferRequestWithApproval
approveTransferRequest
approveTransferRequestWithId | - -### Graph - -![surya_graph_Whitelist](../surya/surya_graph/surya_graph_RuleConditionalTransfer.sol.png) - - - -## Time Condition - -- Once a request is `Approved`, the token holder has a date limit (e.g. 7 days) to perform the transfer. After that, he has to begin the whole process again. This parameter can be changed by the rule operator. -- Once a request is created `Wait`, the operator has a date limit (e.g. 7 days) to approve the transfer. After that, the token holder has to begin the whole process again. This parameter can be changed by the rule operator. - -# FAQ - -> With transferFrom, what is the corresponding workflow ? - -With `transferFrom`, the sender, which has the approval from the token holder, is not part of the Vinkulierung workflow. Thus, a valid request for “from, to, value” has to exist. - -There is no control performed on the sender of the `transferFrom` call - -> Can I create several transfer requests with the same value/amount? - -No, it is not possible since each request has a key under the form of - -`hash(from, to, value`) 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 deleted file mode 100644 index 3ce697e..0000000 --- a/doc/technical/RuleSanctionList.md +++ /dev/null @@ -1,38 +0,0 @@ -# Rule SanctionList - -[TOC] - -This document defines the rule SanctionList - -## How to use - -The purpose of this contract is to use the oracle contract from Chainalysis to forbid transfer from/to an address included in a sanctions designation (US, EU, or UN). - -The documentation and the contracts addresses are available here: [Chainalysis oracle for sanctions screening](https://go.chainalysis.com/chainalysis-oracle-docs.html) - -## Schema - -### Graph - -### SanctionList - -![surya_graph_Whitelist](../surya/surya_graph/surya_graph_RuleSanctionList.sol.png) - -### Inheritance - -![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleSanctionList.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. - -**RuleSanctionList** - -![alt text](../security/accessControl/access-control-RuleSanctionList.drawio.png) - diff --git a/doc/technical/RuleWhitelist.md b/doc/technical/RuleWhitelist.md deleted file mode 100644 index d74b8aa..0000000 --- a/doc/technical/RuleWhitelist.md +++ /dev/null @@ -1,50 +0,0 @@ -# Rule Whitelist - -[TOC] - -This rule can be used to restrict transfers from/to only addresses inside a whitelist. - -## Schema - -### Graph - -![surya_graph_Whitelist](../surya/surya_graph/surya_graph_RuleWhitelist.sol.png) - -### Inheritance - -![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleWhitelist.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 whitelist. It is a requirement from the CMTAT to be able to mint tokens. - -It is not a security problem because OpenZeppelin doesn't authorize the transfer of tokens to the zero address. - -### 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/RuleWhitelistWrapper.md b/doc/technical/RuleWhitelistWrapper.md deleted file mode 100644 index 4895bf1..0000000 --- a/doc/technical/RuleWhitelistWrapper.md +++ /dev/null @@ -1,32 +0,0 @@ -# Rule Whitelist Wrapper - -[TOC] - -This rule allows to have several different whitelist rules, managed by different operators. - -The rule will call each whitelist rule to know if during a transfer the address `from`or the address `to`is in the whitelist. -If this is the case, the rule return 0 (transfer valid) or an error otherwise. - -## Schema - -### Architecture - -![ruleWhitelistWrapper.drawio](../schema/rule/ruleWhitelistWrapper.drawio.png) - -### Graph - -![surya_graph_Whitelist](../surya/surya_graph/surya_graph_RuleWhitelistWrapper.sol.png) - -### 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 - -The default admin is the address put in argument(`admin`) inside the constructor. It is set in the constructor when the contract is deployed. diff --git a/foundry.toml b/foundry.toml index abc90ea..090a5e1 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,10 +1,10 @@ [profile.default] -solc = "0.8.27" +solc = "0.8.30" src = 'src' out = 'out' libs = ['lib'] optimizer = true optimizer_runs = 200 -evm_version = 'cancun' +evm_version = 'prague' # See more config options https://github.com/foundry-rs/foundry/tree/master/config diff --git a/hardhat.config.js b/hardhat.config.js index 83d9e54..6ca0075 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -2,12 +2,12 @@ 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 04dad82..305351b 160000 --- a/lib/CMTAT +++ b/lib/CMTAT @@ -1 +1 @@ -Subproject commit 04dad821f2adc29e323d89820046a39cf76fad1b +Subproject commit 305351bb1cff10cd87ff4bda6e263628c34b9543 diff --git a/lib/forge-std b/lib/forge-std index 1eea5ba..8bbcf6e 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 1eea5bae12ae557d589f9f0f0edae2faa47cb262 +Subproject commit 8bbcf6e3f8f62f419e5429a0bd89331c85c37824 diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts index e4f7021..c64a1ed 160000 --- a/lib/openzeppelin-contracts +++ b/lib/openzeppelin-contracts @@ -1 +1 @@ -Subproject commit e4f70216d759d8e6a64144a9e1f7bbeed78e7079 +Subproject commit c64a1edb67b6e3f4a15cca8909c9482ad33a02b0 diff --git a/package-lock.json b/package-lock.json index 755c254..05686eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "RuleEngine", + "name": "RuleEngineNew", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index b76074f..0fd2a8c 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "uml": "npx sol2uml class src", "uml:ruleEngine": "npx sol2uml src contracts -b RuleEngine", "uml:test": "npx sol2uml class test", - "surya:report": "npx surya mdreport surya_report_ruleEngine.md src/RuleEngine.sol && npx surya mdreport surya_report_ruleWhitelist.md src/RuleWhitelist.sol", - "surya:graph": "npx surya graph src/rules/operation/RuleConditionalTransfer.sol | dot -Tpng > surya_graph_conditionalTransfer.png && npx surya graph src/rules/validation/RuleBlacklist.sol| dot -Tpng > surya_graph_blacklist.png && npx surya graph src/rules/validation/RuleWhitelist.sol | dot -Tpng > surya_graph_Whitelist.png && npx surya graph src/RuleEngine.sol | dot -Tpng > surya_graph_RuleEngine.png && npx surya graph src/rules/validation/RuleSanctionList.sol | dot -Tpng > surya_graph_SanctionList.png", + "surya:report": "npx surya mdreport surya_report_ruleEngine.md src/RuleEngine.sol", + "surya:graph": "npx surya graph src/RuleEngine.sol | dot -Tpng > surya_graph_RuleEngine.png", "docgen": "npx hardhat docgen" }, "devDependencies": { diff --git a/script/CMTATWithRuleEngineScript.s.sol b/script/CMTATWithRuleEngineScript.s.sol index 65aec2c..718a221 100644 --- a/script/CMTATWithRuleEngineScript.s.sol +++ b/script/CMTATWithRuleEngineScript.s.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MPL-2.0 + // Documentation : // https://book.getfoundry.sh/tutorials/solidity-scripting pragma solidity ^0.8.17; @@ -6,11 +7,11 @@ pragma solidity ^0.8.17; import "forge-std/Script.sol"; import "../test/HelperContract.sol"; import {RuleEngine} from "src/RuleEngine.sol"; -import {RuleWhitelist} from "src/rules/validation/RuleWhitelist.sol"; +import {RuleWhitelist} from "src/mocks/rules/validation/RuleWhitelist.sol"; /** -@title Deploy a CMTAT, a RuleWhitelist and a RuleEngine -*/ + * @title Deploy a CMTAT, a RuleWhitelist and a RuleEngine + */ contract CMTATWithRuleEngineScript is Script, HelperContract { function run() external { // Get env variable @@ -35,7 +36,7 @@ contract CMTATWithRuleEngineScript is Script, HelperContract { address(CMTAT_CONTRACT) ); console.log("RuleEngine : ", address(RULE_ENGINE)); - RULE_ENGINE.addRuleValidation(ruleWhitelist); + RULE_ENGINE.addRule(ruleWhitelist); CMTAT_CONTRACT.setRuleEngine(RULE_ENGINE); vm.stopBroadcast(); diff --git a/script/RuleEngineScript.s.sol b/script/RuleEngineScript.s.sol index a182928..c133f87 100644 --- a/script/RuleEngineScript.s.sol +++ b/script/RuleEngineScript.s.sol @@ -1,12 +1,12 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MPL-2.0 + // Documentation : // https://book.getfoundry.sh/tutorials/solidity-scripting pragma solidity ^0.8.17; import "forge-std/Script.sol"; -//import "CMTAT/CMTAT_STANDALONE.sol"; import {RuleEngine} from "src/RuleEngine.sol"; -import {RuleWhitelist} from "src/rules/validation/RuleWhitelist.sol"; +import {RuleWhitelist} from "src/mocks/rules/validation/RuleWhitelist.sol"; import {ValidationModuleRuleEngine} from "CMTAT/modules/wrapper/extensions/ValidationModule/ValidationModuleRuleEngine.sol"; /** @@ -25,10 +25,13 @@ contract RuleEngineScript is Script { // ruleEngine RuleEngine RULE_ENGINE = new RuleEngine(ADMIN, address(0), address(0)); console.log("RuleEngine: ", address(RULE_ENGINE)); - RULE_ENGINE.addRuleValidation(ruleWhitelist); + RULE_ENGINE.addRule(ruleWhitelist); // Configure the new ruleEngine for CMTAT (bool success, ) = address(CMTAT_Address).call( - abi.encodeCall(ValidationModuleRuleEngine.setRuleEngine, RULE_ENGINE) + abi.encodeCall( + ValidationModuleRuleEngine.setRuleEngine, + RULE_ENGINE + ) ); require(success); vm.stopBroadcast(); diff --git a/src/RuleEngine.sol b/src/RuleEngine.sol index 619d6ee..a98baae 100644 --- a/src/RuleEngine.sol +++ b/src/RuleEngine.sol @@ -2,27 +2,17 @@ pragma solidity ^0.8.20; -import "CMTAT/interfaces/engine/IRuleEngine.sol"; -import "./modules/MetaTxModuleStandalone.sol"; -import "./modules/RuleEngineOperation.sol"; -import {RuleEngineValidation} from "./modules/RuleEngineValidation.sol"; -import {IRuleValidation} from "./interfaces/IRuleValidation.sol"; +/* ==== OpenZeppelin === */ +import {Context} from "OZ/utils/Context.sol"; +/* ==== Modules === */ +import {ERC2771ModuleStandalone, ERC2771Context} from "./modules/ERC2771ModuleStandalone.sol"; +/* ==== Base contract === */ +import {RuleEngineBase} from "./RuleEngineBase.sol"; + /** * @title Implementation of a ruleEngine as defined by the CMTAT */ -contract RuleEngine is - IRuleEngine, - RuleEngineOperation, - RuleEngineValidation, - MetaTxModuleStandalone -{ - - /** - * @notice - * Get the current version of the smart contract - */ - string public constant VERSION = "2.0.5"; - +contract RuleEngine is ERC2771ModuleStandalone, RuleEngineBase { /** * @param admin Address of the contract (Access Control) * @param forwarderIrrevocable Address of the forwarder, required for the gasless support @@ -31,193 +21,16 @@ contract RuleEngine is address admin, address forwarderIrrevocable, address tokenContract - ) MetaTxModuleStandalone(forwarderIrrevocable) { + ) ERC2771ModuleStandalone(forwarderIrrevocable) { if (admin == address(0)) { revert RuleEngine_AdminWithAddressZeroNotAllowed(); } if (tokenContract != address(0)) { - _grantRole(TOKEN_CONTRACT_ROLE, tokenContract); + _bindToken(tokenContract); } _grantRole(DEFAULT_ADMIN_ROLE, admin); } - /** - * @notice Go through all the rule to know if a restriction exists on the transfer - * @param from the origin address - * @param to the destination address - * @param value to transfer - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - **/ - function detectTransferRestriction( - address from, - address to, - uint256 value - ) public view override returns (uint8) { - // Validation - uint8 code = RuleEngineValidation.detectTransferRestrictionValidation( - from, - to, - value - ); - if (code != uint8(REJECTED_CODE_BASE.TRANSFER_OK)) { - return code; - } - - // Operation - uint256 rulesLength = _rulesOperation.length; - for (uint256 i = 0; i < rulesLength; ++i) { - uint8 restriction = IRuleValidation(_rulesOperation[i]) - .detectTransferRestriction(from, to, value); - if (restriction > 0) { - return restriction; - } - } - - return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - } - - function detectTransferRestrictionFrom( - address spender, - address from, - address to, - uint256 value - ) public view override returns (uint8) { - // Validation - uint8 code = RuleEngineValidation.detectTransferRestrictionValidationFrom(spender, - from, - to, - value - ); - if (code != uint8(REJECTED_CODE_BASE.TRANSFER_OK)) { - return code; - } - - // Operation - uint256 rulesLength = _rulesOperation.length; - for (uint256 i = 0; i < rulesLength; ++i) { - uint8 restriction = IRuleValidation(_rulesOperation[i]) - .detectTransferRestrictionFrom(spender,from, to, value); - if (restriction > 0) { - return restriction; - } - } - - return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - } - - /** - * @notice Validate a transfer - * @param from the origin address - * @param to the destination address - * @param value to transfer - * @return True if the transfer is valid, false otherwise - **/ - function canTransfer( - address from, - address to, - uint256 value - ) public view override returns (bool) { - return - detectTransferRestriction(from, to, value) == - uint8(REJECTED_CODE_BASE.TRANSFER_OK); - } - - /** - * @notice Validate a transfer - * @param from the origin address - * @param to the destination address - * @param value to transfer - * @return True if the transfer is valid, false otherwise - **/ - function canTransferFrom( - address /*spender*/, - address from, - address to, - uint256 value - ) public view override returns (bool) { - return - detectTransferRestriction(from, to, value) == - uint8(REJECTED_CODE_BASE.TRANSFER_OK); - } - - /** - * @notice Return the message corresponding to the code - * @param _restrictionCode The target restriction code - * @return True if the transfer is valid, false otherwise - **/ - function messageForTransferRestriction( - uint8 _restrictionCode - ) external view override returns (string memory) { - // Validation - uint256 rulesLength = _rulesValidation.length; - for (uint256 i = 0; i < rulesLength; ++i) { - if ( - IRuleValidation(_rulesValidation[i]) - .canReturnTransferRestrictionCode(_restrictionCode) - ) { - return - IRuleValidation(_rulesValidation[i]) - .messageForTransferRestriction(_restrictionCode); - } - } - // operation - rulesLength = _rulesOperation.length; - for (uint256 i = 0; i < rulesLength; ++i) { - if ( - IRuleValidation(_rulesOperation[i]) - .canReturnTransferRestrictionCode(_restrictionCode) - ) { - return - IRuleValidation(_rulesOperation[i]) - .messageForTransferRestriction(_restrictionCode); - } - } - return "Unknown restriction code"; - } - - /* - * @notice function protected by access control - */ - function transferred( - address spender, - address from, - address to, - uint256 amount - ) external override onlyRole(TOKEN_CONTRACT_ROLE) { - // Validate transfer - require(RuleEngineValidation.canTransferValidation(from, to, amount),RuleEngine_InvalidTransfer(from, to, amount)); - - // Apply operation on RuleEngine - require(RuleEngineOperation._operateOnTransfer(from, to, amount),RuleEngine_InvalidTransfer(from, to, amount)); - } - - function transferred( - address from, - address to, - uint256 amount - ) external override onlyRole(TOKEN_CONTRACT_ROLE) { - // Validate transfer - require(RuleEngineValidation.canTransferValidation(from, to, amount),RuleEngine_InvalidTransfer(from, to, amount)); - - // Apply operation on RuleEngine - require(RuleEngineOperation._operateOnTransfer(from, to, amount),RuleEngine_InvalidTransfer(from, to, amount)); - } - - /* ============ 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 //////////////////////////////////////////////////////////////*/ @@ -228,6 +41,7 @@ contract RuleEngine is function _msgSender() internal view + virtual override(ERC2771Context, Context) returns (address sender) { @@ -240,6 +54,7 @@ contract RuleEngine is function _msgData() internal view + virtual override(ERC2771Context, Context) returns (bytes calldata) { @@ -252,6 +67,7 @@ contract RuleEngine is function _contextSuffixLength() internal view + virtual override(ERC2771Context, Context) returns (uint256) { diff --git a/src/RuleEngineBase.sol b/src/RuleEngineBase.sol new file mode 100644 index 0000000..da5d4ef --- /dev/null +++ b/src/RuleEngineBase.sol @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +/* ==== OpenZeppelin === */ +import {AccessControl} from "OZ/access/AccessControl.sol"; +/* ==== CMTAT === */ +import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; +import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; +import {IERC3643ComplianceRead, IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; +import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol"; + +/* ==== Modules === */ +import {ERC3643ComplianceModule, IERC3643Compliance} from "./modules/ERC3643ComplianceModule.sol"; +import {VersionModule} from "./modules/VersionModule.sol"; +import {RulesManagementModule} from "./modules/RulesManagementModule.sol"; + +/* ==== Interface and other library === */ +import {IRule} from "./interfaces/IRule.sol"; +import {RuleEngineInvariantStorage} from "./modules/library/RuleEngineInvariantStorage.sol"; + +/** + * @title Implementation of a ruleEngine as defined by the CMTAT + */ +abstract contract RuleEngineBase is + VersionModule, + RulesManagementModule, + ERC3643ComplianceModule, + RuleEngineInvariantStorage, + IRuleEngine +{ + /* ============ State functions ============ */ + /* + * @inheritdoc IRuleEngine + */ + function transferred( + address spender, + address from, + address to, + uint256 value + ) public virtual override(IRuleEngine) onlyBoundToken { + // Apply on RuleEngine + RulesManagementModule._transferred(spender, from, to, value); + } + + /** + * @inheritdoc IERC3643IComplianceContract + */ + function transferred( + address from, + address to, + uint256 value + ) public virtual override(IERC3643IComplianceContract) onlyBoundToken { + _transferred(from, to, value); + } + + /// @inheritdoc IERC3643Compliance + function created( + address to, + uint256 value + ) public virtual override(IERC3643Compliance) onlyBoundToken { + _transferred(address(0), to, value); + } + + /// @inheritdoc IERC3643Compliance + function destroyed( + address from, + uint256 value + ) public virtual override(IERC3643Compliance) onlyBoundToken { + _transferred(from, address(0), value); + } + + /* ============ View functions ============ */ + /** + * @notice Go through all the rule to know if a restriction exists on the transfer + * @param from the origin address + * @param to the destination address + * @param value to transfer + * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid + **/ + function detectTransferRestriction( + address from, + address to, + uint256 value + ) public view virtual override returns (uint8) { + uint256 rulesLength = rulesCount(); + for (uint256 i = 0; i < rulesLength; ++i) { + uint8 restriction = IRule(rule(i)).detectTransferRestriction( + from, + to, + value + ); + if (restriction > 0) { + return restriction; + } + } + return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + /** + * @inheritdoc IERC1404Extend + */ + function detectTransferRestrictionFrom( + address spender, + address from, + address to, + uint256 value + ) public view virtual override(IERC1404Extend) returns (uint8) { + uint256 rulesLength = rulesCount(); + for (uint256 i = 0; i < rulesLength; ++i) { + uint8 restriction = IRule(rule(i)).detectTransferRestrictionFrom( + spender, + from, + to, + value + ); + if (restriction > 0) { + return restriction; + } + } + + return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + /** + * @inheritdoc IERC1404 + */ + function messageForTransferRestriction( + uint8 restrictionCode + ) public view virtual override(IERC1404) returns (string memory) { + // + uint256 rulesLength = rulesCount(); + for (uint256 i = 0; i < rulesLength; ++i) { + if ( + IRule(rule(i)).canReturnTransferRestrictionCode(restrictionCode) + ) { + return + IRule(rule(i)).messageForTransferRestriction( + restrictionCode + ); + } + } + return "Unknown restriction code"; + } + + /** + * @inheritdoc IERC3643ComplianceRead + */ + function canTransfer( + address from, + address to, + uint256 value + ) public view virtual override(IERC3643ComplianceRead) returns (bool) { + return + detectTransferRestriction(from, to, value) == + uint8(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 + detectTransferRestrictionFrom(spender, from, to, value) == + uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + /* ============ ACCESS CONTROL ============ */ + /** + * @notice Returns `true` if `account` has been granted `role`. + * @dev The Default Admin has all roles + */ + function hasRole( + bytes32 role, + address account + ) public view virtual override(AccessControl) returns (bool) { + if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { + return true; + } else { + return AccessControl.hasRole(role, account); + } + } +} diff --git a/src/interfaces/IERC3643Compliance.sol b/src/interfaces/IERC3643Compliance.sol new file mode 100644 index 0000000..2956259 --- /dev/null +++ b/src/interfaces/IERC3643Compliance.sol @@ -0,0 +1,89 @@ +//SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +/* ==== CMTAT === */ +import {IERC3643ComplianceRead, IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; + +interface IERC3643Compliance is + IERC3643ComplianceRead, + IERC3643IComplianceContract +{ + /* ============ Events ============ */ + /** + * @notice Emitted when a token is successfully bound to the compliance contract. + * @param token The address of the token that was bound. + */ + event TokenBound(address token); + + /** + * @notice Emitted when a token is successfully unbound from the compliance contract. + * @param token The address of the token that was unbound. + */ + event TokenUnbound(address token); + + /* ============ Functions ============ */ + /** + * @notice Associates a token contract with this compliance contract. + * @dev The compliance contract may restrict operations on the bound token + * according to the compliance logic. + * Reverts if the token is already bound. + * Complexity: O(1). + * @param token The address of the token to bind. + */ + function bindToken(address token) external; + + /** + * @notice Removes the association of a token contract from this compliance contract. + * @dev Reverts if the token is not currently bound. + * Complexity: O(1). + * @param token The address of the token to unbind. + */ + function unbindToken(address token) external; + + /** + * @notice Checks whether a token is currently bound to this compliance contract. + * @dev + * Complexity: O(1). + * Note that there are no guarantees on the ordering of values inside the array, + * and it may change when more values are added or removed. + * @param token The token address to verify. + * @return isBound True if the token is bound, false otherwise. + */ + function isTokenBound(address token) external view returns (bool isBound); + + /** + * @notice Returns the single token currently bound to this compliance contract. + * @dev If multiple tokens are supported, consider using getTokenBounds(). + * @return token The address of the currently bound token. + */ + function getTokenBound() external view returns (address token); + + /** + * @notice Returns all tokens currently bound to this compliance contract. + * @dev This is a view-only function and does not modify state. + * This function is not part of the original ERC-3643 specification + * This operation will copy the entire storage to memory, which can be quite expensive. + * This is designed to mostly be used by view accessors that are queried without any gas fees. + * @return tokens An array of addresses of bound token contracts. + */ + function getTokenBounds() external view returns (address[] memory tokens); + + /** + * @notice Updates the compliance contract state when tokens are created (minted). + * @dev Called by the token contract when new tokens are issued to an account. + * Reverts if the minting does not comply with the rules. + * @param to The address receiving the minted tokens. + * @param value The number of tokens created. + */ + function created(address to, uint256 value) external; + + /** + * @notice Updates the compliance contract state when tokens are destroyed (burned). + * @dev Called by the token contract when tokens are redeemed or burned. + * Reverts if the burning does not comply with the rules. + * @param from The address whose tokens are being destroyed. + * @param value The number of tokens destroyed. + */ + function destroyed(address from, uint256 value) external; +} diff --git a/src/interfaces/IRule.sol b/src/interfaces/IRule.sol new file mode 100644 index 0000000..0f43b7a --- /dev/null +++ b/src/interfaces/IRule.sol @@ -0,0 +1,17 @@ +//SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +/* ==== CMTAT === */ +import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; + +/* ==== Interfaces === */ + +interface IRule is IRuleEngine { + /** + * @dev Returns true if the restriction code exists, and false otherwise. + */ + function canReturnTransferRestrictionCode( + uint8 restrictionCode + ) external view returns (bool); +} diff --git a/src/interfaces/IRuleEngineOperation.sol b/src/interfaces/IRuleEngineOperation.sol deleted file mode 100644 index 7b17e2d..0000000 --- a/src/interfaces/IRuleEngineOperation.sol +++ /dev/null @@ -1,25 +0,0 @@ -//SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -interface IRuleEngineOperation { - /** - * @dev define the rules, the precedent rules will be overwritten - */ - function setRulesOperation(address[] calldata rules_) external; - - /** - * @dev return the number of rules - */ - function rulesCountOperation() external view returns (uint256); - - /** - * @dev return the rule at the index specified by ruleId - */ - function ruleOperation(uint256 ruleId) external view returns (address); - - /** - * @dev return all the rules - */ - function rulesOperation() external view returns (address[] memory); -} diff --git a/src/interfaces/IRuleEngineValidation.sol b/src/interfaces/IRuleEngineValidation.sol deleted file mode 100644 index 736be39..0000000 --- a/src/interfaces/IRuleEngineValidation.sol +++ /dev/null @@ -1,54 +0,0 @@ -//SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -interface IRuleEngineValidation { - /** - * @dev See ERC-1404 - * - */ - function detectTransferRestrictionValidation( - address _from, - address _to, - uint256 _amount - ) external view returns (uint8); - - function detectTransferRestrictionValidationFrom( - address spender, - address _from, - address _to, - uint256 _amount - ) external view returns (uint8); - - /** - * @dev Returns true if the transfer is valid, and false otherwise. - */ - function canTransferValidationFrom( - address spender, - address _from, - address _to, - uint256 _amount - ) external view returns (bool isValid); -} - -interface IRuleEngineValidationCommon { - /** - * @dev define the rules, the precedent rules will be overwritten - */ - function setRulesValidation(address[] calldata rules_) external; - - /** - * @dev return the number of rules - */ - function rulesCountValidation() external view returns (uint256); - - /** - * @dev return the rule at the index specified by ruleId - */ - function ruleValidation(uint256 ruleId) external view returns (address); - - /** - * @dev return all the rules - */ - function rulesValidation() external view returns (address[] memory); -} diff --git a/src/interfaces/IRuleOperation.sol b/src/interfaces/IRuleOperation.sol deleted file mode 100644 index 5874646..0000000 --- a/src/interfaces/IRuleOperation.sol +++ /dev/null @@ -1,14 +0,0 @@ -//SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -interface IRuleOperation { - /** - * @dev Returns true if the transfer is valid, and false otherwise. - */ - function operateOnTransfer( - address _from, - address _to, - uint256 _amount - ) external returns (bool isValid); -} diff --git a/src/interfaces/IRuleValidation.sol b/src/interfaces/IRuleValidation.sol deleted file mode 100644 index 538d514..0000000 --- a/src/interfaces/IRuleValidation.sol +++ /dev/null @@ -1,22 +0,0 @@ -//SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; -import {IERC7551Compliance} from "CMTAT/interfaces//tokenization/draft-IERC7551.sol"; -interface IRuleValidation is IERC1404Extend, IERC7551Compliance { - /** - * @dev Returns true if the restriction code exists, and false otherwise. - */ - function canReturnTransferRestrictionCode( - uint8 _restrictionCode - ) external view returns (bool); - - function detectTransferRestrictionFrom( - address spender, - address _from, - address _to, - uint256 _amount - ) external view override returns (uint8); - -} diff --git a/src/interfaces/IRulesManagementModule.sol b/src/interfaces/IRulesManagementModule.sol new file mode 100644 index 0000000..81dfced --- /dev/null +++ b/src/interfaces/IRulesManagementModule.sol @@ -0,0 +1,80 @@ +//SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +/* ==== Interfaces === */ +import {IRule} from "./IRule.sol"; + +interface IRulesManagementModule { + /** + * @notice Defines the rules for the rule engine. + * @dev Sets the list of rule contract addresses for s. + * Any previously set rules will be completely overwritten by the new list. + * Rules should be deployed contracts that implement the expected interface. + * @param rules_ The array of addresses representing the new rules to be set. + * @dev Revert if one rule is a zero address or if the rule is already present + * This function calls _clearRules if at least one rule is still configured + */ + function setRules(IRule[] calldata rules_) external; + + /** + * @notice Returns the total number of currently configured rules. + * @dev Equivalent to the length of the internal rules array. + * Complexity: O(1) + * @return numberOfrules The number of active rules. + */ + function rulesCount() external view returns (uint256 numberOfrules); + + /** + * @notice Retrieves the rule address at a specific index. + * @dev Reverts if `ruleId` is out of bounds. + * Complexity: O(1). + * Note that there are no guarantees on the ordering of values inside the array, + * and it may change when more values are added or removed. + * @param ruleId The index of the desired rule in the array. + * @return ruleAddress The address of the corresponding IRule contract, return the `zero address` is out of bounds. + */ + function rule(uint256 ruleId) external view returns (address ruleAddress); + + /** + * @notice Returns the full list of currently configured rules. + * @dev This is a view-only function that does not modify state. + * This operation will copy the entire storage to memory, which can be quite expensive. + * This is designed to mostly be used by view accessors that are queried without any gas fees. + * @return ruleAddresses An array of all active rule contract addresses. + */ + function rules() external view returns (address[] memory ruleAddresses); + + /** + * @notice Removes all configured rules. + * @dev After calling this function, no rules will remain set. + * Developers should keep in mind that this function has an unbounded cost + * and using it may render the function uncallable if the set grows to the point + * where clearing it consumes too much gas to fit in a block. + */ + function clearRules() external; + + /** + * @notice Adds a new rule to the current rule set. + * @dev Reverts if the rule address is zero or already exists in the set. + * Complexity: O(1). + * @param rule_ The IRule contract to add. + */ + function addRule(IRule rule_) external; + + /** + * @notice Removes a specific rule from the current rule set. + * @dev Reverts if the provided rule is not found or does not match the stored rule at its index. + * Complexity: O(1). + * @param rule_ The IRule contract to remove. + */ + function removeRule(IRule rule_) external; + + /** + * @notice Checks whether a specific rule is currently configured. + * @param rule_ The IRule contract to check for membership. + * @dev Complexity: O(1). + * @return exists True if the rule is present, false otherwise. + */ + function containsRule(IRule rule_) external returns (bool exists); +} diff --git a/src/mocks/rules/operation/RuleConditionalTransferLight.sol b/src/mocks/rules/operation/RuleConditionalTransferLight.sol new file mode 100644 index 0000000..36f2c41 --- /dev/null +++ b/src/mocks/rules/operation/RuleConditionalTransferLight.sol @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "OZ/access/AccessControl.sol"; +import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; +import {RuleConditionalTransferLightInvariantStorage} from "./abstract/RuleConditionalTransferLightInvariantStorage.sol"; +import {IRule} from "../../../interfaces/IRule.sol"; + +/** + * @title TransferApprovalRule + * @dev Requires operator approval for each ERC20 transfer. + * Same transfer (from, to, value) can be approved multiple times. + */ +contract RuleConditionalTransferLight is + AccessControl, + RuleConditionalTransferLightInvariantStorage, + IRule +{ + // Mapping from transfer hash to approval count + mapping(bytes32 => uint256) public approvalCounts; + + constructor(address admin, IRuleEngine ruleEngineContract) { + require(admin != address(0), "Invalid operator"); + + _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); + _grantRole(OPERATOR_ROLE, admin); + if (address(ruleEngineContract) != address(0x0)) { + _grantRole(RULE_ENGINE_CONTRACT_ROLE, address(ruleEngineContract)); + } + } + + /** + * @notice Approve a specific transfer. Can be approved multiple times. + */ + function approveTransfer( + address from, + address to, + uint256 value + ) public onlyRole(OPERATOR_ROLE) { + bytes32 transferHash = keccak256(abi.encodePacked(from, to, value)); + approvalCounts[transferHash] += 1; + emit TransferApproved(from, to, value, approvalCounts[transferHash]); + } + + /** + * @notice Returns number of times a transfer is approved. + */ + function approvedCount( + address from, + address to, + uint256 value + ) public view returns (uint256) { + bytes32 transferHash = keccak256(abi.encodePacked(from, to, value)); + return approvalCounts[transferHash]; + } + + /** + * @notice Called when a transfer occurs. Decrements approval count if allowed. + * @dev `spender` is part of the interface but unused. + */ + function transferred(address from, address to, uint256 value) public { + bytes32 transferHash = keccak256(abi.encodePacked(from, to, value)); + uint256 count = approvalCounts[transferHash]; + + if (count == 0) revert TransferNotApproved(); + + approvalCounts[transferHash] = count - 1; + emit TransferExecuted(from, to, value, approvalCounts[transferHash]); + } + + function transferred( + address /* spender */, + address from, + address to, + uint256 value + ) public { + transferred(from, to, value); + } + + /** + * @notice Check if the transfer is valid + * @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) { + bytes32 transferHash = keccak256(abi.encodePacked(from, to, value)); + uint256 count = approvalCounts[transferHash]; + if (count == 0) { + return CODE_TRANSFER_REQUEST_NOT_APPROVED; + } + return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + /** + * @notice Check if the transfer is valid + * @param from the origin address + * @param to the destination address + * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + **/ + function detectTransferRestrictionFrom( + address /* spender*/, + address from, + address to, + uint256 value + ) public view override returns (uint8) { + return detectTransferRestriction(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_TRANSFER_REQUEST_NOT_APPROVED; + } + + /** + * @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_TRANSFER_REQUEST_NOT_APPROVED) { + return TEXT_TRANSFER_REQUEST_NOT_APPROVED; + } else { + return TEXT_CODE_NOT_FOUND; + } + } + + /** + * @notice Validate a 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) { + return + detectTransferRestriction(_from, _to, _amount) == + uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + function canTransferFrom( + address spender, + address from, + address to, + uint256 value + ) public view virtual override returns (bool) { + return + detectTransferRestrictionFrom(spender, from, to, value) == + uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } +} diff --git a/src/mocks/rules/operation/RuleOperationRevert.sol b/src/mocks/rules/operation/RuleOperationRevert.sol new file mode 100644 index 0000000..141d9f4 --- /dev/null +++ b/src/mocks/rules/operation/RuleOperationRevert.sol @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "OZ/access/AccessControl.sol"; +import "../validation/abstract/RuleCommonInvariantStorage.sol"; +import {IRule} from "../../../interfaces/IRule.sol"; + +/** + * @title TransferApprovalRule + * @dev Requires operator approval for each ERC20 transfer. + * Same transfer (from, to, value) can be approved multiple times. + */ +contract RuleOperationRevert is + AccessControl, + IRule, + RuleCommonInvariantStorage +{ + error RuleConditionalTransferLight_InvalidTransfer(); + // It is very important that each rule uses an unique code + uint8 public constant CODE_TRANSFER_REQUEST_NOT_APPROVED = 71; + + /** + * @notice Called when a transfer occurs. Decrements approval count if allowed. + * @dev `spender` is part of the interface but unused. + */ + function transferred( + address /*from*/, + address /* to */, + uint256 /* value */ + ) public pure { + revert RuleConditionalTransferLight_InvalidTransfer(); + } + + function transferred( + address /* spender */, + address /*from*/, + address /* to */, + uint256 /* value */ + ) public pure { + revert RuleConditionalTransferLight_InvalidTransfer(); + } + + /** + * @notice Check if the transfer is valid + * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + **/ + function detectTransferRestriction( + address /* from */, + address /* to */, + uint256 /* value */ + ) public pure override returns (uint8) { + return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + /** + * @notice Check if the transfer is valid + * @param from the origin address + * @param to the destination address + * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + **/ + function detectTransferRestrictionFrom( + address /* spender*/, + address from, + address to, + uint256 value + ) public pure override returns (uint8) { + return detectTransferRestriction(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_TRANSFER_REQUEST_NOT_APPROVED; + } + + /** + * @notice Return the corresponding message + * @return true if the transfer is valid, false otherwise + **/ + function messageForTransferRestriction( + uint8 /* restrictionCode */ + ) external pure override returns (string memory) { + return TEXT_CODE_NOT_FOUND; + } + + /** + * @notice Validate a 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 pure override returns (bool isValid) { + return + detectTransferRestriction(_from, _to, _amount) == + uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + function canTransferFrom( + address spender, + address from, + address to, + uint256 value + ) public view virtual override returns (bool) { + return + detectTransferRestrictionFrom(spender, from, to, value) == + uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } +} diff --git a/src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol b/src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol new file mode 100644 index 0000000..10732d4 --- /dev/null +++ b/src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; +import "OZ/token/ERC20/IERC20.sol"; + +import "../../validation/abstract/RuleCommonInvariantStorage.sol"; +import "src/mocks/rules/validation/RuleWhitelist.sol"; + +abstract contract RuleConditionalTransferLightInvariantStorage is + RuleCommonInvariantStorage +{ + /* ============ Role ============ */ + bytes32 public constant RULE_ENGINE_CONTRACT_ROLE = + keccak256("RULE_ENGINE_CONTRACT_ROLE"); + bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); + + /* ============ State variables ============ */ + string constant TEXT_TRANSFER_REQUEST_NOT_APPROVED = + "ConditionalTransferLight: The request is not approved"; + // Code + // It is very important that each rule uses an unique code + uint8 public constant CODE_TRANSFER_REQUEST_NOT_APPROVED = 71; + + /* ============ Custom error ============ */ + error TransferNotApproved(); + + /* ============ Events ============ */ + event TransferApproved( + address indexed from, + address indexed to, + uint256 value, + uint256 count + ); + event TransferExecuted( + address indexed from, + address indexed to, + uint256 value, + uint256 remaining + ); +} diff --git a/src/mocks/rules/validation/RuleWhitelist.sol b/src/mocks/rules/validation/RuleWhitelist.sol new file mode 100644 index 0000000..1c1e7ec --- /dev/null +++ b/src/mocks/rules/validation/RuleWhitelist.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +import "./abstract/RuleAddressList/RuleAddressList.sol"; +import "./abstract/RuleWhitelistCommon.sol"; + +/** + * @title a whitelist manager + */ +contract RuleWhitelist is RuleAddressList, RuleWhitelistCommon { + error RuleWhitelist_InvalidTransfer( + address from, + address to, + uint256 value, + uint8 code + ); + + /** + * @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) {} + + /** + * @notice Validate a 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) { + return + detectTransferRestriction(_from, _to, _amount) == + uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + function canTransferFrom( + address spender, + address from, + address to, + uint256 value + ) public view virtual override returns (bool) { + return + detectTransferRestrictionFrom(spender, from, to, value) == + uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + /** + * @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)) { + return CODE_ADDRESS_FROM_NOT_WHITELISTED; + } else if (!addressIsListed(to)) { + return CODE_ADDRESS_TO_NOT_WHITELISTED; + } else { + return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + } + + function detectTransferRestrictionFrom( + address spender, + address from, + address to, + uint256 value + ) public view override returns (uint8) { + if (!addressIsListed(spender)) { + return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; + } else { + return detectTransferRestriction(from, to, value); + } + } + + function transferred(address from, address to, uint256 value) public view { + uint8 code = detectTransferRestriction(from, to, value); + require( + code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + RuleWhitelist_InvalidTransfer(from, to, value, code) + ); + } + + function transferred( + address spender, + address from, + address to, + uint256 value + ) public view { + uint8 code = detectTransferRestrictionFrom(spender, from, to, value); + require( + code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + RuleWhitelist_InvalidTransfer(from, to, value, code) + ); + } +} diff --git a/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol b/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol similarity index 96% rename from src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol rename to src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol index ddcdb54..85f23d9 100644 --- a/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol +++ b/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.20; import "OZ/access/AccessControl.sol"; -import "./../../../../modules/MetaTxModuleStandalone.sol"; +import "../../../../../modules/ERC2771ModuleStandalone.sol"; import "./RuleAddressListInternal.sol"; import "./invariantStorage/RuleAddressListInvariantStorage.sol"; @@ -13,7 +13,7 @@ import "./invariantStorage/RuleAddressListInvariantStorage.sol"; abstract contract RuleAddressList is AccessControl, - MetaTxModuleStandalone, + ERC2771ModuleStandalone, RuleAddressListInternal, RuleAddressListInvariantStorage { @@ -27,7 +27,7 @@ abstract contract RuleAddressList is constructor( address admin, address forwarderIrrevocable - ) MetaTxModuleStandalone(forwarderIrrevocable) { + ) ERC2771ModuleStandalone(forwarderIrrevocable) { if (admin == address(0)) { revert RuleAddressList_AdminWithAddressZeroNotAllowed(); } @@ -139,7 +139,7 @@ abstract contract RuleAddressList is //////////////////////////////////////////////////////////////*/ /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule + * @dev This surcharge is not necessary if you do not use the ERC2771Module */ function _msgSender() internal @@ -151,7 +151,7 @@ abstract contract RuleAddressList is } /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule + * @dev This surcharge is not necessary if you do not use the ERC2771Module */ function _msgData() internal @@ -163,7 +163,7 @@ abstract contract RuleAddressList is } /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule + * @dev This surcharge is not necessary if you do not use the ERC2771Module */ function _contextSuffixLength() internal diff --git a/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol b/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol similarity index 100% rename from src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol rename to src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol diff --git a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol b/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol similarity index 100% rename from src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol rename to src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol diff --git a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol b/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol similarity index 100% rename from src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol rename to src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol diff --git a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol b/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol similarity index 100% rename from src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol rename to src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol diff --git a/src/rules/validation/abstract/RuleCommonInvariantStorage.sol b/src/mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol similarity index 100% rename from src/rules/validation/abstract/RuleCommonInvariantStorage.sol rename to src/mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol diff --git a/src/rules/validation/abstract/RuleWhitelistCommon.sol b/src/mocks/rules/validation/abstract/RuleWhitelistCommon.sol similarity index 54% rename from src/rules/validation/abstract/RuleWhitelistCommon.sol rename to src/mocks/rules/validation/abstract/RuleWhitelistCommon.sol index dedd371..d10041c 100644 --- a/src/rules/validation/abstract/RuleWhitelistCommon.sol +++ b/src/mocks/rules/validation/abstract/RuleWhitelistCommon.sol @@ -3,39 +3,36 @@ pragma solidity ^0.8.20; import "./RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol"; -import "./RuleValidateTransfer.sol"; +import {IRule} from "../../../../interfaces/IRule.sol"; -abstract contract RuleWhitelistCommon is - RuleValidateTransfer, - RuleWhitelistInvariantStorage -{ +abstract contract RuleWhitelistCommon is RuleWhitelistInvariantStorage, IRule { /** * @notice To know if the restriction code is valid for this rule or not - * @param _restrictionCode The target restriction code + * @param restrictionCode The target restriction code * @return true if the restriction code is known, false otherwise **/ function canReturnTransferRestrictionCode( - uint8 _restrictionCode + 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; + 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 + * @param restrictionCode The target restriction code * @return true if the transfer is valid, false otherwise **/ function messageForTransferRestriction( - uint8 _restrictionCode + uint8 restrictionCode ) external pure override returns (string memory) { - if (_restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) { + 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; diff --git a/src/modules/MetaTxModuleStandalone.sol b/src/modules/ERC2771ModuleStandalone.sol similarity index 59% rename from src/modules/MetaTxModuleStandalone.sol rename to src/modules/ERC2771ModuleStandalone.sol index a234a35..f256909 100644 --- a/src/modules/MetaTxModuleStandalone.sol +++ b/src/modules/ERC2771ModuleStandalone.sol @@ -2,12 +2,13 @@ pragma solidity ^0.8.20; -import "OZ/metatx/ERC2771Context.sol"; +/* ==== OpenZeppelin === */ +import {ERC2771Context} from "OZ/metatx/ERC2771Context.sol"; /** * @dev Meta transaction (gasless) module. */ -abstract contract MetaTxModuleStandalone is ERC2771Context { +abstract contract ERC2771ModuleStandalone is ERC2771Context { constructor(address trustedForwarder) ERC2771Context(trustedForwarder) { // Nothing to do } diff --git a/src/modules/ERC3643ComplianceModule.sol b/src/modules/ERC3643ComplianceModule.sol new file mode 100644 index 0000000..23326fb --- /dev/null +++ b/src/modules/ERC3643ComplianceModule.sol @@ -0,0 +1,112 @@ +//SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +/* ==== OpenZeppelin === */ +import {AccessControl} from "OZ/access/AccessControl.sol"; +import {EnumerableSet} from "OZ/utils/structs/EnumerableSet.sol"; +/* ==== Interface and other library === */ +import {IERC3643Compliance} from "../interfaces/IERC3643Compliance.sol"; + +abstract contract ERC3643ComplianceModule is IERC3643Compliance, AccessControl { + /* ==== Type declaration === */ + using EnumerableSet for EnumerableSet.AddressSet; + /* ==== State Variables === */ + // Token binding tracking + EnumerableSet.AddressSet private _boundTokens; + // Access Control + bytes32 public constant COMPLIANCE_MANAGER_ROLE = + keccak256("COMPLIANCE_MANAGER_ROLE"); + + /* ==== Errors === */ + error RuleEngine_ERC3643Compliance_InvalidTokenAddress(); + error RuleEngine_ERC3643Compliance_TokenAlreadyBound(); + error RuleEngine_ERC3643Compliance_TokenNotBound(); + error RuleEngine_ERC3643Compliance_UnauthorizedCaller(); + error RuleEngine_ERC3643Compliance_OperationNotSuccessful(); + + /* ==== Modifier === */ + modifier onlyBoundToken() { + if (!_boundTokens.contains(_msgSender())) { + revert RuleEngine_ERC3643Compliance_UnauthorizedCaller(); + } + _; + } + + /*////////////////////////////////////////////////////////////// + PUBLIC/public FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + /* ============ State functions ============ */ + /// @inheritdoc IERC3643Compliance + function bindToken( + address token + ) public virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) { + _bindToken(token); + } + + /// @inheritdoc IERC3643Compliance + function unbindToken( + address token + ) public virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) { + _unbindToken(token); + } + + /// @inheritdoc IERC3643Compliance + function isTokenBound( + address token + ) public view virtual override returns (bool) { + return _boundTokens.contains(token); + } + + /// @inheritdoc IERC3643Compliance + function getTokenBound() public view virtual override returns (address) { + if (_boundTokens.length() > 0) { + // Note that there are no guarantees on the ordering of values inside the array, + // and it may change when more values are added or removed. + return _boundTokens.at(0); + } else { + return address(0); + } + } + + /// @inheritdoc IERC3643Compliance + function getTokenBounds() public view override returns (address[] memory) { + return _boundTokens.values(); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL/PRIVATE FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + function _unbindToken(address token) internal { + require( + _boundTokens.contains(token), + RuleEngine_ERC3643Compliance_TokenNotBound() + ); + // Should never revert because we check if the token address is already set before + require( + _boundTokens.remove(token), + RuleEngine_ERC3643Compliance_OperationNotSuccessful() + ); + + emit TokenUnbound(token); + } + + function _bindToken(address token) internal { + require( + token != address(0), + RuleEngine_ERC3643Compliance_InvalidTokenAddress() + ); + require( + !_boundTokens.contains(token), + RuleEngine_ERC3643Compliance_TokenAlreadyBound() + ); + // Should never revert because we check if the token address is already set before + require( + _boundTokens.add(token), + RuleEngine_ERC3643Compliance_OperationNotSuccessful() + ); + emit TokenBound(token); + } +} diff --git a/src/modules/RuleEngineInvariantStorage.sol b/src/modules/RuleEngineInvariantStorage.sol deleted file mode 100644 index e1e28e2..0000000 --- a/src/modules/RuleEngineInvariantStorage.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -abstract contract RuleEngineInvariantStorage { - error RuleEngine_RuleAddressZeroNotAllowed(); - error RuleEngine_RuleAlreadyExists(); - error RuleEngine_RuleDoNotMatch(); - error RuleEngine_AdminWithAddressZeroNotAllowed(); - error RuleEngine_ArrayIsEmpty(); - error RuleEngine_InvalidTransfer(address from, address to, uint256 value); - - /// @notice Generate when a rule is added - event AddRule(address indexed rule); - /// @notice Generate when a rule is removed - event RemoveRule(address indexed rule); - /// @notice Generate when all the rules are cleared - event ClearRules(address[] rulesRemoved); - - /// @notice Role to manage the ruleEngine - bytes32 public constant RULE_ENGINE_OPERATOR_ROLE = - keccak256("RULE_ENGINE_OPERATOR_ROLE"); - - /// @notice token contract - bytes32 public constant TOKEN_CONTRACT_ROLE = - keccak256("TOKEN_CONTRACT_ROLE"); -} diff --git a/src/modules/RuleEngineOperation.sol b/src/modules/RuleEngineOperation.sol deleted file mode 100644 index 7ff4937..0000000 --- a/src/modules/RuleEngineOperation.sol +++ /dev/null @@ -1,170 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -import "./RuleInternal.sol"; -import "../interfaces/IRuleEngineOperation.sol"; -import "../interfaces/IRuleOperation.sol"; -import "OZ/access/AccessControl.sol"; - -/** - * @title Implementation of a ruleEngine defined by the CMTAT - */ -abstract contract RuleEngineOperation is - AccessControl, - RuleInternal, - IRuleEngineOperation -{ - /// @dev Array of rules - address[] internal _rulesOperation; - - /** - * @notice Set all the rules, will overwrite all the previous rules. \n - * Revert if one rule is a zero address or if the rule is already present - * - */ - function setRulesOperation( - address[] calldata rules_ - ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { - if (_rulesOperation.length > 0) { - _clearRulesOperation(); - } - _setRules(rules_); - _rulesOperation = rules_; - } - - /** - * @notice Clear all the rules of the array of rules - * - */ - function clearRulesOperation() public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { - _clearRulesOperation(); - } - - /** - * @notice Clear all the rules of the array of rules - * - */ - function _clearRulesOperation() internal { - uint256 index; - // we remove the last element first since it is more optimized. - for (uint256 i = _rulesOperation.length; i > 0; --i) { - unchecked { - // don't underflow since i > 0 - index = i - 1; - } - _removeRuleOperation(_rulesOperation[index], index); - } - emit ClearRules(_rulesOperation); - } - - /** - * @notice Add a rule to the array of rules - * Revert if one rule is a zero address or if the rule is already present - * - */ - function addRuleOperation( - IRuleOperation rule_ - ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { - RuleInternal._addRule(_rulesOperation, address(rule_)); - emit AddRule(address(rule_)); - } - - /** - * @notice Remove a rule from the array of rules - * Revert if the rule found at the specified index does not match the rule in argument - * @param rule_ address of the target rule - * @param index the position inside the array of rule - * @dev To reduce the array size, the last rule is moved to the location occupied - * by the rule to remove - * - * - */ - function removeRuleOperation( - IRuleOperation rule_, - uint256 index - ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { - _removeRuleOperation(address(rule_), index); - } - - /** - * @notice Remove a rule from the array of rules - * Revert if the rule found at the specified index does not match the rule in argument - * @param rule_ address of the target rule - * @param index the position inside the array of rule - * @dev To reduce the array size, the last rule is moved to the location occupied - * by the rule to remove - * - * - */ - function _removeRuleOperation(address rule_, uint256 index) internal { - RuleInternal._removeRule(_rulesOperation, rule_, index); - emit RemoveRule(address(rule_)); - } - - /** - * @return The number of rules inside the array - */ - function rulesCountOperation() external view override returns (uint256) { - return _rulesOperation.length; - } - - /** - * @notice Get the index of a rule inside the list - * @return index if the rule is found, _rulesOperation.length otherwise - */ - function getRuleIndexOperation( - IRuleOperation rule_ - ) external view returns (uint256 index) { - return RuleInternal._getRuleIndex(_rulesOperation, address(rule_)); - } - - /** - * @notice Get the rule at the position specified by ruleId - * @param ruleId index of the rule - * @return a rule address - */ - function ruleOperation( - uint256 ruleId - ) external view override returns (address) { - return _rulesOperation[ruleId]; - } - - /** - * @notice Get all the rules - * @return An array of rules - */ - function rulesOperation() - external - view - override - returns (address[] memory) - { - return _rulesOperation; - } - - /** - * @notice Go through all the rule to know if a restriction exists on the transfer - * @param _from the origin address - * @param _to the destination address - * @param _amount to transfer - **/ - function _operateOnTransfer( - address _from, - address _to, - uint256 _amount - ) internal returns (bool isValid) { - uint256 rulesLength = _rulesOperation.length; - for (uint256 i = 0; i < rulesLength; ++i) { - bool result = IRuleOperation(_rulesOperation[i]).operateOnTransfer( - _from, - _to, - _amount - ); - if (!result) { - return false; - } - } - return true; - } -} diff --git a/src/modules/RuleEngineValidation.sol b/src/modules/RuleEngineValidation.sol deleted file mode 100644 index 05cc697..0000000 --- a/src/modules/RuleEngineValidation.sol +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -import "OZ/access/AccessControl.sol"; -import "./RuleInternal.sol"; -import "./RuleEngineValidationCommon.sol"; -import "../interfaces/IRuleEngineValidation.sol"; -import "../interfaces/IRuleValidation.sol"; -import "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; - -/** - * @title Implementation of a ruleEngine defined by the CMTAT - */ -abstract contract RuleEngineValidation is - AccessControl, - RuleInternal, - RuleEngineValidationCommon, - IRuleEngineValidation -{ - /** - * @notice Go through all the rule to know if a restriction exists on the transfer - * @param _from the origin address - * @param _to the destination address - * @param _amount to transfer - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - **/ - function detectTransferRestrictionValidation( - address _from, - address _to, - uint256 _amount - ) public view override returns (uint8) { - uint256 rulesLength = _rulesValidation.length; - for (uint256 i = 0; i < rulesLength; ++i) { - uint8 restriction = IRuleValidation(_rulesValidation[i]) - .detectTransferRestriction(_from, _to, _amount); - if (restriction > 0) { - return restriction; - } - } - - return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); - } - - function detectTransferRestrictionValidationFrom( - address spender, - address _from, - address _to, - uint256 _amount - ) public view override returns (uint8) { - uint256 rulesLength = _rulesValidation.length; - for (uint256 i = 0; i < rulesLength; ++i) { - uint8 restriction = IRuleValidation(_rulesValidation[i]) - .detectTransferRestrictionFrom(spender, _from, _to, _amount); - if (restriction > 0) { - return restriction; - } - } - return 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 - * @return True if the transfer is valid, false otherwise - **/ - function canTransferValidation( - address _from, - address _to, - uint256 _amount - ) public view returns (bool) { - return - detectTransferRestrictionValidation(_from, _to, _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 - * @return True if the transfer is valid, false otherwise - **/ - function canTransferValidationFrom( - address spender, - address _from, - address _to, - uint256 _amount - ) public view override returns (bool) { - return - detectTransferRestrictionValidationFrom(spender, _from, _to, _amount) == - uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); - } -} diff --git a/src/modules/RuleEngineValidationCommon.sol b/src/modules/RuleEngineValidationCommon.sol deleted file mode 100644 index c1cccc2..0000000 --- a/src/modules/RuleEngineValidationCommon.sol +++ /dev/null @@ -1,152 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -import "OZ/access/AccessControl.sol"; -import "./RuleInternal.sol"; -import "../interfaces/IRuleEngineValidation.sol"; -import "../interfaces/IRuleValidation.sol"; - -/** - * @title Implementation of a ruleEngine defined by the CMTAT - */ -abstract contract RuleEngineValidationCommon is - AccessControl, - RuleInternal, - IRuleEngineValidationCommon -{ - /// @dev Array of rules - address[] internal _rulesValidation; - - /*////////////////////////////////////////////////////////////// - PUBLIC/EXTERNAL FUNCTIONS - //////////////////////////////////////////////////////////////*/ - /** - * @notice Set all the rules, will overwrite all the previous rules. \n - * Revert if one rule is a zero address or if the rule is already present - * @dev take address[] instead of IRuleEngineValidation[] since it is not possible to cast IRuleEngineValidation[] -> address[] - * - */ - function setRulesValidation( - address[] calldata rules_ - ) public override onlyRole(RULE_ENGINE_OPERATOR_ROLE) { - if (_rulesValidation.length > 0) { - _clearRulesValidation(); - } - _setRules(rules_); - _rulesValidation = rules_; - } - - /** - * @notice Clear all the rules of the array of rules - * - */ - function clearRulesValidation() public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { - _clearRulesValidation(); - } - - /** - * @notice Add a rule to the array of rules - * Revert if one rule is a zero address or if the rule is already present - * - */ - function addRuleValidation( - IRuleValidation rule_ - ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { - RuleInternal._addRule(_rulesValidation, address(rule_)); - emit AddRule(address(rule_)); - } - - /** - * @notice Remove a rule from the array of rules - * Revert if the rule found at the specified index does not match the rule in argument - * @param rule_ address of the target rule - * @param index the position inside the array of rule - * @dev To reduce the array size, the last rule is moved to the location occupied - * by the rule to remove - * - * - */ - function removeRuleValidation( - IRuleValidation rule_, - uint256 index - ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { - _removeRuleValidation(address(rule_), index); - } - - /** - * @return The number of rules inside the array - */ - function rulesCountValidation() external view override returns (uint256) { - return _rulesValidation.length; - } - - /** - * @notice Get the index of a rule inside the list - * @return index if the rule is found, _rulesValidation.length otherwise - */ - function getRuleIndexValidation( - IRuleValidation rule_ - ) external view returns (uint256 index) { - return RuleInternal._getRuleIndex(_rulesValidation, address(rule_)); - } - - /** - * @notice Get the rule at the position specified by ruleId - * @param ruleId index of the rule - * @return a rule address - */ - function ruleValidation( - uint256 ruleId - ) external view override returns (address) { - return _rulesValidation[ruleId]; - } - - /** - * @notice Get all the rules - * @return An array of rules - */ - function rulesValidation() - external - view - override - returns (address[] memory) - { - return _rulesValidation; - } - - /*////////////////////////////////////////////////////////////// - INTERNAL FUNCTIONS - //////////////////////////////////////////////////////////////*/ - /** - * @notice Clear all the rules of the array of rules - * - */ - function _clearRulesValidation() internal { - uint256 index; - // we remove the last element first since it is more optimized. - for (uint256 i = _rulesValidation.length; i > 0; --i) { - unchecked { - // don't underflow since i > 0 - index = i - 1; - } - _removeRuleValidation(_rulesValidation[index], index); - } - emit ClearRules(_rulesValidation); - } - - /** - * @notice Remove a rule from the array of rules - * Revert if the rule found at the specified index does not match the rule in argument - * @param rule_ address of the target rule - * @param index the position inside the array of rule - * @dev To reduce the array size, the last rule is moved to the location occupied - * by the rule to remove - * - * - */ - function _removeRuleValidation(address rule_, uint256 index) internal { - RuleInternal._removeRule(_rulesValidation, rule_, index); - emit RemoveRule(address(rule_)); - } -} diff --git a/src/modules/RuleInternal.sol b/src/modules/RuleInternal.sol deleted file mode 100644 index 15bc236..0000000 --- a/src/modules/RuleInternal.sol +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; -import "./RuleEngineInvariantStorage.sol"; - -/** - * @title Implementation of a ruleEngine defined by the CMTAT - */ -abstract contract RuleInternal is RuleEngineInvariantStorage { - /// @dev Indicate if a rule already exists - // Can be shared betwen RuleOperation and RuleValidation since it is a mapping - mapping(address => bool) _ruleIsPresent; - - /** - * @notice Set all the rules, will overwrite all the previous rules. \n - * Revert if one rule is a zero address or if the rule is already present - * - */ - function _setRules(address[] calldata rules_) internal { - if (rules_.length == 0) { - revert RuleEngine_ArrayIsEmpty(); - } - for (uint256 i = 0; i < rules_.length; ) { - if (address(rules_[i]) == address(0x0)) { - revert RuleEngine_RuleAddressZeroNotAllowed(); - } - if (_ruleIsPresent[rules_[i]]) { - revert RuleEngine_RuleAlreadyExists(); - } - _ruleIsPresent[rules_[i]] = true; - emit AddRule(rules_[i]); - unchecked { - ++i; - } - } - } - - /** - * @notice Add a rule to the array of rules - * Revert if one rule is a zero address or if the rule is already present - * - */ - function _addRule(address[] storage _rules, address rule_) internal { - if (address(rule_) == address(0x0)) { - revert RuleEngine_RuleAddressZeroNotAllowed(); - } - if (_ruleIsPresent[rule_]) { - revert RuleEngine_RuleAlreadyExists(); - } - _rules.push(rule_); - _ruleIsPresent[rule_] = true; - } - - /** - * @notice Remove a rule from the array of rules - * Revert if the rule found at the specified index does not match the rule in argument - * @param rule_ address of the target rule - * @param index the position inside the array of rule - * @dev To reduce the array size, the last rule is moved to the location occupied - * by the rule to remove - * - * - */ - function _removeRule( - address[] storage _rules, - address rule_, - uint256 index - ) internal { - if (_rules[index] != rule_) { - revert RuleEngine_RuleDoNotMatch(); - } - if (index != _rules.length - 1) { - _rules[index] = _rules[_rules.length - 1]; - } - _rules.pop(); - _ruleIsPresent[rule_] = false; - emit RemoveRule(rule_); - } - - /** - * @notice Get the index of a rule inside the list - * @return index if the rule is found, _rules.length otherwise - */ - function _getRuleIndex( - address[] storage _rules, - address rule_ - ) internal view returns (uint256 index) { - uint256 rulesLength = _rules.length; - for (index = 0; index < rulesLength; ) { - if (_rules[index] == rule_) { - return index; - } - unchecked { - ++index; - } - } - return _rules.length; - } -} diff --git a/src/modules/RulesManagementModule.sol b/src/modules/RulesManagementModule.sol new file mode 100644 index 0000000..9e5a848 --- /dev/null +++ b/src/modules/RulesManagementModule.sol @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +/* ==== OpenZeppelin === */ +import {EnumerableSet} from "OZ/utils/structs/EnumerableSet.sol"; +import {AccessControl} from "OZ/access/AccessControl.sol"; +/* ==== Interface and other library === */ +import {IRulesManagementModule} from "../interfaces/IRulesManagementModule.sol"; +import {IRule} from "../interfaces/IRule.sol"; +import {RulesManagementModuleInvariantStorage} from "./library/RulesManagementModuleInvariantStorage.sol"; + +/** + * @title RuleEngine - part + */ +abstract contract RulesManagementModule is + AccessControl, + RulesManagementModuleInvariantStorage, + IRulesManagementModule +{ + /* ==== Type declaration === */ + using EnumerableSet for EnumerableSet.AddressSet; + + /* ==== State Variables === */ + /// @dev Array of rules + EnumerableSet.AddressSet internal _rules; + + /*////////////////////////////////////////////////////////////// + PUBLIC/EXTERNAL FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + /* ============ State functions ============ */ + + /** + * @inheritdoc IRulesManagementModule + */ + function setRules( + IRule[] calldata rules_ + ) + public + virtual + override(IRulesManagementModule) + onlyRole(RULES_MANAGEMENT_ROLE) + { + if (rules_.length == 0) { + revert RuleEngine_RulesManagementModule_ArrayIsEmpty(); + } + if (_rules.length() > 0) { + _clearRules(); + } + for (uint256 i = 0; i < rules_.length; ++i) { + _checkRule(address(rules_[i])); + // Should never revert because we check the presence of the rule before + require( + _rules.add(address(rules_[i])), + RuleEngine_RulesManagementModule_OperationNotSuccessful() + ); + emit AddRule(rules_[i]); + } + } + + /** + * @inheritdoc IRulesManagementModule + */ + function clearRules() + public + virtual + override(IRulesManagementModule) + onlyRole(RULES_MANAGEMENT_ROLE) + { + _clearRules(); + } + + /** + * @inheritdoc IRulesManagementModule + */ + function addRule( + IRule rule_ + ) + public + virtual + override(IRulesManagementModule) + onlyRole(RULES_MANAGEMENT_ROLE) + { + _checkRule(address(rule_)); + require( + _rules.add(address(rule_)), + RuleEngine_RulesManagementModule_OperationNotSuccessful() + ); + emit AddRule(rule_); + } + + /** + * @inheritdoc IRulesManagementModule + */ + function removeRule( + IRule rule_ + ) + public + virtual + override(IRulesManagementModule) + onlyRole(RULES_MANAGEMENT_ROLE) + { + require( + _rules.contains(address(rule_)), + RuleEngine_RulesManagementModule_RuleDoNotMatch() + ); + _removeRule(rule_); + } + + /* ============ View functions ============ */ + + /** + * @inheritdoc IRulesManagementModule + */ + function rulesCount() + public + view + virtual + override(IRulesManagementModule) + returns (uint256) + { + return _rules.length(); + } + + /** + * @inheritdoc IRulesManagementModule + */ + function containsRule( + IRule rule_ + ) public view virtual override(IRulesManagementModule) returns (bool) { + return _rules.contains(address(rule_)); + } + + /** + * @inheritdoc IRulesManagementModule + */ + function rule( + uint256 ruleId + ) public view virtual override(IRulesManagementModule) returns (address) { + if (ruleId < _rules.length()) { + // Note that there are no guarantees on the ordering of values inside the array, + // and it may change when more values are added or removed. + return _rules.at(ruleId); + } else { + return address(0); + } + } + + /** + * @inheritdoc IRulesManagementModule + */ + function rules() + public + view + virtual + override(IRulesManagementModule) + returns (address[] memory) + { + return _rules.values(); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL/PRIVATE FUNCTIONS + //////////////////////////////////////////////////////////////*/ + /** + * @notice Clear all the rules of the array of rules + * + */ + function _clearRules() internal virtual { + emit ClearRules(); + _rules.clear(); + } + + /** + * @notice Remove a rule from the array of rules + * Revert if the rule found at the specified index does not match the rule in argument + * @param rule_ address of the target rule + * + * + */ + function _removeRule(IRule rule_) internal virtual { + // Should never revert because we check the presence of the rule before + require( + _rules.remove(address(rule_)), + RuleEngine_RulesManagementModule_OperationNotSuccessful() + ); + emit RemoveRule(rule_); + } + + /** + * @dev check if a rule is valid, revert otherwise + */ + function _checkRule(address rule_) internal view { + if (rule_ == address(0x0)) { + revert RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed(); + } + if (_rules.contains(rule_)) { + revert RuleEngine_RulesManagementModule_RuleAlreadyExists(); + } + } + + /* ============ Transferred functions ============ */ + + /** + * @notice Go through all the rule to know if a restriction exists on the transfer + * @param from the origin address + * @param to the destination address + * @param value to transfer + **/ + function _transferred( + address from, + address to, + uint256 value + ) internal virtual { + uint256 rulesLength = _rules.length(); + for (uint256 i = 0; i < rulesLength; ++i) { + IRule(_rules.at(i)).transferred(from, to, value); + } + } + + /** + * @notice Go through all the rule to know if a restriction exists on the transfer + * @param spender the spender address (transferFrom) + * @param from the origin address + * @param to the destination address + * @param value to transfer + **/ + function _transferred( + address spender, + address from, + address to, + uint256 value + ) internal virtual { + uint256 rulesLength = _rules.length(); + for (uint256 i = 0; i < rulesLength; ++i) { + IRule(_rules.at(i)).transferred(spender, from, to, value); + } + } +} diff --git a/src/modules/VersionModule.sol b/src/modules/VersionModule.sol new file mode 100644 index 0000000..33cf30c --- /dev/null +++ b/src/modules/VersionModule.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +/* ==== CMTAT === */ +import {IERC3643Base} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; + +abstract contract VersionModule is IERC3643Base { + /* ============ State Variables ============ */ + /** + * @dev + * Get the current version of the smart contract + */ + string private constant VERSION = "3.0.0"; + + /* ============ Events ============ */ + /*////////////////////////////////////////////////////////////// + PUBLIC/EXTERNAL FUNCTIONS + //////////////////////////////////////////////////////////////*/ + /** + * @inheritdoc IERC3643Base + */ + function version() + public + view + virtual + override(IERC3643Base) + returns (string memory version_) + { + return VERSION; + } +} diff --git a/src/modules/library/RuleEngineInvariantStorage.sol b/src/modules/library/RuleEngineInvariantStorage.sol new file mode 100644 index 0000000..9cd4ed5 --- /dev/null +++ b/src/modules/library/RuleEngineInvariantStorage.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +abstract contract RuleEngineInvariantStorage { + /* ==== Errors === */ + error RuleEngine_AdminWithAddressZeroNotAllowed(); +} diff --git a/src/modules/library/RulesManagementModuleInvariantStorage.sol b/src/modules/library/RulesManagementModuleInvariantStorage.sol new file mode 100644 index 0000000..bb8dea0 --- /dev/null +++ b/src/modules/library/RulesManagementModuleInvariantStorage.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +import {IRule} from "../../interfaces/IRule.sol"; + +abstract contract RulesManagementModuleInvariantStorage { + /* ==== Errors === */ + error RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed(); + error RuleEngine_RulesManagementModule_RuleAlreadyExists(); + error RuleEngine_RulesManagementModule_RuleDoNotMatch(); + error RuleEngine_RulesManagementModule_ArrayIsEmpty(); + error RuleEngine_RulesManagementModule_OperationNotSuccessful(); + + /* ============ Events ============ */ + /** + * @notice Emitted when a new rule is added to the rule set. + * @param rule The address of the rule contract that was added. + */ + event AddRule(IRule indexed rule); + + /** + * @notice Emitted when a rule is removed from the rule set. + * @param rule The address of the rule contract that was removed. + */ + event RemoveRule(IRule indexed rule); + + /** + * @notice Emitted when all rules are cleared from the rule set. + */ + event ClearRules(); + + /* ==== Constant === */ + /// @notice Role to manage the ruleEngine + bytes32 public constant RULES_MANAGEMENT_ROLE = + keccak256("RULES_MANAGEMENT_ROLE"); +} diff --git a/src/rules/operation/RuleConditionalTransfer.sol b/src/rules/operation/RuleConditionalTransfer.sol deleted file mode 100644 index 34458f6..0000000 --- a/src/rules/operation/RuleConditionalTransfer.sol +++ /dev/null @@ -1,416 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -import "OZ/access/AccessControl.sol"; -import "../../interfaces/IRuleOperation.sol"; -import "./../../modules/MetaTxModuleStandalone.sol"; -import "./abstract/RuleConditionalTransferInvariantStorage.sol"; -import "./abstract/RuleConditionalTransferOperator.sol"; -import "../validation/abstract/RuleValidateTransfer.sol"; -import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; - -/** - * @title RuleConditionalTransfer - */ - -contract RuleConditionalTransfer is - RuleValidateTransfer, - IRuleOperation, - RuleConditionalTransferOperator, - MetaTxModuleStandalone -{ - /** - * @param admin Address of the contract (Access Control) - * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - */ - constructor( - address admin, - address forwarderIrrevocable, - IRuleEngine ruleEngineContract, - OPTION memory options_ - ) MetaTxModuleStandalone(forwarderIrrevocable) { - if (admin == address(0)) { - revert RuleConditionalTransfer_AdminWithAddressZeroNotAllowed(); - } - _grantRole(DEFAULT_ADMIN_ROLE, admin); - if (address(ruleEngineContract) != address(0x0)) { - _grantRole(RULE_ENGINE_CONTRACT_ROLE, address(ruleEngineContract)); - } - options = options_; - } - - /*////////////////////////////////////////////////////////////// - PUBLIC/EXTERNAL FUNCTIONS - //////////////////////////////////////////////////////////////*/ - /** - * @notice function called by the RuleEngine - * @dev Returns true if the transfer is valid, and false otherwise. - * Add access control with the RuleEngine - */ - function operateOnTransfer( - address _from, - address _to, - uint256 _amount - ) - public - override - onlyRole(RULE_ENGINE_CONTRACT_ROLE) - returns (bool isValid) - { - if (_validateTransfer(_from, _to)) { - return true; - } else { - bytes32 key = keccak256(abi.encode(_from, _to, _amount)); - if (_validateApproval(key)) { - _updateProcessedTransfer(key); - return true; - } else { - return false; - } - } - } - - /** - * @notice Create a request of transfer for yourselves - * @param to recipient of tokens - * @param value amount of tokens to transfer - */ - function createTransferRequest(address to, uint256 value) public { - // WAIT => Will set a new delay to approve - // APPROVED => will overwrite previous status - // DENIED => reject - address from = _msgSender(); - bytes32 key = keccak256(abi.encode(from, to, value)); - if (transferRequests[key].status == STATUS.DENIED) { - revert RuleConditionalTransfer_TransferDenied(); - } - if (_checkRequestStatus(key)) { - uint256 requestIdLocal = requestId; - TransferRequest memory newTransferApproval = TransferRequest({ - key: key, - id: requestIdLocal, - keyElement: TransferRequestKeyElement({ - from: from, - to: to, - value: value - }), - askTime: block.timestamp, - maxTime: 0, - status: STATUS.WAIT - }); - transferRequests[key] = newTransferApproval; - IdToKey[requestIdLocal] = key; - emit transferWaiting(key, from, to, value, requestId); - ++requestId; - } else { - // Overwrite previous approval - transferRequests[key].askTime = block.timestamp; - transferRequests[key].status = STATUS.WAIT; - emit transferWaiting( - key, - from, - to, - value, - transferRequests[key].id - ); - } - } - - /** - * @notice Batch version of {createTransferRequest} - */ - function createTransferRequestBatch( - address[] memory tos, - uint256[] memory values - ) public { - if (tos.length == 0) { - revert RuleConditionalTransfer_EmptyArray(); - } - if (tos.length != values.length) { - revert RuleConditionalTransfer_InvalidLengthArray(); - } - for (uint256 i = 0; i < tos.length; ++i) { - createTransferRequest(tos[i], values[i]); - } - } - - /** - * @notice allow a token holder to cancel/reset his own request - */ - function cancelTransferRequest(uint256 requestId_) public { - _cancelTransferRequest(requestId_); - } - - /** - * @notice allow a token holder to cancel/reset his own request - */ - function cancelTransferRequestBatch(uint256[] memory requestIds) public { - if (requestIds.length == 0) { - revert RuleConditionalTransfer_EmptyArray(); - } - // Check id validity before performing actions - for (uint256 i = 0; i < requestIds.length; ++i) { - if (requestIds[i] + 1 > requestId) { - revert RuleConditionalTransfer_InvalidId(); - } - } - for (uint256 i = 0; i < requestIds.length; ++i) { - _cancelTransferRequest(requestIds[i]); - } - } - - function getRequestTrade( - address from, - address to, - uint256 value - ) public view returns (TransferRequest memory) { - bytes32 key = keccak256(abi.encode(from, to, value)); - return transferRequests[key]; - } - - /** - * @notice get Trade by status - * @param _targetStatus The status of the transactions you want to retrieve - * @return array with corresponding transactions - */ - function getRequestByStatus( - STATUS _targetStatus - ) public view returns (TransferRequest[] memory) { - uint totalRequestCount = requestId; - uint requestCount = 0; - uint currentIndex = 0; - - // We count the number of requests matching the criteria - for (uint i = 0; i < totalRequestCount; ++i) { - if (transferRequests[IdToKey[i]].status == _targetStatus) { - requestCount += 1; - } - } - - // We reserve the memory to store the trade - TransferRequest[] memory requests = new TransferRequest[](requestCount); - - // We create an array with the list of trade - for (uint i = 0; i < totalRequestCount; ++i) { - if (transferRequests[IdToKey[i]].status == _targetStatus) { - //uint currentId = i + 1; - TransferRequest memory currentRequest = transferRequests[ - IdToKey[i] - ]; - requests[currentIndex] = currentRequest; - currentIndex += 1; - } - } - return requests; - } - - /** - * @notice Check if the transfer is valid - * @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 _amount - ) public view override returns (uint8) { - // No need of approval if from and to are in the whitelist - if (_validateTransfer(_from, _to)) { - return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - } - bytes32 key = keccak256(abi.encode(_from, _to, _amount)); - if (_validateApproval(key)) { - return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - } else { - return CODE_TRANSFER_REQUEST_NOT_APPROVED; - } - } - - /** - * @notice Check if the transfer is valid - * @param _from the origin address - * @param _to the destination address - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - **/ - function detectTransferRestrictionFrom( - address /* spender*/, - address _from, - address _to, - uint256 _amount - ) public view override returns (uint8) { - return detectTransferRestriction(_from,_to, _amount ); - } - - /** - * @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_TRANSFER_REQUEST_NOT_APPROVED; - } - - /** - * @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_TRANSFER_REQUEST_NOT_APPROVED) { - return TEXT_TRANSFER_REQUEST_NOT_APPROVED; - } else { - return TEXT_CODE_NOT_FOUND; - } - } - - /*////////////////////////////////////////////////////////////// - INTERNAL FUNCTIONS - //////////////////////////////////////////////////////////////*/ - function _validateTransfer( - address _from, - address _to - ) internal view returns (bool) { - // No need of approval if from and to are in the whitelist - if (address(whitelistConditionalTransfer) != address(0)) { - if ( - whitelistConditionalTransfer.addressIsListed(_from) && - whitelistConditionalTransfer.addressIsListed(_to) - ) { - return true; - } - } - - // Mint & Burn - if (_validateBurnMint(_from, _to)) { - return true; - } - return false; - } - - function _cancelTransferRequest(uint256 requestId_) internal { - if (requestId_ + 1 > requestId) { - revert RuleConditionalTransfer_InvalidId(); - } - bytes32 key = IdToKey[requestId_]; - // Check Sender - if (transferRequests[key].keyElement.from != _msgSender()) { - revert RuleConditionalTransfer_InvalidSender(); - } - // Check status - if ( - transferRequests[key].status != STATUS.WAIT && - transferRequests[key].status != STATUS.APPROVED - ) { - revert RuleConditionalTransfer_Wrong_Status(); - } - _resetRequestStatus(key); - } - - /** - * - * @dev - * Test burn and mint condition - * Returns true if the transfer is valid, and false otherwise. - * - */ - function _validateBurnMint( - address _from, - address _to - ) internal view returns (bool isValid) { - // Mint & Burn - if ( - (_from == address(0) && - options.issuance.authorizedMintWithoutApproval) || - (_to == address(0) && - options.issuance.authorizedBurnWithoutApproval) - ) { - return true; - } - return false; - } - - /** - * - * @dev - * Test transfer approval condition - * Returns true if the transfer is valid, and false otherwise. - */ - function _validateApproval( - bytes32 key - ) internal view returns (bool isValid) { - // If automatic approval is activate and time to approve the request has passed - if(transferRequests[key].status == STATUS.NONE - || - transferRequests[key].status == STATUS.DENIED - || - transferRequests[key].status == STATUS.EXECUTED) - { - return false; - } - bool isTransferApproved; - bool automaticApprovalCondition; - if(transferRequests[key].status == - STATUS.APPROVED){ - isTransferApproved = (transferRequests[key].maxTime >= block.timestamp); - } else if(options - .automaticApproval - .isActivate){ - // Warning: overflow possible if timeLimitBeforeAutomaticApproval == max(uint256) - automaticApprovalCondition= block.timestamp >= - (transferRequests[key].askTime + - options.automaticApproval.timeLimitBeforeAutomaticApproval); - } - // If the transfer is approved and delay to perform the transfer is respected - if (automaticApprovalCondition || isTransferApproved) { - return true; - } else { - return false; - } - } - - /*////////////////////////////////////////////////////////////// - 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/operation/abstract/RuleConditionalTransferInvariantStorage.sol b/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol deleted file mode 100644 index cfd5536..0000000 --- a/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol +++ /dev/null @@ -1,142 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; -import "OZ/token/ERC20/IERC20.sol"; - -import "../../validation/abstract/RuleCommonInvariantStorage.sol"; -import "src/rules/validation/RuleWhitelist.sol"; - -abstract contract RuleConditionalTransferInvariantStorage is - RuleCommonInvariantStorage -{ - /* ============ Struct ============ */ - /** - * perform automatically a transfer if the transfer request is approved. - * To perform the transfer, the token holder has to approve the rule to spend tokens on his behalf (standard ERC-20 approval). - * If the allowance is not sufficient, the request will be approved, but without performing the transfer. - */ - struct AUTOMATIC_TRANSFER { - bool isActivate; - IERC20 cmtat; - } - - struct ISSUANCE { - // Authorize mint without the need of approval - bool authorizedMintWithoutApproval; - // Authorize burn without the need of approval - bool authorizedBurnWithoutApproval; - } - - struct TIME_LIMIT { - // time limit for an operator to approve a request - uint256 timeLimitToApprove; - // once a request is approved, time limit for the token holder to perform the transfer - uint256 timeLimitToTransfer; - } - - struct AUTOMATIC_APPROVAL { - bool isActivate; - /** - * If the transfer is not approved or denied within {timeLimitBeforeAutomaticApproval}, - * the request is considered as approved during a transfer. - */ - uint256 timeLimitBeforeAutomaticApproval; - } - - struct OPTION { - ISSUANCE issuance; - TIME_LIMIT timeLimit; - AUTOMATIC_APPROVAL automaticApproval; - AUTOMATIC_TRANSFER automaticTransfer; - } - - struct TransferRequestKeyElement { - address from; - address to; - uint256 value; - } - - struct TransferRequest { - bytes32 key; - uint256 id; - TransferRequestKeyElement keyElement; - uint256 askTime; - uint256 maxTime; - STATUS status; - } - /* ============ Enum ============ */ - enum STATUS { - NONE, - WAIT, - APPROVED, - DENIED, - EXECUTED - } - - /* ============ Role ============ */ - bytes32 public constant RULE_ENGINE_CONTRACT_ROLE = - keccak256("RULE_ENGINE_CONTRACT_ROLE"); - bytes32 public constant RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE = - keccak256("RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE"); - - /* ============ State variables ============ */ - string constant TEXT_TRANSFER_REQUEST_NOT_APPROVED = - "The request is not approved"; - // Code - // It is very important that each rule uses an unique code - uint8 public constant CODE_TRANSFER_REQUEST_NOT_APPROVED = 51; - - /* ============ Custom error ============ */ - error RuleConditionalTransfer_AdminWithAddressZeroNotAllowed(); - error RuleConditionalTransfer_TransferAlreadyApproved(); - error RuleConditionalTransfer_Wrong_Status(); - error RuleConditionalTransfer_timeExceeded(); - error RuleConditionalTransfer_TransferDenied(); - error RuleConditionalTransfer_InvalidId(); - error RuleConditionalTransfer_InvalidSender(); - error RuleConditionalTransfer_InvalidValueApproved(); - error RuleConditionalTransfer_CannotDeniedPartially(); - error RuleConditionalTransfer_InvalidLengthArray(); - error RuleConditionalTransfer_EmptyArray(); - - /* ============ Events ============ */ - event transferProcessed( - bytes32 indexed key, - address indexed from, - address indexed to, - uint256 value, - uint256 id - ); - event transferWaiting( - bytes32 indexed key, - address indexed from, - address indexed to, - uint256 value, - uint256 id - ); - event transferApproved( - bytes32 indexed key, - address indexed from, - address indexed to, - uint256 value, - uint256 id - ); - event transferDenied( - bytes32 indexed key, - address indexed from, - address indexed to, - uint256 value, - uint256 id - ); - event transferReset( - bytes32 indexed key, - address indexed from, - address indexed to, - uint256 value, - uint256 id - ); - - event WhitelistConditionalTransfer( - RuleWhitelist indexed whitelistConditionalTransfer - ); -} diff --git a/src/rules/operation/abstract/RuleConditionalTransferOperator.sol b/src/rules/operation/abstract/RuleConditionalTransferOperator.sol deleted file mode 100644 index b96b55a..0000000 --- a/src/rules/operation/abstract/RuleConditionalTransferOperator.sol +++ /dev/null @@ -1,473 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -import "OZ/access/AccessControl.sol"; -import "./RuleConditionalTransferInvariantStorage.sol"; -import "OZ/token/ERC20/utils/SafeERC20.sol"; - -/** - * @title Restricted functions - */ -abstract contract RuleConditionalTransferOperator is - AccessControl, - RuleConditionalTransferInvariantStorage -{ - // Security - using SafeERC20 for IERC20; - /* ============ State Variables ============ */ - OPTION public options; - uint256 public requestId; - mapping(uint256 => bytes32) public IdToKey; - mapping(bytes32 => TransferRequest) public transferRequests; - RuleWhitelist public whitelistConditionalTransfer; - - /*////////////////////////////////////////////////////////////// - PUBLIC/EXTERNAL FUNCTIONS - //////////////////////////////////////////////////////////////*/ - - /** - * @notice set a whitelist. A transfer does not need of an approved request if from and to are in the whitelist - */ - function setConditionalWhitelist( - RuleWhitelist newWhitelistConditionalTransfer - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - whitelistConditionalTransfer = newWhitelistConditionalTransfer; - emit WhitelistConditionalTransfer(newWhitelistConditionalTransfer); - } - - /** - * @notice set/unset the issuance options (mint & burn) - */ - function setIssuanceOptions( - ISSUANCE calldata issuance_ - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - if ( - options.issuance.authorizedMintWithoutApproval != - issuance_.authorizedMintWithoutApproval - ) { - options.issuance.authorizedMintWithoutApproval = issuance_ - .authorizedMintWithoutApproval; - } - if ( - options.issuance.authorizedBurnWithoutApproval != - issuance_.authorizedBurnWithoutApproval - ) { - options.issuance.authorizedBurnWithoutApproval = issuance_ - .authorizedBurnWithoutApproval; - } - } - - /** - * @notice set/unset the option to perform the transfer if the request is approved by the rule operator. - * To perform the transfer, the token holder has to approve the rule to spend tokens on his behalf (standard ERC-20 approval). - * If the allowance is not sufficient, the request will be approved, but without performing the transfer. - */ - function setAutomaticTransfer( - AUTOMATIC_TRANSFER calldata automaticTransfer_ - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - if ( - automaticTransfer_.isActivate != - options.automaticTransfer.isActivate - ) { - options.automaticTransfer.isActivate = automaticTransfer_ - .isActivate; - } - // No need to put the cmtat to zero to deactivate automaticTransfer - if ( - address(automaticTransfer_.cmtat) != - address(options.automaticTransfer.cmtat) - ) { - options.automaticTransfer.cmtat = automaticTransfer_.cmtat; - } - } - - /** - * @notice set time limit for new requests (Approval and transfer) - * timeLimitToApprove: time limit for an operator to approve a request - * timeLimitToTransfer: once a request is approved, time limit for the token holder to perform the transfer - */ - function setTimeLimit( - TIME_LIMIT memory timeLimit_ - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - if ( - options.timeLimit.timeLimitToApprove != - timeLimit_.timeLimitToApprove - ) { - options.timeLimit.timeLimitToApprove = timeLimit_ - .timeLimitToApprove; - } - if ( - options.timeLimit.timeLimitToTransfer != - timeLimit_.timeLimitToTransfer - ) { - options.timeLimit.timeLimitToTransfer = timeLimit_ - .timeLimitToTransfer; - } - } - - /** - * @notice If the transfer is not approved or denied within {timeLimitBeforeAutomaticApproval}, - * the request is considered as approved during a transfer. - * - */ - function setAutomaticApproval( - AUTOMATIC_APPROVAL memory automaticApproval_ - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - if ( - options.automaticApproval.isActivate != - automaticApproval_.isActivate - ) { - options.automaticApproval.isActivate = automaticApproval_ - .isActivate; - } - if ( - options.automaticApproval.timeLimitBeforeAutomaticApproval != - automaticApproval_.timeLimitBeforeAutomaticApproval - ) { - options - .automaticApproval - .timeLimitBeforeAutomaticApproval = automaticApproval_ - .timeLimitBeforeAutomaticApproval; - } - } - - /** - * @notice create a transfer request directly approved - */ - function createTransferRequestWithApproval( - TransferRequestKeyElement calldata keyElement - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - _createTransferRequestWithApproval(keyElement); - } - - /** - * @notice approve a transferRequest - * @param keyElement contains from, to, value - * @param partialValue amount approved. Put 0 if all the amount specified by value is approved. - * @param isApproved approved (true) or refused (false). Put true if you use partialApproval - */ - function approveTransferRequest( - TransferRequestKeyElement calldata keyElement, - uint256 partialValue, - bool isApproved - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - _approveTransferRequestKeyElement(keyElement, partialValue, isApproved); - } - - /** - * @notice approve a transferRequestby using its id - */ - function approveTransferRequestWithId( - uint256 requestId_, - bool isApproved - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - if (requestId_ + 1 > requestId) { - revert RuleConditionalTransfer_InvalidId(); - } - TransferRequest memory transferRequest = transferRequests[ - IdToKey[requestId_] - ]; - _approveRequest(transferRequest, isApproved); - } - - /** - * @notice reset to None the status of a request - */ - function resetRequestStatus( - uint256 requestId_ - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - if (requestId_ + 1 > requestId) { - revert RuleConditionalTransfer_InvalidId(); - } - bytes32 key = IdToKey[requestId_]; - _resetRequestStatus(key); - } - - /* ============ Batch function ============ */ - /** - * @notice Batch version of {approveTransferRequestWithId} - */ - function approveTransferRequestBatchWithId( - uint256[] calldata requestId_, - bool[] calldata isApproved - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - if (requestId_.length == 0) { - revert RuleConditionalTransfer_EmptyArray(); - } - if (requestId_.length != isApproved.length) { - revert RuleConditionalTransfer_InvalidLengthArray(); - } - // Check id validity before performing actions - for (uint256 i = 0; i < requestId_.length; ++i) { - if (requestId_[i] + 1 > requestId) { - revert RuleConditionalTransfer_InvalidId(); - } - } - for (uint256 i = 0; i < requestId_.length; ++i) { - TransferRequest memory transferRequest = transferRequests[ - IdToKey[requestId_[i]] - ]; - _approveRequest(transferRequest, isApproved[i]); - } - } - - /** - * @notice Batch version of {approveTransferRequest} - */ - function approveTransferRequestBatch( - TransferRequestKeyElement[] calldata keyElements, - uint256[] calldata partialValues, - bool[] calldata isApproved - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - if (keyElements.length == 0) { - revert RuleConditionalTransfer_EmptyArray(); - } - if ( - (keyElements.length != partialValues.length) || - (partialValues.length != isApproved.length) - ) { - revert RuleConditionalTransfer_InvalidLengthArray(); - } - for (uint256 i = 0; i < keyElements.length; ++i) { - _approveTransferRequestKeyElement( - keyElements[i], - partialValues[i], - isApproved[i] - ); - } - } - - /** - * @notice Batch version of {createTransferRequestWithApproval} - */ - function createTransferRequestWithApprovalBatch( - TransferRequestKeyElement[] calldata keyElements - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - if (keyElements.length == 0) { - revert RuleConditionalTransfer_EmptyArray(); - } - for (uint256 i = 0; i < keyElements.length; ++i) { - _createTransferRequestWithApproval(keyElements[i]); - } - } - - /** - * @notice Batch version of {resetRequestStatus} - */ - function resetRequestStatusBatch( - uint256[] memory requestIds - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - if (requestIds.length == 0) { - revert RuleConditionalTransfer_EmptyArray(); - } - // Check id validity before performing actions - for (uint256 i = 0; i < requestIds.length; ++i) { - if (requestIds[i] + 1 > requestId) { - revert RuleConditionalTransfer_InvalidId(); - } - } - for (uint256 i = 0; i < requestIds.length; ++i) { - bytes32 key = IdToKey[requestIds[i]]; - _resetRequestStatus(key); - } - } - - /* ============ 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 _approveTransferRequestKeyElement( - TransferRequestKeyElement calldata keyElement, - uint256 partialValue, - bool isApproved - ) internal { - if (partialValue > keyElement.value) { - revert RuleConditionalTransfer_InvalidValueApproved(); - } - bytes32 key = keccak256( - abi.encode(keyElement.from, keyElement.to, keyElement.value) - ); - TransferRequest memory transferRequest = transferRequests[key]; - if (partialValue > 0) { - if (!isApproved) { - revert RuleConditionalTransfer_CannotDeniedPartially(); - } - // Denied the first request - _approveRequest(transferRequest, false); - // Create new request - _createTransferRequestWithApproval( - TransferRequestKeyElement({ - from: keyElement.from, - to: keyElement.to, - value: partialValue - }) - ); - } else { - _approveRequest(transferRequest, isApproved); - } - } - - function _createTransferRequestWithApproval( - TransferRequestKeyElement memory keyElement_ - ) internal { - // WAIT => Will overwrite - // APPROVED => will overwrite previous status with a new delay - // DENIED => will overwrite - bytes32 key = keccak256( - abi.encode(keyElement_.from, keyElement_.to, keyElement_.value) - ); - if (_checkRequestStatus(key)) { - // Only if it is a new request - TransferRequest memory newTransferApproval = TransferRequest({ - key: key, - id: requestId, - keyElement: keyElement_, - askTime: 0, - // Warning: overflow possible if timeLimitToTransfer == max(uint256) - maxTime: block.timestamp + - options.timeLimit.timeLimitToTransfer, - status: STATUS.APPROVED - }); - transferRequests[key] = newTransferApproval; - IdToKey[requestId] = key; - emit transferApproved( - key, - keyElement_.from, - keyElement_.to, - keyElement_.value, - requestId - ); - ++requestId; - } else { - // Overwrite previous approval - // Warning: overflow possible if timeLimitToTransfer == max(uint256) - transferRequests[key].maxTime = - block.timestamp + - options.timeLimit.timeLimitToTransfer; - transferRequests[key].status = STATUS.APPROVED; - emit transferApproved( - key, - keyElement_.from, - keyElement_.to, - keyElement_.value, - transferRequests[key].id - ); - } - } - - function _resetRequestStatus(bytes32 key) internal { - transferRequests[key].status = STATUS.NONE; - emit transferReset( - key, - transferRequests[key].keyElement.from, - transferRequests[key].keyElement.to, - transferRequests[key].keyElement.value, - transferRequests[key].id - ); - } - - /** - * @dev check if it is a new request or not - */ - function _checkRequestStatus(bytes32 key) internal view returns (bool) { - // Status NONE not enough because reset is possible - return - (transferRequests[key].status == STATUS.NONE) && - (transferRequests[key].key == 0x0); - } - - function _approveRequest( - TransferRequest memory transferRequest, - bool isApproved - ) internal { - // status - if (transferRequest.status != STATUS.WAIT) { - revert RuleConditionalTransfer_Wrong_Status(); - } - if (isApproved) { - // Time - if ( - block.timestamp > - (transferRequest.askTime + options.timeLimit.timeLimitToApprove) - ) { - revert RuleConditionalTransfer_timeExceeded(); - } - // Set status - transferRequests[transferRequest.key].status = STATUS.APPROVED; - // Set max time - transferRequests[transferRequest.key].maxTime = - block.timestamp + - options.timeLimit.timeLimitToTransfer; - emit transferApproved( - transferRequest.key, - transferRequest.keyElement.from, - transferRequest.keyElement.to, - transferRequest.keyElement.value, - transferRequests[transferRequest.key].id - ); - if ( - options.automaticTransfer.isActivate && - address(options.automaticTransfer.cmtat) != address(0) - ) { - // Transfer with approval - // External call - if ( - options.automaticTransfer.cmtat.allowance( - transferRequest.keyElement.from, - address(this) - ) >= transferRequest.keyElement.value - ) { - // Will call the ruleEngine and the rule again... - options.automaticTransfer.cmtat.safeTransferFrom( - transferRequest.keyElement.from, - transferRequest.keyElement.to, - transferRequest.keyElement.value - ); - } - } - } else { - transferRequests[transferRequest.key].status = STATUS.DENIED; - emit transferDenied( - transferRequest.key, - transferRequest.keyElement.from, - transferRequest.keyElement.to, - transferRequest.keyElement.value, - transferRequests[transferRequest.key].id - ); - } - } - - /** - * @notice update the request during a transfer - */ - function _updateProcessedTransfer(bytes32 key) internal { - // Reset to zero - transferRequests[key].maxTime = 0; - transferRequests[key].askTime = 0; - // Change status - transferRequests[key].status = STATUS.EXECUTED; - // Emit event - emit transferProcessed( - key, - transferRequests[key].keyElement.from, - transferRequests[key].keyElement.to, - transferRequests[key].keyElement.value, - transferRequests[key].id - ); - } -} diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol deleted file mode 100644 index 693961a..0000000 --- a/src/rules/validation/RuleBlacklist.sol +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -import "./abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol"; -import "./abstract/RuleAddressList/RuleAddressList.sol"; -import "./abstract/RuleValidateTransfer.sol"; - -/** - * @title a blacklist manager - */ - -contract RuleBlacklist is - RuleValidateTransfer, - RuleAddressList, - RuleBlacklistInvariantStorage -{ - /** - * @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) {} - - /** - * @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 /*_amount */ - ) public view override returns (uint8) { - if (addressIsListed(_from)) { - return CODE_ADDRESS_FROM_IS_BLACKLISTED; - } else if (addressIsListed(_to)) { - return CODE_ADDRESS_TO_IS_BLACKLISTED; - } else { - return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - } - } - - function detectTransferRestrictionFrom( - address spender, - address from, - address to, - uint256 amount - ) public view override returns (uint8) { - if(addressIsListed(spender)){ - return CODE_ADDRESS_SPENDER_IS_BLACKLISTED; - } else { - return detectTransferRestriction(from, to, amount); - } - } - - - /** - * @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; - } - - /** - * @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_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 { - return TEXT_CODE_NOT_FOUND; - } - } -} diff --git a/src/rules/validation/RuleSanctionList.sol b/src/rules/validation/RuleSanctionList.sol deleted file mode 100644 index 4d85966..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 /*_amount */ - ) 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 _amount - ) 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,_amount); - } - } - 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/RuleWhitelist.sol b/src/rules/validation/RuleWhitelist.sol deleted file mode 100644 index b8ac216..0000000 --- a/src/rules/validation/RuleWhitelist.sol +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -import "./abstract/RuleAddressList/RuleAddressList.sol"; -import "./abstract/RuleWhitelistCommon.sol"; - -/** - * @title a whitelist manager - */ -contract RuleWhitelist is RuleAddressList, RuleWhitelistCommon { - /** - * @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) {} - - /** - * @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 /*_amount */ - ) public view override returns (uint8) { - if (!addressIsListed(_from)) { - return CODE_ADDRESS_FROM_NOT_WHITELISTED; - } else if (!addressIsListed(_to)) { - return CODE_ADDRESS_TO_NOT_WHITELISTED; - } else { - return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - } - } - - function detectTransferRestrictionFrom( - address spender, - address _from, - address _to, - uint256 _amount - ) public view override returns (uint8) { - if (addressIsListed(spender)) { - return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; - } else { - return detectTransferRestriction(_from,_to,_amount); - } - } -} diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol deleted file mode 100644 index 619ecc8..0000000 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ /dev/null @@ -1,175 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -import "OZ/access/AccessControl.sol"; -import "../../modules/RuleEngineValidationCommon.sol"; -import "../../modules/MetaTxModuleStandalone.sol"; -import "./abstract/RuleAddressList/RuleAddressList.sol"; -import "./abstract/RuleWhitelistCommon.sol"; - -/** - * @title Wrapper to call several different whitelist rules - */ -contract RuleWhitelistWrapper is - RuleEngineValidationCommon, - MetaTxModuleStandalone, - RuleWhitelistCommon -{ - /** - * @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); - } - - /** - * @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 /*_amount*/ - ) public view override 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; - } - } - if (!result[0]) { - return CODE_ADDRESS_FROM_NOT_WHITELISTED; - } else if (!result[1]) { - return CODE_ADDRESS_TO_NOT_WHITELISTED; - } else { - return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - } - } - - function detectTransferRestrictionFrom( - address spender, - address _from, - address _to, - uint256 /*_amount*/ - ) public view override returns (uint8) { - 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; - } - } - if (!result[0]) { - return CODE_ADDRESS_FROM_NOT_WHITELISTED; - } else if (!result[1]) { - return CODE_ADDRESS_TO_NOT_WHITELISTED; - } else if (!result[2]) { - return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; - } else { - return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - } - } - - /* ============ 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/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/RuleValidateTransfer.sol b/src/rules/validation/abstract/RuleValidateTransfer.sol deleted file mode 100644 index 8430be6..0000000 --- a/src/rules/validation/abstract/RuleValidateTransfer.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -import {IRuleValidation} from "../../../interfaces/IRuleValidation.sol"; -import {IERC1404} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; -abstract contract RuleValidateTransfer is IRuleValidation { - /** - * @notice Validate a 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) { - // does not work without `this` keyword => "Undeclared identifier" - return - this.detectTransferRestriction(_from, _to, _amount) == - uint8(REJECTED_CODE_BASE.TRANSFER_OK); - } - - 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); - } -} diff --git a/test/HelperContract.sol b/test/HelperContract.sol index c5ebd4d..17b19df 100644 --- a/test/HelperContract.sol +++ b/test/HelperContract.sol @@ -5,27 +5,23 @@ import "forge-std/Test.sol"; import "CMTAT/deployment/CMTATStandalone.sol"; import "CMTAT/libraries/Errors.sol"; -import {RuleEngineInvariantStorage} from "src/modules/RuleEngineInvariantStorage.sol"; +import {RuleEngineInvariantStorage} from "src/modules/library/RuleEngineInvariantStorage.sol"; +import {RulesManagementModuleInvariantStorage} from "src/modules/library/RulesManagementModuleInvariantStorage.sol"; // RuleEngine import {RuleEngine} from "src/RuleEngine.sol"; +import {RulesManagementModule} from "src/RuleEngineBase.sol"; +import {ERC3643ComplianceModule} from "src/RuleEngineBase.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"; -// RUleBlackList -import {RuleBlacklist} from "src/rules/validation/RuleBlacklist.sol"; -import {RuleBlacklistInvariantStorage} from "src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol"; +import {RuleConditionalTransferLight} from "src/mocks/rules/operation/RuleConditionalTransferLight.sol"; +import {RuleConditionalTransferLightInvariantStorage} from "src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.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 {RuleWhitelist} from "src/mocks/rules/validation/RuleWhitelist.sol"; +import {RuleWhitelistInvariantStorage} from "src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol"; +import {RuleAddressListInvariantStorage} from "src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol"; -import {RuleSanctionlistInvariantStorage}from "src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol"; // Rule interface -import {IRuleValidation} from "src/interfaces/IRuleValidation.sol"; -import {IRuleOperation} from "src/interfaces/IRuleOperation.sol"; + +import {IRule} from "src/interfaces/IRule.sol"; // utils import "./utils/CMTATDeployment.sol"; @@ -35,11 +31,10 @@ import "./utils/CMTATDeployment.sol"; */ abstract contract HelperContract is RuleWhitelistInvariantStorage, - RuleBlacklistInvariantStorage, RuleAddressListInvariantStorage, - RuleSanctionlistInvariantStorage, RuleEngineInvariantStorage, - RuleConditionalTransferInvariantStorage + RuleConditionalTransferLightInvariantStorage, + RulesManagementModuleInvariantStorage { // Test result uint256 internal resUint256; @@ -47,12 +42,12 @@ abstract contract HelperContract is bool internal resBool; bool internal resCallBool; string internal resString; + address internal resAddr; // EOA to perform tests address constant ZERO_ADDRESS = address(0); address constant DEFAULT_ADMIN_ADDRESS = address(1); address constant WHITELIST_OPERATOR_ADDRESS = address(2); address constant RULE_ENGINE_OPERATOR_ADDRESS = address(3); - address constant SANCTIONLIST_OPERATOR_ADDRESS = address(8); address constant CONDITIONAL_TRANSFER_OPERATOR_ADDRESS = address(9); address constant ATTACKER = address(4); address constant ADDRESS1 = address(5); @@ -66,12 +61,9 @@ abstract contract HelperContract is 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; + RuleConditionalTransferLight public ruleConditionalTransferLight; // CMTAT CMTATDeployment cmtatDeployment; diff --git a/test/RuleBlacklist/CMTATIntegration.t.sol b/test/RuleBlacklist/CMTATIntegration.t.sol deleted file mode 100644 index 245b1a3..0000000 --- a/test/RuleBlacklist/CMTATIntegration.t.sol +++ /dev/null @@ -1,262 +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 "src/RuleEngine.sol"; - -/** - * @title Integration test with the CMTAT - */ -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 - cmtatDeployment = new CMTATDeployment(); - CMTAT_CONTRACT = cmtatDeployment.cmtat(); - - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleBlacklist = new RuleBlacklist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); - - // specific arrange - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock = new RuleEngine( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS, - address(CMTAT_CONTRACT) - ); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock.addRuleValidation(ruleBlacklist); - 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); - } - - /******* 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); - } - - function testCannotTransferIfAddressToIsBlacklisted() public { - // Arrange - uint256 amount = 21; - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleBlacklist.addAddressToTheList(ADDRESS2); - - vm.prank(ADDRESS1); - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - amount - ) - ); - // Act - CMTAT_CONTRACT.transfer(ADDRESS2, amount); - } - - function testCannotTransferIfAddressFronIsBlacklisted() public { - // Arrange - uint256 amount = 21; - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleBlacklist.addAddressToTheList(ADDRESS1); - - vm.prank(ADDRESS1); - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - amount - ) - ); - // Act - CMTAT_CONTRACT.transfer(ADDRESS2, amount); - } - - function testCannotTransferIfBothAddressesAreBlacklisted() public { - uint256 amount = 21; - // Arrange - address[] memory blacklist = new address[](2); - blacklist[0] = ADDRESS1; - blacklist[1] = ADDRESS2; - vm.prank(DEFAULT_ADMIN_ADDRESS); - (bool success, ) = address(ruleBlacklist).call( - abi.encodeWithSignature( - "addAddressesToTheList(address[])", - blacklist - ) - ); - require(success); - - // Act - vm.prank(ADDRESS1); - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - amount - ) - ); - CMTAT_CONTRACT.transfer(ADDRESS2, amount); - } - - /******* detectTransferRestriction & messageForTransferRestriction *******/ - function testDetectAndMessageWithToBlacklisted() public { - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleBlacklist.addAddressToTheList(ADDRESS2); - resBool = ruleBlacklist.addressIsListed(ADDRESS2); - // Assert - assertEq(resBool, true); - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); - // Assert - assertEq(res1, CODE_ADDRESS_TO_IS_BLACKLISTED); - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); - // Assert - assertEq(message1, TEXT_ADDRESS_TO_IS_BLACKLISTED); - } - - function testDetectAndMessageWithFromBlacklisted() public { - // Arrange - // We add the sender to the whitelist - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleBlacklist.addAddressToTheList(ADDRESS1); - // Arrange - Assert - resBool = ruleBlacklist.addressIsListed(ADDRESS1); - assertEq(resBool, true); - // Act - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); - // Assert - assertEq(res1, CODE_ADDRESS_FROM_IS_BLACKLISTED); - // Act - 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 - ); - - // Assert - assertEq(res1, TRANSFER_OK); - // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); - // Assert - assertEq(message1, TEXT_TRANSFER_OK); - } - - function testDetectAndMessageWithFromAndToBlacklisted() public { - // Arrange - // We add the sender and the recipient to the whitelist. - address[] memory blacklist = new address[](2); - blacklist[0] = ADDRESS1; - blacklist[1] = ADDRESS2; - vm.prank(DEFAULT_ADMIN_ADDRESS); - (bool success, ) = address(ruleBlacklist).call( - abi.encodeWithSignature( - "addAddressesToTheList(address[])", - blacklist - ) - ); - require(success); - // Act - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); - // Assert - assertEq(res1, CODE_ADDRESS_FROM_IS_BLACKLISTED); - // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); - // Assert - assertEq(message1, TEXT_ADDRESS_FROM_IS_BLACKLISTED); - } - - function testCanMintIfAddressNotInTheBlacklist() public { - // Act - vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.mint(ADDRESS1, 11); - - // Assert - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); - assertEq(resUint256, ADDRESS1_BALANCE_INIT + 11); - } - - 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); - // Arrange - Assert - resBool = ruleBlacklist.addressIsListed(ZERO_ADDRESS); - assertEq(resBool, true); - - // Act - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ZERO_ADDRESS, - ADDRESS1, - amount - ) - ); - vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.mint(ADDRESS1, amount); - } - - function testCanReturnMessageNotFoundWithUnknownCodeId() public view { - // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - 255 - ); - - // Assert - assertEq(message1, TEXT_CODE_NOT_FOUND); - } -} diff --git a/test/RuleBlacklist/RuleBlacklist.t.sol b/test/RuleBlacklist/RuleBlacklist.t.sol deleted file mode 100644 index 92504d0..0000000 --- a/test/RuleBlacklist/RuleBlacklist.t.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../HelperContract.sol"; -import "src/RuleEngine.sol"; - -/** - * @title Integration test with the CMTAT - */ -contract RuleBlacklistTest is Test, HelperContract { - // Arrange - function setUp() public { - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleBlacklist = new RuleBlacklist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); - } - - function testCanRuleBlacklistReturnMessageNotFoundWithUnknownCodeId() - public - view - { - // Act - string memory message1 = ruleBlacklist.messageForTransferRestriction( - 255 - ); - - // Assert - assertEq(message1, TEXT_CODE_NOT_FOUND); - } -} diff --git a/test/RuleConditionalTransfer/CMTATIntegration.t.sol b/test/RuleConditionalTransfer/CMTATIntegration.t.sol deleted file mode 100644 index 1ba0080..0000000 --- a/test/RuleConditionalTransfer/CMTATIntegration.t.sol +++ /dev/null @@ -1,161 +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 "src/RuleEngine.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 b11cb0d..0000000 --- a/test/RuleConditionalTransfer/CMTATIntegrationConditionalTransfer.t.sol +++ /dev/null @@ -1,322 +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 "src/RuleEngine.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 d05ba53..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 "src/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 fae3211..0000000 --- a/test/RuleConditionalTransfer/RuleConditionalTransfer.t.sol +++ /dev/null @@ -1,980 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../HelperContract.sol"; -import "src/RuleEngine.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 07cf3dd..0000000 --- a/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol +++ /dev/null @@ -1,247 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../HelperContract.sol"; -import "src/RuleEngine.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 fa6cf9f..0000000 --- a/test/RuleConditionalTransfer/RuleConditionalTransferDeployment.t.sol +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../HelperContract.sol"; -import "src/RuleEngine.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 7b6404f..0000000 --- a/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol +++ /dev/null @@ -1,441 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../HelperContract.sol"; -import "src/RuleEngine.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 e08b17c..0000000 --- a/test/RuleConditionalTransfer/RuleConditionalTransferRestriction.t.sol +++ /dev/null @@ -1,118 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../HelperContract.sol"; -import "src/RuleEngine.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 30c0611..0000000 --- a/test/RuleConditionalTransfer/utils/CMTATIntegrationShare.sol +++ /dev/null @@ -1,483 +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 "src/RuleEngine.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 946c0d9..0000000 --- a/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../../HelperContract.sol"; -import "src/RuleEngine.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/RuleEngine/AccessControl/RuleEngineAccessControl.sol b/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol index 42aca5e..edf578a 100644 --- a/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol +++ b/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../../HelperContract.sol"; -import "src/RuleEngine.sol"; /** * @title Tests on the Access Control @@ -24,16 +23,16 @@ contract RuleEngineAccessControlTest is Test, HelperContract { ZERO_ADDRESS, ZERO_ADDRESS ); - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelist); + ruleEngineMock.addRule(ruleWhitelist); // Arrange - Assert - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } - function testCannotAttackerSetRulesValidation() public { + function testCannotAttackerSetRules() public { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleWhitelist ruleWhitelist1 = new RuleWhitelist( @@ -45,9 +44,9 @@ contract RuleEngineAccessControlTest is Test, HelperContract { WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS ); - address[] memory ruleWhitelistTab = new address[](2); - ruleWhitelistTab[0] = address(ruleWhitelist1); - ruleWhitelistTab[1] = address(ruleWhitelist2); + IRule[] memory ruleWhitelistTab = new IRule[](2); + ruleWhitelistTab[0] = ruleWhitelist1; + ruleWhitelistTab[1] = ruleWhitelist2; // Act vm.prank(ATTACKER); @@ -55,16 +54,16 @@ contract RuleEngineAccessControlTest is Test, HelperContract { abi.encodeWithSelector( AccessControlUnauthorizedAccount.selector, ATTACKER, - RULE_ENGINE_OPERATOR_ROLE + RULES_MANAGEMENT_ROLE ) ); (bool success, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) + abi.encodeCall(ruleEngineMock.setRules, ruleWhitelistTab) ); // Assert assertEq(success, true); - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } @@ -75,13 +74,13 @@ contract RuleEngineAccessControlTest is Test, HelperContract { abi.encodeWithSelector( AccessControlUnauthorizedAccount.selector, ATTACKER, - RULE_ENGINE_OPERATOR_ROLE + RULES_MANAGEMENT_ROLE ) ); - ruleEngineMock.clearRulesValidation(); + ruleEngineMock.clearRules(); // Assert - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } @@ -92,13 +91,13 @@ contract RuleEngineAccessControlTest is Test, HelperContract { abi.encodeWithSelector( AccessControlUnauthorizedAccount.selector, ATTACKER, - RULE_ENGINE_OPERATOR_ROLE + RULES_MANAGEMENT_ROLE ) ); - ruleEngineMock.addRuleValidation(ruleWhitelist); + ruleEngineMock.addRule(ruleWhitelist); // Assert - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } @@ -109,13 +108,13 @@ contract RuleEngineAccessControlTest is Test, HelperContract { abi.encodeWithSelector( AccessControlUnauthorizedAccount.selector, ATTACKER, - RULE_ENGINE_OPERATOR_ROLE + RULES_MANAGEMENT_ROLE ) ); - ruleEngineMock.removeRuleValidation(ruleWhitelist, 0); + ruleEngineMock.removeRule(ruleWhitelist); // Assert - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } @@ -123,11 +122,9 @@ contract RuleEngineAccessControlTest is Test, HelperContract { // Act vm.prank(ATTACKER); vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - TOKEN_CONTRACT_ROLE - ) + ERC3643ComplianceModule + .RuleEngine_ERC3643Compliance_UnauthorizedCaller + .selector ); ruleEngineMock.transferred(address(0), ADDRESS1, ADDRESS2, 10); } diff --git a/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol b/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol index 1bfe450..20de13b 100644 --- a/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol +++ b/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../../../lib/openzeppelin-contracts/contracts/access/AccessControl.sol"; import "../../HelperContract.sol"; -import "src/RuleEngine.sol"; /** * @title Tests on the provided functions by OpenZeppelin @@ -22,12 +21,12 @@ contract RuleEngineAccessControlTest is Test, HelperContract, AccessControl { ZERO_ADDRESS, ZERO_ADDRESS ); - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelist); + ruleEngineMock.addRule(ruleWhitelist); // Arrange - Assert - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } @@ -36,41 +35,41 @@ contract RuleEngineAccessControlTest is Test, HelperContract, AccessControl { vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); vm.expectEmit(true, true, false, true); emit RoleGranted( - RULE_ENGINE_OPERATOR_ROLE, + RULES_MANAGEMENT_ROLE, ADDRESS1, RULE_ENGINE_OPERATOR_ADDRESS ); - ruleEngineMock.grantRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); + ruleEngineMock.grantRole(RULES_MANAGEMENT_ROLE, ADDRESS1); // Assert - bool res1 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); + bool res1 = ruleEngineMock.hasRole(RULES_MANAGEMENT_ROLE, ADDRESS1); assertEq(res1, true); } function testRevokeRoleAsAdmin() public { // Arrange vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.grantRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); + ruleEngineMock.grantRole(RULES_MANAGEMENT_ROLE, ADDRESS1); // Arrange - Assert - bool res1 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); + bool res1 = ruleEngineMock.hasRole(RULES_MANAGEMENT_ROLE, ADDRESS1); assertEq(res1, true); // Act vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); vm.expectEmit(true, true, false, true); emit RoleRevoked( - RULE_ENGINE_OPERATOR_ROLE, + RULES_MANAGEMENT_ROLE, ADDRESS1, RULE_ENGINE_OPERATOR_ADDRESS ); - ruleEngineMock.revokeRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); + ruleEngineMock.revokeRole(RULES_MANAGEMENT_ROLE, ADDRESS1); // Assert - bool res2 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); + bool res2 = ruleEngineMock.hasRole(RULES_MANAGEMENT_ROLE, ADDRESS1); assertFalse(res2); } function testCannotGrantFromNonAdmin() public { // Arrange - Assert - bool res1 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); + bool res1 = ruleEngineMock.hasRole(RULES_MANAGEMENT_ROLE, ADDRESS1); assertFalse(res1); // Act @@ -82,22 +81,22 @@ contract RuleEngineAccessControlTest is Test, HelperContract, AccessControl { ) ); vm.prank(ADDRESS2); - ruleEngineMock.grantRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS2); + ruleEngineMock.grantRole(RULES_MANAGEMENT_ROLE, ADDRESS2); // Assert - bool res2 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); + bool res2 = ruleEngineMock.hasRole(RULES_MANAGEMENT_ROLE, ADDRESS1); assertFalse(res2); } function testCannotRevokeFromNonAdmin() public { // Arrange - Assert - bool res1 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); + bool res1 = ruleEngineMock.hasRole(RULES_MANAGEMENT_ROLE, ADDRESS1); assertFalse(res1); // Arrange vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.grantRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); + ruleEngineMock.grantRole(RULES_MANAGEMENT_ROLE, ADDRESS1); // Arrange - Assert - bool res2 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); + bool res2 = ruleEngineMock.hasRole(RULES_MANAGEMENT_ROLE, ADDRESS1); assertEq(res2, true); // Act @@ -109,10 +108,10 @@ contract RuleEngineAccessControlTest is Test, HelperContract, AccessControl { DEFAULT_ADMIN_ROLE ) ); - ruleEngineMock.revokeRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); + ruleEngineMock.revokeRole(RULES_MANAGEMENT_ROLE, ADDRESS1); // Assert - bool res3 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); + bool res3 = ruleEngineMock.hasRole(RULES_MANAGEMENT_ROLE, ADDRESS1); assertEq(res3, true); } } diff --git a/test/RuleEngine/ERC3643Compliance.t.sol b/test/RuleEngine/ERC3643Compliance.t.sol new file mode 100644 index 0000000..dd64ade --- /dev/null +++ b/test/RuleEngine/ERC3643Compliance.t.sol @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "forge-std/Test.sol"; +import "../HelperContract.sol"; +import {IERC3643Compliance} from "../../src/interfaces/IERC3643Compliance.sol"; +import {ERC3643ComplianceModule} from "../../src/modules/ERC3643ComplianceModule.sol"; + +// Minimal mock ERC-3643 token to simulate calls to RuleEngine +contract ERC3643MockToken { + IERC3643Compliance public ruleEngine; + + constructor(address _ruleEngine) { + ruleEngine = IERC3643Compliance(_ruleEngine); + } + + function simulateCreated(address to, uint256 amount) external { + ruleEngine.created(to, amount); + } + + function simulateDestroyed(address from, uint256 amount) external { + ruleEngine.destroyed(from, amount); + } + + function simulateTransferred( + address from, + address to, + uint256 amount + ) external { + ruleEngine.transferred(from, to, amount); + } +} + +contract RuleEngineTest is Test, HelperContract { + RuleEngine public ruleEngine; + ERC3643MockToken public token1; + ERC3643MockToken public token2; + ERC3643MockToken public token3; + + address public admin = address(0xA11CE); + address public operator = address(0x7); + address public user1 = address(0xB0B); + address public user2 = address(0xC0C); + + function setUp() public { + // Deploy RuleEngine with admin + ruleEngine = new RuleEngine(admin, ZERO_ADDRESS, ZERO_ADDRESS); + + // Deploy multiple mock tokens + token1 = new ERC3643MockToken(address(ruleEngine)); + token2 = new ERC3643MockToken(address(ruleEngine)); + token3 = new ERC3643MockToken(address(ruleEngine)); + + vm.startPrank(admin); + ruleEngine.grantRole(ruleEngine.COMPLIANCE_MANAGER_ROLE(), operator); + vm.stopPrank(); + } + + function testBindToken() public { + // Expect events for each bound token + vm.startPrank(operator); + + vm.expectEmit(true, false, false, true); + emit IERC3643Compliance.TokenBound(address(token1)); + ruleEngine.bindToken(address(token1)); + + vm.expectEmit(true, false, false, true); + emit IERC3643Compliance.TokenBound(address(token2)); + ruleEngine.bindToken(address(token2)); + + vm.expectEmit(true, false, false, true); + emit IERC3643Compliance.TokenBound(address(token3)); + ruleEngine.bindToken(address(token3)); + + vm.stopPrank(); + + // Check bindings + assertTrue(ruleEngine.isTokenBound(address(token1))); + assertTrue(ruleEngine.isTokenBound(address(token2))); + assertTrue(ruleEngine.isTokenBound(address(token3))); + + // getTokenBound() should return a value different from 0 + // Since we use EnumerableSet, we can not guarantee the address returned if there are mot than 1 token bound + assertNotEq(ruleEngine.getTokenBound(), address(0)); + + // getTokenBounds() should return all 3 + address[] memory tokens = ruleEngine.getTokenBounds(); + assertEq(tokens.length, 3); + assertEq(tokens[0], address(token1)); + assertEq(tokens[1], address(token2)); + assertEq(tokens[2], address(token3)); + } + + function testCanUnbindToken() public { + // Bind all first + vm.startPrank(operator); + + ruleEngine.bindToken(address(token1)); + ruleEngine.bindToken(address(token2)); + ruleEngine.bindToken(address(token3)); + + // Expect events for each unbind + vm.expectEmit(true, false, false, true); + emit IERC3643Compliance.TokenUnbound(address(token2)); + ruleEngine.unbindToken(address(token2)); + + vm.expectEmit(true, false, false, true); + emit IERC3643Compliance.TokenUnbound(address(token1)); + ruleEngine.unbindToken(address(token1)); + + vm.expectEmit(true, false, false, true); + emit IERC3643Compliance.TokenUnbound(address(token3)); + ruleEngine.unbindToken(address(token3)); + + vm.stopPrank(); + + // All should be unbound now + assertFalse(ruleEngine.isTokenBound(address(token1))); + assertFalse(ruleEngine.isTokenBound(address(token2))); + assertFalse(ruleEngine.isTokenBound(address(token3))); + + assertEq(ruleEngine.getTokenBound(), address(0)); + assertEq(ruleEngine.getTokenBounds().length, 0); + } + + function testCanCreatedAndDestroyed() public { + vm.prank(operator); + ruleEngine.bindToken(address(token1)); + + vm.startPrank(address(user1)); + token1.simulateCreated(user1, 100); + token1.simulateDestroyed(user2, 50); + vm.stopPrank(); + } + + function testCanTransferred() public { + vm.startPrank(address(operator)); + ruleEngine.bindToken(address(token1)); + + vm.startPrank(address(user1)); + token1.simulateTransferred(user1, user2, 200); + vm.stopPrank(); + } + + function testCannotBoundIfInvalidAddress() public { + vm.expectRevert( + ERC3643ComplianceModule + .RuleEngine_ERC3643Compliance_InvalidTokenAddress + .selector + ); + vm.prank(admin); + ruleEngine.bindToken(address(ZERO_ADDRESS)); + } + + function testCannotUnBoundIfTokenIsNotBound() public { + vm.expectRevert( + ERC3643ComplianceModule + .RuleEngine_ERC3643Compliance_TokenNotBound + .selector + ); + vm.prank(admin); + ruleEngine.unbindToken(address(0x100)); + } + + function testCannotBoundIfTokenIsAlreadyBound() public { + // Arrange + vm.prank(admin); + ruleEngine.bindToken(address(0x1)); + + // Assert + vm.expectRevert( + ERC3643ComplianceModule + .RuleEngine_ERC3643Compliance_TokenAlreadyBound + .selector + ); + vm.prank(admin); + ruleEngine.bindToken(address(0x1)); + } + + function testCannotCreatedIfNotBound() public { + vm.expectRevert( + ERC3643ComplianceModule + .RuleEngine_ERC3643Compliance_UnauthorizedCaller + .selector + ); + ruleEngine.created(user1, 100); + } + + function testCannotDestroyedIfNotBound() public { + vm.expectRevert( + ERC3643ComplianceModule + .RuleEngine_ERC3643Compliance_UnauthorizedCaller + .selector + ); + ruleEngine.destroyed(user2, 50); + } + + function testCannotTransferredIfNotBound() public { + vm.expectRevert( + ERC3643ComplianceModule + .RuleEngine_ERC3643Compliance_UnauthorizedCaller + .selector + ); + ruleEngine.transferred(user1, user2, 200); + } +} diff --git a/test/RuleEngine/RuleEngineDeployment.t.sol b/test/RuleEngine/RuleEngineDeployment.t.sol index 67b27d4..d826814 100644 --- a/test/RuleEngine/RuleEngineDeployment.t.sol +++ b/test/RuleEngine/RuleEngineDeployment.t.sol @@ -4,8 +4,6 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; import "CMTAT/mocks/MinimalForwarderMock.sol"; -import "src/RuleEngine.sol"; -import "src/RuleEngine.sol"; /** * @title General functions of the RuleEngine @@ -29,7 +27,7 @@ contract RuleEngineTest is Test, HelperContract { // assert resBool = ruleEngineMock.hasRole( - RULE_ENGINE_OPERATOR_ROLE, + RULES_MANAGEMENT_ROLE, RULE_ENGINE_OPERATOR_ADDRESS ); assertEq(resBool, true); @@ -37,6 +35,31 @@ contract RuleEngineTest is Test, HelperContract { assertEq(resBool, true); } + function testReturnZeroAddressForRule() public { + // Arrange + ruleEngineMock = new RuleEngine( + RULE_ENGINE_OPERATOR_ADDRESS, + address(0x0), + ZERO_ADDRESS + ); + // Act + resAddr = ruleEngineMock.rule(0); + // Assert + assertEq(resAddr, ZERO_ADDRESS); + } + + function testHasRightVersion() public { + // Act + ruleEngineMock = new RuleEngine( + RULE_ENGINE_OPERATOR_ADDRESS, + address(0x0), + ZERO_ADDRESS + ); + + // Assert + assertEq(ruleEngineMock.version(), "3.0.0"); + } + function testCannotDeployContractifAdminAddressIsZero() public { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); diff --git a/test/RuleEngine/RulesManagementModuleTest/CMTATIntegration.t.sol b/test/RuleEngine/RulesManagementModuleTest/CMTATIntegration.t.sol new file mode 100644 index 0000000..70c0fa8 --- /dev/null +++ b/test/RuleEngine/RulesManagementModuleTest/CMTATIntegration.t.sol @@ -0,0 +1,233 @@ +// 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 "OZ/token/ERC20/IERC20.sol"; + +/** + * @title General functions of the RuleEngine + */ +contract RuleEngineCMTATIntegrationTest is Test, HelperContract { + uint256 defaultValue = 20; + + // Arrange + function setUp() public { + // global arrange + cmtatDeployment = new CMTATDeployment(); + CMTAT_CONTRACT = cmtatDeployment.cmtat(); + + // CMTAT + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT.mint(ADDRESS1, defaultValue * 2); + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT.mint(ADDRESS2, defaultValue); + + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock = new RuleEngine( + RULE_ENGINE_OPERATOR_ADDRESS, + ZERO_ADDRESS, + address(CMTAT_CONTRACT) + ); + ruleConditionalTransferLight = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.addRule(ruleConditionalTransferLight); + // Arrange - Assert + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 1); + + // We set the Rule Engine + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT.setRuleEngine(ruleEngineMock); + } + + function testCanDetectTransferRestrictionOK() public { + // Arrange + vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + + vm.expectEmit(true, true, true, true); + emit TransferApproved(ADDRESS1, ADDRESS2, defaultValue, 1); + ruleConditionalTransferLight.approveTransfer( + ADDRESS1, + ADDRESS2, + defaultValue + ); + // Act + // RuleEngine + resUint8 = ruleEngineMock.detectTransferRestriction( + ADDRESS1, + ADDRESS2, + defaultValue + ); + + // Assert + assertEq(resUint8, 0); + + resUint8 = ruleEngineMock.detectTransferRestrictionFrom( + address(0), + ADDRESS1, + ADDRESS2, + defaultValue + ); + + // Assert + assertEq(resUint8, 0); + + // CMTAT + resUint8 = CMTAT_CONTRACT.detectTransferRestriction( + ADDRESS1, + ADDRESS2, + defaultValue + ); + + // Assert + assertEq(resUint8, 0); + + resUint8 = CMTAT_CONTRACT.detectTransferRestrictionFrom( + address(0), + ADDRESS1, + ADDRESS2, + defaultValue + ); + + // Assert + assertEq(resUint8, 0); + + // RuleEngine + resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, defaultValue); + + // Assert + assertEq(resBool, true); + + resBool = ruleEngineMock.canTransferFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + defaultValue + ); + + // Assert + assertEq(resBool, true); + + // CMTAT + resBool = CMTAT_CONTRACT.canTransfer(ADDRESS1, ADDRESS2, defaultValue); + + // Assert + assertEq(resBool, true); + + resBool = CMTAT_CONTRACT.canTransferFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + defaultValue + ); + + // Assert + assertEq(resBool, true); + } + + function testCanDetectTransferRestrictionNotOk() public { + // Act + resUint8 = ruleEngineMock.detectTransferRestriction( + ADDRESS1, + ADDRESS2, + 20 + ); + + // Assert + assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED); + + // CMTAT + resUint8 = CMTAT_CONTRACT.detectTransferRestriction( + ADDRESS1, + ADDRESS2, + 20 + ); + + // Assert + assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED); + + // Act + resUint8 = ruleEngineMock.detectTransferRestrictionFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20 + ); + + // Assert + assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED); + + // CMTAT + resUint8 = CMTAT_CONTRACT.detectTransferRestrictionFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20 + ); + + // Assert + assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED); + + // Act + resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); + + // Assert + assertFalse(resBool); + + // CMTAT + resBool = CMTAT_CONTRACT.canTransfer(ADDRESS1, ADDRESS2, 20); + + // Assert + assertFalse(resBool); + + // Act + resBool = ruleEngineMock.canTransferFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20 + ); + + // Assert + assertFalse(resBool); + + // CMTAT + resBool = CMTAT_CONTRACT.canTransferFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20 + ); + + // Assert + assertFalse(resBool); + } + + function testCanPerfromATransfer() public { + vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + ruleConditionalTransferLight.approveTransfer( + ADDRESS1, + ADDRESS2, + defaultValue + ); + vm.prank(ADDRESS1); + CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); + + vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + ruleConditionalTransferLight.approveTransfer( + ADDRESS1, + ADDRESS2, + defaultValue + ); + vm.prank(ADDRESS1); + CMTAT_CONTRACT.approve(ADDRESS3, defaultValue); + vm.prank(ADDRESS3); + CMTAT_CONTRACT.transferFrom(ADDRESS1, ADDRESS2, defaultValue); + } +} diff --git a/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperation.t.sol b/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperation.t.sol new file mode 100644 index 0000000..04a73d1 --- /dev/null +++ b/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperation.t.sol @@ -0,0 +1,579 @@ +// 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 RuleEngine + */ +contract RulesManagementModuleInvariantStorageTest is Test, HelperContract { + IRule[] ruleConditionalTransferLightTab = new IRule[](2); + + // Arrange + function setUp() public { + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock = new RuleEngine( + RULE_ENGINE_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ZERO_ADDRESS + ); + ruleConditionalTransferLight = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.addRule(ruleConditionalTransferLight); + // Arrange - Assert + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 1); + assertEq( + ruleEngineMock.containsRule(ruleConditionalTransferLight), + true + ); + } + + function testCanSetRules() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + RuleConditionalTransferLight ruleConditionalTransferLight1 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + RuleConditionalTransferLight ruleConditionalTransferLight2 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + ruleConditionalTransferLightTab[0] = IRule( + ruleConditionalTransferLight1 + ); + ruleConditionalTransferLightTab[1] = IRule( + ruleConditionalTransferLight2 + ); + // Act + vm.expectEmit(true, false, false, false); + emit RulesManagementModuleInvariantStorage.AddRule( + ruleConditionalTransferLight1 + ); + vm.expectEmit(true, false, false, false); + emit RulesManagementModuleInvariantStorage.AddRule( + ruleConditionalTransferLight2 + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.setRules(ruleConditionalTransferLightTab); + // Assert + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 2); + + assertEq( + ruleEngineMock.containsRule(ruleConditionalTransferLight1), + true + ); + assertEq( + ruleEngineMock.containsRule(ruleConditionalTransferLight2), + true + ); + } + + function testCannotSetRuleIfARuleIsAlreadyPresent() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + RuleConditionalTransferLight ruleConditionalTransferLight1 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + ruleConditionalTransferLightTab[0] = ruleConditionalTransferLight1; + ruleConditionalTransferLightTab[1] = ruleConditionalTransferLight1; + + // Act + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + vm.expectRevert( + RuleEngine_RulesManagementModule_RuleAlreadyExists.selector + ); + ruleEngineMock.setRules(ruleConditionalTransferLightTab); + + // Assert + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 1); + } + + function testCannotSetEmptyRulesT1WithEmptyTab() public { + // Arrange + ruleConditionalTransferLightTab = new IRule[](0); + resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); + assertFalse(resBool); + + // Act + vm.expectRevert( + RulesManagementModuleInvariantStorage + .RuleEngine_RulesManagementModule_ArrayIsEmpty + .selector + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.setRules(ruleConditionalTransferLightTab); + // Assert + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 1); + + // Assert + // previous rule still present => invalid Transfer + resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); + assertFalse(resBool); + } + + function testCannotSetEmptyRulesT2WithZeroAddress() public { + // Arrange + ruleConditionalTransferLightTab = new IRule[](0); + // Act + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + vm.expectRevert( + RulesManagementModuleInvariantStorage + .RuleEngine_RulesManagementModule_ArrayIsEmpty + .selector + ); + ruleEngineMock.setRules(ruleConditionalTransferLightTab); + + // Assert1 + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 1); + + // Assert2 + // previous rule still present => invalid Transfer + resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); + assertFalse(resBool); + } + + function testCanClearRules() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + RuleConditionalTransferLight ruleConditionalTransferLight1 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + RuleConditionalTransferLight ruleConditionalTransferLight2 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + ruleConditionalTransferLightTab[0] = IRule( + ruleConditionalTransferLight1 + ); + ruleConditionalTransferLightTab[1] = IRule( + ruleConditionalTransferLight2 + ); + + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.setRules(ruleConditionalTransferLightTab); + address[] memory rulesResult = ruleEngineMock.rules(); + if ( + (rulesResult[0] != address(ruleConditionalTransferLight1)) || + (rulesResult[0] != address(ruleConditionalTransferLight1)) + ) { + revert("Invalid array storage 1"); + } + if ( + (rulesResult[1] != address(ruleConditionalTransferLight2)) || + (rulesResult[1] != address(ruleConditionalTransferLight2)) + ) { + revert("Invalid array storage 2"); + } + // Assert - Arrange + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 2); + assertEq( + ruleEngineMock.containsRule(ruleConditionalTransferLight1), + true + ); + assertEq( + ruleEngineMock.containsRule(ruleConditionalTransferLight2), + true + ); + + // Act + vm.expectEmit(true, false, false, false); + emit RulesManagementModuleInvariantStorage.ClearRules(); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.clearRules(); + + // Assert + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 0); + assertFalse(ruleEngineMock.containsRule(ruleConditionalTransferLight1)); + assertFalse(ruleEngineMock.containsRule(ruleConditionalTransferLight2)); + } + + function testCanClearRulesAndAddAgain() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + RuleConditionalTransferLight ruleConditionalTransferLight1 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + RuleConditionalTransferLight ruleConditionalTransferLight2 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + ruleConditionalTransferLightTab[0] = IRule( + ruleConditionalTransferLight1 + ); + ruleConditionalTransferLightTab[1] = IRule( + ruleConditionalTransferLight2 + ); + + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + (bool resCallBool, ) = address(ruleEngineMock).call( + abi.encodeCall( + ruleEngineMock.setRules, + ruleConditionalTransferLightTab + ) + ); + + // Act + vm.expectEmit(true, false, false, false); + emit RulesManagementModuleInvariantStorage.ClearRules(); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.clearRules(); + + // Assert + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 0); + + // Can set again the previous rules + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + (resCallBool, ) = address(ruleEngineMock).call( + abi.encodeCall( + ruleEngineMock.setRules, + ruleConditionalTransferLightTab + ) + ); + assertEq(resCallBool, true); + // Arrange before assert + + // Act + vm.expectEmit(true, false, false, false); + emit RulesManagementModuleInvariantStorage.ClearRules(); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.clearRules(); + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 0); + + // Can add previous rule again + vm.expectEmit(true, false, false, false); + emit RulesManagementModuleInvariantStorage.AddRule( + ruleConditionalTransferLight1 + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.addRule(ruleConditionalTransferLight1); + } + + function testCanAddRule() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + RuleConditionalTransferLight ruleConditionalTransferLight1 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + + // Act + vm.expectEmit(true, false, false, false); + emit RulesManagementModuleInvariantStorage.AddRule( + ruleConditionalTransferLight1 + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.addRule(ruleConditionalTransferLight1); + + // Assert + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 2); + } + + function testCannotAddRuleZeroAddress() public { + // Act + vm.expectRevert( + RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed.selector + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.addRule(IRule(address(0x0))); + + // Assert + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 1); + } + + function testCannotAddARuleAlreadyPresent() public { + // Act + vm.expectRevert( + RuleEngine_RulesManagementModule_RuleAlreadyExists.selector + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.addRule(ruleConditionalTransferLight); + + // Assert + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 1); + } + + function testCanAddARuleAfterThisRuleWasRemoved() public { + // Arrange - Assert + address[] memory _rules = ruleEngineMock.rules(); + assertEq(address(_rules[0]), address(ruleConditionalTransferLight)); + + // Arrange + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.removeRule(ruleConditionalTransferLight); + + // Act + vm.expectEmit(true, false, false, false); + emit RulesManagementModuleInvariantStorage.AddRule( + ruleConditionalTransferLight + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.addRule(ruleConditionalTransferLight); + + // Assert + _rules = ruleEngineMock.rules(); + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 1); + } + + function testCannotRemoveNonExistantRule() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + RuleConditionalTransferLight ruleConditionalTransferLight1 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + + // Act + vm.expectRevert( + RuleEngine_RulesManagementModule_RuleDoNotMatch.selector + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.removeRule(ruleConditionalTransferLight1); + + // Assert + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 1); + } + + function testCanRemoveLatestRule() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + RuleConditionalTransferLight ruleConditionalTransferLight1 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.addRule(ruleConditionalTransferLight1); + + // Act + vm.expectEmit(true, false, false, false); + emit RulesManagementModuleInvariantStorage.RemoveRule( + ruleConditionalTransferLight1 + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.removeRule(ruleConditionalTransferLight1); + + // Assert + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 1); + } + + function testCanRemoveFirstRule() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + RuleConditionalTransferLight ruleConditionalTransferLight1 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.addRule(ruleConditionalTransferLight1); + + // Act + vm.expectEmit(true, false, false, false); + emit RulesManagementModuleInvariantStorage.RemoveRule( + ruleConditionalTransferLight + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.removeRule(ruleConditionalTransferLight); + + // Assert + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 1); + } + + function testCanRemoveRule() public { + // Arrange + // First rule + vm.prank(WHITELIST_OPERATOR_ADDRESS); + RuleConditionalTransferLight ruleConditionalTransferLight1 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.addRule(ruleConditionalTransferLight1); + // Second rule + vm.prank(WHITELIST_OPERATOR_ADDRESS); + RuleConditionalTransferLight ruleConditionalTransferLight2 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.addRule(ruleConditionalTransferLight2); + + // Act + vm.expectEmit(true, false, false, false); + emit RulesManagementModuleInvariantStorage.RemoveRule( + ruleConditionalTransferLight1 + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.removeRule(ruleConditionalTransferLight1); + + // Assert + address[] memory _rules = ruleEngineMock.rules(); + // RuleConditionalTransferLight1 has been removed + assertEq(address(_rules[0]), address(ruleConditionalTransferLight)); + assertEq(address(_rules[1]), address(ruleConditionalTransferLight2)); + + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 2); + } + + function testRuleLength() public { + // Act + resUint256 = ruleEngineMock.rulesCount(); + + // Assert + assertEq(resUint256, 1); + + // Arrange + RuleConditionalTransferLight ruleConditionalTransferLight1 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + RuleConditionalTransferLight ruleConditionalTransferLight2 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + ruleConditionalTransferLightTab[0] = IRule( + ruleConditionalTransferLight1 + ); + ruleConditionalTransferLightTab[1] = IRule( + ruleConditionalTransferLight2 + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.setRules(ruleConditionalTransferLightTab); + + // Act + resUint256 = ruleEngineMock.rulesCount(); + + // Assert + assertEq(resUint256, 2); + } + + function testGetRule() public { + // Arrange + RuleConditionalTransferLight ruleConditionalTransferLight1 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + RuleConditionalTransferLight ruleConditionalTransferLight2 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + ruleConditionalTransferLightTab[0] = IRule( + ruleConditionalTransferLight1 + ); + ruleConditionalTransferLightTab[1] = IRule( + ruleConditionalTransferLight2 + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.setRules(ruleConditionalTransferLightTab); + + // Act + address rule = ruleEngineMock.rule(0); + + // Assert + assertEq(address(rule), address(ruleConditionalTransferLight1)); + } + + function testGetRules() public { + // Arrange + RuleConditionalTransferLight ruleConditionalTransferLight1 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + RuleConditionalTransferLight ruleConditionalTransferLight2 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + ruleConditionalTransferLightTab[0] = IRule( + ruleConditionalTransferLight1 + ); + ruleConditionalTransferLightTab[1] = IRule( + ruleConditionalTransferLight2 + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.setRules(ruleConditionalTransferLightTab); + + // Act + address[] memory rules = ruleEngineMock.rules(); + + // Assert + assertEq(ruleConditionalTransferLightTab.length, rules.length); + for (uint256 i = 0; i < rules.length; ++i) { + assertEq( + address(ruleConditionalTransferLightTab[i]), + address(rules[i]) + ); + } + } + + function testCanGetRuleIndex() public { + // Arrange + RuleConditionalTransferLight ruleConditionalTransferLight1 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + RuleConditionalTransferLight ruleConditionalTransferLight2 = new RuleConditionalTransferLight( + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ruleEngineMock + ); + ruleConditionalTransferLightTab[0] = IRule( + ruleConditionalTransferLight1 + ); + ruleConditionalTransferLightTab[1] = IRule( + ruleConditionalTransferLight2 + ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + (bool resCallBool, ) = address(ruleEngineMock).call( + abi.encodeCall( + ruleEngineMock.setRules, + ruleConditionalTransferLightTab + ) + ); + // Arrange - Assert + assertEq(resCallBool, true); + + // Act + /* uint256 index1 = ruleEngineMock.getRuleIndex( + ruleConditionalTransferLight1 + ); + uint256 index2 = ruleEngineMock.getRuleIndex( + ruleConditionalTransferLight2 + ); + // Length of the list because RuleConditionalTransferLight is not in the list + uint256 index3 = ruleEngineMock.getRuleIndex( + ruleConditionalTransferLight + ); + + // Assert + assertEq(index1, 0); + assertEq(index2, 1); + assertEq(index3, ruleConditionalTransferLightTab.length);*/ + } +} diff --git a/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevert.t.sol b/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevert.t.sol new file mode 100644 index 0000000..bb712b1 --- /dev/null +++ b/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevert.t.sol @@ -0,0 +1,47 @@ +// 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"; +import "src/mocks/rules/operation/RuleOperationRevert.sol"; + +/** + * @title General functions of the RuleEngine + */ +contract RuleEngineOperationTestRevert is Test, HelperContract { + // Arrange + function setUp() public { + // CMTAT + cmtatDeployment = new CMTATDeployment(); + CMTAT_CONTRACT = cmtatDeployment.cmtat(); + + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock = new RuleEngine( + RULE_ENGINE_OPERATOR_ADDRESS, + ZERO_ADDRESS, + address(CMTAT_CONTRACT) + ); + RuleOperationRevert ruleOperationRevert = new RuleOperationRevert(); + + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.addRule(ruleOperationRevert); + // Arrange - Assert + resUint256 = ruleEngineMock.rulesCount(); + assertEq(resUint256, 1); + + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT.setRuleEngine(ruleEngineMock); + } + + function testRuleEngineTransferredRevert() public { + // Arrange + vm.expectRevert( + RuleOperationRevert + .RuleConditionalTransferLight_InvalidTransfer + .selector + ); + // Act + CMTAT_CONTRACT.transfer(ADDRESS2, 21); + } +} diff --git a/test/RuleEngine/ruleEngineOperation/RuleEngineRestriction.t.sol b/test/RuleEngine/RulesManagementModuleTest/RuleEngineRestriction.t.sol similarity index 57% rename from test/RuleEngine/ruleEngineOperation/RuleEngineRestriction.t.sol rename to test/RuleEngine/RulesManagementModuleTest/RuleEngineRestriction.t.sol index 336a9d6..c6cc4ae 100644 --- a/test/RuleEngine/ruleEngineOperation/RuleEngineRestriction.t.sol +++ b/test/RuleEngine/RulesManagementModuleTest/RuleEngineRestriction.t.sol @@ -3,48 +3,15 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../../HelperContract.sol"; -import "src/RuleEngine.sol"; import "OZ/token/ERC20/IERC20.sol"; + //ADmin, forwarder irrect /RuleEngine /** * @title General functions of the RuleEngine */ -contract RuleEngineOperationTest is Test, HelperContract { +contract RuleEngineTest 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 { vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); @@ -53,28 +20,28 @@ contract RuleEngineOperationTest is Test, HelperContract { ZERO_ADDRESS, ZERO_ADDRESS ); - ruleConditionalTransfer = new RuleConditionalTransfer( + ruleConditionalTransferLight = new RuleConditionalTransferLight( CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options + ruleEngineMock ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleOperation(ruleConditionalTransfer); + ruleEngineMock.addRule(ruleConditionalTransferLight); // Arrange - Assert - resUint256 = ruleEngineMock.rulesCountOperation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } function testCanDetectTransferRestrictionOK() public { // 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 + emit TransferApproved(ADDRESS1, ADDRESS2, defaultValue, 1); + ruleConditionalTransferLight.approveTransfer( + ADDRESS1, + ADDRESS2, + defaultValue ); // Act resUint8 = ruleEngineMock.detectTransferRestriction( @@ -85,6 +52,31 @@ contract RuleEngineOperationTest is Test, HelperContract { // Assert assertEq(resUint8, 0); + + resUint8 = ruleEngineMock.detectTransferRestrictionFrom( + address(0), + ADDRESS1, + ADDRESS2, + defaultValue + ); + + // Assert + assertEq(resUint8, 0); + + resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, defaultValue); + + // Assert + assertEq(resBool, true); + + resBool = ruleEngineMock.canTransferFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + defaultValue + ); + + // Assert + assertEq(resBool, true); } function testCanDetectTransferRestrictionNotOk() public { @@ -97,12 +89,40 @@ contract RuleEngineOperationTest is Test, HelperContract { // Assert assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED); + + // Act + resUint8 = ruleEngineMock.detectTransferRestrictionFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20 + ); + + // Assert + assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED); + + // Act + resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); + + // Assert + assertFalse(resBool); + + // Act + resBool = ruleEngineMock.canTransferFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20 + ); + + // Assert + assertFalse(resBool); } function testMessageForTransferRestrictionNoRule() public { // Arrange vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.clearRulesOperation(); + ruleEngineMock.clearRules(); // Act resString = ruleEngineMock.messageForTransferRestriction(50); diff --git a/test/RuleEngine/ruleEngineOperation/RuleEngineOperation.t.sol b/test/RuleEngine/ruleEngineOperation/RuleEngineOperation.t.sol deleted file mode 100644 index afec4da..0000000 --- a/test/RuleEngine/ruleEngineOperation/RuleEngineOperation.t.sol +++ /dev/null @@ -1,639 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../../HelperContract.sol"; -import "src/RuleEngine.sol"; -import "OZ/token/ERC20/IERC20.sol"; -/** - * @title General functions of the RuleEngine - */ -contract RuleEngineOperationTest is Test, HelperContract { - 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_ - }); - - // Arrange - function setUp() public { - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock = new RuleEngine( - RULE_ENGINE_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ZERO_ADDRESS - ); - ruleConditionalTransfer = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleOperation(ruleConditionalTransfer); - // Arrange - Assert - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 1); - } - - function testCanSetRulesOperation() public { - // Arrange - vm.prank(WHITELIST_OPERATOR_ADDRESS); - RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - vm.prank(WHITELIST_OPERATOR_ADDRESS); - RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - address[] memory RuleConditionalTransferTab = new address[](2); - RuleConditionalTransferTab[0] = address( - IRuleOperation(RuleConditionalTransfer1) - ); - RuleConditionalTransferTab[1] = address( - IRuleOperation(RuleConditionalTransfer2) - ); - // Act - vm.expectEmit(true, false, false, false); - emit AddRule(address(RuleConditionalTransfer1)); - vm.expectEmit(true, false, false, false); - emit AddRule(address(RuleConditionalTransfer2)); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall( - ruleEngineMock.setRulesOperation, - RuleConditionalTransferTab - ) - ); - - // Assert - assertEq(resCallBool, true); - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 2); - } - - function testCannotSetRuleIfARuleIsAlreadyPresent() public { - // Arrange - vm.prank(WHITELIST_OPERATOR_ADDRESS); - RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - address[] memory RuleConditionalTransferTab = new address[](2); - RuleConditionalTransferTab[0] = address(RuleConditionalTransfer1); - RuleConditionalTransferTab[1] = address(RuleConditionalTransfer1); - - // Act - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - vm.expectRevert(RuleEngine_RuleAlreadyExists.selector); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall( - ruleEngineMock.setRulesOperation, - RuleConditionalTransferTab - ) - ); - - // Assert - // I do not know why but the function call return true - // if the call is reverted with the message indicated in expectRevert - // assertFalse(resCallBool); - assertEq(resCallBool, true); - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 1); - } - - function testCannotSetEmptyRulesT1WithEmptyTab() public { - // Arrange - address[] memory RuleConditionalTransferTab = new address[](0); - resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); - assertFalse(resBool); - - // Act - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall( - ruleEngineMock.setRulesOperation, - RuleConditionalTransferTab - ) - ); - - // Assert - assertFalse(resCallBool); - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 1); - - // Assert - // previous rule still present => invalid Transfer - resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); - assertFalse(resBool); - } - - function testCannotSetEmptyRulesT2WithZeroAddress() public { - // Arrange - address[] memory RuleConditionalTransferTab = new address[](2); - - // Act - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - vm.expectRevert("The array is empty2"); - - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall( - ruleEngineMock.setRulesOperation, - RuleConditionalTransferTab - ) - ); - - resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); - - // Assert1 - assertFalse(resCallBool); - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 1); - - // Assert2 - // previous rule still present => invalid Transfer - resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); - assertFalse(resBool); - } - - function testCanClearRules() public { - // Arrange - vm.prank(WHITELIST_OPERATOR_ADDRESS); - RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - vm.prank(WHITELIST_OPERATOR_ADDRESS); - RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - address[] memory RuleConditionalTransferTab = new address[](2); - RuleConditionalTransferTab[0] = address( - IRuleOperation(RuleConditionalTransfer1) - ); - RuleConditionalTransferTab[1] = address( - IRuleOperation(RuleConditionalTransfer2) - ); - - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall( - ruleEngineMock.setRulesOperation, - RuleConditionalTransferTab - ) - ); - ruleEngineMock.rulesOperation(); - // Assert - Arrange - assertEq(resCallBool, true); - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 2); - - // Act - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.clearRulesOperation(); - - // Assert - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 0); - } - - function testCanClearRulesAndAddAgain() public { - // Arrange - vm.prank(WHITELIST_OPERATOR_ADDRESS); - RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - vm.prank(WHITELIST_OPERATOR_ADDRESS); - RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - address[] memory RuleConditionalTransferTab = new address[](2); - RuleConditionalTransferTab[0] = address( - IRuleOperation(RuleConditionalTransfer1) - ); - RuleConditionalTransferTab[1] = address( - IRuleOperation(RuleConditionalTransfer2) - ); - - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall( - ruleEngineMock.setRulesOperation, - RuleConditionalTransferTab - ) - ); - - // Act - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.clearRulesOperation(); - - // Assert - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 0); - - // Can set again the previous rules - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall( - ruleEngineMock.setRulesOperation, - RuleConditionalTransferTab - ) - ); - assertEq(resCallBool, true); - // Arrange before assert - - // Act - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.clearRulesOperation(); - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 0); - - // Can add previous rule again - vm.expectEmit(true, false, false, false); - emit AddRule(address(RuleConditionalTransfer1)); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleOperation(RuleConditionalTransfer1); - } - - function testCanAddRule() public { - // Arrange - vm.prank(WHITELIST_OPERATOR_ADDRESS); - RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - - // Act - vm.expectEmit(true, false, false, false); - emit AddRule(address(RuleConditionalTransfer1)); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleOperation(RuleConditionalTransfer1); - - // Assert - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 2); - } - - function testCannotAddRuleZeroAddress() public { - // Act - vm.expectRevert(RuleEngine_RuleAddressZeroNotAllowed.selector); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleOperation(IRuleOperation(address(0x0))); - - // Assert - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 1); - } - - function testCannotAddARuleAlreadyPresent() public { - // Act - vm.expectRevert(RuleEngine_RuleAlreadyExists.selector); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleOperation(ruleConditionalTransfer); - - // Assert - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 1); - } - - function testCanAddARuleAfterThisRuleWasRemoved() public { - // Arrange - Assert - address[] memory _rules = ruleEngineMock.rulesOperation(); - assertEq(address(_rules[0]), address(ruleConditionalTransfer)); - - // Arrange - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.removeRuleOperation(ruleConditionalTransfer, 0); - - // Act - vm.expectEmit(true, false, false, false); - emit AddRule(address(ruleConditionalTransfer)); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleOperation(ruleConditionalTransfer); - - // Assert - _rules = ruleEngineMock.rulesOperation(); - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 1); - } - - function testCanRemoveNonExistantRule() public { - // Arrange - vm.prank(WHITELIST_OPERATOR_ADDRESS); - RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - - // Act - vm.expectRevert(RuleEngine_RuleDoNotMatch.selector); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.removeRuleOperation(RuleConditionalTransfer1, 0); - - // Assert - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 1); - } - - function testCanRemoveLatestRule() public { - // Arrange - vm.prank(WHITELIST_OPERATOR_ADDRESS); - RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleOperation(RuleConditionalTransfer1); - - // Act - vm.expectEmit(true, false, false, false); - emit RemoveRule(address(RuleConditionalTransfer1)); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.removeRuleOperation(RuleConditionalTransfer1, 1); - - // Assert - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 1); - } - - function testCanRemoveFirstRule() public { - // Arrange - vm.prank(WHITELIST_OPERATOR_ADDRESS); - RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleOperation(RuleConditionalTransfer1); - - // Act - vm.expectEmit(true, false, false, false); - emit RemoveRule(address(ruleConditionalTransfer)); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.removeRuleOperation(ruleConditionalTransfer, 0); - - // Assert - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 1); - } - - function testCanRemoveRuleOperation() public { - // Arrange - // First rule - vm.prank(WHITELIST_OPERATOR_ADDRESS); - RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleOperation(RuleConditionalTransfer1); - // Second rule - vm.prank(WHITELIST_OPERATOR_ADDRESS); - RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleOperation(RuleConditionalTransfer2); - - // Act - vm.expectEmit(true, false, false, false); - emit RemoveRule(address(RuleConditionalTransfer1)); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.removeRuleOperation(RuleConditionalTransfer1, 1); - - // Assert - address[] memory _rules = ruleEngineMock.rulesOperation(); - // RuleConditionalTransfer1 has been removed - assertEq(address(_rules[0]), address(ruleConditionalTransfer)); - assertEq(address(_rules[1]), address(RuleConditionalTransfer2)); - - resUint256 = ruleEngineMock.rulesCountOperation(); - assertEq(resUint256, 2); - } - - function testRuleLength() public { - // Act - resUint256 = ruleEngineMock.rulesCountOperation(); - - // Assert - assertEq(resUint256, 1); - - // Arrange - RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - address[] memory RuleConditionalTransferTab = new address[](2); - RuleConditionalTransferTab[0] = address( - IRuleOperation(RuleConditionalTransfer1) - ); - RuleConditionalTransferTab[1] = address( - IRuleOperation(RuleConditionalTransfer2) - ); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall( - ruleEngineMock.setRulesOperation, - RuleConditionalTransferTab - ) - ); - - // Arrange - Assert - assertEq(resCallBool, true); - - // Act - resUint256 = ruleEngineMock.rulesCountOperation(); - - // Assert - assertEq(resUint256, 2); - } - - function testGetRule() public { - // Arrange - RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - address[] memory RuleConditionalTransferTab = new address[](2); - RuleConditionalTransferTab[0] = address( - IRuleOperation(RuleConditionalTransfer1) - ); - RuleConditionalTransferTab[1] = address( - IRuleOperation(RuleConditionalTransfer2) - ); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall( - ruleEngineMock.setRulesOperation, - RuleConditionalTransferTab - ) - ); - // Arrange - Assert - assertEq(resCallBool, true); - - // Act - address rule = ruleEngineMock.ruleOperation(0); - - // Assert - assertEq(address(rule), address(RuleConditionalTransfer1)); - } - - function testGetRules() public { - // Arrange - RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - address[] memory RuleConditionalTransferTab = new address[](2); - RuleConditionalTransferTab[0] = address( - IRuleOperation(RuleConditionalTransfer1) - ); - RuleConditionalTransferTab[1] = address( - IRuleOperation(RuleConditionalTransfer2) - ); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall( - ruleEngineMock.setRulesOperation, - RuleConditionalTransferTab - ) - ); - // Arrange - Assert - assertEq(resCallBool, true); - - // Act - address[] memory rules = ruleEngineMock.rulesOperation(); - - // Assert - assertEq(RuleConditionalTransferTab.length, rules.length); - for (uint256 i = 0; i < rules.length; ++i) { - assertEq(address(RuleConditionalTransferTab[i]), address(rules[i])); - } - } - - function testCanGetRuleIndex() public { - // Arrange - RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - address[] memory RuleConditionalTransferTab = new address[](2); - RuleConditionalTransferTab[0] = address( - IRuleOperation(RuleConditionalTransfer1) - ); - RuleConditionalTransferTab[1] = address( - IRuleOperation(RuleConditionalTransfer2) - ); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall( - ruleEngineMock.setRulesOperation, - RuleConditionalTransferTab - ) - ); - // Arrange - Assert - assertEq(resCallBool, true); - - // Act - uint256 index1 = ruleEngineMock.getRuleIndexOperation( - RuleConditionalTransfer1 - ); - uint256 index2 = ruleEngineMock.getRuleIndexOperation( - RuleConditionalTransfer2 - ); - // Length of the list because RuleConditionalTransfer is not in the list - uint256 index3 = ruleEngineMock.getRuleIndexOperation( - ruleConditionalTransfer - ); - - // Assert - assertEq(index1, 0); - assertEq(index2, 1); - assertEq(index3, RuleConditionalTransferTab.length); - } -} diff --git a/test/RuleEngine/ruleEngineValidation/RuleEngineRestriction.t.sol b/test/RuleEngine/ruleEngineValidation/RuleEngineRestriction.sol similarity index 66% rename from test/RuleEngine/ruleEngineValidation/RuleEngineRestriction.t.sol rename to test/RuleEngine/ruleEngineValidation/RuleEngineRestriction.sol index 02a55dd..4904813 100644 --- a/test/RuleEngine/ruleEngineValidation/RuleEngineRestriction.t.sol +++ b/test/RuleEngine/ruleEngineValidation/RuleEngineRestriction.sol @@ -3,10 +3,10 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../../HelperContract.sol"; -import "src/RuleEngine.sol"; import "OZ/token/ERC20/IERC20.sol"; + /** - * @title tests concerning the restrictions and validation for the transfers + * @title tests concerning the restrictions and for the transfers */ contract RuleEngineRestrictionTest is Test, HelperContract { RuleWhitelist ruleWhitelist1; @@ -24,9 +24,9 @@ contract RuleEngineRestrictionTest is Test, HelperContract { ZERO_ADDRESS ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelist); + ruleEngineMock.addRule(ruleWhitelist); // Arrange - Assert - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); // Arrange @@ -34,11 +34,11 @@ contract RuleEngineRestrictionTest is Test, HelperContract { WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS ); - address[] memory ruleWhitelistTab = new address[](1); - ruleWhitelistTab[0] = address(ruleWhitelist1); + IRule[] memory ruleWhitelistTab = new IRule[](1); + ruleWhitelistTab[0] = ruleWhitelist1; vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); (bool success, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) + abi.encodeCall(ruleEngineMock.setRules, ruleWhitelistTab) ); // Arrange - Assert @@ -62,10 +62,10 @@ contract RuleEngineRestrictionTest is Test, HelperContract { // Assert assertEq(resUint8, 0); - // ruleEngineValidation + // ruleEngine // Act - resUint8 = ruleEngineMock.detectTransferRestrictionValidation( + resUint8 = ruleEngineMock.detectTransferRestriction( ADDRESS1, ADDRESS2, 20 @@ -75,7 +75,35 @@ contract RuleEngineRestrictionTest is Test, HelperContract { assertEq(resUint8, 0); } + function testCanDetectTransferRestrictionWithSpender() public { + // Act + resUint8 = ruleEngineMock.detectTransferRestrictionFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20 + ); + + // Assert + assertEq(resUint8, CODE_ADDRESS_SPENDER_NOT_WHITELISTED); + + // ruleEngine + + // Act + resBool = ruleEngineMock.canTransferFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20 + ); + // Assert + assertFalse(resBool); + } + function testCanDetectTransferRestrictionWithFrom() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist1.addAddressToTheList(ADDRESS3); // Act resUint8 = ruleEngineMock.detectTransferRestriction( ADDRESS1, @@ -86,10 +114,21 @@ contract RuleEngineRestrictionTest is Test, HelperContract { // Assert assertEq(resUint8, CODE_ADDRESS_FROM_NOT_WHITELISTED); - // ruleEngineValidation + // Act + resUint8 = ruleEngineMock.detectTransferRestrictionFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20 + ); + + // Assert + assertEq(resUint8, CODE_ADDRESS_FROM_NOT_WHITELISTED); + + // ruleEngine // Act - resUint8 = ruleEngineMock.detectTransferRestrictionValidation( + resUint8 = ruleEngineMock.detectTransferRestriction( ADDRESS1, ADDRESS2, 20 @@ -97,6 +136,20 @@ contract RuleEngineRestrictionTest is Test, HelperContract { // Assert assertEq(resUint8, CODE_ADDRESS_FROM_NOT_WHITELISTED); + + // Act + resBool = ruleEngineMock.canTransferFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20 + ); + // Assert + assertFalse(resBool); + + resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); + // Assert + assertFalse(resBool); } function testCanDetectTransferRestrictionWithTo() public { @@ -114,10 +167,10 @@ contract RuleEngineRestrictionTest is Test, HelperContract { // Assert assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED); - // ruleEngineValidation + // ruleEngine // Act - resUint8 = ruleEngineMock.detectTransferRestrictionValidation( + resUint8 = ruleEngineMock.detectTransferRestriction( ADDRESS1, ADDRESS2, 20 @@ -125,6 +178,20 @@ contract RuleEngineRestrictionTest is Test, HelperContract { // Assert assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED); + + // Assert + resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); + // Assert + assertFalse(resBool); + + resBool = ruleEngineMock.canTransferFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20 + ); + // Assert + assertFalse(resBool); } function testMessageForTransferRestrictionWithValidRC() public { @@ -140,7 +207,7 @@ contract RuleEngineRestrictionTest is Test, HelperContract { function testMessageForTransferRestrictionNoRule() public { // Arrange vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.clearRulesValidation(); + ruleEngineMock.clearRules(); // Act resString = ruleEngineMock.messageForTransferRestriction(50); @@ -172,14 +239,10 @@ contract RuleEngineRestrictionTest is Test, HelperContract { // Assert assertEq(resBool, true); - // ruleEngineValidation + // ruleEngine // Act - resBool = ruleEngineMock.canTransferValidation( - ADDRESS1, - ADDRESS2, - 20 - ); + resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); // Assert assertEq(resBool, true); @@ -192,14 +255,10 @@ contract RuleEngineRestrictionTest is Test, HelperContract { // Assert assertFalse(resBool); - // ruleEngineValidation + // ruleEngine // Act - resBool = ruleEngineMock.canTransferValidation( - ADDRESS1, - ADDRESS2, - 20 - ); + resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); // Assert assertFalse(resBool); diff --git a/test/RuleEngine/ruleEngineValidation/RuleEngineValidation.t.sol b/test/RuleEngine/ruleEngineValidation/RuleEngineValidation.sol similarity index 56% rename from test/RuleEngine/ruleEngineValidation/RuleEngineValidation.t.sol rename to test/RuleEngine/ruleEngineValidation/RuleEngineValidation.sol index a84cffc..5b1b22c 100644 --- a/test/RuleEngine/ruleEngineValidation/RuleEngineValidation.t.sol +++ b/test/RuleEngine/ruleEngineValidation/RuleEngineValidation.sol @@ -3,12 +3,13 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../../HelperContract.sol"; -import "src/RuleEngine.sol"; /** * @title General functions of the RuleEngine */ -contract RuleEngineValidationTest is Test, HelperContract { +contract RuleEngineTest is Test, HelperContract { + IRule[] ruleWhitelistTab = new IRule[](2); + // Arrange function setUp() public { ruleWhitelist = new RuleWhitelist( @@ -23,13 +24,13 @@ contract RuleEngineValidationTest is Test, HelperContract { ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelist); + ruleEngineMock.addRule(ruleWhitelist); // Arrange - Assert - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } - function testCanSetRulesValidation() public { + function testCanSetRules() public { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleWhitelist ruleWhitelist1 = new RuleWhitelist( @@ -41,22 +42,18 @@ contract RuleEngineValidationTest is Test, HelperContract { WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS ); - address[] memory ruleWhitelistTab = new address[](2); - ruleWhitelistTab[0] = address(IRuleValidation(ruleWhitelist1)); - ruleWhitelistTab[1] = address(IRuleValidation(ruleWhitelist2)); + ruleWhitelistTab[0] = IRule(ruleWhitelist1); + ruleWhitelistTab[1] = IRule(ruleWhitelist2); // Act vm.expectEmit(true, false, false, false); - emit AddRule(address(ruleWhitelist1)); + emit RulesManagementModuleInvariantStorage.AddRule(ruleWhitelist1); vm.expectEmit(true, false, false, false); - emit AddRule(address(ruleWhitelist2)); + emit RulesManagementModuleInvariantStorage.AddRule(ruleWhitelist2); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) - ); + ruleEngineMock.setRules(ruleWhitelistTab); // Assert - assertEq(resCallBool, true); - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 2); } @@ -67,23 +64,17 @@ contract RuleEngineValidationTest is Test, HelperContract { WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS ); - address[] memory ruleWhitelistTab = new address[](2); - ruleWhitelistTab[0] = address(ruleWhitelist1); - ruleWhitelistTab[1] = address(ruleWhitelist1); + ruleWhitelistTab[0] = ruleWhitelist1; + ruleWhitelistTab[1] = ruleWhitelist1; // Act - vm.expectRevert(RuleEngine_RuleAlreadyExists.selector); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) + vm.expectRevert( + RuleEngine_RulesManagementModule_RuleAlreadyExists.selector ); + vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); + ruleEngineMock.setRules(ruleWhitelistTab); // Assert - // I do not know why but the function call return true - // Probably due to the vm.expectRevert - // if the call is reverted with the message indicated in expectRevert - // assertFalse(resCallBool); - assertEq(resCallBool, true); - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } @@ -94,71 +85,88 @@ contract RuleEngineValidationTest is Test, HelperContract { WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS ); - address[] memory ruleWhitelistTab = new address[](1); - ruleWhitelistTab[0] = address(ruleWhitelist1); + ruleWhitelistTab = new IRule[](1); + ruleWhitelistTab[0] = ruleWhitelist1; // Arrange vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) - ); + ruleEngineMock.setRules(ruleWhitelistTab); // Act vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); (resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) + abi.encodeCall(ruleEngineMock.setRules, ruleWhitelistTab) ); // Assert assertEq(resCallBool, true); - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } function testCannotSetEmptyRulesT1() public { // Arrange - address[] memory ruleWhitelistTab = new address[](0); + ruleWhitelistTab = new IRule[](0); // Act vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) + vm.expectRevert( + RulesManagementModuleInvariantStorage + .RuleEngine_RulesManagementModule_ArrayIsEmpty + .selector ); + ruleEngineMock.setRules(ruleWhitelistTab); // Assert - assertFalse(resCallBool); - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); // Assert2 // false because the ruleWhitelist is still present resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); + + resBool = ruleEngineMock.canTransferFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20 + ); + // Assert assertFalse(resBool); } function testCannotSetEmptyRulesT2() public { // Arrange - address[] memory ruleWhitelistTab = new address[](2); - + ruleWhitelistTab = new IRule[](0); // Act vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - vm.expectRevert("The array is empty2"); - - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) + vm.expectRevert( + RulesManagementModuleInvariantStorage + .RuleEngine_RulesManagementModule_ArrayIsEmpty + .selector ); + ruleEngineMock.setRules(ruleWhitelistTab); + resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); // Assert1 - assertFalse(resCallBool); - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); // Assert2 // false because the ruleWhitelist is still present resBool = ruleEngineMock.canTransfer(ADDRESS1, ADDRESS2, 20); assertFalse(resBool); + + resBool = ruleEngineMock.canTransferFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20 + ); + // Assert + assertFalse(resBool); } function testCanClearRules() public { @@ -173,26 +181,24 @@ contract RuleEngineValidationTest is Test, HelperContract { WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS ); - address[] memory ruleWhitelistTab = new address[](2); - ruleWhitelistTab[0] = address(IRuleValidation(ruleWhitelist1)); - ruleWhitelistTab[1] = address(IRuleValidation(ruleWhitelist2)); + ruleWhitelistTab[0] = IRule(ruleWhitelist1); + ruleWhitelistTab[1] = IRule(ruleWhitelist2); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) - ); - ruleEngineMock.rulesValidation(); + ruleEngineMock.setRules(ruleWhitelistTab); + ruleEngineMock.rules(); // Assert - Arrange - assertEq(resCallBool, true); - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 2); // Act + vm.expectEmit(true, false, false, false); + emit RulesManagementModuleInvariantStorage.ClearRules(); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.clearRulesValidation(); + ruleEngineMock.clearRules(); // Assert - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 0); } @@ -208,42 +214,40 @@ contract RuleEngineValidationTest is Test, HelperContract { WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS ); - address[] memory ruleWhitelistTab = new address[](2); - ruleWhitelistTab[0] = address(IRuleValidation(ruleWhitelist1)); - ruleWhitelistTab[1] = address(IRuleValidation(ruleWhitelist2)); + ruleWhitelistTab[0] = IRule(ruleWhitelist1); + ruleWhitelistTab[1] = IRule(ruleWhitelist2); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) - ); + ruleEngineMock.setRules(ruleWhitelistTab); // Act + vm.expectEmit(true, false, false, false); + emit RulesManagementModuleInvariantStorage.ClearRules(); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.clearRulesValidation(); + ruleEngineMock.clearRules(); // Assert - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 0); // Can set again the previous rules vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) - ); - assertEq(resCallBool, true); + ruleEngineMock.setRules(ruleWhitelistTab); // Arrange before assert // Act + vm.expectEmit(true, false, false, false); + emit RulesManagementModuleInvariantStorage.ClearRules(); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.clearRulesValidation(); - resUint256 = ruleEngineMock.rulesCountValidation(); + ruleEngineMock.clearRules(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 0); // Can add previous rule again vm.expectEmit(true, false, false, false); - emit AddRule(address(ruleWhitelist1)); + emit RulesManagementModuleInvariantStorage.AddRule(ruleWhitelist1); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelist1); + ruleEngineMock.addRule(ruleWhitelist1); } function testCanAddRule() public { @@ -256,55 +260,59 @@ contract RuleEngineValidationTest is Test, HelperContract { // Act vm.expectEmit(true, false, false, false); - emit AddRule(address(ruleWhitelist1)); + emit RulesManagementModuleInvariantStorage.AddRule(ruleWhitelist1); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelist1); + ruleEngineMock.addRule(ruleWhitelist1); // Assert - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 2); } function testCannotAddRuleZeroAddress() public { // Act - vm.expectRevert(RuleEngine_RuleAddressZeroNotAllowed.selector); + vm.expectRevert( + RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed.selector + ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleValidation(IRuleValidation(address(0x0))); + ruleEngineMock.addRule(IRule(address(0x0))); // Assert - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } function testCannotAddARuleAlreadyPresent() public { // Act - vm.expectRevert(RuleEngine_RuleAlreadyExists.selector); + vm.expectRevert( + RuleEngine_RulesManagementModule_RuleAlreadyExists.selector + ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelist); + ruleEngineMock.addRule(ruleWhitelist); // Assert - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } function testCanAddARuleAfterThisRuleWasRemoved() public { // Arrange - Assert - address[] memory _rules = ruleEngineMock.rulesValidation(); + address[] memory _rules = ruleEngineMock.rules(); assertEq(address(_rules[0]), address(ruleWhitelist)); // Arrange vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.removeRuleValidation(ruleWhitelist, 0); + ruleEngineMock.removeRule(ruleWhitelist); // Act vm.expectEmit(true, false, false, false); - emit AddRule(address(ruleWhitelist)); + emit RulesManagementModuleInvariantStorage.AddRule(ruleWhitelist); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelist); + ruleEngineMock.addRule(ruleWhitelist); // Assert - _rules = ruleEngineMock.rulesValidation(); - resUint256 = ruleEngineMock.rulesCountValidation(); + _rules = ruleEngineMock.rules(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } @@ -317,12 +325,14 @@ contract RuleEngineValidationTest is Test, HelperContract { ); // Act - vm.expectRevert(RuleEngine_RuleDoNotMatch.selector); + vm.expectRevert( + RuleEngine_RulesManagementModule_RuleDoNotMatch.selector + ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.removeRuleValidation(ruleWhitelist1, 0); + ruleEngineMock.removeRule(ruleWhitelist1); // Assert - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } @@ -334,16 +344,16 @@ contract RuleEngineValidationTest is Test, HelperContract { ZERO_ADDRESS ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelist1); + ruleEngineMock.addRule(ruleWhitelist1); // Act vm.expectEmit(true, false, false, false); - emit RemoveRule(address(ruleWhitelist1)); + emit RulesManagementModuleInvariantStorage.RemoveRule(ruleWhitelist1); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.removeRuleValidation(ruleWhitelist1, 1); + ruleEngineMock.removeRule(ruleWhitelist1); // Assert - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } @@ -355,20 +365,20 @@ contract RuleEngineValidationTest is Test, HelperContract { ZERO_ADDRESS ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelist1); + ruleEngineMock.addRule(ruleWhitelist1); // Act vm.expectEmit(true, false, false, false); - emit RemoveRule(address(ruleWhitelist)); + emit RulesManagementModuleInvariantStorage.RemoveRule(ruleWhitelist); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.removeRuleValidation(ruleWhitelist, 0); + ruleEngineMock.removeRule(ruleWhitelist); // Assert - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 1); } - function testCanRemoveRuleValidation() public { + function testCanRemoveRule() public { // Arrange // First rule vm.prank(WHITELIST_OPERATOR_ADDRESS); @@ -377,7 +387,7 @@ contract RuleEngineValidationTest is Test, HelperContract { ZERO_ADDRESS ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelist1); + ruleEngineMock.addRule(ruleWhitelist1); // Second rule vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleWhitelist ruleWhitelist2 = new RuleWhitelist( @@ -385,27 +395,27 @@ contract RuleEngineValidationTest is Test, HelperContract { ZERO_ADDRESS ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelist2); + ruleEngineMock.addRule(ruleWhitelist2); // Act vm.expectEmit(true, false, false, false); - emit RemoveRule(address(ruleWhitelist1)); + emit RulesManagementModuleInvariantStorage.RemoveRule(ruleWhitelist1); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.removeRuleValidation(ruleWhitelist1, 1); + ruleEngineMock.removeRule(ruleWhitelist1); // Assert - address[] memory _rules = ruleEngineMock.rulesValidation(); + address[] memory _rules = ruleEngineMock.rules(); // ruleWhitelist1 has been removed assertEq(address(_rules[0]), address(ruleWhitelist)); assertEq(address(_rules[1]), address(ruleWhitelist2)); - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); assertEq(resUint256, 2); } function testRuleLength() public { // Act - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); // Assert assertEq(resUint256, 1); @@ -419,19 +429,13 @@ contract RuleEngineValidationTest is Test, HelperContract { WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS ); - address[] memory ruleWhitelistTab = new address[](2); - ruleWhitelistTab[0] = address(IRuleValidation(ruleWhitelist1)); - ruleWhitelistTab[1] = address(IRuleValidation(ruleWhitelist2)); + ruleWhitelistTab[0] = IRule(ruleWhitelist1); + ruleWhitelistTab[1] = IRule(ruleWhitelist2); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) - ); - - // Arrange - Assert - assertEq(resCallBool, true); + ruleEngineMock.setRules(ruleWhitelistTab); // Act - resUint256 = ruleEngineMock.rulesCountValidation(); + resUint256 = ruleEngineMock.rulesCount(); // Assert assertEq(resUint256, 2); @@ -447,18 +451,13 @@ contract RuleEngineValidationTest is Test, HelperContract { WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS ); - address[] memory ruleWhitelistTab = new address[](2); - ruleWhitelistTab[0] = address(IRuleValidation(ruleWhitelist1)); - ruleWhitelistTab[1] = address(IRuleValidation(ruleWhitelist2)); + ruleWhitelistTab[0] = IRule(ruleWhitelist1); + ruleWhitelistTab[1] = IRule(ruleWhitelist2); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) - ); - // Arrange - Assert - assertEq(resCallBool, true); + ruleEngineMock.setRules(ruleWhitelistTab); // Act - address rule = ruleEngineMock.ruleValidation(0); + address rule = ruleEngineMock.rule(0); // Assert assertEq(address(rule), address(ruleWhitelist1)); @@ -474,18 +473,13 @@ contract RuleEngineValidationTest is Test, HelperContract { WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS ); - address[] memory ruleWhitelistTab = new address[](2); - ruleWhitelistTab[0] = address(IRuleValidation(ruleWhitelist1)); - ruleWhitelistTab[1] = address(IRuleValidation(ruleWhitelist2)); + ruleWhitelistTab[0] = IRule(ruleWhitelist1); + ruleWhitelistTab[1] = IRule(ruleWhitelist2); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) - ); - // Arrange - Assert - assertEq(resCallBool, true); + ruleEngineMock.setRules(ruleWhitelistTab); // Act - address[] memory rules = ruleEngineMock.rulesValidation(); + address[] memory rules = ruleEngineMock.rules(); // Assert assertEq(ruleWhitelistTab.length, rules.length); @@ -504,26 +498,21 @@ contract RuleEngineValidationTest is Test, HelperContract { WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS ); - address[] memory ruleWhitelistTab = new address[](2); - ruleWhitelistTab[0] = address(IRuleValidation(ruleWhitelist1)); - ruleWhitelistTab[1] = address(IRuleValidation(ruleWhitelist2)); + ruleWhitelistTab[0] = IRule(ruleWhitelist1); + ruleWhitelistTab[1] = IRule(ruleWhitelist2); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) - ); - // Arrange - Assert - assertEq(resCallBool, true); + ruleEngineMock.setRules(ruleWhitelistTab); // Act - uint256 index1 = ruleEngineMock.getRuleIndexValidation(ruleWhitelist1); - uint256 index2 = ruleEngineMock.getRuleIndexValidation(ruleWhitelist2); + /* uint256 index1 = ruleEngineMock.getRuleIndex(ruleWhitelist1); + uint256 index2 = ruleEngineMock.getRuleIndex(ruleWhitelist2); // Length of the list because ruleWhitelist is not in the list - uint256 index3 = ruleEngineMock.getRuleIndexValidation(ruleWhitelist); + uint256 index3 = ruleEngineMock.getRuleIndex(ruleWhitelist); // Assert assertEq(index1, 0); assertEq(index2, 1); - assertEq(index3, ruleWhitelistTab.length); + assertEq(index3, ruleWhitelistTab.length);*/ } function testMessageForTransferRestrictionWithUnknownRestrictionCodeAndNoRuless() @@ -531,7 +520,7 @@ contract RuleEngineValidationTest is Test, HelperContract { { // Arrange vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.clearRulesValidation(); + ruleEngineMock.clearRules(); // Act resString = ruleEngineMock.messageForTransferRestriction(50); diff --git a/test/RuleSanctionList/RuleSanctionListAddTest.t.sol b/test/RuleSanctionList/RuleSanctionListAddTest.t.sol deleted file mode 100644 index 2a92081..0000000 --- a/test/RuleSanctionList/RuleSanctionListAddTest.t.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../HelperContract.sol"; -import "src/RuleEngine.sol"; -import "../utils/SanctionListOracle.sol"; -import {RuleSanctionList, SanctionsList} from "src/rules/validation/RuleSanctionList.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; - - // 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 - ); - } - - function testCanSetandRemoveOracle() public { - // ADD - vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - emit SetSanctionListOracle(address(sanctionlistOracle)); - ruleSanctionList.setSanctionListOracle(address(sanctionlistOracle)); - - SanctionsList sanctionListOracleGet = ruleSanctionList.sanctionsList(); - // Assert - vm.assertEq( - address(sanctionListOracleGet), - address(sanctionlistOracle) - ); - // Remove - vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - emit SetSanctionListOracle(ZERO_ADDRESS); - ruleSanctionList.setSanctionListOracle(ZERO_ADDRESS); - // Assert - sanctionListOracleGet = ruleSanctionList.sanctionsList(); - vm.assertEq(address(sanctionListOracleGet), address(ZERO_ADDRESS)); - } - - function testCannotAttackerSetOracle() public { - vm.prank(ATTACKER); - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - SANCTIONLIST_ROLE - ) - ); - ruleSanctionList.setSanctionListOracle(address(sanctionlistOracle)); - } -} diff --git a/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol b/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol deleted file mode 100644 index ee2e75f..0000000 --- a/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -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"; -/** - * @title General functions of the ruleSanctionList - */ -contract RuleSanctionListDeploymentTest is Test, HelperContract { - RuleSanctionList ruleSanctionList; - SanctionListOracle sanctionlistOracle; - event Testa(); - - // Arrange - function setUp() public {} - - function testRightDeployment() public { - // Arrange - vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - MinimalForwarderMock forwarder = new MinimalForwarderMock(); - forwarder.initialize(ERC2771ForwarderDomain); - vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - ruleSanctionList = new RuleSanctionList( - SANCTIONLIST_OPERATOR_ADDRESS, - address(forwarder), - ZERO_ADDRESS - ); - - // assert - resBool = ruleSanctionList.hasRole( - SANCTIONLIST_ROLE, - SANCTIONLIST_OPERATOR_ADDRESS - ); - assertEq(resBool, true); - resBool = ruleSanctionList.isTrustedForwarder(address(forwarder)); - assertEq(resBool, true); - } - - function testCannotDeployContractIfAdminAddressIsZero() public { - // Arrange - vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - MinimalForwarderMock forwarder = new MinimalForwarderMock(); - forwarder.initialize(ERC2771ForwarderDomain); - vm.expectRevert( - RuleSanctionList_AdminWithAddressZeroNotAllowed.selector - ); - vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - ruleSanctionList = new RuleSanctionList( - address(0), - address(forwarder), - 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)); - - ruleSanctionList = new RuleSanctionList( - SANCTIONLIST_OPERATOR_ADDRESS, - ZERO_ADDRESS, - address(sanctionlistOracle) - ); - assertEq( - address(ruleSanctionList.sanctionsList()), - address(sanctionlistOracle) - ); - } -} diff --git a/test/RuleSanctionList/RuleSanctionListTest.t.sol b/test/RuleSanctionList/RuleSanctionListTest.t.sol deleted file mode 100644 index 7060d40..0000000 --- a/test/RuleSanctionList/RuleSanctionListTest.t.sol +++ /dev/null @@ -1,128 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../HelperContract.sol"; -import "src/RuleEngine.sol"; -import "../utils/SanctionListOracle.sol"; -import {RuleSanctionList, SanctionsList} from "src/rules/validation/RuleSanctionList.sol"; -/** - * @title General functions of the ruleSanctionList - */ -contract RuleSanctionlistTest is Test, HelperContract { - SanctionListOracle sanctionlistOracle; - RuleSanctionList 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 - ); - vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - ruleSanctionList.setSanctionListOracle(address(sanctionlistOracle)); - } - - function testCanReturnTransferRestrictionCode() public { - // Act - resBool = ruleSanctionList.canReturnTransferRestrictionCode( - CODE_ADDRESS_FROM_IS_SANCTIONED - ); - // Assert - assertEq(resBool, true); - // Act - resBool = ruleSanctionList.canReturnTransferRestrictionCode( - CODE_ADDRESS_TO_IS_SANCTIONED - ); - // Assert - assertEq(resBool, true); - // Act - resBool = ruleSanctionList.canReturnTransferRestrictionCode( - CODE_NONEXISTENT - ); - // Assert - assertFalse(resBool); - } - - function testReturnTheRightMessageForAGivenCode() public { - // Assert - 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 - ); - // Assert - assertEq(resString, TEXT_ADDRESS_TO_IS_SANCTIONED); - // Act - resString = ruleSanctionList.messageForTransferRestriction( - CODE_NONEXISTENT - ); - // Assert - assertEq(resString, TEXT_CODE_NOT_FOUND); - } - - function testcanTransfer() public { - // Act - // ADDRESS1 -> ADDRESS2 - resBool = ruleSanctionList.canTransfer(ADDRESS1, ADDRESS2, 20); - assertEq(resBool, true); - // ADDRESS2 -> ADDRESS1 - resBool = ruleSanctionList.canTransfer(ADDRESS2, ADDRESS1, 20); - assertEq(resBool, true); - } - - function testTransferFromDetectedAsInvalid() public { - // Act - resBool = ruleSanctionList.canTransfer(ATTACKER, ADDRESS2, 20); - // Assert - assertFalse(resBool); - } - - function testTransferToDetectedAsInvalid() public { - // Act - resBool = ruleSanctionList.canTransfer(ADDRESS1, ATTACKER, 20); - // Assert - assertFalse(resBool); - } - - function testDetectTransferRestrictionFrom() public { - // Act - resUint8 = ruleSanctionList.detectTransferRestriction( - ATTACKER, - ADDRESS2, - 20 - ); - // Assert - assertEq(resUint8, CODE_ADDRESS_FROM_IS_SANCTIONED); - } - - function testDetectTransferRestrictionTo() public { - // Act - resUint8 = ruleSanctionList.detectTransferRestriction( - ADDRESS1, - ATTACKER, - 20 - ); - // Assert - assertEq(resUint8, CODE_ADDRESS_TO_IS_SANCTIONED); - } - - function testDetectTransferRestrictionOk() public { - // Act - resUint8 = ruleSanctionList.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 20 - ); - // Assert - assertEq(resUint8, NO_ERROR); - } -} diff --git a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol index c87e62b..5e5aff6 100644 --- a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol +++ b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../../HelperContract.sol"; -import "src/RuleEngine.sol"; /** * @title Tests on the Access Control diff --git a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol index 4aacfac..2fb3bbe 100644 --- a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol +++ b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../../HelperContract.sol"; import "../../../lib/openzeppelin-contracts/contracts/access/AccessControl.sol"; -import "src/RuleEngine.sol"; /** * @title Tests on the provided functions by OpenZeppelin diff --git a/test/RuleWhitelist/CMTATIntegration.t.sol b/test/RuleWhitelist/CMTATIntegration.t.sol index 246d9db..40c2281 100644 --- a/test/RuleWhitelist/CMTATIntegration.t.sol +++ b/test/RuleWhitelist/CMTATIntegration.t.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "CMTAT/deployment/CMTATStandalone.sol"; import "../HelperContract.sol"; -import "src/RuleEngine.sol"; /** * @title Integration test with the CMTAT @@ -32,28 +31,40 @@ contract CMTATIntegration is Test, HelperContract { address(CMTAT_CONTRACT) ); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelist); + ruleEngineMock.addRule(ruleWhitelist); + + // Assert + assertEq(ruleEngineMock.containsRule(ruleWhitelist), true); + + // CMTAT 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 + vm.prank(DEFAULT_ADMIN_ADDRESS); CMTAT_CONTRACT.setRuleEngine(ruleEngineMock); } /******* Transfer *******/ function testCannotTransferWithoutAddressWhitelisted() public { + uint8 code = CMTAT_CONTRACT.detectTransferRestriction( + ADDRESS1, + ADDRESS2, + 21 + ); // Arrange vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, + RuleWhitelist.RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, - 21 + 21, + code ) ); // Act @@ -66,13 +77,19 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(DEFAULT_ADMIN_ADDRESS); ruleWhitelist.addAddressToTheList(ADDRESS2); + uint8 code = CMTAT_CONTRACT.detectTransferRestriction( + ADDRESS1, + ADDRESS2, + amount + ); vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, + RuleWhitelist.RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, - amount + amount, + code ) ); // Act @@ -85,19 +102,56 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(DEFAULT_ADMIN_ADDRESS); ruleWhitelist.addAddressToTheList(ADDRESS1); + uint8 code = CMTAT_CONTRACT.detectTransferRestriction( + ADDRESS1, + ADDRESS2, + amount + ); vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, + RuleWhitelist.RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, - amount + amount, + code ) ); // Act CMTAT_CONTRACT.transfer(ADDRESS2, amount); } + function testCannotTransferWithoutSpenderAddressWhitelisted() public { + // Arrange + uint256 amount = 21; + vm.prank(ADDRESS1); + CMTAT_CONTRACT.approve(ADDRESS3, amount); + + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelist.addAddressToTheList(ADDRESS1); + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelist.addAddressToTheList(ADDRESS2); + + uint8 code = CMTAT_CONTRACT.detectTransferRestrictionFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + amount + ); + vm.prank(ADDRESS3); + vm.expectRevert( + abi.encodeWithSelector( + RuleWhitelist.RuleWhitelist_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + amount, + code + ) + ); + // Act + CMTAT_CONTRACT.transferFrom(ADDRESS1, ADDRESS2, amount); + } + function testCanMakeATransfer() public { // Arrange address[] memory whitelist = new address[](2); @@ -168,6 +222,16 @@ contract CMTATIntegration is Test, HelperContract { ); // Assert assertEq(message1, TEXT_ADDRESS_TO_NOT_WHITELISTED); + + // res1 + res1 = ruleEngineMock.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); + // Assert + assertEq(res1, CODE_ADDRESS_TO_NOT_WHITELISTED); + + message1 = ruleEngineMock.messageForTransferRestriction(res1); + + // Assert + assertEq(message1, TEXT_ADDRESS_TO_NOT_WHITELISTED); } function testDetectAndMessageWithFromAndToNotWhitelisted() public view { @@ -187,6 +251,16 @@ contract CMTATIntegration is Test, HelperContract { // Assert assertEq(message1, TEXT_ADDRESS_FROM_NOT_WHITELISTED); + + // RuleEngine + res1 = ruleEngineMock.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); + // Assert + assertEq(res1, CODE_ADDRESS_FROM_NOT_WHITELISTED); + + message1 = ruleEngineMock.messageForTransferRestriction(res1); + + // Assert + assertEq(message1, TEXT_ADDRESS_FROM_NOT_WHITELISTED); } function testDetectAndMessageWithAValidTransfer() public { @@ -219,6 +293,73 @@ contract CMTATIntegration is Test, HelperContract { assertEq(message1, TEXT_TRANSFER_OK); } + function testDetectAndMessageWithInvalidTransferFrom() public { + // Arrange + // We add the sender and the recipient to the whitelist. + address[] memory whitelist = new address[](2); + whitelist[0] = ADDRESS1; + whitelist[1] = ADDRESS2; + vm.prank(DEFAULT_ADMIN_ADDRESS); + (bool success, ) = address(ruleWhitelist).call( + abi.encodeWithSignature( + "addAddressesToTheList(address[])", + whitelist + ) + ); + require(success); + // Act + uint8 res1 = CMTAT_CONTRACT.detectTransferRestrictionFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 11 + ); + // Assert + assertEq(res1, CODE_ADDRESS_SPENDER_NOT_WHITELISTED); + + res1 = ruleEngineMock.detectTransferRestrictionFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 11 + ); + // Assert + assertEq(res1, CODE_ADDRESS_SPENDER_NOT_WHITELISTED); + + resBool = CMTAT_CONTRACT.canTransferFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 11 + ); + // Assert + assertFalse(resBool); + + resBool = ruleEngineMock.canTransferFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 11 + ); + // Assert + assertFalse(resBool); + + resBool = ruleEngineMock.canTransferFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 11 + ); + // Assert + assertFalse(resBool); + // Act + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( + res1 + ); + // Assert + assertEq(message1, TEXT_ADDRESS_SPENDER_NOT_WHITELISTED); + } + function testCanMint() public { // Arrange // Add address zero to the whitelist diff --git a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol deleted file mode 100644 index 5786da9..0000000 --- a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol +++ /dev/null @@ -1,322 +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 "src/RuleEngine.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(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 - ); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelistWrapper.addRuleValidation(ruleWhitelist); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelistWrapper.addRuleValidation(ruleWhitelist2); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelistWrapper.addRuleValidation(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) - ); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelistWrapper); - 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); - } - - /******* Deployment *******/ - - function testCannotDeployContractIfAdminAddressIsZero() public { - vm.prank(WHITELIST_OPERATOR_ADDRESS); - vm.expectRevert(RuleEngine_AdminWithAddressZeroNotAllowed.selector); - ruleWhitelistWrapper = new RuleWhitelistWrapper( - ZERO_ADDRESS, - ZERO_ADDRESS - ); - } - - /******* Transfer *******/ - function testCannotTransferWithoutAddressWhitelisted() public { - // Arrange - vm.prank(ADDRESS1); - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - 21 - ) - ); - // Act - CMTAT_CONTRACT.transfer(ADDRESS2, 21); - } - - function testCannotTransferWithoutFromAddressWhitelisted() public { - // Arrange - uint256 amount = 21; - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS2); - - vm.prank(ADDRESS1); - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - amount - ) - ); - // Act - CMTAT_CONTRACT.transfer(ADDRESS2, amount); - } - - function testCannotTransferWithoutToAddressWhitelisted() public { - // Arrange - uint256 amount = 21; - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); - - vm.prank(ADDRESS1); - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - amount - ) - ); - // Act - CMTAT_CONTRACT.transfer(ADDRESS2, amount); - } - - function testCanMakeATransferIfWhitelistedInSeveralDifferentList() public { - // Arrange - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist3.addAddressToTheList(ADDRESS1); - - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist2.addAddressToTheList(ADDRESS2); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist3.addAddressToTheList(ADDRESS2); - - // Act - vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2, 11); - - // Assert - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); - assertEq(resUint256, 20); - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS2); - assertEq(resUint256, 43); - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS3); - assertEq(resUint256, 33); - } - - function testCanMakeATransferIfWhitelistedInDifferentList() public { - // Arrange - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); - - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist2.addAddressToTheList(ADDRESS2); - - // Act - vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2, 11); - - // Assert - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); - assertEq(resUint256, 20); - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS2); - assertEq(resUint256, 43); - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS3); - assertEq(resUint256, 33); - } - - function testCanMakeATransfer() public { - // Arrange - address[] memory whitelist = new address[](2); - whitelist[0] = ADDRESS1; - whitelist[1] = ADDRESS2; - vm.prank(DEFAULT_ADMIN_ADDRESS); - (bool success, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "addAddressesToTheList(address[])", - whitelist - ) - ); - require(success); - - // Act - vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2, 11); - - // Assert - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); - assertEq(resUint256, 20); - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS2); - assertEq(resUint256, 43); - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS3); - assertEq(resUint256, 33); - } - - /******* detectTransferRestriction & messageForTransferRestriction *******/ - function testDetectAndMessageWithFromNotWhitelisted() public { - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS2); - resBool = ruleWhitelist.addressIsListed(ADDRESS2); - // Assert - assertEq(resBool, true); - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); - // Assert - assertEq(res1, CODE_ADDRESS_FROM_NOT_WHITELISTED); - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); - // Assert - assertEq(message1, TEXT_ADDRESS_FROM_NOT_WHITELISTED); - } - - function testDetectAndMessageWithToNotWhitelisted() public { - // Arrange - // We add the sender to the whitelist - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); - // Arrange - Assert - resBool = ruleWhitelist.addressIsListed(ADDRESS1); - assertEq(resBool, true); - // Act - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); - // Assert - assertEq(res1, CODE_ADDRESS_TO_NOT_WHITELISTED); - // Act - 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 - ); - - // Assert - assertEq(res1, CODE_ADDRESS_FROM_NOT_WHITELISTED); - // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); - - // Assert - assertEq(message1, TEXT_ADDRESS_FROM_NOT_WHITELISTED); - } - - function testCanReturnUnknownTextMessage() public view { - // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - 200 - ); - - // Assert - assertEq(message1, TEXT_CODE_NOT_FOUND); - } - - function testDetectAndMessageWithAValidTransfer() public { - // Arrange - // We add the sender and the recipient to the whitelist. - address[] memory whitelist = new address[](2); - whitelist[0] = ADDRESS1; - whitelist[1] = ADDRESS2; - vm.prank(DEFAULT_ADMIN_ADDRESS); - (bool success, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "addAddressesToTheList(address[])", - whitelist - ) - ); - require(success); - // Act - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); - // Assert - assertEq(res1, TRANSFER_OK); - // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); - // Assert - assertEq(message1, TEXT_TRANSFER_OK); - } - - function testCanMint() public { - // Arrange - // Add address zero to the whitelist - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ZERO_ADDRESS); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); - // Arrange - Assert - resBool = ruleWhitelist.addressIsListed(ZERO_ADDRESS); - assertEq(resBool, true); - - // Act - vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.mint(ADDRESS1, 11); - - // Assert - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); - assertEq(resUint256, ADDRESS1_BALANCE_INIT + 11); - } -} diff --git a/test/RuleWhitelist/RuleWhitelist.t.sol b/test/RuleWhitelist/RuleWhitelist.t.sol index 76af66b..df517a6 100644 --- a/test/RuleWhitelist/RuleWhitelist.t.sol +++ b/test/RuleWhitelist/RuleWhitelist.t.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; -import "src/RuleEngine.sol"; /** * @title General functions of the RuleWhitelist @@ -131,7 +130,7 @@ contract RuleWhitelistTest is Test, HelperContract { assertEq(resString, TEXT_CODE_NOT_FOUND); } - function testcanTransfer() public { + function testCanTransfer() public { // Arrange _addAddressesToTheList(); // Act @@ -141,6 +140,26 @@ contract RuleWhitelistTest is Test, HelperContract { // ADDRESS2 -> ADDRESS1 resBool = ruleWhitelist.canTransfer(ADDRESS2, ADDRESS1, 20); assertEq(resBool, true); + + // Spender is not whitelisted + resBool = ruleWhitelist.canTransferFrom( + ADDRESS3, + ADDRESS2, + ADDRESS1, + 20 + ); + assertEq(resBool, false); + + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddressToTheList(ADDRESS3); + + resBool = ruleWhitelist.canTransferFrom( + ADDRESS3, + ADDRESS2, + ADDRESS1, + 20 + ); + assertEq(resBool, true); } function testTransferDetectedAsInvalid() public { @@ -199,6 +218,18 @@ contract RuleWhitelistTest is Test, HelperContract { assertEq(resUint8, CODE_ADDRESS_FROM_NOT_WHITELISTED); } + function testDetectTransferRestrictionSpender() public { + // Act + resUint8 = ruleWhitelist.detectTransferRestrictionFrom( + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20 + ); + // Assert + assertEq(resUint8, CODE_ADDRESS_SPENDER_NOT_WHITELISTED); + } + function testDetectTransferRestrictionTo() public { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); diff --git a/test/RuleWhitelist/RuleWhitelistAdd.t.sol b/test/RuleWhitelist/RuleWhitelistAdd.t.sol index 6cadac7..054af69 100644 --- a/test/RuleWhitelist/RuleWhitelistAdd.t.sol +++ b/test/RuleWhitelist/RuleWhitelistAdd.t.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; -import "src/RuleEngine.sol"; /** * @title Tests the functions to add addresses to the whitelist diff --git a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol index 9f3b11f..ef219a9 100644 --- a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol +++ b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; -import "src/RuleEngine.sol"; import "CMTAT/mocks/MinimalForwarderMock.sol"; /** diff --git a/test/RuleWhitelist/RuleWhitelistRemove.t.sol b/test/RuleWhitelist/RuleWhitelistRemove.t.sol index 0da5d26..f992563 100644 --- a/test/RuleWhitelist/RuleWhitelistRemove.t.sol +++ b/test/RuleWhitelist/RuleWhitelistRemove.t.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; -import "src/RuleEngine.sol"; /** * @title Tests the functions to remove addresses from the whitelist diff --git a/test/utils/CMTATDeployment.sol b/test/utils/CMTATDeployment.sol index 1f7d310..6bf3762 100644 --- a/test/utils/CMTATDeployment.sol +++ b/test/utils/CMTATDeployment.sol @@ -8,6 +8,7 @@ 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); diff --git a/test/utils/SanctionListOracle.sol b/test/utils/SanctionListOracle.sol deleted file mode 100644 index 2edaee7..0000000 --- a/test/utils/SanctionListOracle.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -/** - * @notice Test contract from - * https://etherscan.io/address/0x40c57923924b5c5c5455c48d93317139addac8fb#code - */ -contract SanctionListOracle { - constructor() {} - - mapping(address => bool) private sanctionedAddresses; - - function addToSanctionsList(address newSanction) public { - sanctionedAddresses[newSanction] = true; - } - - function removeFromSanctionsList(address removeSanction) public { - sanctionedAddresses[removeSanction] = true; - } - - function isSanctioned(address addr) public view returns (bool) { - return sanctionedAddresses[addr] == true; - } -}