diff --git a/CHANGELOG.md b/CHANGELOG.md index ed13192..88be8b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ Please follow [https://changelog.md/](https://changelog.md/) conventions. - Add the rule ConditionalTransfer as an Operation rule - Add the rule Blacklist as a Validation rule - Whitelist and blacklist rules share a part of their code. -- Upgrade the library CMTAT to the version [v2.3.1](https://github.com/CMTA/CMTAT/releases/tag/v2.3.1) +- Upgrade the library CMTAT to the version [v2.4.0](https://github.com/CMTA/CMTAT/releases/tag/v2.4.0) - Fix a minor bug when rules are deleted with clearRules ## v1.0.3 - 20231122 diff --git a/README.md b/README.md index f68b522..d0bd2d4 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,10 @@ The following rules are available: | Rule | Type | Description | Doc | | ------------------------------------------------------------ | -------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | -| [RuleWhitelist](src/rules/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) | -| [RuleBlacklist](src/rules/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/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/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) | +| [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) | +| [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) | diff --git a/doc/codelist.md b/doc/codelist.md index 2816c98..2ad6da6 100644 --- a/doc/codelist.md +++ b/doc/codelist.md @@ -4,16 +4,16 @@ 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 | -| RuleVinkulierung | CODE_TRANSFER_REQUEST_NOT_APPROVED | 51 | +| 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 | diff --git a/doc/schema/rule/conditionalTransfer-Storage.drawio.png b/doc/schema/rule/conditionalTransfer-Storage.drawio.png index 3da4cc5..6fa3d10 100644 Binary files a/doc/schema/rule/conditionalTransfer-Storage.drawio.png and b/doc/schema/rule/conditionalTransfer-Storage.drawio.png differ diff --git a/doc/schema/rule/conditionalTransfer-automaticTransfer.drawio.png b/doc/schema/rule/conditionalTransfer-automaticTransfer.drawio.png index 9163396..2a97df8 100644 Binary files a/doc/schema/rule/conditionalTransfer-automaticTransfer.drawio.png and b/doc/schema/rule/conditionalTransfer-automaticTransfer.drawio.png differ diff --git a/doc/schema/rule/conditionalTransfer-state machine.drawio.png b/doc/schema/rule/conditionalTransfer-state machine.drawio.png new file mode 100644 index 0000000..ff4388e Binary files /dev/null and b/doc/schema/rule/conditionalTransfer-state machine.drawio.png differ diff --git a/doc/schema/rule/conditionalTransfer.drawio b/doc/schema/rule/conditionalTransfer.drawio index 04e2b4d..43823b2 100644 --- a/doc/schema/rule/conditionalTransfer.drawio +++ b/doc/schema/rule/conditionalTransfer.drawio @@ -1 +1 @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/doc/schema/rule/conditionalTransferCMTAT.drawio.png b/doc/schema/rule/conditionalTransferCMTAT.drawio.png index 5cf44cf..83cf658 100644 Binary files a/doc/schema/rule/conditionalTransferCMTAT.drawio.png and b/doc/schema/rule/conditionalTransferCMTAT.drawio.png differ diff --git a/doc/schema/rule/virkulierung-Page-4.drawio.png b/doc/schema/rule/conditionalTransferTime.png similarity index 100% rename from doc/schema/rule/virkulierung-Page-4.drawio.png rename to doc/schema/rule/conditionalTransferTime.png diff --git a/doc/surya/surya_graph/surya_graph_RuleConditionalTransfer.sol.png b/doc/surya/surya_graph/surya_graph_RuleConditionalTransfer.sol.png index b04bbad..63ada00 100644 Binary files a/doc/surya/surya_graph/surya_graph_RuleConditionalTransfer.sol.png and b/doc/surya/surya_graph/surya_graph_RuleConditionalTransfer.sol.png differ diff --git a/doc/surya/surya_graph/surya_graph_RuleConditionalTransferOperator.sol.png b/doc/surya/surya_graph/surya_graph_RuleConditionalTransferOperator.sol.png index 3002409..9458b0d 100644 Binary files a/doc/surya/surya_graph/surya_graph_RuleConditionalTransferOperator.sol.png and b/doc/surya/surya_graph/surya_graph_RuleConditionalTransferOperator.sol.png differ diff --git a/doc/surya/surya_report/surya_report_RuleConditionalTransfer.sol.md b/doc/surya/surya_report/surya_report_RuleConditionalTransfer.sol.md index 13ce9d8..a6b5528 100644 --- a/doc/surya/surya_report/surya_report_RuleConditionalTransfer.sol.md +++ b/doc/surya/surya_report/surya_report_RuleConditionalTransfer.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/operation/RuleConditionalTransfer.sol | 474d9ae65276913c7b367dbf47439e3a0558cf7a | +| ./rules/operation/RuleConditionalTransfer.sol | 9e082774ea9e8c645735266d8935f0cea686ef07 | ### Contracts Description Table @@ -18,7 +18,10 @@ | **RuleConditionalTransfer** | Implementation | RuleValidateTransfer, IRuleOperation, RuleConditionalTransferOperator, MetaTxModuleStandalone ||| | └ | | Public ❗️ | 🛑 | MetaTxModuleStandalone | | └ | createTransferRequest | Public ❗️ | 🛑 |NO❗️ | +| └ | createTransferRequestBatch | Public ❗️ | 🛑 |NO❗️ | | └ | cancelTransferRequest | Public ❗️ | 🛑 |NO❗️ | +| └ | cancelTransferRequestBatch | Public ❗️ | 🛑 |NO❗️ | +| └ | _cancelTransferRequest | Internal 🔒 | 🛑 | | | └ | getRequestTrade | Public ❗️ | |NO❗️ | | └ | getRequestByStatus | Public ❗️ | |NO❗️ | | └ | operateOnTransfer | Public ❗️ | 🛑 | onlyRole | diff --git a/doc/surya/surya_report/surya_report_RuleConditionalTransferInvariantStorage.sol.md b/doc/surya/surya_report/surya_report_RuleConditionalTransferInvariantStorage.sol.md index f3ae1f7..3e68d6f 100644 --- a/doc/surya/surya_report/surya_report_RuleConditionalTransferInvariantStorage.sol.md +++ b/doc/surya/surya_report/surya_report_RuleConditionalTransferInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol | 4f6a42a549cb435d490721e8091f34f9ac55fd1c | +| ./rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol | fca0008dbf1e9645944506d01fea4281a5e5208b | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleConditionalTransferOperator.sol.md b/doc/surya/surya_report/surya_report_RuleConditionalTransferOperator.sol.md index 4660310..11d4af0 100644 --- a/doc/surya/surya_report/surya_report_RuleConditionalTransferOperator.sol.md +++ b/doc/surya/surya_report/surya_report_RuleConditionalTransferOperator.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/operation/abstract/RuleConditionalTransferOperator.sol | 76e5a428623395575861a4d45bdc3f5b6f797f7e | +| ./rules/operation/abstract/RuleConditionalTransferOperator.sol | 5e35d28ab99475759783fca1614544e132797487 | ### Contracts Description Table @@ -16,6 +16,7 @@ | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| | **RuleConditionalTransferOperator** | Implementation | AccessControl, RuleConditionalTransferInvariantStorage ||| +| └ | setConditionalWhitelist | Public ❗️ | 🛑 | onlyRole | | └ | setIssuanceOptions | Public ❗️ | 🛑 | onlyRole | | └ | setAutomaticTransfer | Public ❗️ | 🛑 | onlyRole | | └ | setTimeLimit | Public ❗️ | 🛑 | onlyRole | @@ -24,6 +25,12 @@ | └ | approveTransferRequest | Public ❗️ | 🛑 | onlyRole | | └ | approveTransferRequestWithId | Public ❗️ | 🛑 | onlyRole | | └ | resetRequestStatus | Public ❗️ | 🛑 | onlyRole | +| └ | approveTransferRequestBatchWithId | Public ❗️ | 🛑 | onlyRole | +| └ | approveTransferRequestBatch | Public ❗️ | 🛑 | onlyRole | +| └ | createTransferRequestWithApprovalBatch | Public ❗️ | 🛑 | onlyRole | +| └ | resetRequestStatusBatch | Public ❗️ | 🛑 | onlyRole | +| └ | _approveTransferRequestKeyElement | Internal 🔒 | 🛑 | | +| └ | _createTransferRequestWithApproval | Public ❗️ | 🛑 | onlyRole | | └ | _resetRequestStatus | Internal 🔒 | 🛑 | | | └ | _checkRequestStatus | Internal 🔒 | | | | └ | _approveRequest | Internal 🔒 | 🛑 | | diff --git a/doc/surya/surya_report/surya_report_RuleEngine.sol.md b/doc/surya/surya_report/surya_report_RuleEngine.sol.md index b596fbb..d0812d9 100644 --- a/doc/surya/surya_report/surya_report_RuleEngine.sol.md +++ b/doc/surya/surya_report/surya_report_RuleEngine.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./RuleEngine.sol | b1c26380badaa4dd34dd75647bb62db7e30e5e40 | +| ./RuleEngine.sol | 0fc418971885c84c32fab8ba76462a7ae5c77b77 | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleEngineOperation.sol.md b/doc/surya/surya_report/surya_report_RuleEngineOperation.sol.md index 5600732..9823a14 100644 --- a/doc/surya/surya_report/surya_report_RuleEngineOperation.sol.md +++ b/doc/surya/surya_report/surya_report_RuleEngineOperation.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/RuleEngineOperation.sol | d3de41695a73eb2f2cb02dbea88b72174a2a9830 | +| ./modules/RuleEngineOperation.sol | a511cf11774bebce822a8b277f0d33a71d6df492 | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleEngineValidation.sol.md b/doc/surya/surya_report/surya_report_RuleEngineValidation.sol.md index 8c67257..fe3ac20 100644 --- a/doc/surya/surya_report/surya_report_RuleEngineValidation.sol.md +++ b/doc/surya/surya_report/surya_report_RuleEngineValidation.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/RuleEngineValidation.sol | 818bc0f7e4fc858d3aa6efc76811268aa81bd3ee | +| ./modules/RuleEngineValidation.sol | 389f8e6a721d981e7704f67c608138af0b3bed97 | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleWhitelist.sol.md b/doc/surya/surya_report/surya_report_RuleWhitelist.sol.md index 308d7d8..dcae5ae 100644 --- a/doc/surya/surya_report/surya_report_RuleWhitelist.sol.md +++ b/doc/surya/surya_report/surya_report_RuleWhitelist.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/RuleWhitelist.sol | a5c81461282137d1360d7934607e6e40c0727aa4 | +| ./rules/validation/RuleWhitelist.sol | 721bc822979b9948547c0d499ccb831ee6083775 | ### Contracts Description Table diff --git a/doc/technical/RuleConditionalTransfer.md b/doc/technical/RuleConditionalTransfer.md index 438a89b..5695a09 100644 --- a/doc/technical/RuleConditionalTransfer.md +++ b/doc/technical/RuleConditionalTransfer.md @@ -77,7 +77,7 @@ 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 diff --git a/doc/test/coverage/index-sort-b.html b/doc/test/coverage/index-sort-b.html index 557016c..a8ed6d6 100644 --- a/doc/test/coverage/index-sort-b.html +++ b/doc/test/coverage/index-sort-b.html @@ -31,17 +31,17 @@ lcov.info Lines: - 356 - 388 - 91.8 % + 364 + 396 + 91.9 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: - 94 - 102 + 95 + 103 92.2 % @@ -49,9 +49,9 @@ Branches: - 148 - 158 - 93.7 % + 154 + 166 + 92.8 % @@ -120,14 +120,14 @@ src/rules/operation -
98.7%98.7%
+
98.8%98.8%
- 98.7 % - 78 / 79 + 98.8 % + 84 / 85 93.8 % 15 / 16 - 94.1 % - 32 / 34 + 90.5 % + 38 / 42 src/modules @@ -147,9 +147,9 @@
100.0%
100.0 % - 94 / 94 - 94.4 % - 17 / 18 + 96 / 96 + 94.7 % + 18 / 19 98.1 % 53 / 54 diff --git a/doc/test/coverage/index-sort-f.html b/doc/test/coverage/index-sort-f.html index 7f71a63..6d4fae1 100644 --- a/doc/test/coverage/index-sort-f.html +++ b/doc/test/coverage/index-sort-f.html @@ -31,17 +31,17 @@ lcov.info Lines: - 356 - 388 - 91.8 % + 364 + 396 + 91.9 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: - 94 - 102 + 95 + 103 92.2 % @@ -49,9 +49,9 @@ Branches: - 148 - 158 - 93.7 % + 154 + 166 + 92.8 % @@ -144,14 +144,14 @@ src/rules/operation -
98.7%98.7%
+
98.8%98.8%
- 98.7 % - 78 / 79 + 98.8 % + 84 / 85 93.8 % 15 / 16 - 94.1 % - 32 / 34 + 90.5 % + 38 / 42 src/rules/operation/abstract @@ -159,9 +159,9 @@
100.0%
100.0 % - 94 / 94 - 94.4 % - 17 / 18 + 96 / 96 + 94.7 % + 18 / 19 98.1 % 53 / 54 diff --git a/doc/test/coverage/index-sort-l.html b/doc/test/coverage/index-sort-l.html index 2131c05..c955df1 100644 --- a/doc/test/coverage/index-sort-l.html +++ b/doc/test/coverage/index-sort-l.html @@ -31,17 +31,17 @@ lcov.info Lines: - 356 - 388 - 91.8 % + 364 + 396 + 91.9 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: - 94 - 102 + 95 + 103 92.2 % @@ -49,9 +49,9 @@ Branches: - 148 - 158 - 93.7 % + 154 + 166 + 92.8 % @@ -144,14 +144,14 @@ src/rules/operation -
98.7%98.7%
+
98.8%98.8%
- 98.7 % - 78 / 79 + 98.8 % + 84 / 85 93.8 % 15 / 16 - 94.1 % - 32 / 34 + 90.5 % + 38 / 42 src/rules/validation/abstract @@ -183,9 +183,9 @@
100.0%
100.0 % - 94 / 94 - 94.4 % - 17 / 18 + 96 / 96 + 94.7 % + 18 / 19 98.1 % 53 / 54 diff --git a/doc/test/coverage/index.html b/doc/test/coverage/index.html index dc0a8e6..960324e 100644 --- a/doc/test/coverage/index.html +++ b/doc/test/coverage/index.html @@ -31,17 +31,17 @@ lcov.info Lines: - 356 - 388 - 91.8 % + 364 + 396 + 91.9 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: - 94 - 102 + 95 + 103 92.2 % @@ -49,9 +49,9 @@ Branches: - 148 - 158 - 93.7 % + 154 + 166 + 92.8 % @@ -120,14 +120,14 @@ src/rules/operation -
98.7%98.7%
+
98.8%98.8%
- 98.7 % - 78 / 79 + 98.8 % + 84 / 85 93.8 % 15 / 16 - 94.1 % - 32 / 34 + 90.5 % + 38 / 42 src/rules/operation/abstract @@ -135,9 +135,9 @@
100.0%
100.0 % - 94 / 94 - 94.4 % - 17 / 18 + 96 / 96 + 94.7 % + 18 / 19 98.1 % 53 / 54 diff --git a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html index 3a16415..104e111 100644 --- a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html +++ b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 0 diff --git a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html index a3a6835..6955f40 100644 --- a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html +++ b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 0 diff --git a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html index a631bb2..fd8f994 100644 --- a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html +++ b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 0 diff --git a/doc/test/coverage/script/RuleEngineScript.s.sol.func-sort-c.html b/doc/test/coverage/script/RuleEngineScript.s.sol.func-sort-c.html index 4c08eb1..0be87b7 100644 --- a/doc/test/coverage/script/RuleEngineScript.s.sol.func-sort-c.html +++ b/doc/test/coverage/script/RuleEngineScript.s.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 0 diff --git a/doc/test/coverage/script/RuleEngineScript.s.sol.func.html b/doc/test/coverage/script/RuleEngineScript.s.sol.func.html index 4707d3f..f91ca3b 100644 --- a/doc/test/coverage/script/RuleEngineScript.s.sol.func.html +++ b/doc/test/coverage/script/RuleEngineScript.s.sol.func.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 0 diff --git a/doc/test/coverage/script/RuleEngineScript.s.sol.gcov.html b/doc/test/coverage/script/RuleEngineScript.s.sol.gcov.html index 173ba22..4eb457e 100644 --- a/doc/test/coverage/script/RuleEngineScript.s.sol.gcov.html +++ b/doc/test/coverage/script/RuleEngineScript.s.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 0 diff --git a/doc/test/coverage/script/index-sort-b.html b/doc/test/coverage/script/index-sort-b.html index fdf335a..7e3a773 100644 --- a/doc/test/coverage/script/index-sort-b.html +++ b/doc/test/coverage/script/index-sort-b.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 0 diff --git a/doc/test/coverage/script/index-sort-f.html b/doc/test/coverage/script/index-sort-f.html index 34b8963..afd417e 100644 --- a/doc/test/coverage/script/index-sort-f.html +++ b/doc/test/coverage/script/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 0 diff --git a/doc/test/coverage/script/index-sort-l.html b/doc/test/coverage/script/index-sort-l.html index f87bbf7..0366127 100644 --- a/doc/test/coverage/script/index-sort-l.html +++ b/doc/test/coverage/script/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 0 diff --git a/doc/test/coverage/script/index.html b/doc/test/coverage/script/index.html index e4c6479..38a89dc 100644 --- a/doc/test/coverage/script/index.html +++ b/doc/test/coverage/script/index.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 0 diff --git a/doc/test/coverage/src/RuleEngine.sol.func-sort-c.html b/doc/test/coverage/src/RuleEngine.sol.func-sort-c.html index 6d7459d..a8539b5 100644 --- a/doc/test/coverage/src/RuleEngine.sol.func-sort-c.html +++ b/doc/test/coverage/src/RuleEngine.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 6 @@ -86,15 +86,15 @@ RuleEngine.operateOnTransfer - 26 + 45 RuleEngine._contextSuffixLength - 203 + 244 RuleEngine._msgSender - 203 + 244
diff --git a/doc/test/coverage/src/RuleEngine.sol.func.html b/doc/test/coverage/src/RuleEngine.sol.func.html index 770c4e9..2250ee1 100644 --- a/doc/test/coverage/src/RuleEngine.sol.func.html +++ b/doc/test/coverage/src/RuleEngine.sol.func.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 6 @@ -70,7 +70,7 @@ RuleEngine._contextSuffixLength - 203 + 244 RuleEngine._msgData @@ -78,7 +78,7 @@ RuleEngine._msgSender - 203 + 244 RuleEngine.detectTransferRestriction @@ -90,7 +90,7 @@ RuleEngine.operateOnTransfer - 26 + 45 RuleEngine.validateTransfer diff --git a/doc/test/coverage/src/RuleEngine.sol.gcov.html b/doc/test/coverage/src/RuleEngine.sol.gcov.html index 40c448b..a5ae197 100644 --- a/doc/test/coverage/src/RuleEngine.sol.gcov.html +++ b/doc/test/coverage/src/RuleEngine.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 6 @@ -186,11 +186,11 @@ 115 : : */ 116 : : function operateOnTransfer(address from, address to, uint256 amount) external override onlyRole(TOKEN_CONTRACT_ROLE) returns (bool isValid) { 117 : : // Validate the transfer - 118 [ + + ]: 50 : if(!RuleEngineValidation.validateTransferValidation(from, to, amount)){ + 118 [ + + ]: 88 : if(!RuleEngineValidation.validateTransferValidation(from, to, amount)){ 119 : 14 : return false; 120 : : } 121 : : // Apply operation on RuleEngine - 122 : 54 : return RuleEngineOperation._operateOnTransfer(from, to, amount); + 122 : 111 : return RuleEngineOperation._operateOnTransfer(from, to, amount); 123 : : } 124 : : 125 : : /** @@ -202,7 +202,7 @@ 131 : : override(ERC2771Context, Context) 132 : : returns (address sender) 133 : : { - 134 : 609 : return ERC2771Context._msgSender(); + 134 : 732 : return ERC2771Context._msgSender(); 135 : : } 136 : : 137 : : /** @@ -221,7 +221,7 @@ 150 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule 151 : : */ 152 : : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { - 153 : 609 : return ERC2771Context._contextSuffixLength(); + 153 : 732 : return ERC2771Context._contextSuffixLength(); 154 : : } 155 : : } diff --git a/doc/test/coverage/src/index-sort-b.html b/doc/test/coverage/src/index-sort-b.html index 329777c..7c7d1c2 100644 --- a/doc/test/coverage/src/index-sort-b.html +++ b/doc/test/coverage/src/index-sort-b.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 6 diff --git a/doc/test/coverage/src/index-sort-f.html b/doc/test/coverage/src/index-sort-f.html index f831a28..6a6bcc1 100644 --- a/doc/test/coverage/src/index-sort-f.html +++ b/doc/test/coverage/src/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 6 diff --git a/doc/test/coverage/src/index-sort-l.html b/doc/test/coverage/src/index-sort-l.html index 177354e..876daf1 100644 --- a/doc/test/coverage/src/index-sort-l.html +++ b/doc/test/coverage/src/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 6 diff --git a/doc/test/coverage/src/index.html b/doc/test/coverage/src/index.html index c29cf55..3326585 100644 --- a/doc/test/coverage/src/index.html +++ b/doc/test/coverage/src/index.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 6 diff --git a/doc/test/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html b/doc/test/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html index 52d0974..60b6676 100644 --- a/doc/test/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html +++ b/doc/test/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 11 @@ -96,21 +96,21 @@ RuleEngineOperation._clearRulesOperation 14 - - RuleEngineOperation._operateOnTransfer - 18 - RuleEngineOperation._removeRuleOperation 22 + + RuleEngineOperation._operateOnTransfer + 37 + RuleEngineOperation.rulesCountOperation 41 RuleEngineOperation.addRuleOperation - 46 + 68
diff --git a/doc/test/coverage/src/modules/RuleEngineOperation.sol.func.html b/doc/test/coverage/src/modules/RuleEngineOperation.sol.func.html index 7911e43..d1a961d 100644 --- a/doc/test/coverage/src/modules/RuleEngineOperation.sol.func.html +++ b/doc/test/coverage/src/modules/RuleEngineOperation.sol.func.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 11 @@ -74,7 +74,7 @@ RuleEngineOperation._operateOnTransfer - 18 + 37 RuleEngineOperation._removeRuleOperation @@ -82,7 +82,7 @@ RuleEngineOperation.addRuleOperation - 46 + 68 RuleEngineOperation.clearRulesOperation diff --git a/doc/test/coverage/src/modules/RuleEngineOperation.sol.gcov.html b/doc/test/coverage/src/modules/RuleEngineOperation.sol.gcov.html index c43cf6a..157fff9 100644 --- a/doc/test/coverage/src/modules/RuleEngineOperation.sol.gcov.html +++ b/doc/test/coverage/src/modules/RuleEngineOperation.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 11 @@ -130,8 +130,8 @@ 59 : : * 60 : : */ 61 : : function addRuleOperation(IRuleOperation rule_) public onlyRole(RULE_ENGINE_ROLE) { - 62 : 92 : RuleInternal._addRule( _rulesOperation, address(rule_)); - 63 : 88 : emit AddRule(address(rule_)); + 62 : 136 : RuleInternal._addRule( _rulesOperation, address(rule_)); + 63 : 132 : emit AddRule(address(rule_)); 64 : : } 65 : : 66 : : /** @@ -213,18 +213,18 @@ 142 : : address _to, 143 : : uint256 _amount 144 : : ) internal returns (bool isValid){ - 145 : 36 : uint256 rulesLength = _rulesOperation.length; - 146 : 68 : for (uint256 i = 0; i < rulesLength; ++i ) { - 147 : 42 : bool result = IRuleOperation(_rulesOperation[i]).operateOnTransfer( + 145 : 74 : uint256 rulesLength = _rulesOperation.length; + 146 : 143 : for (uint256 i = 0; i < rulesLength; ++i ) { + 147 : 99 : bool result = IRuleOperation(_rulesOperation[i]).operateOnTransfer( 148 : : _from, 149 : : _to, 150 : : _amount 151 : : ); - 152 [ + + ]: 28 : if(!result){ - 153 : 14 : return false; + 152 [ + + ]: 66 : if(!result){ + 153 : 34 : return false; 154 : : } 155 : : } - 156 : 22 : return true; + 156 : 40 : return true; 157 : : } 158 : : } diff --git a/doc/test/coverage/src/modules/RuleEngineValidation.sol.func-sort-c.html b/doc/test/coverage/src/modules/RuleEngineValidation.sol.func-sort-c.html index d91e642..25488e0 100644 --- a/doc/test/coverage/src/modules/RuleEngineValidation.sol.func-sort-c.html +++ b/doc/test/coverage/src/modules/RuleEngineValidation.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 12 diff --git a/doc/test/coverage/src/modules/RuleEngineValidation.sol.func.html b/doc/test/coverage/src/modules/RuleEngineValidation.sol.func.html index 06fb650..0e25146 100644 --- a/doc/test/coverage/src/modules/RuleEngineValidation.sol.func.html +++ b/doc/test/coverage/src/modules/RuleEngineValidation.sol.func.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 12 diff --git a/doc/test/coverage/src/modules/RuleEngineValidation.sol.gcov.html b/doc/test/coverage/src/modules/RuleEngineValidation.sol.gcov.html index 6182787..d78351a 100644 --- a/doc/test/coverage/src/modules/RuleEngineValidation.sol.gcov.html +++ b/doc/test/coverage/src/modules/RuleEngineValidation.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 12 @@ -216,8 +216,8 @@ 145 : : address _to, 146 : : uint256 _amount 147 : : ) public view override returns (uint8) { - 148 : 104 : uint256 rulesLength = _rulesValidation.length; - 149 : 176 : for (uint256 i = 0; i < rulesLength; ++i ) { + 148 : 142 : uint256 rulesLength = _rulesValidation.length; + 149 : 233 : for (uint256 i = 0; i < rulesLength; ++i ) { 150 : 96 : uint8 restriction = IRuleValidation(_rulesValidation[i]).detectTransferRestriction( 151 : : _from, 152 : : _to, @@ -228,7 +228,7 @@ 157 : : } 158 : : } 159 : : - 160 : 90 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 160 : 147 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); 161 : : } 162 : : 163 : : /** @@ -243,7 +243,7 @@ 172 : : address _to, 173 : : uint256 _amount 174 : : ) public view override returns (bool) { - 175 : 135 : return detectTransferRestrictionValidation(_from, _to, _amount) == uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 175 : 230 : return detectTransferRestrictionValidation(_from, _to, _amount) == uint8(REJECTED_CODE_BASE.TRANSFER_OK); 176 : : } 177 : : } diff --git a/doc/test/coverage/src/modules/RuleInternal.sol.func-sort-c.html b/doc/test/coverage/src/modules/RuleInternal.sol.func-sort-c.html index 90d60ca..7f87299 100644 --- a/doc/test/coverage/src/modules/RuleInternal.sol.func-sort-c.html +++ b/doc/test/coverage/src/modules/RuleInternal.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 4 @@ -82,7 +82,7 @@ RuleInternal._addRule - 112 + 134
diff --git a/doc/test/coverage/src/modules/RuleInternal.sol.func.html b/doc/test/coverage/src/modules/RuleInternal.sol.func.html index e2594ba..3682d83 100644 --- a/doc/test/coverage/src/modules/RuleInternal.sol.func.html +++ b/doc/test/coverage/src/modules/RuleInternal.sol.func.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 4 @@ -70,7 +70,7 @@ RuleInternal._addRule - 112 + 134 RuleInternal._removeRule diff --git a/doc/test/coverage/src/modules/RuleInternal.sol.gcov.html b/doc/test/coverage/src/modules/RuleInternal.sol.gcov.html index a3b8f90..56428d7 100644 --- a/doc/test/coverage/src/modules/RuleInternal.sol.gcov.html +++ b/doc/test/coverage/src/modules/RuleInternal.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 4 @@ -115,16 +115,16 @@ 44 : : * 45 : : */ 46 : : function _addRule(address[] storage _rules, address rule_) internal { - 47 [ + + ]: 448 : if( address(rule_) == address(0x0)) + 47 [ + + ]: 536 : if( address(rule_) == address(0x0)) 48 : : { 49 : 4 : revert RuleEngine_RuleAddressZeroNotAllowed(); 50 : : } - 51 [ + + ]: 110 : if( _ruleIsPresent[rule_]) + 51 [ + + ]: 132 : if( _ruleIsPresent[rule_]) 52 : : { 53 : 4 : revert RuleEngine_RuleAlreadyExists(); 54 : : } - 55 : 216 : _rules.push(rule_); - 56 : 216 : _ruleIsPresent[rule_] = true; + 55 : 260 : _rules.push(rule_); + 56 : 260 : _ruleIsPresent[rule_] = true; 57 : : } 58 : : 59 : : /** diff --git a/doc/test/coverage/src/modules/index-sort-b.html b/doc/test/coverage/src/modules/index-sort-b.html index b1b0d46..85bb87e 100644 --- a/doc/test/coverage/src/modules/index-sort-b.html +++ b/doc/test/coverage/src/modules/index-sort-b.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 27 diff --git a/doc/test/coverage/src/modules/index-sort-f.html b/doc/test/coverage/src/modules/index-sort-f.html index 3897b8f..a84ef03 100644 --- a/doc/test/coverage/src/modules/index-sort-f.html +++ b/doc/test/coverage/src/modules/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 27 diff --git a/doc/test/coverage/src/modules/index-sort-l.html b/doc/test/coverage/src/modules/index-sort-l.html index cb2ba07..49f111f 100644 --- a/doc/test/coverage/src/modules/index-sort-l.html +++ b/doc/test/coverage/src/modules/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 27 diff --git a/doc/test/coverage/src/modules/index.html b/doc/test/coverage/src/modules/index.html index b8940ef..373a764 100644 --- a/doc/test/coverage/src/modules/index.html +++ b/doc/test/coverage/src/modules/index.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 27 diff --git a/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func-sort-c.html b/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func-sort-c.html index 5e3af45..6760052 100644 --- a/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func-sort-c.html +++ b/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 78 - 79 - 98.7 % + 84 + 85 + 98.8 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 15 @@ -49,9 +49,9 @@ Branches: - 32 - 34 - 94.1 % + 38 + 42 + 90.5 % @@ -69,68 +69,68 @@ Hit count Sort by hit count - RuleConditionalTransfer._msgData + RuleConditionalTransfer._msgData 0 - RuleConditionalTransfer.canReturnTransferRestrictionCode + RuleConditionalTransfer.canReturnTransferRestrictionCode 2 - RuleConditionalTransfer.cancelTransferRequestBatch + RuleConditionalTransfer.cancelTransferRequestBatch 3 - RuleConditionalTransfer.createTransferRequestBatch + RuleConditionalTransfer.createTransferRequestBatch 3 - RuleConditionalTransfer.messageForTransferRestriction + RuleConditionalTransfer.messageForTransferRestriction 3 - RuleConditionalTransfer.cancelTransferRequest - 5 + RuleConditionalTransfer.cancelTransferRequest + 6 - RuleConditionalTransfer._cancelTransferRequest - 8 + RuleConditionalTransfer._cancelTransferRequest + 9 - RuleConditionalTransfer.detectTransferRestriction - 8 + RuleConditionalTransfer.detectTransferRestriction + 11 - RuleConditionalTransfer.operateOnTransfer - 14 + RuleConditionalTransfer.operateOnTransfer + 33 - RuleConditionalTransfer._validateApproval - 20 + RuleConditionalTransfer.getRequestByStatus + 35 - RuleConditionalTransfer._validateBurnMint - 22 + RuleConditionalTransfer._validateApproval + 37 - RuleConditionalTransfer.getRequestByStatus - 35 + RuleConditionalTransfer._validateBurnMint + 41 - RuleConditionalTransfer.getRequestTrade + RuleConditionalTransfer.getRequestTrade 57 - RuleConditionalTransfer.createTransferRequest - 91 + RuleConditionalTransfer.createTransferRequest + 102 - RuleConditionalTransfer._contextSuffixLength - 328 + RuleConditionalTransfer._contextSuffixLength + 452 - RuleConditionalTransfer._msgSender - 328 + RuleConditionalTransfer._msgSender + 452
diff --git a/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func.html b/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func.html index d783f66..4bb3fe2 100644 --- a/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func.html +++ b/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 78 - 79 - 98.7 % + 84 + 85 + 98.8 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 15 @@ -49,9 +49,9 @@ Branches: - 32 - 34 - 94.1 % + 38 + 42 + 90.5 % @@ -69,68 +69,68 @@ Hit count Sort by hit count - RuleConditionalTransfer._cancelTransferRequest - 8 + RuleConditionalTransfer._cancelTransferRequest + 9 - RuleConditionalTransfer._contextSuffixLength - 328 + RuleConditionalTransfer._contextSuffixLength + 452 - RuleConditionalTransfer._msgData + RuleConditionalTransfer._msgData 0 - RuleConditionalTransfer._msgSender - 328 + RuleConditionalTransfer._msgSender + 452 - RuleConditionalTransfer._validateApproval - 20 + RuleConditionalTransfer._validateApproval + 37 - RuleConditionalTransfer._validateBurnMint - 22 + RuleConditionalTransfer._validateBurnMint + 41 - RuleConditionalTransfer.canReturnTransferRestrictionCode + RuleConditionalTransfer.canReturnTransferRestrictionCode 2 - RuleConditionalTransfer.cancelTransferRequest - 5 + RuleConditionalTransfer.cancelTransferRequest + 6 - RuleConditionalTransfer.cancelTransferRequestBatch + RuleConditionalTransfer.cancelTransferRequestBatch 3 - RuleConditionalTransfer.createTransferRequest - 91 + RuleConditionalTransfer.createTransferRequest + 102 - RuleConditionalTransfer.createTransferRequestBatch + RuleConditionalTransfer.createTransferRequestBatch 3 - RuleConditionalTransfer.detectTransferRestriction - 8 + RuleConditionalTransfer.detectTransferRestriction + 11 - RuleConditionalTransfer.getRequestByStatus + RuleConditionalTransfer.getRequestByStatus 35 - RuleConditionalTransfer.getRequestTrade + RuleConditionalTransfer.getRequestTrade 57 - RuleConditionalTransfer.messageForTransferRestriction + RuleConditionalTransfer.messageForTransferRestriction 3 - RuleConditionalTransfer.operateOnTransfer - 14 + RuleConditionalTransfer.operateOnTransfer + 33
diff --git a/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.gcov.html b/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.gcov.html index 946bf16..d822f2b 100644 --- a/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.gcov.html +++ b/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 78 - 79 - 98.7 % + 84 + 85 + 98.8 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 15 @@ -49,9 +49,9 @@ Branches: - 32 - 34 - 94.1 % + 38 + 42 + 90.5 % @@ -113,284 +113,304 @@ 42 : : options = options_; 43 : : } 44 : : - 45 : : function createTransferRequest( - 46 : : address to, uint256 value - 47 : : ) public { - 48 : : // WAIT => Will set a new delay to approve - 49 : : // APPROVED => will overwrite previous status - 50 : : // DENIED => KO - 51 : 282 : address from = _msgSender(); - 52 : 282 : bytes32 key = keccak256(abi.encode(from, to, value)); - 53 [ + + ]: 188 : if(transferRequests[key].status == STATUS.DENIED){ - 54 : 2 : revert RuleConditionalTransfer_TransferDenied(); - 55 : : } - 56 : : // Status NONE not enough because reset is possible - 57 [ # + ]: 186 : if(_checkRequestStatus(key)){ - 58 : 180 : uint256 requestIdLocal = requestId; - 59 : 270 : TransferRequest memory newTransferApproval = TransferRequest({ - 60 : : key:key, - 61 : : id: requestIdLocal, - 62 : : from: from, - 63 : : to:to, - 64 : : value:value, - 65 : : askTime: block.timestamp, - 66 : : maxTime:0, - 67 : : status: STATUS.WAIT - 68 : : } - 69 : : ); - 70 : 180 : transferRequests[key] = newTransferApproval; - 71 : 180 : IdToKey[requestIdLocal] = key; - 72 : 180 : emit transferWaiting(key, from, to, value, requestId); - 73 : 180 : ++requestId; - 74 : : } else { - 75 : : // Overwrite previous approval - 76 : 6 : transferRequests[key].askTime = block.timestamp; - 77 : 6 : transferRequests[key].status = STATUS.WAIT; - 78 : 6 : emit transferWaiting(key, from, to, value, transferRequests[key].id); - 79 : : } - 80 : : } - 81 : : - 82 : : function createTransferRequestBatch(address[] memory tos, uint256[] memory values) public{ - 83 [ + + ]: 6 : if(tos.length == 0){ - 84 : 2 : revert RuleConditionalTransfer_EmptyArray(); - 85 : : } - 86 [ + + ]: 4 : if(tos.length != values.length){ - 87 : 2 : revert RuleConditionalTransfer_InvalidLengthArray(); - 88 : : } - 89 : 9 : for(uint256 i = 0; i < tos.length; ++i){ - 90 : 6 : createTransferRequest(tos[i], values[i]); - 91 : : } - 92 : : } - 93 : : - 94 : : /** - 95 : : * @notice allow a token holder to cancel/reset his own request - 96 : : */ - 97 : : function cancelTransferRequest( - 98 : : uint256 requestId_ - 99 : : ) public { - 100 : 10 : _cancelTransferRequest(requestId_); - 101 : : } - 102 : : - 103 : : /** - 104 : : * @notice allow a token holder to cancel/reset his own request - 105 : : */ - 106 : : function cancelTransferRequestBatch( - 107 : : uint256[] memory requestIds - 108 : : ) public { - 109 [ + + ]: 6 : if(requestIds.length == 0){ - 110 : 2 : revert RuleConditionalTransfer_EmptyArray(); - 111 : : } - 112 : : // Check id validity before performing actions - 113 : 14 : for(uint256 i = 0; i < requestIds.length; ++i){ - 114 [ + + ]: 15 : if(requestIds[i] + 1 > requestId) { - 115 : 2 : revert RuleConditionalTransfer_InvalidId(); - 116 : : } - 117 : : } - 118 : 9 : for(uint256 i = 0; i < requestIds.length; ++i){ - 119 : 6 : _cancelTransferRequest(requestIds[i]); - 120 : : } - 121 : : - 122 : : } - 123 : : - 124 : : function _cancelTransferRequest( - 125 : : uint256 requestId_ - 126 : : ) internal { - 127 [ + + ]: 24 : if(requestId_ + 1 > requestId) { - 128 : 2 : revert RuleConditionalTransfer_InvalidId(); - 129 : : } - 130 : 14 : bytes32 key = IdToKey[requestId_]; - 131 : : // Check Sender - 132 [ + + ]: 21 : if(transferRequests[key].from != _msgSender()){ - 133 : 2 : revert RuleConditionalTransfer_InvalidSender(); - 134 : : } - 135 : : // Check status - 136 [ + + ]: 18 : if(transferRequests[key].status != STATUS.WAIT - 137 : 4 : && transferRequests[key].status != STATUS.APPROVED - 138 : : ){ - 139 : 2 : revert RuleConditionalTransfer_Wrong_Status(); - 140 : : } - 141 : 10 : _resetRequestStatus(key); - 142 : : } - 143 : : - 144 : : - 145 : : function getRequestTrade(address from, address to, uint256 value) public view returns (TransferRequest memory) { - 146 : 171 : bytes32 key = keccak256(abi.encode(from, to, value)); - 147 : 114 : return transferRequests[key]; - 148 : : } - 149 : : - 150 : : /** - 151 : : * @notice get Trade by status - 152 : : * @param _targetStatus The status of the transactions you want to retrieve - 153 : : * @return array with corresponding transactions - 154 : : */ - 155 : : function getRequestByStatus(STATUS _targetStatus) public view returns (TransferRequest[] memory) { - 156 : 70 : uint totalRequestCount = requestId; - 157 : 70 : uint requestCount = 0; - 158 : 70 : uint currentIndex = 0; - 159 : : - 160 : : // We count the number of requests matching the criteria - 161 : 181 : for (uint i = 0; i < totalRequestCount; ++i) { - 162 [ + + ]: 76 : if (transferRequests[IdToKey[i]].status == _targetStatus) { - 163 : 72 : requestCount += 1; - 164 : : } - 165 : : } + 45 : : /** + 46 : : * @notice Create a request of transfer for yourselves + 47 : : * @param to recipient of tokens + 48 : : * @param value amount of tokens to transfer + 49 : : */ + 50 : : function createTransferRequest( + 51 : : address to, uint256 value + 52 : : ) public { + 53 : : // WAIT => Will set a new delay to approve + 54 : : // APPROVED => will overwrite previous status + 55 : : // DENIED => reject + 56 : 315 : address from = _msgSender(); + 57 : 315 : bytes32 key = keccak256(abi.encode(from, to, value)); + 58 [ + + ]: 210 : if(transferRequests[key].status == STATUS.DENIED){ + 59 : 2 : revert RuleConditionalTransfer_TransferDenied(); + 60 : : } + 61 [ # + ]: 208 : if(_checkRequestStatus(key)){ + 62 : 202 : uint256 requestIdLocal = requestId; + 63 : 303 : TransferRequest memory newTransferApproval = TransferRequest({ + 64 : : key:key, + 65 : : id: requestIdLocal, + 66 : : from: from, + 67 : : to:to, + 68 : : value:value, + 69 : : askTime: block.timestamp, + 70 : : maxTime:0, + 71 : : status: STATUS.WAIT + 72 : : } + 73 : : ); + 74 : 202 : transferRequests[key] = newTransferApproval; + 75 : 202 : IdToKey[requestIdLocal] = key; + 76 : 202 : emit transferWaiting(key, from, to, value, requestId); + 77 : 202 : ++requestId; + 78 : : } else { + 79 : : // Overwrite previous approval + 80 : 6 : transferRequests[key].askTime = block.timestamp; + 81 : 6 : transferRequests[key].status = STATUS.WAIT; + 82 : 6 : emit transferWaiting(key, from, to, value, transferRequests[key].id); + 83 : : } + 84 : : } + 85 : : + 86 : : /** + 87 : : * @notice Batch version of {createTransferRequest} + 88 : : */ + 89 : : function createTransferRequestBatch(address[] memory tos, uint256[] memory values) public{ + 90 [ + + ]: 6 : if(tos.length == 0){ + 91 : 2 : revert RuleConditionalTransfer_EmptyArray(); + 92 : : } + 93 [ + + ]: 4 : if(tos.length != values.length){ + 94 : 2 : revert RuleConditionalTransfer_InvalidLengthArray(); + 95 : : } + 96 : 9 : for(uint256 i = 0; i < tos.length; ++i){ + 97 : 6 : createTransferRequest(tos[i], values[i]); + 98 : : } + 99 : : } + 100 : : + 101 : : /** + 102 : : * @notice allow a token holder to cancel/reset his own request + 103 : : */ + 104 : : function cancelTransferRequest( + 105 : : uint256 requestId_ + 106 : : ) public { + 107 : 12 : _cancelTransferRequest(requestId_); + 108 : : } + 109 : : + 110 : : /** + 111 : : * @notice allow a token holder to cancel/reset his own request + 112 : : */ + 113 : : function cancelTransferRequestBatch( + 114 : : uint256[] memory requestIds + 115 : : ) public { + 116 [ + + ]: 6 : if(requestIds.length == 0){ + 117 : 2 : revert RuleConditionalTransfer_EmptyArray(); + 118 : : } + 119 : : // Check id validity before performing actions + 120 : 14 : for(uint256 i = 0; i < requestIds.length; ++i){ + 121 [ + + ]: 15 : if(requestIds[i] + 1 > requestId) { + 122 : 2 : revert RuleConditionalTransfer_InvalidId(); + 123 : : } + 124 : : } + 125 : 9 : for(uint256 i = 0; i < requestIds.length; ++i){ + 126 : 6 : _cancelTransferRequest(requestIds[i]); + 127 : : } + 128 : : + 129 : : } + 130 : : + 131 : : function _cancelTransferRequest( + 132 : : uint256 requestId_ + 133 : : ) internal { + 134 [ + + ]: 27 : if(requestId_ + 1 > requestId) { + 135 : 2 : revert RuleConditionalTransfer_InvalidId(); + 136 : : } + 137 : 16 : bytes32 key = IdToKey[requestId_]; + 138 : : // Check Sender + 139 [ + + ]: 24 : if(transferRequests[key].from != _msgSender()){ + 140 : 2 : revert RuleConditionalTransfer_InvalidSender(); + 141 : : } + 142 : : // Check status + 143 [ + + ]: 21 : if(transferRequests[key].status != STATUS.WAIT + 144 : 4 : && transferRequests[key].status != STATUS.APPROVED + 145 : : ){ + 146 : 2 : revert RuleConditionalTransfer_Wrong_Status(); + 147 : : } + 148 : 12 : _resetRequestStatus(key); + 149 : : } + 150 : : + 151 : : + 152 : : function getRequestTrade(address from, address to, uint256 value) public view returns (TransferRequest memory) { + 153 : 171 : bytes32 key = keccak256(abi.encode(from, to, value)); + 154 : 114 : return transferRequests[key]; + 155 : : } + 156 : : + 157 : : /** + 158 : : * @notice get Trade by status + 159 : : * @param _targetStatus The status of the transactions you want to retrieve + 160 : : * @return array with corresponding transactions + 161 : : */ + 162 : : function getRequestByStatus(STATUS _targetStatus) public view returns (TransferRequest[] memory) { + 163 : 70 : uint totalRequestCount = requestId; + 164 : 70 : uint requestCount = 0; + 165 : 70 : uint currentIndex = 0; 166 : : - 167 : : // We reserve the memory to store the trade - 168 : 105 : TransferRequest[] memory requests = new TransferRequest[](requestCount); - 169 : : - 170 : : // We create an array with the list of trade - 171 : 181 : for (uint i = 0; i < totalRequestCount; ++i) { - 172 [ # + ]: 76 : if (transferRequests[IdToKey[i]].status == _targetStatus) { - 173 : : //uint currentId = i + 1; - 174 : 72 : TransferRequest memory currentRequest = transferRequests[IdToKey[i]]; - 175 : 72 : requests[currentIndex] = currentRequest; - 176 : 72 : currentIndex += 1; - 177 : : } - 178 : : } - 179 : 70 : return requests; - 180 : : } - 181 : : - 182 : : /** - 183 : : * @dev Returns true if the transfer is valid, and false otherwise. - 184 : : * Add access control with the RuleEngine - 185 : : */ - 186 : : function operateOnTransfer( - 187 : : address _from, - 188 : : address _to, - 189 : : uint256 _amount - 190 : : ) public override onlyRole(RULE_ENGINE_CONTRACT_ROLE) returns(bool isValid){ - 191 : : // Mint & Burn - 192 [ + + ]: 28 : if(_validateBurnMint(_from, _to)) { - 193 : 4 : return true; - 194 : : } - 195 : 36 : bytes32 key = keccak256(abi.encode(_from, _to, _amount)); - 196 [ + + ]: 24 : if(_validateApproval(key)) { - 197 : 10 : _updateProcessedTransfer(key); - 198 : 10 : return true; - 199 : : } else { - 200 : 14 : return false; - 201 : : } - 202 : : } - 203 : : - 204 : : /** - 205 : : * @notice Check if the transfer is valid - 206 : : * @param _from the origin address - 207 : : * @param _to the destination address - 208 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - 209 : : **/ - 210 : : function detectTransferRestriction( - 211 : : address _from, - 212 : : address _to, - 213 : : uint256 _amount - 214 : : ) public view override returns (uint8) { - 215 : 24 : bytes32 key = keccak256(abi.encode(_from, _to, _amount)); - 216 [ + + ]: 32 : if (!_validateBurnMint(_from,_to) && !_validateApproval(key)) { - 217 : 12 : return CODE_TRANSFER_REQUEST_NOT_APPROVED; - 218 : : } - 219 : : else { - 220 : 6 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 221 : : } - 222 : : } - 223 : : - 224 : : /** - 225 : : * @notice To know if the restriction code is valid for this rule or not. - 226 : : * @param _restrictionCode The target restriction code - 227 : : * @return true if the restriction code is known, false otherwise - 228 : : **/ - 229 : : function canReturnTransferRestrictionCode( - 230 : : uint8 _restrictionCode - 231 : : ) external pure override returns (bool) { - 232 : 4 : return - 233 : 4 : _restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED; - 234 : : } - 235 : : - 236 : : /** - 237 : : * @notice Return the corresponding message - 238 : : * @param _restrictionCode The target restriction code - 239 : : * @return true if the transfer is valid, false otherwise - 240 : : **/ - 241 : : function messageForTransferRestriction( - 242 : : uint8 _restrictionCode - 243 : : ) external pure override returns (string memory) { - 244 [ + + ]: 6 : if (_restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED) { - 245 : 4 : return TEXT_TRANSFER_REQUEST_NOT_APPROVED; - 246 : : } else { - 247 : 2 : return TEXT_CODE_NOT_FOUND; - 248 : : } - 249 : : } - 250 : : - 251 : : /** - 252 : : * - 253 : : * @dev - 254 : : * Test burn and mint condition - 255 : : * Returns true if the transfer is valid, and false otherwise. - 256 : : * - 257 : : */ - 258 : : function _validateBurnMint( - 259 : : address _from, - 260 : : address _to - 261 : : ) internal view returns(bool isValid){ - 262 : : // Mint & Burn - 263 [ + + ]: : if( - 264 : 44 : (_from == address(0) && options.issuance.authorizedMintWithoutApproval) - 265 : : || (_to == address(0) && options.issuance.authorizedBurnWithoutApproval) - 266 : : ){ - 267 : 4 : return true; + 167 : : // We count the number of requests matching the criteria + 168 : 181 : for (uint i = 0; i < totalRequestCount; ++i) { + 169 [ + + ]: 76 : if (transferRequests[IdToKey[i]].status == _targetStatus) { + 170 : 72 : requestCount += 1; + 171 : : } + 172 : : } + 173 : : + 174 : : // We reserve the memory to store the trade + 175 : 105 : TransferRequest[] memory requests = new TransferRequest[](requestCount); + 176 : : + 177 : : // We create an array with the list of trade + 178 : 181 : for (uint i = 0; i < totalRequestCount; ++i) { + 179 [ # + ]: 76 : if (transferRequests[IdToKey[i]].status == _targetStatus) { + 180 : : //uint currentId = i + 1; + 181 : 72 : TransferRequest memory currentRequest = transferRequests[IdToKey[i]]; + 182 : 72 : requests[currentIndex] = currentRequest; + 183 : 72 : currentIndex += 1; + 184 : : } + 185 : : } + 186 : 70 : return requests; + 187 : : } + 188 : : + 189 : : /** + 190 : : * @dev Returns true if the transfer is valid, and false otherwise. + 191 : : * Add access control with the RuleEngine + 192 : : */ + 193 : : function operateOnTransfer( + 194 : : address _from, + 195 : : address _to, + 196 : : uint256 _amount + 197 : : ) public override onlyRole(RULE_ENGINE_CONTRACT_ROLE) returns(bool isValid){ + 198 : : // No need of approval if from and to are in the whitelist + 199 [ + + ]: 132 : if(address(whitelistConditionalTransfer) != address(0)){ + 200 [ + + ]: 57 : if(whitelistConditionalTransfer.addressIsListed(_from) && whitelistConditionalTransfer.addressIsListed(_to)){ + 201 : 4 : return true; + 202 : : } + 203 : : } + 204 : : + 205 : : // Mint & Burn + 206 [ + + ]: 62 : if(_validateBurnMint(_from, _to)) { + 207 : 8 : return true; + 208 : : } + 209 : 81 : bytes32 key = keccak256(abi.encode(_from, _to, _amount)); + 210 [ + + ]: 54 : if(_validateApproval(key)) { + 211 : 20 : _updateProcessedTransfer(key); + 212 : 20 : return true; + 213 : : } else { + 214 : 34 : return false; + 215 : : } + 216 : : } + 217 : : + 218 : : /** + 219 : : * @notice Check if the transfer is valid + 220 : : * @param _from the origin address + 221 : : * @param _to the destination address + 222 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + 223 : : **/ + 224 : : function detectTransferRestriction( + 225 : : address _from, + 226 : : address _to, + 227 : : uint256 _amount + 228 : : ) public view override returns (uint8) { + 229 : : // No need of approval if from and to are in the whitelist + 230 [ # + ]: 44 : if(address(whitelistConditionalTransfer) != address(0)){ + 231 [ # + ]: 11 : if(whitelistConditionalTransfer.addressIsListed(_from) && whitelistConditionalTransfer.addressIsListed(_to)){ + 232 : 3 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 233 : : } + 234 : : } + 235 : 30 : bytes32 key = keccak256(abi.encode(_from, _to, _amount)); + 236 [ + + ]: 40 : if (!_validateBurnMint(_from,_to) && !_validateApproval(key)) { + 237 : 16 : return CODE_TRANSFER_REQUEST_NOT_APPROVED; + 238 : : } + 239 : : else { + 240 : 6 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 241 : : } + 242 : : } + 243 : : + 244 : : /** + 245 : : * @notice To know if the restriction code is valid for this rule or not. + 246 : : * @param _restrictionCode The target restriction code + 247 : : * @return true if the restriction code is known, false otherwise + 248 : : **/ + 249 : : function canReturnTransferRestrictionCode( + 250 : : uint8 _restrictionCode + 251 : : ) external pure override returns (bool) { + 252 : 4 : return + 253 : 4 : _restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED; + 254 : : } + 255 : : + 256 : : /** + 257 : : * @notice Return the corresponding message + 258 : : * @param _restrictionCode The target restriction code + 259 : : * @return true if the transfer is valid, false otherwise + 260 : : **/ + 261 : : function messageForTransferRestriction( + 262 : : uint8 _restrictionCode + 263 : : ) external pure override returns (string memory) { + 264 [ + + ]: 6 : if (_restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED) { + 265 : 4 : return TEXT_TRANSFER_REQUEST_NOT_APPROVED; + 266 : : } else { + 267 : 2 : return TEXT_CODE_NOT_FOUND; 268 : : } - 269 : 40 : return false; - 270 : : } - 271 : : - 272 : : /** - 273 : : * - 274 : : * @dev - 275 : : * Test transfer approval condition - 276 : : * Returns true if the transfer is valid, and false otherwise. + 269 : : } + 270 : : + 271 : : /** + 272 : : * + 273 : : * @dev + 274 : : * Test burn and mint condition + 275 : : * Returns true if the transfer is valid, and false otherwise. + 276 : : * 277 : : */ - 278 : : function _validateApproval( - 279 : : bytes32 key - 280 : : ) internal view returns(bool isValid){ - 281 : 60 : bool automaticApprovalCondition = options.automaticApproval.isActivate && ((transferRequests[key].askTime + options.automaticApproval.timeLimitBeforeAutomaticApproval ) >= block.timestamp); - 282 : 60 : bool isTransferApproved = (transferRequests[key].status == STATUS.APPROVED) - 283 : : && (transferRequests[key].maxTime >= block.timestamp); - 284 [ + + ]: 40 : if(automaticApprovalCondition || isTransferApproved) - 285 : : { - 286 : 14 : return true; - 287 : : } else { - 288 : 26 : return false; - 289 : : } + 278 : : function _validateBurnMint( + 279 : : address _from, + 280 : : address _to + 281 : : ) internal view returns(bool isValid){ + 282 : : // Mint & Burn + 283 [ + + ]: : if( + 284 : 82 : (_from == address(0) && options.issuance.authorizedMintWithoutApproval) + 285 : : || (_to == address(0) && options.issuance.authorizedBurnWithoutApproval) + 286 : : ){ + 287 : 8 : return true; + 288 : : } + 289 : 74 : return false; 290 : : } 291 : : - 292 : : /** - 293 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 294 : : */ - 295 : : function _msgSender() - 296 : : internal - 297 : : view - 298 : : override(ERC2771Context, Context) - 299 : : returns (address sender) - 300 : : { - 301 : 984 : return ERC2771Context._msgSender(); - 302 : : } - 303 : : - 304 : : /** - 305 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 306 : : */ - 307 : : function _msgData() - 308 : : internal - 309 : : view - 310 : : override(ERC2771Context, Context) - 311 : : returns (bytes calldata) - 312 : : { - 313 : 0 : return ERC2771Context._msgData(); - 314 : : } - 315 : : - 316 : : /** - 317 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 318 : : */ - 319 : : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { - 320 : 984 : return ERC2771Context._contextSuffixLength(); - 321 : : } - 322 : : } + 292 : : /** + 293 : : * + 294 : : * @dev + 295 : : * Test transfer approval condition + 296 : : * Returns true if the transfer is valid, and false otherwise. + 297 : : */ + 298 : : function _validateApproval( + 299 : : bytes32 key + 300 : : ) internal view returns(bool isValid){ + 301 : 111 : bool automaticApprovalCondition = options.automaticApproval.isActivate && ((transferRequests[key].askTime + options.automaticApproval.timeLimitBeforeAutomaticApproval ) >= block.timestamp); + 302 : 111 : bool isTransferApproved = (transferRequests[key].status == STATUS.APPROVED) + 303 : : && (transferRequests[key].maxTime >= block.timestamp); + 304 [ + + ]: 74 : if(automaticApprovalCondition || isTransferApproved) + 305 : : { + 306 : 24 : return true; + 307 : : } else { + 308 : 50 : return false; + 309 : : } + 310 : : } + 311 : : + 312 : : /** + 313 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 314 : : */ + 315 : : function _msgSender() + 316 : : internal + 317 : : view + 318 : : override(ERC2771Context, Context) + 319 : : returns (address sender) + 320 : : { + 321 : 1356 : return ERC2771Context._msgSender(); + 322 : : } + 323 : : + 324 : : /** + 325 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 326 : : */ + 327 : : function _msgData() + 328 : : internal + 329 : : view + 330 : : override(ERC2771Context, Context) + 331 : : returns (bytes calldata) + 332 : : { + 333 : 0 : return ERC2771Context._msgData(); + 334 : : } + 335 : : + 336 : : /** + 337 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 338 : : */ + 339 : : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { + 340 : 1356 : return ERC2771Context._contextSuffixLength(); + 341 : : } + 342 : : } diff --git a/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func-sort-c.html b/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func-sort-c.html index 48bbaa7..b1117d6 100644 --- a/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func-sort-c.html +++ b/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func-sort-c.html @@ -31,18 +31,18 @@ lcov.info Lines: - 94 - 94 + 96 + 96 100.0 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: - 17 18 - 94.4 % + 19 + 94.7 % @@ -69,76 +69,80 @@ Hit count Sort by hit count - RuleConditionalTransferOperator._createTransferRequestWithApproval + RuleConditionalTransferOperator._createTransferRequestWithApproval 0 - RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch - 2 - - - RuleConditionalTransferOperator.setAutomaticTransfer - 2 + RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch + 3 - RuleConditionalTransferOperator.resetRequestStatus + RuleConditionalTransferOperator.resetRequestStatus 3 - RuleConditionalTransferOperator.resetRequestStatusBatch + RuleConditionalTransferOperator.resetRequestStatusBatch 3 - RuleConditionalTransferOperator.setAutomaticApproval + RuleConditionalTransferOperator.setAutomaticTransfer 3 - RuleConditionalTransferOperator.setIssuanceOptions - 3 + RuleConditionalTransferOperator.setTimeLimit + 4 - RuleConditionalTransferOperator.setTimeLimit - 3 + RuleConditionalTransferOperator.approveTransferRequestWithId + 5 - RuleConditionalTransferOperator._updateProcessedTransfer + RuleConditionalTransferOperator.setAutomaticApproval 5 - RuleConditionalTransferOperator.approveTransferRequestWithId + RuleConditionalTransferOperator.setIssuanceOptions 5 - RuleConditionalTransferOperator.approveTransferRequestBatch + RuleConditionalTransferOperator.createTransferRequestWithApproval 6 - RuleConditionalTransferOperator.approveTransferRequestBatchWithId - 6 + RuleConditionalTransferOperator.approveTransferRequestBatch + 7 - RuleConditionalTransferOperator.createTransferRequestWithApproval - 6 + RuleConditionalTransferOperator.approveTransferRequestBatchWithId + 7 + + + RuleConditionalTransferOperator._resetRequestStatus + 10 + + + RuleConditionalTransferOperator._updateProcessedTransfer + 10 - RuleConditionalTransferOperator._resetRequestStatus - 9 + RuleConditionalTransferOperator.setConditionalWhitelist + 25 - RuleConditionalTransferOperator.approveTransferRequest - 26 + RuleConditionalTransferOperator.approveTransferRequest + 33 - RuleConditionalTransferOperator._approveTransferRequestKeyElement - 34 + RuleConditionalTransferOperator._approveTransferRequestKeyElement + 41 - RuleConditionalTransferOperator._approveRequest - 39 + RuleConditionalTransferOperator._approveRequest + 46 - RuleConditionalTransferOperator._checkRequestStatus - 106 + RuleConditionalTransferOperator._checkRequestStatus + 119
diff --git a/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func.html b/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func.html index 2636fb2..7f4ac9d 100644 --- a/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func.html +++ b/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func.html @@ -31,18 +31,18 @@ lcov.info Lines: - 94 - 94 + 96 + 96 100.0 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: - 17 18 - 94.4 % + 19 + 94.7 % @@ -69,76 +69,80 @@ Hit count Sort by hit count - RuleConditionalTransferOperator._approveRequest - 39 + RuleConditionalTransferOperator._approveRequest + 46 - RuleConditionalTransferOperator._approveTransferRequestKeyElement - 34 + RuleConditionalTransferOperator._approveTransferRequestKeyElement + 41 - RuleConditionalTransferOperator._checkRequestStatus - 106 + RuleConditionalTransferOperator._checkRequestStatus + 119 - RuleConditionalTransferOperator._createTransferRequestWithApproval + RuleConditionalTransferOperator._createTransferRequestWithApproval 0 - RuleConditionalTransferOperator._resetRequestStatus - 9 + RuleConditionalTransferOperator._resetRequestStatus + 10 - RuleConditionalTransferOperator._updateProcessedTransfer - 5 + RuleConditionalTransferOperator._updateProcessedTransfer + 10 - RuleConditionalTransferOperator.approveTransferRequest - 26 + RuleConditionalTransferOperator.approveTransferRequest + 33 - RuleConditionalTransferOperator.approveTransferRequestBatch - 6 + RuleConditionalTransferOperator.approveTransferRequestBatch + 7 - RuleConditionalTransferOperator.approveTransferRequestBatchWithId - 6 + RuleConditionalTransferOperator.approveTransferRequestBatchWithId + 7 - RuleConditionalTransferOperator.approveTransferRequestWithId + RuleConditionalTransferOperator.approveTransferRequestWithId 5 - RuleConditionalTransferOperator.createTransferRequestWithApproval + RuleConditionalTransferOperator.createTransferRequestWithApproval 6 - RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch - 2 + RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch + 3 - RuleConditionalTransferOperator.resetRequestStatus + RuleConditionalTransferOperator.resetRequestStatus 3 - RuleConditionalTransferOperator.resetRequestStatusBatch + RuleConditionalTransferOperator.resetRequestStatusBatch 3 - RuleConditionalTransferOperator.setAutomaticApproval + RuleConditionalTransferOperator.setAutomaticApproval + 5 + + + RuleConditionalTransferOperator.setAutomaticTransfer 3 - RuleConditionalTransferOperator.setAutomaticTransfer - 2 + RuleConditionalTransferOperator.setConditionalWhitelist + 25 - RuleConditionalTransferOperator.setIssuanceOptions - 3 + RuleConditionalTransferOperator.setIssuanceOptions + 5 - RuleConditionalTransferOperator.setTimeLimit - 3 + RuleConditionalTransferOperator.setTimeLimit + 4
diff --git a/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.gcov.html b/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.gcov.html index 7f605fd..0c436a8 100644 --- a/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.gcov.html +++ b/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.gcov.html @@ -31,18 +31,18 @@ lcov.info Lines: - 94 - 94 + 96 + 96 100.0 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: - 17 18 - 94.4 % + 19 + 94.7 % @@ -76,279 +76,313 @@ 5 : : import "OZ/access/AccessControl.sol"; 6 : : import "./RuleConditionalTransferInvariantStorage.sol"; 7 : : import "OZ/token/ERC20/utils/SafeERC20.sol"; - 8 : : - 9 : : /** - 10 : : * @title a RuleConditionalTransfer manager - 11 : : */ - 12 : : - 13 : : abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditionalTransferInvariantStorage { - 14 : : // Security - 15 : : using SafeERC20 for IERC20; - 16 : : - 17 : : OPTION internal options; - 18 : : - 19 : : - 20 : : // Getter - 21 : : uint256 public requestId; - 22 : : mapping(uint256 => bytes32) public IdToKey; - 23 : : mapping(bytes32 => TransferRequest) public transferRequests; - 24 : : - 25 : : - 26 : : function setIssuanceOptions(ISSUANCE calldata issuance_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - 27 [ + + ]: 4 : if(options.issuance.authorizedMintWithoutApproval != issuance_.authorizedMintWithoutApproval ){ - 28 : 2 : options.issuance.authorizedMintWithoutApproval = issuance_.authorizedMintWithoutApproval; - 29 : : } - 30 [ + + ]: 4 : if(options.issuance.authorizedBurnWithoutApproval != issuance_.authorizedBurnWithoutApproval ){ - 31 : 2 : options.issuance.authorizedBurnWithoutApproval = issuance_.authorizedBurnWithoutApproval; - 32 : : } - 33 : : } - 34 : : - 35 : : function setAutomaticTransfer(AUTOMATIC_TRANSFER calldata automaticTransfer_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - 36 [ + + ]: 2 : if(automaticTransfer_.isActivate != options.automaticTransfer.isActivate){ - 37 : 2 : options.automaticTransfer.isActivate = automaticTransfer_.isActivate; - 38 : : } - 39 : : // No need to put the cmtat to zero to deactivate automaticTransfer - 40 [ + + ]: 4 : if(address(automaticTransfer_.cmtat) != address(options.automaticTransfer.cmtat)){ - 41 : 2 : options.automaticTransfer.cmtat = automaticTransfer_.cmtat; - 42 : : } - 43 : : } - 44 : : - 45 : : /** - 46 : : * @notice set time limit for new requests (Approval and transfer) - 47 : : * Don't affect already created requests - 48 : : */ - 49 : : function setTimeLimit(TIME_LIMIT memory timeLimit_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - 50 [ + + ]: 4 : if(options.timeLimit.timeLimitToApprove != timeLimit_.timeLimitToApprove){ - 51 : 4 : options.timeLimit.timeLimitToApprove = timeLimit_.timeLimitToApprove; - 52 : : } - 53 [ + + ]: 4 : if(options.timeLimit.timeLimitToTransfer != timeLimit_.timeLimitToTransfer){ - 54 : 4 : options.timeLimit.timeLimitToTransfer = timeLimit_.timeLimitToTransfer; - 55 : : } - 56 : : } - 57 : : - 58 : : function setAutomaticApproval(AUTOMATIC_APPROVAL memory automaticApproval_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - 59 [ + + ]: 4 : if(options.automaticApproval.isActivate != automaticApproval_.isActivate ){ - 60 : 4 : options.automaticApproval.isActivate = automaticApproval_.isActivate; - 61 : : } - 62 [ + + ]: 4 : if(options.automaticApproval.timeLimitBeforeAutomaticApproval != automaticApproval_.timeLimitBeforeAutomaticApproval){ - 63 : 4 : options.automaticApproval.timeLimitBeforeAutomaticApproval = automaticApproval_.timeLimitBeforeAutomaticApproval; - 64 : : } - 65 : : } - 66 : : - 67 : : - 68 : : function createTransferRequestWithApproval( - 69 : : TransferRequestKeyElement calldata keyElement - 70 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - 71 : 10 : _createTransferRequestWithApproval(keyElement); - 72 : : } - 73 : : - 74 : : /** - 75 : : @param keyElement contains from, to, value - 76 : : @param partialValue amount approved. Put 0 if all the amount specified by value is approved. - 77 : : @param isApproved_ approved (true) or refused (false). Put true if you use partialApproval - 78 : : */ - 79 : : function approveTransferRequest( - 80 : : TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved_ - 81 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - 82 : 50 : _approveTransferRequestKeyElement(keyElement, partialValue, isApproved_); - 83 : : } - 84 : : - 85 : : function approveTransferRequestWithId( - 86 : : uint256 requestId_, bool isApproved_ - 87 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - 88 [ + + ]: 12 : if(requestId_ + 1 > requestId) { - 89 : 4 : revert RuleConditionalTransfer_InvalidId(); - 90 : : } - 91 : 4 : TransferRequest memory transferRequest = transferRequests[IdToKey[requestId_]]; - 92 : 4 : _approveRequest(transferRequest, isApproved_); - 93 : : } - 94 : : - 95 : : - 96 : : function resetRequestStatus( - 97 : : uint256 requestId_ - 98 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - 99 [ + + ]: 6 : if(requestId_ + 1 > requestId) { - 100 : 2 : revert RuleConditionalTransfer_InvalidId(); - 101 : : } - 102 : 2 : bytes32 key = IdToKey[requestId_]; - 103 : 2 : _resetRequestStatus(key); - 104 : : } - 105 : : - 106 : : /***** Batch function */ - 107 : : - 108 : : function approveTransferRequestBatchWithId( - 109 : : uint256[] calldata requestId_, bool[] calldata isApproved_ + 8 : : /** + 9 : : * @title Restricted functions + 10 : : */ + 11 : : abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditionalTransferInvariantStorage { + 12 : : // Security + 13 : : using SafeERC20 for IERC20; + 14 : : + 15 : : // public variable with automatic Getter + 16 : : OPTION public options; + 17 : : uint256 public requestId; + 18 : : mapping(uint256 => bytes32) public IdToKey; + 19 : : mapping(bytes32 => TransferRequest) public transferRequests; + 20 : : RuleWhitelist public whitelistConditionalTransfer; + 21 : : + 22 : : /** + 23 : : * @notice set a whitelist. A transfer does not need of an approved request if from and to are in the whitelist + 24 : : */ + 25 : : function setConditionalWhitelist(RuleWhitelist newWhitelistConditionalTransfer) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ + 26 : 50 : whitelistConditionalTransfer = newWhitelistConditionalTransfer; + 27 : 50 : emit WhitelistConditionalTransfer(newWhitelistConditionalTransfer); + 28 : : } + 29 : : + 30 : : /** + 31 : : set/unset the issuance options (mint & burn) + 32 : : */ + 33 : : function setIssuanceOptions(ISSUANCE calldata issuance_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ + 34 [ + + ]: 8 : if(options.issuance.authorizedMintWithoutApproval != issuance_.authorizedMintWithoutApproval ){ + 35 : 4 : options.issuance.authorizedMintWithoutApproval = issuance_.authorizedMintWithoutApproval; + 36 : : } + 37 [ + + ]: 8 : if(options.issuance.authorizedBurnWithoutApproval != issuance_.authorizedBurnWithoutApproval ){ + 38 : 4 : options.issuance.authorizedBurnWithoutApproval = issuance_.authorizedBurnWithoutApproval; + 39 : : } + 40 : : } + 41 : : + 42 : : /** + 43 : : * @notice set/unset the option to perform the transfer if the request is approved by the rule operator. + 44 : : * To perform the transfer, the token holder has to approve the rule to spend tokens on his behalf (standard ERC-20 approval). + 45 : : * If the allowance is not sufficient, the request will be approved, but without performing the transfer. + 46 : : */ + 47 : : function setAutomaticTransfer(AUTOMATIC_TRANSFER calldata automaticTransfer_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ + 48 [ + + ]: 4 : if(automaticTransfer_.isActivate != options.automaticTransfer.isActivate){ + 49 : 4 : options.automaticTransfer.isActivate = automaticTransfer_.isActivate; + 50 : : } + 51 : : // No need to put the cmtat to zero to deactivate automaticTransfer + 52 [ + + ]: 8 : if(address(automaticTransfer_.cmtat) != address(options.automaticTransfer.cmtat)){ + 53 : 4 : options.automaticTransfer.cmtat = automaticTransfer_.cmtat; + 54 : : } + 55 : : } + 56 : : + 57 : : /** + 58 : : * @notice set time limit for new requests (Approval and transfer) + 59 : : * timeLimitToApprove: time limit for an operator to approve a request + 60 : : * timeLimitToTransfer: once a request is approved, time limit for the token holder to perform the transfer + 61 : : */ + 62 : : function setTimeLimit(TIME_LIMIT memory timeLimit_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ + 63 [ + + ]: 6 : if(options.timeLimit.timeLimitToApprove != timeLimit_.timeLimitToApprove){ + 64 : 6 : options.timeLimit.timeLimitToApprove = timeLimit_.timeLimitToApprove; + 65 : : } + 66 [ + + ]: 6 : if(options.timeLimit.timeLimitToTransfer != timeLimit_.timeLimitToTransfer){ + 67 : 6 : options.timeLimit.timeLimitToTransfer = timeLimit_.timeLimitToTransfer; + 68 : : } + 69 : : } + 70 : : /** + 71 : : * @notice If the transfer is not approved or denied within {timeLimitBeforeAutomaticApproval}, + 72 : : * the request is considered as approved during a transfer. + 73 : : * + 74 : : */ + 75 : : function setAutomaticApproval(AUTOMATIC_APPROVAL memory automaticApproval_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ + 76 [ + + ]: 8 : if(options.automaticApproval.isActivate != automaticApproval_.isActivate ){ + 77 : 8 : options.automaticApproval.isActivate = automaticApproval_.isActivate; + 78 : : } + 79 [ + + ]: 8 : if(options.automaticApproval.timeLimitBeforeAutomaticApproval != automaticApproval_.timeLimitBeforeAutomaticApproval){ + 80 : 8 : options.automaticApproval.timeLimitBeforeAutomaticApproval = automaticApproval_.timeLimitBeforeAutomaticApproval; + 81 : : } + 82 : : } + 83 : : + 84 : : /** + 85 : : * @notice create a transfer request directly approved + 86 : : */ + 87 : : function createTransferRequestWithApproval( + 88 : : TransferRequestKeyElement calldata keyElement + 89 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ + 90 : 10 : _createTransferRequestWithApproval(keyElement); + 91 : : } + 92 : : + 93 : : /** + 94 : : @notice approve a transferRequest + 95 : : @param keyElement contains from, to, value + 96 : : @param partialValue amount approved. Put 0 if all the amount specified by value is approved. + 97 : : @param isApproved approved (true) or refused (false). Put true if you use partialApproval + 98 : : */ + 99 : : function approveTransferRequest( + 100 : : TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved + 101 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + 102 : 64 : _approveTransferRequestKeyElement(keyElement, partialValue, isApproved); + 103 : : } + 104 : : + 105 : : /** + 106 : : * @notice approve a transferRequestby using its id + 107 : : */ + 108 : : function approveTransferRequestWithId( + 109 : : uint256 requestId_, bool isApproved 110 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - 111 [ + + ]: 10 : if(requestId_.length == 0){ - 112 : 2 : revert RuleConditionalTransfer_EmptyArray(); + 111 [ + + ]: 12 : if(requestId_ + 1 > requestId) { + 112 : 4 : revert RuleConditionalTransfer_InvalidId(); 113 : : } - 114 [ + + ]: 8 : if(requestId_.length != isApproved_.length){ - 115 : 2 : revert RuleConditionalTransfer_InvalidLengthArray(); - 116 : : } - 117 : : // Check id validity before performing actions - 118 : 29 : for(uint256 i = 0; i < requestId_.length; ++i){ - 119 [ + + ]: 33 : if(requestId_[i] + 1 > requestId) { - 120 : 2 : revert RuleConditionalTransfer_InvalidId(); - 121 : : } - 122 : : } - 123 : 14 : for(uint256 i = 0; i < requestId_.length; ++i){ - 124 : 10 : TransferRequest memory transferRequest = transferRequests[IdToKey[requestId_[i]]]; - 125 : 10 : _approveRequest(transferRequest, isApproved_[i]); + 114 : 4 : TransferRequest memory transferRequest = transferRequests[IdToKey[requestId_]]; + 115 : 4 : _approveRequest(transferRequest, isApproved); + 116 : : } + 117 : : + 118 : : /** + 119 : : * @notice reset to None the status of a request + 120 : : */ + 121 : : function resetRequestStatus( + 122 : : uint256 requestId_ + 123 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ + 124 [ + + ]: 6 : if(requestId_ + 1 > requestId) { + 125 : 2 : revert RuleConditionalTransfer_InvalidId(); 126 : : } - 127 : : } - 128 : : - 129 : : - 130 : : function approveTransferRequestBatch( - 131 : : TransferRequestKeyElement[] calldata keyElements, uint256[] calldata partialValues, bool[] calldata isApproved_ - 132 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - 133 [ + + ]: 12 : if(keyElements.length == 0){ - 134 : 2 : revert RuleConditionalTransfer_EmptyArray(); - 135 : : } - 136 [ + + ]: 10 : if((keyElements.length != partialValues.length) || (partialValues.length != isApproved_.length)){ - 137 : 6 : revert RuleConditionalTransfer_InvalidLengthArray(); - 138 : : } - 139 : 24 : for(uint256 i = 0; i < keyElements.length; ++i){ - 140 : 18 : _approveTransferRequestKeyElement(keyElements[i], partialValues[i], isApproved_[i]); - 141 : : } - 142 : : } - 143 : : - 144 : : - 145 : : function createTransferRequestWithApprovalBatch( - 146 : : TransferRequestKeyElement[] calldata keyElements - 147 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - 148 [ + + ]: 4 : if(keyElements.length == 0){ - 149 : 2 : revert RuleConditionalTransfer_EmptyArray(); - 150 : : } - 151 : 11 : for(uint256 i = 0; i < keyElements.length; ++i){ - 152 : 8 : _createTransferRequestWithApproval(keyElements[i]); + 127 : 2 : bytes32 key = IdToKey[requestId_]; + 128 : 2 : _resetRequestStatus(key); + 129 : : } + 130 : : + 131 : : /***** Batch function */ + 132 : : /** + 133 : : * @notice Batch version of {approveTransferRequestWithId} + 134 : : */ + 135 : : function approveTransferRequestBatchWithId( + 136 : : uint256[] calldata requestId_, bool[] calldata isApproved + 137 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ + 138 [ + + ]: 10 : if(requestId_.length == 0){ + 139 : 2 : revert RuleConditionalTransfer_EmptyArray(); + 140 : : } + 141 [ + + ]: 8 : if(requestId_.length != isApproved.length){ + 142 : 2 : revert RuleConditionalTransfer_InvalidLengthArray(); + 143 : : } + 144 : : // Check id validity before performing actions + 145 : 29 : for(uint256 i = 0; i < requestId_.length; ++i){ + 146 [ + + ]: 33 : if(requestId_[i] + 1 > requestId) { + 147 : 2 : revert RuleConditionalTransfer_InvalidId(); + 148 : : } + 149 : : } + 150 : 14 : for(uint256 i = 0; i < requestId_.length; ++i){ + 151 : 10 : TransferRequest memory transferRequest = transferRequests[IdToKey[requestId_[i]]]; + 152 : 10 : _approveRequest(transferRequest, isApproved[i]); 153 : : } 154 : : } 155 : : - 156 : : - 157 : : function resetRequestStatusBatch( - 158 : : uint256[] memory requestIds - 159 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - 160 [ + + ]: 6 : if(requestIds.length == 0){ - 161 : 2 : revert RuleConditionalTransfer_EmptyArray(); - 162 : : } - 163 : : // Check id validity before performing actions - 164 : 12 : for(uint256 i = 0; i < requestIds.length; ++i){ - 165 [ + + ]: 12 : if(requestIds[i] + 1 > requestId) { - 166 : 2 : revert RuleConditionalTransfer_InvalidId(); - 167 : : } - 168 : : } - 169 : 9 : for(uint256 i = 0; i < requestIds.length; ++i){ - 170 : 6 : bytes32 key = IdToKey[requestIds[i]]; - 171 : 6 : _resetRequestStatus(key); - 172 : : } - 173 : : } - 174 : : - 175 : : - 176 : : /*** Internal functions ****/ - 177 : : - 178 : : function _approveTransferRequestKeyElement( - 179 : : TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved_ - 180 : : ) internal { - 181 [ + + ]: 68 : if(partialValue > keyElement.value){ - 182 : 2 : revert RuleConditionalTransfer_InvalidValueApproved(); - 183 : : } - 184 : 99 : bytes32 key = keccak256(abi.encode(keyElement.from, keyElement.to, keyElement.value)); - 185 : 66 : TransferRequest memory transferRequest = transferRequests[key]; - 186 [ + + ]: 66 : if(partialValue > 0 ){ - 187 [ + + ]: 10 : if(! isApproved_){ - 188 : 2 : revert RuleConditionalTransfer_CannotDeniedPartially(); - 189 : : } - 190 : : // Denied the first request - 191 : 8 : _approveRequest(transferRequest, false); - 192 : : // Create new request - 193 : 8 : _createTransferRequestWithApproval(TransferRequestKeyElement({from: keyElement.from, to: keyElement.to, value: partialValue})); - 194 : : }else{ - 195 : 56 : _approveRequest(transferRequest, isApproved_); - 196 : : } - 197 : : } - 198 : : - 199 : : function _createTransferRequestWithApproval( - 200 : : TransferRequestKeyElement memory keyElement - 201 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - 202 : : // WAIT => Will overwrite - 203 : : // APPROVED => will overwrite previous status with a new delay - 204 : : // DENIED => will overwrite - 205 : 39 : bytes32 key = keccak256(abi.encode(keyElement.from, keyElement.to, keyElement.value)); - 206 : : // Status NONE not enough because reset is possible - 207 [ # + ]: 26 : if(_checkRequestStatus(key)){ - 208 : 36 : TransferRequest memory newTransferApproval = TransferRequest({ - 209 : : key: key, - 210 : : id: requestId, - 211 : : from: keyElement.from, - 212 : : to: keyElement.to, - 213 : : value: keyElement.value, - 214 : : askTime:0, - 215 : : maxTime : block.timestamp + options.timeLimit.timeLimitToTransfer, - 216 : : status:STATUS.APPROVED - 217 : : }); - 218 : 24 : transferRequests[key] = newTransferApproval; - 219 : 24 : IdToKey[requestId] = key; - 220 : 24 : emit transferApproved(key, keyElement.from, keyElement.to, keyElement.value, requestId); - 221 : 24 : ++requestId; - 222 : : } else { - 223 : : // Overwrite previous approval - 224 : 2 : transferRequests[key].maxTime = block.timestamp + options.timeLimit.timeLimitToTransfer; - 225 : 2 : transferRequests[key].status = STATUS.APPROVED; - 226 : 2 : emit transferApproved(key, keyElement.from, keyElement.to, keyElement.value, transferRequests[key].id); - 227 : : } - 228 : : } - 229 : : - 230 : : function _resetRequestStatus( - 231 : : bytes32 key - 232 : : ) internal { - 233 : 18 : transferRequests[key].status = STATUS.NONE; - 234 : 18 : emit transferReset(key, transferRequests[key].from, transferRequests[key].to, transferRequests[key].value, transferRequests[key].id ); - 235 : : } - 236 : : - 237 : : function _checkRequestStatus(bytes32 key) internal view returns(bool) { - 238 : 318 : return (transferRequests[key].status == STATUS.NONE) && (transferRequests[key].key == 0x0); - 239 : : } - 240 : : - 241 : : function _approveRequest(TransferRequest memory transferRequest , bool isApproved_) internal{ - 242 : : // status - 243 [ + + ]: 78 : if(transferRequest.status != STATUS.WAIT){ - 244 : 2 : revert RuleConditionalTransfer_Wrong_Status(); - 245 : : } - 246 [ + + ]: 38 : if(isApproved_){ - 247 : : // Time - 248 [ + + ]: 44 : if(block.timestamp > (transferRequest.askTime + options.timeLimit.timeLimitToApprove)){ - 249 : 6 : revert RuleConditionalTransfer_timeExceeded(); - 250 : : } - 251 : : // Set status - 252 : 38 : transferRequests[transferRequest.key].status = STATUS.APPROVED; - 253 : : // Set max time - 254 : 38 : transferRequests[transferRequest.key].maxTime = block.timestamp + options.timeLimit.timeLimitToTransfer; - 255 : 38 : emit transferApproved(transferRequest.key, transferRequest.from, transferRequest.to, transferRequest.value, transferRequests[transferRequest.key].id ); - 256 [ + + ]: 41 : if(options.automaticTransfer.isActivate && address(options.automaticTransfer.cmtat) != address(0)){ - 257 : : // Transfer with approval - 258 : : // External call - 259 [ + + ]: 3 : if(options.automaticTransfer.cmtat.allowance(transferRequest.from, address(this)) >= transferRequest.value){ - 260 : : //_updateProcessedTransfer(transferRequest.key); - 261 : : // Will call the ruleEngine and the rule again... - 262 : 2 : options.automaticTransfer.cmtat.safeTransferFrom(transferRequest.from, transferRequest.to, transferRequest.value); - 263 : : } - 264 : : } - 265 : : } else { - 266 : 32 : transferRequests[transferRequest.key].status = STATUS.DENIED; - 267 : 32 : emit transferDenied(transferRequest.key, transferRequest.from, transferRequest.to, transferRequest.value, transferRequests[transferRequest.key].id ); - 268 : : } - 269 : : } - 270 : : - 271 : : function _updateProcessedTransfer(bytes32 key) internal { - 272 : : // Reset to zero - 273 : 10 : transferRequests[key].maxTime = 0; - 274 : 10 : transferRequests[key].askTime = 0; - 275 : : // Change status - 276 : 10 : transferRequests[key].status = STATUS.EXECUTED; - 277 : : // Emit event - 278 : 10 : emit transferProcessed(key, transferRequests[key].from, transferRequests[key].to, transferRequests[key].value, transferRequests[key].id); - 279 : : } - 280 : : } + 156 : : /** + 157 : : * @notice Batch version of {approveTransferRequest} + 158 : : */ + 159 : : function approveTransferRequestBatch( + 160 : : TransferRequestKeyElement[] calldata keyElements, uint256[] calldata partialValues, bool[] calldata isApproved + 161 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + 162 [ + + ]: 12 : if(keyElements.length == 0){ + 163 : 2 : revert RuleConditionalTransfer_EmptyArray(); + 164 : : } + 165 [ + + ]: 10 : if((keyElements.length != partialValues.length) || (partialValues.length != isApproved.length)){ + 166 : 6 : revert RuleConditionalTransfer_InvalidLengthArray(); + 167 : : } + 168 : 24 : for(uint256 i = 0; i < keyElements.length; ++i){ + 169 : 18 : _approveTransferRequestKeyElement(keyElements[i], partialValues[i], isApproved[i]); + 170 : : } + 171 : : } + 172 : : + 173 : : /** + 174 : : * @notice Batch version of {createTransferRequestWithApproval} + 175 : : */ + 176 : : function createTransferRequestWithApprovalBatch( + 177 : : TransferRequestKeyElement[] calldata keyElements + 178 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ + 179 [ + + ]: 4 : if(keyElements.length == 0){ + 180 : 2 : revert RuleConditionalTransfer_EmptyArray(); + 181 : : } + 182 : 11 : for(uint256 i = 0; i < keyElements.length; ++i){ + 183 : 8 : _createTransferRequestWithApproval(keyElements[i]); + 184 : : } + 185 : : } + 186 : : + 187 : : /** + 188 : : * @notice Batch version of {resetRequestStatus} + 189 : : */ + 190 : : function resetRequestStatusBatch( + 191 : : uint256[] memory requestIds + 192 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ + 193 [ + + ]: 6 : if(requestIds.length == 0){ + 194 : 2 : revert RuleConditionalTransfer_EmptyArray(); + 195 : : } + 196 : : // Check id validity before performing actions + 197 : 12 : for(uint256 i = 0; i < requestIds.length; ++i){ + 198 [ + + ]: 12 : if(requestIds[i] + 1 > requestId) { + 199 : 2 : revert RuleConditionalTransfer_InvalidId(); + 200 : : } + 201 : : } + 202 : 9 : for(uint256 i = 0; i < requestIds.length; ++i){ + 203 : 6 : bytes32 key = IdToKey[requestIds[i]]; + 204 : 6 : _resetRequestStatus(key); + 205 : : } + 206 : : } + 207 : : + 208 : : + 209 : : /*** Internal functions ****/ + 210 : : function _approveTransferRequestKeyElement( + 211 : : TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved + 212 : : ) internal { + 213 [ + + ]: 82 : if(partialValue > keyElement.value){ + 214 : 2 : revert RuleConditionalTransfer_InvalidValueApproved(); + 215 : : } + 216 : 120 : bytes32 key = keccak256(abi.encode(keyElement.from, keyElement.to, keyElement.value)); + 217 : 80 : TransferRequest memory transferRequest = transferRequests[key]; + 218 [ + + ]: 80 : if(partialValue > 0 ){ + 219 [ + + ]: 14 : if(! isApproved){ + 220 : 2 : revert RuleConditionalTransfer_CannotDeniedPartially(); + 221 : : } + 222 : : // Denied the first request + 223 : 12 : _approveRequest(transferRequest, false); + 224 : : // Create new request + 225 : 12 : _createTransferRequestWithApproval(TransferRequestKeyElement({from: keyElement.from, to: keyElement.to, value: partialValue})); + 226 : : }else{ + 227 : 66 : _approveRequest(transferRequest, isApproved); + 228 : : } + 229 : : } + 230 : : + 231 : : function _createTransferRequestWithApproval( + 232 : : TransferRequestKeyElement memory keyElement + 233 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ + 234 : : // WAIT => Will overwrite + 235 : : // APPROVED => will overwrite previous status with a new delay + 236 : : // DENIED => will overwrite + 237 : 45 : bytes32 key = keccak256(abi.encode(keyElement.from, keyElement.to, keyElement.value)); + 238 [ # + ]: 30 : if(_checkRequestStatus(key)){ + 239 : 42 : TransferRequest memory newTransferApproval = TransferRequest({ + 240 : : key: key, + 241 : : id: requestId, + 242 : : from: keyElement.from, + 243 : : to: keyElement.to, + 244 : : value: keyElement.value, + 245 : : askTime:0, + 246 : : maxTime : block.timestamp + options.timeLimit.timeLimitToTransfer, + 247 : : status:STATUS.APPROVED + 248 : : }); + 249 : 28 : transferRequests[key] = newTransferApproval; + 250 : 28 : IdToKey[requestId] = key; + 251 : 28 : emit transferApproved(key, keyElement.from, keyElement.to, keyElement.value, requestId); + 252 : 28 : ++requestId; + 253 : : } else { + 254 : : // Overwrite previous approval + 255 : 2 : transferRequests[key].maxTime = block.timestamp + options.timeLimit.timeLimitToTransfer; + 256 : 2 : transferRequests[key].status = STATUS.APPROVED; + 257 : 2 : emit transferApproved(key, keyElement.from, keyElement.to, keyElement.value, transferRequests[key].id); + 258 : : } + 259 : : } + 260 : : + 261 : : function _resetRequestStatus( + 262 : : bytes32 key + 263 : : ) internal { + 264 : 20 : transferRequests[key].status = STATUS.NONE; + 265 : 20 : emit transferReset(key, transferRequests[key].from, transferRequests[key].to, transferRequests[key].value, transferRequests[key].id ); + 266 : : } + 267 : : + 268 : : function _checkRequestStatus(bytes32 key) internal view returns(bool) { + 269 : : // Status NONE not enough because reset is possible + 270 : 357 : return (transferRequests[key].status == STATUS.NONE) && (transferRequests[key].key == 0x0); + 271 : : } + 272 : : + 273 : : function _approveRequest(TransferRequest memory transferRequest , bool isApproved) internal{ + 274 : : // status + 275 [ + + ]: 92 : if(transferRequest.status != STATUS.WAIT){ + 276 : 2 : revert RuleConditionalTransfer_Wrong_Status(); + 277 : : } + 278 [ + + ]: 45 : if(isApproved){ + 279 : : // Time + 280 [ + + ]: 54 : if(block.timestamp > (transferRequest.askTime + options.timeLimit.timeLimitToApprove)){ + 281 : 6 : revert RuleConditionalTransfer_timeExceeded(); + 282 : : } + 283 : : // Set status + 284 : 48 : transferRequests[transferRequest.key].status = STATUS.APPROVED; + 285 : : // Set max time + 286 : 48 : transferRequests[transferRequest.key].maxTime = block.timestamp + options.timeLimit.timeLimitToTransfer; + 287 : 48 : emit transferApproved(transferRequest.key, transferRequest.from, transferRequest.to, transferRequest.value, transferRequests[transferRequest.key].id ); + 288 [ + + ]: 54 : if(options.automaticTransfer.isActivate && address(options.automaticTransfer.cmtat) != address(0)){ + 289 : : // Transfer with approval + 290 : : // External call + 291 [ + + ]: 6 : if(options.automaticTransfer.cmtat.allowance(transferRequest.from, address(this)) >= transferRequest.value){ + 292 : : // Will call the ruleEngine and the rule again... + 293 : 4 : options.automaticTransfer.cmtat.safeTransferFrom(transferRequest.from, transferRequest.to, transferRequest.value); + 294 : : } + 295 : : } + 296 : : } else { + 297 : 36 : transferRequests[transferRequest.key].status = STATUS.DENIED; + 298 : 36 : emit transferDenied(transferRequest.key, transferRequest.from, transferRequest.to, transferRequest.value, transferRequests[transferRequest.key].id ); + 299 : : } + 300 : : } + 301 : : + 302 : : /** + 303 : : * @notice update the request during a transfer + 304 : : */ + 305 : : function _updateProcessedTransfer(bytes32 key) internal { + 306 : : // Reset to zero + 307 : 20 : transferRequests[key].maxTime = 0; + 308 : 20 : transferRequests[key].askTime = 0; + 309 : : // Change status + 310 : 20 : transferRequests[key].status = STATUS.EXECUTED; + 311 : : // Emit event + 312 : 20 : emit transferProcessed(key, transferRequests[key].from, transferRequests[key].to, transferRequests[key].value, transferRequests[key].id); + 313 : : } + 314 : : } diff --git a/doc/test/coverage/src/rules/operation/abstract/index-sort-b.html b/doc/test/coverage/src/rules/operation/abstract/index-sort-b.html index 5ba2b4f..ceeab30 100644 --- a/doc/test/coverage/src/rules/operation/abstract/index-sort-b.html +++ b/doc/test/coverage/src/rules/operation/abstract/index-sort-b.html @@ -31,18 +31,18 @@ lcov.info Lines: - 94 - 94 + 96 + 96 100.0 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: - 17 18 - 94.4 % + 19 + 94.7 % @@ -87,9 +87,9 @@
100.0%
100.0 % - 94 / 94 - 94.4 % - 17 / 18 + 96 / 96 + 94.7 % + 18 / 19 98.1 % 53 / 54 diff --git a/doc/test/coverage/src/rules/operation/abstract/index-sort-f.html b/doc/test/coverage/src/rules/operation/abstract/index-sort-f.html index 8bfc934..8096c28 100644 --- a/doc/test/coverage/src/rules/operation/abstract/index-sort-f.html +++ b/doc/test/coverage/src/rules/operation/abstract/index-sort-f.html @@ -31,18 +31,18 @@ lcov.info Lines: - 94 - 94 + 96 + 96 100.0 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: - 17 18 - 94.4 % + 19 + 94.7 % @@ -87,9 +87,9 @@
100.0%
100.0 % - 94 / 94 - 94.4 % - 17 / 18 + 96 / 96 + 94.7 % + 18 / 19 98.1 % 53 / 54 diff --git a/doc/test/coverage/src/rules/operation/abstract/index-sort-l.html b/doc/test/coverage/src/rules/operation/abstract/index-sort-l.html index b1b2f31..e6d471d 100644 --- a/doc/test/coverage/src/rules/operation/abstract/index-sort-l.html +++ b/doc/test/coverage/src/rules/operation/abstract/index-sort-l.html @@ -31,18 +31,18 @@ lcov.info Lines: - 94 - 94 + 96 + 96 100.0 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: - 17 18 - 94.4 % + 19 + 94.7 % @@ -87,9 +87,9 @@
100.0%
100.0 % - 94 / 94 - 94.4 % - 17 / 18 + 96 / 96 + 94.7 % + 18 / 19 98.1 % 53 / 54 diff --git a/doc/test/coverage/src/rules/operation/abstract/index.html b/doc/test/coverage/src/rules/operation/abstract/index.html index 2fe8a0d..1e6e812 100644 --- a/doc/test/coverage/src/rules/operation/abstract/index.html +++ b/doc/test/coverage/src/rules/operation/abstract/index.html @@ -31,18 +31,18 @@ lcov.info Lines: - 94 - 94 + 96 + 96 100.0 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: - 17 18 - 94.4 % + 19 + 94.7 % @@ -87,9 +87,9 @@
100.0%
100.0 % - 94 / 94 - 94.4 % - 17 / 18 + 96 / 96 + 94.7 % + 18 / 19 98.1 % 53 / 54 diff --git a/doc/test/coverage/src/rules/operation/index-sort-b.html b/doc/test/coverage/src/rules/operation/index-sort-b.html index bcc11c2..d557abc 100644 --- a/doc/test/coverage/src/rules/operation/index-sort-b.html +++ b/doc/test/coverage/src/rules/operation/index-sort-b.html @@ -31,13 +31,13 @@ lcov.info Lines: - 78 - 79 - 98.7 % + 84 + 85 + 98.8 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 15 @@ -49,9 +49,9 @@ Branches: - 32 - 34 - 94.1 % + 38 + 42 + 90.5 % @@ -84,14 +84,14 @@ RuleConditionalTransfer.sol -
98.7%98.7%
+
98.8%98.8%
- 98.7 % - 78 / 79 + 98.8 % + 84 / 85 93.8 % 15 / 16 - 94.1 % - 32 / 34 + 90.5 % + 38 / 42 diff --git a/doc/test/coverage/src/rules/operation/index-sort-f.html b/doc/test/coverage/src/rules/operation/index-sort-f.html index dd060b7..412cd56 100644 --- a/doc/test/coverage/src/rules/operation/index-sort-f.html +++ b/doc/test/coverage/src/rules/operation/index-sort-f.html @@ -31,13 +31,13 @@ lcov.info Lines: - 78 - 79 - 98.7 % + 84 + 85 + 98.8 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 15 @@ -49,9 +49,9 @@ Branches: - 32 - 34 - 94.1 % + 38 + 42 + 90.5 % @@ -84,14 +84,14 @@ RuleConditionalTransfer.sol -
98.7%98.7%
+
98.8%98.8%
- 98.7 % - 78 / 79 + 98.8 % + 84 / 85 93.8 % 15 / 16 - 94.1 % - 32 / 34 + 90.5 % + 38 / 42 diff --git a/doc/test/coverage/src/rules/operation/index-sort-l.html b/doc/test/coverage/src/rules/operation/index-sort-l.html index 83181d3..af166d2 100644 --- a/doc/test/coverage/src/rules/operation/index-sort-l.html +++ b/doc/test/coverage/src/rules/operation/index-sort-l.html @@ -31,13 +31,13 @@ lcov.info Lines: - 78 - 79 - 98.7 % + 84 + 85 + 98.8 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 15 @@ -49,9 +49,9 @@ Branches: - 32 - 34 - 94.1 % + 38 + 42 + 90.5 % @@ -84,14 +84,14 @@ RuleConditionalTransfer.sol -
98.7%98.7%
+
98.8%98.8%
- 98.7 % - 78 / 79 + 98.8 % + 84 / 85 93.8 % 15 / 16 - 94.1 % - 32 / 34 + 90.5 % + 38 / 42 diff --git a/doc/test/coverage/src/rules/operation/index.html b/doc/test/coverage/src/rules/operation/index.html index ae0bbcb..2ae074f 100644 --- a/doc/test/coverage/src/rules/operation/index.html +++ b/doc/test/coverage/src/rules/operation/index.html @@ -31,13 +31,13 @@ lcov.info Lines: - 78 - 79 - 98.7 % + 84 + 85 + 98.8 % Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 15 @@ -49,9 +49,9 @@ Branches: - 32 - 34 - 94.1 % + 38 + 42 + 90.5 % @@ -84,14 +84,14 @@ RuleConditionalTransfer.sol -
98.7%98.7%
+
98.8%98.8%
- 98.7 % - 78 / 79 + 98.8 % + 84 / 85 93.8 % 15 / 16 - 94.1 % - 32 / 34 + 90.5 % + 38 / 42 diff --git a/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func-sort-c.html b/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func-sort-c.html index 0b60d76..d6b2d99 100644 --- a/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func-sort-c.html +++ b/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 3 diff --git a/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func.html b/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func.html index 33fcc3e..b63e470 100644 --- a/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func.html +++ b/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 3 diff --git a/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html b/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html index 4cbb535..8f51703 100644 --- a/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html +++ b/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 3 diff --git a/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html b/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html index d8b841d..03e72d5 100644 --- a/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html +++ b/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 6 diff --git a/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func.html b/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func.html index 34d35df..0dfd668 100644 --- a/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func.html +++ b/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 6 diff --git a/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.gcov.html b/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.gcov.html index 707a87b..a629c51 100644 --- a/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.gcov.html +++ b/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 6 diff --git a/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func-sort-c.html b/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func-sort-c.html index 1123b81..625c644 100644 --- a/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func-sort-c.html +++ b/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 3 diff --git a/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func.html b/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func.html index 21066ab..0b98954 100644 --- a/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func.html +++ b/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 3 diff --git a/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.gcov.html b/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.gcov.html index 0380e6e..158f5d7 100644 --- a/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.gcov.html +++ b/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 3 diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func-sort-c.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func-sort-c.html index 3a1b62b..7380e8e 100644 --- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func-sort-c.html +++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 8 @@ -90,19 +90,19 @@ RuleAddressList.addAddressToTheList - 28 - - - RuleAddressList.addressIsListed - 57 + 40 RuleAddressList._contextSuffixLength - 60 + 72 RuleAddressList._msgSender - 60 + 72 + + + RuleAddressList.addressIsListed + 83
diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func.html index 7688e84..0905f5b 100644 --- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func.html +++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 8 @@ -70,7 +70,7 @@ RuleAddressList._contextSuffixLength - 60 + 72 RuleAddressList._msgData @@ -78,11 +78,11 @@ RuleAddressList._msgSender - 60 + 72 RuleAddressList.addAddressToTheList - 28 + 40 RuleAddressList.addAddressesToTheList @@ -90,7 +90,7 @@ RuleAddressList.addressIsListed - 57 + 83 RuleAddressList.numberListedAddress diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html index 8c4f707..ae31a25 100644 --- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html +++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 8 @@ -133,7 +133,7 @@ 62 : : function addAddressToTheList( 63 : : address _newWhitelistAddress 64 : : ) public onlyRole(ADDRESS_LIST_ROLE) { - 65 : 54 : _addAddressToThelist(_newWhitelistAddress); + 65 : 78 : _addAddressToThelist(_newWhitelistAddress); 66 : : } 67 : : 68 : : /** @@ -167,7 +167,7 @@ 96 : : function addressIsListed( 97 : : address _targetAddress 98 : : ) public view returns (bool) { - 99 : 345 : return _addressIsListed(_targetAddress); + 99 : 423 : return _addressIsListed(_targetAddress); 100 : : } 101 : : 102 : : @@ -180,7 +180,7 @@ 109 : : override(ERC2771Context, Context) 110 : : returns (address sender) 111 : : { - 112 : 180 : return ERC2771Context._msgSender(); + 112 : 216 : return ERC2771Context._msgSender(); 113 : : } 114 : : 115 : : /** @@ -199,7 +199,7 @@ 128 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule 129 : : */ 130 : : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { - 131 : 180 : return ERC2771Context._contextSuffixLength(); + 131 : 216 : return ERC2771Context._contextSuffixLength(); 132 : : } 133 : : } diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func-sort-c.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func-sort-c.html index 9ad25a7..511dbce 100644 --- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func-sort-c.html +++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 6 @@ -86,11 +86,11 @@ RuleAddressListInternal._addAddressToThelist - 27 + 39 RuleAddressListInternal._addressIsListed - 115 + 141
diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func.html index a964c88..66d10d6 100644 --- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func.html +++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 6 @@ -70,7 +70,7 @@ RuleAddressListInternal._addAddressToThelist - 27 + 39 RuleAddressListInternal._addAddressesToThelist @@ -78,7 +78,7 @@ RuleAddressListInternal._addressIsListed - 115 + 141 RuleAddressListInternal._numberListedAddress diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.gcov.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.gcov.html index 99e1724..5e74800 100644 --- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.gcov.html +++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 6 @@ -131,12 +131,12 @@ 60 : : function _addAddressToThelist( 61 : : address _newlistAddress 62 : : ) internal { - 63 [ + + ]: 27 : if(list[_newlistAddress]) + 63 [ + + ]: 39 : if(list[_newlistAddress]) 64 : : { 65 : 2 : revert Rulelist_AddressAlreadylisted(); 66 : : } - 67 : 52 : list[_newlistAddress] = true; - 68 : 52 : ++numAddressesList; + 67 : 76 : list[_newlistAddress] = true; + 68 : 76 : ++numAddressesList; 69 : : } 70 : : 71 : : /** @@ -173,7 +173,7 @@ 102 : : function _addressIsListed( 103 : : address _targetAddress 104 : : ) internal view returns (bool) { - 105 : 230 : return list[_targetAddress]; + 105 : 282 : return list[_targetAddress]; 106 : : } 107 : : } diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-b.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-b.html index 7c0ccfa..2c18e01 100644 --- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-b.html +++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-b.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 14 diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-f.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-f.html index a1b176a..3b3a30a 100644 --- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-f.html +++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 14 diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-l.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-l.html index fd999fe..ab0cc0e 100644 --- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-l.html +++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 14 diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index.html index b53a392..1c40a15 100644 --- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index.html +++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 14 diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html b/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html index 7ac9ecf..4495caa 100644 --- a/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html +++ b/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 1 diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func.html b/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func.html index 33499de..97372fa 100644 --- a/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func.html +++ b/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 1 diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.gcov.html b/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.gcov.html index a779a34..a4ed5c4 100644 --- a/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.gcov.html +++ b/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 1 diff --git a/doc/test/coverage/src/rules/validation/abstract/index-sort-b.html b/doc/test/coverage/src/rules/validation/abstract/index-sort-b.html index d9e93ed..760e987 100644 --- a/doc/test/coverage/src/rules/validation/abstract/index-sort-b.html +++ b/doc/test/coverage/src/rules/validation/abstract/index-sort-b.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 1 diff --git a/doc/test/coverage/src/rules/validation/abstract/index-sort-f.html b/doc/test/coverage/src/rules/validation/abstract/index-sort-f.html index 0564c85..f0ef7d6 100644 --- a/doc/test/coverage/src/rules/validation/abstract/index-sort-f.html +++ b/doc/test/coverage/src/rules/validation/abstract/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 1 diff --git a/doc/test/coverage/src/rules/validation/abstract/index-sort-l.html b/doc/test/coverage/src/rules/validation/abstract/index-sort-l.html index 34e0d10..464156f 100644 --- a/doc/test/coverage/src/rules/validation/abstract/index-sort-l.html +++ b/doc/test/coverage/src/rules/validation/abstract/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 1 diff --git a/doc/test/coverage/src/rules/validation/abstract/index.html b/doc/test/coverage/src/rules/validation/abstract/index.html index 43f9ffe..093d2c0 100644 --- a/doc/test/coverage/src/rules/validation/abstract/index.html +++ b/doc/test/coverage/src/rules/validation/abstract/index.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 1 diff --git a/doc/test/coverage/src/rules/validation/index-sort-b.html b/doc/test/coverage/src/rules/validation/index-sort-b.html index 877d72e..4fe50bf 100644 --- a/doc/test/coverage/src/rules/validation/index-sort-b.html +++ b/doc/test/coverage/src/rules/validation/index-sort-b.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 12 @@ -82,7 +82,7 @@ Branches Sort by branch coverage - RuleWhitelist.sol + RuleBlacklist.sol
100.0%
@@ -94,7 +94,7 @@ 8 / 8 - RuleBlacklist.sol + RuleWhitelist.sol
100.0%
diff --git a/doc/test/coverage/src/rules/validation/index-sort-f.html b/doc/test/coverage/src/rules/validation/index-sort-f.html index 424f9dd..946c249 100644 --- a/doc/test/coverage/src/rules/validation/index-sort-f.html +++ b/doc/test/coverage/src/rules/validation/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 12 @@ -94,7 +94,7 @@ 10 / 10 - RuleWhitelist.sol + RuleBlacklist.sol
100.0%
@@ -106,7 +106,7 @@ 8 / 8 - RuleBlacklist.sol + RuleWhitelist.sol
100.0%
diff --git a/doc/test/coverage/src/rules/validation/index-sort-l.html b/doc/test/coverage/src/rules/validation/index-sort-l.html index 4baedd9..ca1eb77 100644 --- a/doc/test/coverage/src/rules/validation/index-sort-l.html +++ b/doc/test/coverage/src/rules/validation/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 12 @@ -94,7 +94,7 @@ 10 / 10 - RuleWhitelist.sol + RuleBlacklist.sol
100.0%
@@ -106,7 +106,7 @@ 8 / 8 - RuleBlacklist.sol + RuleWhitelist.sol
100.0%
diff --git a/doc/test/coverage/src/rules/validation/index.html b/doc/test/coverage/src/rules/validation/index.html index 374f3ea..7799d57 100644 --- a/doc/test/coverage/src/rules/validation/index.html +++ b/doc/test/coverage/src/rules/validation/index.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 12 diff --git a/doc/test/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html b/doc/test/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html index 2e88446..70f8339 100644 --- a/doc/test/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html +++ b/doc/test/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 2 diff --git a/doc/test/coverage/test/utils/SanctionListOracle.sol.func.html b/doc/test/coverage/test/utils/SanctionListOracle.sol.func.html index 4fedaf7..0928957 100644 --- a/doc/test/coverage/test/utils/SanctionListOracle.sol.func.html +++ b/doc/test/coverage/test/utils/SanctionListOracle.sol.func.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 2 diff --git a/doc/test/coverage/test/utils/SanctionListOracle.sol.gcov.html b/doc/test/coverage/test/utils/SanctionListOracle.sol.gcov.html index f1a8bb0..fb570e9 100644 --- a/doc/test/coverage/test/utils/SanctionListOracle.sol.gcov.html +++ b/doc/test/coverage/test/utils/SanctionListOracle.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 2 diff --git a/doc/test/coverage/test/utils/index-sort-b.html b/doc/test/coverage/test/utils/index-sort-b.html index 7e7cf2c..252f067 100644 --- a/doc/test/coverage/test/utils/index-sort-b.html +++ b/doc/test/coverage/test/utils/index-sort-b.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 2 diff --git a/doc/test/coverage/test/utils/index-sort-f.html b/doc/test/coverage/test/utils/index-sort-f.html index 5fdec17..25b4893 100644 --- a/doc/test/coverage/test/utils/index-sort-f.html +++ b/doc/test/coverage/test/utils/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 2 diff --git a/doc/test/coverage/test/utils/index-sort-l.html b/doc/test/coverage/test/utils/index-sort-l.html index 744f83f..2c71311 100644 --- a/doc/test/coverage/test/utils/index-sort-l.html +++ b/doc/test/coverage/test/utils/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 2 diff --git a/doc/test/coverage/test/utils/index.html b/doc/test/coverage/test/utils/index.html index 7ab6a37..487e98c 100644 --- a/doc/test/coverage/test/utils/index.html +++ b/doc/test/coverage/test/utils/index.html @@ -37,7 +37,7 @@ Date: - 2024-05-14 11:13:54 + 2024-05-15 12:20:21 Functions: 2 diff --git a/doc/test/lcov.info b/doc/test/lcov.info index d13b46a..0ce6817 100644 --- a/doc/test/lcov.info +++ b/doc/test/lcov.info @@ -160,31 +160,31 @@ DA:107,1 DA:110,6 DA:110,6 FN:116,RuleEngine.operateOnTransfer -FNDA:26,RuleEngine.operateOnTransfer -DA:118,25 -DA:118,25 +FNDA:45,RuleEngine.operateOnTransfer +DA:118,44 +DA:118,44 BRDA:118,4,0,7 -BRDA:118,4,1,18 +BRDA:118,4,1,37 DA:119,7 DA:119,7 -DA:122,18 -DA:122,18 -DA:122,18 +DA:122,37 +DA:122,37 +DA:122,37 FN:128,RuleEngine._msgSender -FNDA:203,RuleEngine._msgSender -DA:134,203 -DA:134,203 -DA:134,203 +FNDA:244,RuleEngine._msgSender +DA:134,244 +DA:134,244 +DA:134,244 FN:140,RuleEngine._msgData FNDA:0,RuleEngine._msgData DA:146,0 DA:146,0 DA:146,0 FN:152,RuleEngine._contextSuffixLength -FNDA:203,RuleEngine._contextSuffixLength -DA:153,203 -DA:153,203 -DA:153,203 +FNDA:244,RuleEngine._contextSuffixLength +DA:153,244 +DA:153,244 +DA:153,244 FNF:7 FNH:6 LF:27 @@ -225,11 +225,11 @@ DA:51,17 DA:53,14 DA:53,14 FN:61,RuleEngineOperation.addRuleOperation -FNDA:46,RuleEngineOperation.addRuleOperation -DA:62,46 -DA:62,46 -DA:63,44 -DA:63,44 +FNDA:68,RuleEngineOperation.addRuleOperation +DA:62,68 +DA:62,68 +DA:63,66 +DA:63,66 FN:76,RuleEngineOperation.removeRuleOperation FNDA:5,RuleEngineOperation.removeRuleOperation DA:80,5 @@ -258,24 +258,24 @@ FNDA:5,RuleEngineOperation.rulesOperation DA:130,5 DA:130,5 FN:140,RuleEngineOperation._operateOnTransfer -FNDA:18,RuleEngineOperation._operateOnTransfer -DA:145,18 -DA:145,18 -DA:146,18 -DA:146,18 -DA:146,25 -DA:146,7 -DA:147,14 -DA:147,14 -DA:147,14 -DA:152,14 -DA:152,14 -BRDA:152,1,0,7 -BRDA:152,1,1,7 -DA:153,7 -DA:153,7 -DA:156,11 -DA:156,11 +FNDA:37,RuleEngineOperation._operateOnTransfer +DA:145,37 +DA:145,37 +DA:146,37 +DA:146,37 +DA:146,53 +DA:146,16 +DA:147,33 +DA:147,33 +DA:147,33 +DA:152,33 +DA:152,33 +BRDA:152,1,0,17 +BRDA:152,1,1,16 +DA:153,17 +DA:153,17 +DA:156,20 +DA:156,20 FNF:11 FNH:11 LF:25 @@ -350,11 +350,11 @@ DA:133,5 DA:133,5 FN:143,RuleEngineValidation.detectTransferRestrictionValidation FNDA:3,RuleEngineValidation.detectTransferRestrictionValidation -DA:148,52 -DA:148,52 -DA:149,52 -DA:149,52 -DA:149,62 +DA:148,71 +DA:148,71 +DA:149,71 +DA:149,71 +DA:149,81 DA:149,10 DA:150,32 DA:150,32 @@ -365,16 +365,16 @@ BRDA:155,1,0,22 BRDA:155,1,1,10 DA:156,22 DA:156,22 -DA:160,30 -DA:160,30 -DA:160,30 +DA:160,49 +DA:160,49 +DA:160,49 FN:170,RuleEngineValidation.validateTransferValidation FNDA:2,RuleEngineValidation.validateTransferValidation -DA:175,27 -DA:175,27 -DA:175,27 -DA:175,27 -DA:175,27 +DA:175,46 +DA:175,46 +DA:175,46 +DA:175,46 +DA:175,46 FNF:12 FNH:12 LF:26 @@ -415,24 +415,24 @@ DA:34,44 DA:36,44 DA:36,44 FN:46,RuleInternal._addRule -FNDA:112,RuleInternal._addRule -DA:47,112 -DA:47,112 -DA:47,112 -DA:47,112 +FNDA:134,RuleInternal._addRule +DA:47,134 +DA:47,134 +DA:47,134 +DA:47,134 BRDA:47,3,0,2 -BRDA:47,3,1,110 +BRDA:47,3,1,132 DA:49,2 DA:49,2 -DA:51,110 +DA:51,132 BRDA:51,4,0,2 -BRDA:51,4,1,108 +BRDA:51,4,1,130 DA:53,2 DA:53,2 -DA:55,108 -DA:55,108 -DA:56,108 -DA:56,108 +DA:55,130 +DA:55,130 +DA:56,130 +DA:56,130 FN:69,RuleInternal._removeRule FNDA:55,RuleInternal._removeRule DA:74,55 @@ -480,575 +480,610 @@ BRH:15 end_of_record TN: SF:src/rules/operation/RuleConditionalTransfer.sol -FN:45,RuleConditionalTransfer.createTransferRequest -FNDA:91,RuleConditionalTransfer.createTransferRequest -DA:51,94 -DA:51,94 -DA:51,94 -DA:52,94 -DA:52,94 -DA:52,94 -DA:53,94 -DA:53,94 -BRDA:53,0,0,1 -BRDA:53,0,1,93 -DA:54,1 -DA:54,1 -DA:57,93 -DA:57,93 -BRDA:57,1,0,- -BRDA:57,1,1,90 -DA:58,90 -DA:58,90 -DA:59,90 -DA:59,90 -DA:59,90 -DA:70,90 -DA:70,90 -DA:71,90 -DA:71,90 -DA:72,90 -DA:72,90 -DA:73,90 -DA:73,90 -DA:76,3 -DA:76,3 -DA:77,3 -DA:77,3 -DA:78,3 -DA:78,3 -FN:82,RuleConditionalTransfer.createTransferRequestBatch +FN:50,RuleConditionalTransfer.createTransferRequest +FNDA:102,RuleConditionalTransfer.createTransferRequest +DA:56,105 +DA:56,105 +DA:56,105 +DA:57,105 +DA:57,105 +DA:57,105 +DA:58,105 +DA:58,105 +BRDA:58,0,0,1 +BRDA:58,0,1,104 +DA:59,1 +DA:59,1 +DA:61,104 +DA:61,104 +BRDA:61,1,0,- +BRDA:61,1,1,101 +DA:62,101 +DA:62,101 +DA:63,101 +DA:63,101 +DA:63,101 +DA:74,101 +DA:74,101 +DA:75,101 +DA:75,101 +DA:76,101 +DA:76,101 +DA:77,101 +DA:77,101 +DA:80,3 +DA:80,3 +DA:81,3 +DA:81,3 +DA:82,3 +DA:82,3 +FN:89,RuleConditionalTransfer.createTransferRequestBatch FNDA:3,RuleConditionalTransfer.createTransferRequestBatch -DA:83,3 -DA:83,3 -BRDA:83,2,0,1 -BRDA:83,2,1,2 -DA:84,1 -DA:84,1 -DA:86,2 -DA:86,2 -BRDA:86,3,0,1 -BRDA:86,3,1,1 -DA:87,1 -DA:87,1 -DA:89,1 -DA:89,1 -DA:89,4 -DA:89,3 DA:90,3 DA:90,3 -FN:97,RuleConditionalTransfer.cancelTransferRequest -FNDA:5,RuleConditionalTransfer.cancelTransferRequest -DA:100,5 -DA:100,5 -FN:106,RuleConditionalTransfer.cancelTransferRequestBatch +BRDA:90,2,0,1 +BRDA:90,2,1,2 +DA:91,1 +DA:91,1 +DA:93,2 +DA:93,2 +BRDA:93,3,0,1 +BRDA:93,3,1,1 +DA:94,1 +DA:94,1 +DA:96,1 +DA:96,1 +DA:96,4 +DA:96,3 +DA:97,3 +DA:97,3 +FN:104,RuleConditionalTransfer.cancelTransferRequest +FNDA:6,RuleConditionalTransfer.cancelTransferRequest +DA:107,6 +DA:107,6 +FN:113,RuleConditionalTransfer.cancelTransferRequestBatch FNDA:3,RuleConditionalTransfer.cancelTransferRequestBatch -DA:109,3 -DA:109,3 -BRDA:109,4,0,1 -BRDA:109,4,1,2 -DA:110,1 -DA:110,1 -DA:113,2 -DA:113,2 -DA:113,6 -DA:113,4 -DA:114,5 -DA:114,5 -DA:114,5 -BRDA:114,5,0,1 -BRDA:114,5,1,4 -DA:115,1 -DA:115,1 -DA:118,1 -DA:118,1 -DA:118,4 -DA:118,3 -DA:119,3 -DA:119,3 -FN:124,RuleConditionalTransfer._cancelTransferRequest -FNDA:8,RuleConditionalTransfer._cancelTransferRequest -DA:127,8 -DA:127,8 -DA:127,8 -BRDA:127,6,0,1 -BRDA:127,6,1,7 -DA:128,1 -DA:128,1 -DA:130,7 -DA:130,7 -DA:132,7 -DA:132,7 -DA:132,7 -BRDA:132,7,0,1 -BRDA:132,7,1,6 -DA:133,1 -DA:133,1 -DA:136,6 -DA:136,6 -DA:136,6 -DA:137,2 -DA:137,2 -BRDA:136,8,0,1 -BRDA:136,8,1,5 -DA:139,1 -DA:139,1 -DA:141,5 -DA:141,5 -FN:145,RuleConditionalTransfer.getRequestTrade +DA:116,3 +DA:116,3 +BRDA:116,4,0,1 +BRDA:116,4,1,2 +DA:117,1 +DA:117,1 +DA:120,2 +DA:120,2 +DA:120,6 +DA:120,4 +DA:121,5 +DA:121,5 +DA:121,5 +BRDA:121,5,0,1 +BRDA:121,5,1,4 +DA:122,1 +DA:122,1 +DA:125,1 +DA:125,1 +DA:125,4 +DA:125,3 +DA:126,3 +DA:126,3 +FN:131,RuleConditionalTransfer._cancelTransferRequest +FNDA:9,RuleConditionalTransfer._cancelTransferRequest +DA:134,9 +DA:134,9 +DA:134,9 +BRDA:134,6,0,1 +BRDA:134,6,1,8 +DA:135,1 +DA:135,1 +DA:137,8 +DA:137,8 +DA:139,8 +DA:139,8 +DA:139,8 +BRDA:139,7,0,1 +BRDA:139,7,1,7 +DA:140,1 +DA:140,1 +DA:143,7 +DA:143,7 +DA:143,7 +DA:144,2 +DA:144,2 +BRDA:143,8,0,1 +BRDA:143,8,1,6 +DA:146,1 +DA:146,1 +DA:148,6 +DA:148,6 +FN:152,RuleConditionalTransfer.getRequestTrade FNDA:57,RuleConditionalTransfer.getRequestTrade -DA:146,57 -DA:146,57 -DA:146,57 -DA:147,57 -DA:147,57 -FN:155,RuleConditionalTransfer.getRequestByStatus +DA:153,57 +DA:153,57 +DA:153,57 +DA:154,57 +DA:154,57 +FN:162,RuleConditionalTransfer.getRequestByStatus FNDA:35,RuleConditionalTransfer.getRequestByStatus -DA:156,35 -DA:156,35 -DA:157,35 -DA:157,35 -DA:158,35 -DA:158,35 -DA:161,35 -DA:161,35 -DA:161,73 -DA:161,38 -DA:162,38 -DA:162,38 -BRDA:162,9,0,36 -BRDA:162,9,1,38 -DA:163,36 -DA:163,36 -DA:168,35 +DA:163,35 +DA:163,35 +DA:164,35 +DA:164,35 +DA:165,35 +DA:165,35 DA:168,35 DA:168,35 -DA:171,35 -DA:171,35 -DA:171,73 -DA:171,38 -DA:172,38 -DA:172,38 -BRDA:172,10,0,- -BRDA:172,10,1,36 -DA:174,36 -DA:174,36 -DA:175,36 -DA:175,36 -DA:176,36 -DA:176,36 -DA:179,35 -DA:179,35 -FN:186,RuleConditionalTransfer.operateOnTransfer -FNDA:14,RuleConditionalTransfer.operateOnTransfer -DA:192,14 -DA:192,14 -BRDA:192,11,0,2 -BRDA:192,11,1,12 -DA:193,2 -DA:193,2 -DA:195,12 -DA:195,12 -DA:195,12 -DA:196,12 -DA:196,12 -BRDA:196,12,0,5 -BRDA:196,12,1,7 -DA:197,5 -DA:197,5 -DA:198,5 -DA:198,5 -DA:200,7 -DA:200,7 -FN:210,RuleConditionalTransfer.detectTransferRestriction -FNDA:8,RuleConditionalTransfer.detectTransferRestriction -DA:215,8 -DA:215,8 -DA:215,8 -DA:216,8 -DA:216,8 -DA:216,8 -DA:216,8 -BRDA:216,13,0,6 -BRDA:216,13,1,2 -DA:217,6 -DA:217,6 -DA:220,2 -DA:220,2 -DA:220,2 -FN:229,RuleConditionalTransfer.canReturnTransferRestrictionCode +DA:168,73 +DA:168,38 +DA:169,38 +DA:169,38 +BRDA:169,9,0,36 +BRDA:169,9,1,38 +DA:170,36 +DA:170,36 +DA:175,35 +DA:175,35 +DA:175,35 +DA:178,35 +DA:178,35 +DA:178,73 +DA:178,38 +DA:179,38 +DA:179,38 +BRDA:179,10,0,- +BRDA:179,10,1,36 +DA:181,36 +DA:181,36 +DA:182,36 +DA:182,36 +DA:183,36 +DA:183,36 +DA:186,35 +DA:186,35 +FN:193,RuleConditionalTransfer.operateOnTransfer +FNDA:33,RuleConditionalTransfer.operateOnTransfer +DA:199,33 +DA:199,33 +DA:199,33 +DA:199,33 +BRDA:199,11,0,2 +BRDA:199,11,1,16 +DA:200,18 +DA:200,18 +DA:200,18 +DA:200,3 +BRDA:200,12,0,2 +BRDA:200,12,1,16 +DA:201,2 +DA:201,2 +DA:206,31 +DA:206,31 +BRDA:206,13,0,4 +BRDA:206,13,1,27 +DA:207,4 +DA:207,4 +DA:209,27 +DA:209,27 +DA:209,27 +DA:210,27 +DA:210,27 +BRDA:210,14,0,10 +BRDA:210,14,1,17 +DA:211,10 +DA:211,10 +DA:212,10 +DA:212,10 +DA:214,17 +DA:214,17 +FN:224,RuleConditionalTransfer.detectTransferRestriction +FNDA:11,RuleConditionalTransfer.detectTransferRestriction +DA:230,11 +DA:230,11 +DA:230,11 +DA:230,11 +BRDA:230,15,0,- +BRDA:230,15,1,1 +DA:231,3 +DA:231,3 +DA:231,3 +DA:231,2 +BRDA:231,16,0,- +BRDA:231,16,1,1 +DA:232,1 +DA:232,1 +DA:232,1 +DA:235,10 +DA:235,10 +DA:235,10 +DA:236,10 +DA:236,10 +DA:236,10 +DA:236,10 +BRDA:236,17,0,8 +BRDA:236,17,1,2 +DA:237,8 +DA:237,8 +DA:240,2 +DA:240,2 +DA:240,2 +FN:249,RuleConditionalTransfer.canReturnTransferRestrictionCode FNDA:2,RuleConditionalTransfer.canReturnTransferRestrictionCode -DA:232,2 -DA:232,2 -DA:233,2 -DA:233,2 -FN:241,RuleConditionalTransfer.messageForTransferRestriction +DA:252,2 +DA:252,2 +DA:253,2 +DA:253,2 +FN:261,RuleConditionalTransfer.messageForTransferRestriction FNDA:3,RuleConditionalTransfer.messageForTransferRestriction -DA:244,3 -DA:244,3 -BRDA:244,14,0,2 -BRDA:244,14,1,1 -DA:245,2 -DA:245,2 -DA:247,1 -DA:247,1 -FN:258,RuleConditionalTransfer._validateBurnMint -FNDA:22,RuleConditionalTransfer._validateBurnMint -DA:264,22 -DA:264,22 -BRDA:263,15,0,2 -BRDA:263,15,1,20 -DA:267,2 -DA:267,2 -DA:269,20 -DA:269,20 -FN:278,RuleConditionalTransfer._validateApproval -FNDA:20,RuleConditionalTransfer._validateApproval -DA:281,20 -DA:281,20 -DA:281,20 -DA:282,20 -DA:282,20 -DA:282,20 -DA:284,20 -DA:284,20 -BRDA:284,16,0,7 -BRDA:284,16,1,13 -DA:286,7 -DA:286,7 -DA:288,13 -DA:288,13 -FN:295,RuleConditionalTransfer._msgSender -FNDA:328,RuleConditionalTransfer._msgSender -DA:301,328 -DA:301,328 -DA:301,328 -FN:307,RuleConditionalTransfer._msgData +DA:264,3 +DA:264,3 +BRDA:264,18,0,2 +BRDA:264,18,1,1 +DA:265,2 +DA:265,2 +DA:267,1 +DA:267,1 +FN:278,RuleConditionalTransfer._validateBurnMint +FNDA:41,RuleConditionalTransfer._validateBurnMint +DA:284,41 +DA:284,41 +BRDA:283,19,0,4 +BRDA:283,19,1,37 +DA:287,4 +DA:287,4 +DA:289,37 +DA:289,37 +FN:298,RuleConditionalTransfer._validateApproval +FNDA:37,RuleConditionalTransfer._validateApproval +DA:301,37 +DA:301,37 +DA:301,37 +DA:302,37 +DA:302,37 +DA:302,37 +DA:304,37 +DA:304,37 +BRDA:304,20,0,12 +BRDA:304,20,1,25 +DA:306,12 +DA:306,12 +DA:308,25 +DA:308,25 +FN:315,RuleConditionalTransfer._msgSender +FNDA:452,RuleConditionalTransfer._msgSender +DA:321,452 +DA:321,452 +DA:321,452 +FN:327,RuleConditionalTransfer._msgData FNDA:0,RuleConditionalTransfer._msgData -DA:313,0 -DA:313,0 -DA:313,0 -FN:319,RuleConditionalTransfer._contextSuffixLength -FNDA:328,RuleConditionalTransfer._contextSuffixLength -DA:320,328 -DA:320,328 -DA:320,328 +DA:333,0 +DA:333,0 +DA:333,0 +FN:339,RuleConditionalTransfer._contextSuffixLength +FNDA:452,RuleConditionalTransfer._contextSuffixLength +DA:340,452 +DA:340,452 +DA:340,452 FNF:16 FNH:15 -LF:79 -LH:78 -BRF:34 -BRH:32 +LF:85 +LH:84 +BRF:42 +BRH:38 end_of_record TN: SF:src/rules/operation/abstract/RuleConditionalTransferOperator.sol -FN:26,RuleConditionalTransferOperator.setIssuanceOptions -FNDA:3,RuleConditionalTransferOperator.setIssuanceOptions -DA:27,2 -DA:27,2 -BRDA:27,0,0,1 -BRDA:27,0,1,2 -DA:28,1 -DA:28,1 -DA:30,2 -DA:30,2 -BRDA:30,1,0,1 -BRDA:30,1,1,2 -DA:31,1 -DA:31,1 -FN:35,RuleConditionalTransferOperator.setAutomaticTransfer -FNDA:2,RuleConditionalTransferOperator.setAutomaticTransfer -DA:36,1 -DA:36,1 -BRDA:36,2,0,1 -BRDA:36,2,1,1 -DA:37,1 -DA:37,1 -DA:40,1 -DA:40,1 -DA:40,1 -DA:40,1 -BRDA:40,3,0,1 -BRDA:40,3,1,1 -DA:41,1 -DA:41,1 -FN:49,RuleConditionalTransferOperator.setTimeLimit -FNDA:3,RuleConditionalTransferOperator.setTimeLimit -DA:50,2 -DA:50,2 -BRDA:50,4,0,2 -BRDA:50,4,1,2 -DA:51,2 -DA:51,2 +FN:25,RuleConditionalTransferOperator.setConditionalWhitelist +FNDA:25,RuleConditionalTransferOperator.setConditionalWhitelist +DA:26,25 +DA:26,25 +DA:27,25 +DA:27,25 +FN:33,RuleConditionalTransferOperator.setIssuanceOptions +FNDA:5,RuleConditionalTransferOperator.setIssuanceOptions +DA:34,4 +DA:34,4 +BRDA:34,0,0,2 +BRDA:34,0,1,4 +DA:35,2 +DA:35,2 +DA:37,4 +DA:37,4 +BRDA:37,1,0,2 +BRDA:37,1,1,4 +DA:38,2 +DA:38,2 +FN:47,RuleConditionalTransferOperator.setAutomaticTransfer +FNDA:3,RuleConditionalTransferOperator.setAutomaticTransfer +DA:48,2 +DA:48,2 +BRDA:48,2,0,2 +BRDA:48,2,1,2 +DA:49,2 +DA:49,2 +DA:52,2 +DA:52,2 +DA:52,2 +DA:52,2 +BRDA:52,3,0,2 +BRDA:52,3,1,2 DA:53,2 DA:53,2 -BRDA:53,5,0,2 -BRDA:53,5,1,2 -DA:54,2 -DA:54,2 -FN:58,RuleConditionalTransferOperator.setAutomaticApproval -FNDA:3,RuleConditionalTransferOperator.setAutomaticApproval -DA:59,2 -DA:59,2 -BRDA:59,6,0,2 -BRDA:59,6,1,2 -DA:60,2 -DA:60,2 -DA:62,2 -DA:62,2 -BRDA:62,7,0,2 -BRDA:62,7,1,2 -DA:63,2 -DA:63,2 -FN:68,RuleConditionalTransferOperator.createTransferRequestWithApproval +FN:62,RuleConditionalTransferOperator.setTimeLimit +FNDA:4,RuleConditionalTransferOperator.setTimeLimit +DA:63,3 +DA:63,3 +BRDA:63,4,0,3 +BRDA:63,4,1,3 +DA:64,3 +DA:64,3 +DA:66,3 +DA:66,3 +BRDA:66,5,0,3 +BRDA:66,5,1,3 +DA:67,3 +DA:67,3 +FN:75,RuleConditionalTransferOperator.setAutomaticApproval +FNDA:5,RuleConditionalTransferOperator.setAutomaticApproval +DA:76,4 +DA:76,4 +BRDA:76,6,0,4 +BRDA:76,6,1,4 +DA:77,4 +DA:77,4 +DA:79,4 +DA:79,4 +BRDA:79,7,0,4 +BRDA:79,7,1,4 +DA:80,4 +DA:80,4 +FN:87,RuleConditionalTransferOperator.createTransferRequestWithApproval FNDA:6,RuleConditionalTransferOperator.createTransferRequestWithApproval -DA:71,5 -DA:71,5 -FN:79,RuleConditionalTransferOperator.approveTransferRequest -FNDA:26,RuleConditionalTransferOperator.approveTransferRequest -DA:82,25 -DA:82,25 -FN:85,RuleConditionalTransferOperator.approveTransferRequestWithId +DA:90,5 +DA:90,5 +FN:99,RuleConditionalTransferOperator.approveTransferRequest +FNDA:33,RuleConditionalTransferOperator.approveTransferRequest +DA:102,32 +DA:102,32 +FN:108,RuleConditionalTransferOperator.approveTransferRequestWithId FNDA:5,RuleConditionalTransferOperator.approveTransferRequestWithId -DA:88,4 -DA:88,4 -DA:88,4 -BRDA:88,8,0,2 -BRDA:88,8,1,2 -DA:89,2 -DA:89,2 -DA:91,2 -DA:91,2 -DA:92,2 -DA:92,2 -FN:96,RuleConditionalTransferOperator.resetRequestStatus +DA:111,4 +DA:111,4 +DA:111,4 +BRDA:111,8,0,2 +BRDA:111,8,1,2 +DA:112,2 +DA:112,2 +DA:114,2 +DA:114,2 +DA:115,2 +DA:115,2 +FN:121,RuleConditionalTransferOperator.resetRequestStatus FNDA:3,RuleConditionalTransferOperator.resetRequestStatus -DA:99,2 -DA:99,2 -DA:99,2 -BRDA:99,9,0,1 -BRDA:99,9,1,1 -DA:100,1 -DA:100,1 -DA:102,1 -DA:102,1 -DA:103,1 -DA:103,1 -FN:108,RuleConditionalTransferOperator.approveTransferRequestBatchWithId -FNDA:6,RuleConditionalTransferOperator.approveTransferRequestBatchWithId -DA:111,5 -DA:111,5 -BRDA:111,10,0,1 -BRDA:111,10,1,4 -DA:112,1 -DA:112,1 -DA:114,4 -DA:114,4 -BRDA:114,11,0,1 -BRDA:114,11,1,3 -DA:115,1 -DA:115,1 -DA:118,3 -DA:118,3 -DA:118,13 -DA:118,10 -DA:119,11 -DA:119,11 -DA:119,11 -BRDA:119,12,0,1 -BRDA:119,12,1,10 -DA:120,1 -DA:120,1 -DA:123,2 -DA:123,2 -DA:123,6 -DA:123,4 -DA:124,5 -DA:124,5 -DA:125,5 -DA:125,5 -FN:130,RuleConditionalTransferOperator.approveTransferRequestBatch -FNDA:6,RuleConditionalTransferOperator.approveTransferRequestBatch -DA:133,6 -DA:133,6 -BRDA:133,13,0,1 -BRDA:133,13,1,5 -DA:134,1 -DA:134,1 -DA:136,5 -DA:136,5 -BRDA:136,14,0,3 -BRDA:136,14,1,2 -DA:137,3 -DA:137,3 -DA:139,2 -DA:139,2 -DA:139,11 -DA:139,9 -DA:140,9 -DA:140,9 -FN:145,RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch -FNDA:2,RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch -DA:148,2 -DA:148,2 -BRDA:148,15,0,1 -BRDA:148,15,1,1 -DA:149,1 -DA:149,1 -DA:151,1 -DA:151,1 +DA:124,2 +DA:124,2 +DA:124,2 +BRDA:124,9,0,1 +BRDA:124,9,1,1 +DA:125,1 +DA:125,1 +DA:127,1 +DA:127,1 +DA:128,1 +DA:128,1 +FN:135,RuleConditionalTransferOperator.approveTransferRequestBatchWithId +FNDA:7,RuleConditionalTransferOperator.approveTransferRequestBatchWithId +DA:138,5 +DA:138,5 +BRDA:138,10,0,1 +BRDA:138,10,1,4 +DA:139,1 +DA:139,1 +DA:141,4 +DA:141,4 +BRDA:141,11,0,1 +BRDA:141,11,1,3 +DA:142,1 +DA:142,1 +DA:145,3 +DA:145,3 +DA:145,13 +DA:145,10 +DA:146,11 +DA:146,11 +DA:146,11 +BRDA:146,12,0,1 +BRDA:146,12,1,10 +DA:147,1 +DA:147,1 +DA:150,2 +DA:150,2 +DA:150,6 +DA:150,4 DA:151,5 -DA:151,4 -DA:152,4 -DA:152,4 -FN:157,RuleConditionalTransferOperator.resetRequestStatusBatch -FNDA:3,RuleConditionalTransferOperator.resetRequestStatusBatch -DA:160,3 -DA:160,3 -BRDA:160,16,0,1 -BRDA:160,16,1,2 -DA:161,1 -DA:161,1 -DA:164,2 -DA:164,2 -DA:164,5 -DA:164,3 -DA:165,4 -DA:165,4 -DA:165,4 -BRDA:165,17,0,1 -BRDA:165,17,1,3 -DA:166,1 -DA:166,1 -DA:169,1 -DA:169,1 -DA:169,4 -DA:169,3 -DA:170,3 -DA:170,3 -DA:171,3 -DA:171,3 -FN:178,RuleConditionalTransferOperator._approveTransferRequestKeyElement -FNDA:34,RuleConditionalTransferOperator._approveTransferRequestKeyElement -DA:181,34 -DA:181,34 -BRDA:181,18,0,1 -BRDA:181,18,1,33 +DA:151,5 +DA:152,5 +DA:152,5 +FN:159,RuleConditionalTransferOperator.approveTransferRequestBatch +FNDA:7,RuleConditionalTransferOperator.approveTransferRequestBatch +DA:162,6 +DA:162,6 +BRDA:162,13,0,1 +BRDA:162,13,1,5 +DA:163,1 +DA:163,1 +DA:165,5 +DA:165,5 +BRDA:165,14,0,3 +BRDA:165,14,1,2 +DA:166,3 +DA:166,3 +DA:168,2 +DA:168,2 +DA:168,11 +DA:168,9 +DA:169,9 +DA:169,9 +FN:176,RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch +FNDA:3,RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch +DA:179,2 +DA:179,2 +BRDA:179,15,0,1 +BRDA:179,15,1,1 +DA:180,1 +DA:180,1 DA:182,1 DA:182,1 -DA:184,33 -DA:184,33 -DA:184,33 -DA:185,33 -DA:185,33 -DA:186,33 -DA:186,33 -BRDA:186,19,0,1 -BRDA:186,19,1,4 -DA:187,5 -DA:187,5 -BRDA:187,20,0,1 -BRDA:187,20,1,4 -DA:188,1 -DA:188,1 -DA:191,4 -DA:191,4 -DA:193,4 -DA:193,4 -DA:195,28 -DA:195,28 -FN:199,RuleConditionalTransferOperator._createTransferRequestWithApproval +DA:182,5 +DA:182,4 +DA:183,4 +DA:183,4 +FN:190,RuleConditionalTransferOperator.resetRequestStatusBatch +FNDA:3,RuleConditionalTransferOperator.resetRequestStatusBatch +DA:193,3 +DA:193,3 +BRDA:193,16,0,1 +BRDA:193,16,1,2 +DA:194,1 +DA:194,1 +DA:197,2 +DA:197,2 +DA:197,5 +DA:197,3 +DA:198,4 +DA:198,4 +DA:198,4 +BRDA:198,17,0,1 +BRDA:198,17,1,3 +DA:199,1 +DA:199,1 +DA:202,1 +DA:202,1 +DA:202,4 +DA:202,3 +DA:203,3 +DA:203,3 +DA:204,3 +DA:204,3 +FN:210,RuleConditionalTransferOperator._approveTransferRequestKeyElement +FNDA:41,RuleConditionalTransferOperator._approveTransferRequestKeyElement +DA:213,41 +DA:213,41 +BRDA:213,18,0,1 +BRDA:213,18,1,40 +DA:214,1 +DA:214,1 +DA:216,40 +DA:216,40 +DA:216,40 +DA:217,40 +DA:217,40 +DA:218,40 +DA:218,40 +BRDA:218,19,0,1 +BRDA:218,19,1,6 +DA:219,7 +DA:219,7 +BRDA:219,20,0,1 +BRDA:219,20,1,6 +DA:220,1 +DA:220,1 +DA:223,6 +DA:223,6 +DA:225,6 +DA:225,6 +DA:227,33 +DA:227,33 +FN:231,RuleConditionalTransferOperator._createTransferRequestWithApproval FNDA:0,RuleConditionalTransferOperator._createTransferRequestWithApproval -DA:205,13 -DA:205,13 -DA:205,13 -DA:207,13 -DA:207,13 -BRDA:207,21,0,- -BRDA:207,21,1,12 -DA:208,12 -DA:208,12 -DA:208,12 -DA:218,12 -DA:218,12 -DA:219,12 -DA:219,12 -DA:220,12 -DA:220,12 -DA:221,12 -DA:221,12 -DA:224,1 -DA:224,1 -DA:225,1 -DA:225,1 -DA:226,1 -DA:226,1 -FN:230,RuleConditionalTransferOperator._resetRequestStatus -FNDA:9,RuleConditionalTransferOperator._resetRequestStatus -DA:233,9 -DA:233,9 -DA:234,9 -DA:234,9 -FN:237,RuleConditionalTransferOperator._checkRequestStatus -FNDA:106,RuleConditionalTransferOperator._checkRequestStatus -DA:238,106 -DA:238,106 -DA:238,106 -FN:241,RuleConditionalTransferOperator._approveRequest -FNDA:39,RuleConditionalTransferOperator._approveRequest -DA:243,39 -DA:243,39 -BRDA:243,22,0,1 -BRDA:243,22,1,38 -DA:244,1 -DA:244,1 -DA:246,38 -BRDA:246,23,0,1 -BRDA:246,23,1,1 -DA:248,22 -DA:248,22 -BRDA:248,24,0,3 -BRDA:248,24,1,19 -DA:249,3 -DA:249,3 -DA:252,19 -DA:252,19 -DA:254,19 -DA:254,19 -DA:255,19 -DA:255,19 -DA:256,19 -DA:256,19 -DA:256,1 +DA:237,15 +DA:237,15 +DA:237,15 +DA:238,15 +DA:238,15 +BRDA:238,21,0,- +BRDA:238,21,1,14 +DA:239,14 +DA:239,14 +DA:239,14 +DA:249,14 +DA:249,14 +DA:250,14 +DA:250,14 +DA:251,14 +DA:251,14 +DA:252,14 +DA:252,14 +DA:255,1 +DA:255,1 DA:256,1 DA:256,1 -BRDA:256,25,0,1 -BRDA:256,25,1,1 -DA:259,1 -DA:259,1 -DA:259,1 -BRDA:259,26,0,1 -BRDA:259,26,1,1 -DA:262,1 -DA:262,1 -DA:266,16 -DA:266,16 -DA:267,16 -DA:267,16 -FN:271,RuleConditionalTransferOperator._updateProcessedTransfer -FNDA:5,RuleConditionalTransferOperator._updateProcessedTransfer -DA:273,5 -DA:273,5 -DA:274,5 -DA:274,5 -DA:276,5 -DA:276,5 -DA:278,5 -DA:278,5 -FNF:18 -FNH:17 -LF:94 -LH:94 +DA:257,1 +DA:257,1 +FN:261,RuleConditionalTransferOperator._resetRequestStatus +FNDA:10,RuleConditionalTransferOperator._resetRequestStatus +DA:264,10 +DA:264,10 +DA:265,10 +DA:265,10 +FN:268,RuleConditionalTransferOperator._checkRequestStatus +FNDA:119,RuleConditionalTransferOperator._checkRequestStatus +DA:270,119 +DA:270,119 +DA:270,119 +FN:273,RuleConditionalTransferOperator._approveRequest +FNDA:46,RuleConditionalTransferOperator._approveRequest +DA:275,46 +DA:275,46 +BRDA:275,22,0,1 +BRDA:275,22,1,45 +DA:276,1 +DA:276,1 +DA:278,45 +BRDA:278,23,0,2 +BRDA:278,23,1,2 +DA:280,27 +DA:280,27 +BRDA:280,24,0,3 +BRDA:280,24,1,24 +DA:281,3 +DA:281,3 +DA:284,24 +DA:284,24 +DA:286,24 +DA:286,24 +DA:287,24 +DA:287,24 +DA:288,24 +DA:288,24 +DA:288,2 +DA:288,2 +DA:288,2 +BRDA:288,25,0,2 +BRDA:288,25,1,2 +DA:291,2 +DA:291,2 +DA:291,2 +BRDA:291,26,0,2 +BRDA:291,26,1,2 +DA:293,2 +DA:293,2 +DA:297,18 +DA:297,18 +DA:298,18 +DA:298,18 +FN:305,RuleConditionalTransferOperator._updateProcessedTransfer +FNDA:10,RuleConditionalTransferOperator._updateProcessedTransfer +DA:307,10 +DA:307,10 +DA:308,10 +DA:308,10 +DA:310,10 +DA:310,10 +DA:312,10 +DA:312,10 +FNF:19 +FNH:18 +LF:96 +LH:96 BRF:54 BRH:53 end_of_record @@ -1241,9 +1276,9 @@ FNDA:4,RuleAddressList.removeAddressesFromTheList DA:54,3 DA:54,3 FN:62,RuleAddressList.addAddressToTheList -FNDA:28,RuleAddressList.addAddressToTheList -DA:65,27 -DA:65,27 +FNDA:40,RuleAddressList.addAddressToTheList +DA:65,39 +DA:65,39 FN:74,RuleAddressList.removeAddressFromTheList FNDA:3,RuleAddressList.removeAddressFromTheList DA:77,2 @@ -1254,25 +1289,25 @@ DA:86,24 DA:86,24 DA:86,24 FN:96,RuleAddressList.addressIsListed -FNDA:57,RuleAddressList.addressIsListed -DA:99,115 -DA:99,115 -DA:99,115 +FNDA:83,RuleAddressList.addressIsListed +DA:99,141 +DA:99,141 +DA:99,141 FN:106,RuleAddressList._msgSender -FNDA:60,RuleAddressList._msgSender -DA:112,60 -DA:112,60 -DA:112,60 +FNDA:72,RuleAddressList._msgSender +DA:112,72 +DA:112,72 +DA:112,72 FN:118,RuleAddressList._msgData FNDA:0,RuleAddressList._msgData DA:124,0 DA:124,0 DA:124,0 FN:130,RuleAddressList._contextSuffixLength -FNDA:60,RuleAddressList._contextSuffixLength -DA:131,60 -DA:131,60 -DA:131,60 +FNDA:72,RuleAddressList._contextSuffixLength +DA:131,72 +DA:131,72 +DA:131,72 FNF:9 FNH:8 LF:9 @@ -1318,16 +1353,16 @@ DA:49,6 DA:52,3 DA:52,3 FN:60,RuleAddressListInternal._addAddressToThelist -FNDA:27,RuleAddressListInternal._addAddressToThelist -DA:63,27 +FNDA:39,RuleAddressListInternal._addAddressToThelist +DA:63,39 BRDA:63,2,0,1 -BRDA:63,2,1,26 +BRDA:63,2,1,38 DA:65,1 DA:65,1 -DA:67,26 -DA:67,26 -DA:68,26 -DA:68,26 +DA:67,38 +DA:67,38 +DA:68,38 +DA:68,38 FN:77,RuleAddressListInternal._removeAddressFromThelist FNDA:2,RuleAddressListInternal._removeAddressFromThelist DA:80,2 @@ -1345,9 +1380,9 @@ FNDA:24,RuleAddressListInternal._numberListedAddress DA:93,24 DA:93,24 FN:102,RuleAddressListInternal._addressIsListed -FNDA:115,RuleAddressListInternal._addressIsListed -DA:105,115 -DA:105,115 +FNDA:141,RuleAddressListInternal._addressIsListed +DA:105,141 +DA:105,141 FNF:6 FNH:6 LF:22 diff --git a/lib/CMTAT b/lib/CMTAT index 4774b7e..23a1e59 160000 --- a/lib/CMTAT +++ b/lib/CMTAT @@ -1 +1 @@ -Subproject commit 4774b7e7aadae29994872c7a4a0445ed819bd570 +Subproject commit 23a1e59f913d079d0c09d32fafbd95ab2d426093 diff --git a/lib/forge-std b/lib/forge-std index e4aef94..978ac6f 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit e4aef94c1768803a16fe19f7ce8b65defd027cfd +Subproject commit 978ac6fadb62f5f0b723c996f64be52eddba6801 diff --git a/src/rules/operation/RuleConditionalTransfer.sol b/src/rules/operation/RuleConditionalTransfer.sol index fed9aee..5b6b03b 100644 --- a/src/rules/operation/RuleConditionalTransfer.sol +++ b/src/rules/operation/RuleConditionalTransfer.sol @@ -42,18 +42,22 @@ contract RuleConditionalTransfer is RuleValidateTransfer, IRuleOperation, RuleC options = options_; } + /** + * @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 => KO + // DENIED => reject address from = _msgSender(); bytes32 key = keccak256(abi.encode(from, to, value)); if(transferRequests[key].status == STATUS.DENIED){ revert RuleConditionalTransfer_TransferDenied(); } - // Status NONE not enough because reset is possible if(_checkRequestStatus(key)){ uint256 requestIdLocal = requestId; TransferRequest memory newTransferApproval = TransferRequest({ @@ -79,6 +83,9 @@ contract RuleConditionalTransfer is RuleValidateTransfer, IRuleOperation, RuleC } } + /** + * @notice Batch version of {createTransferRequest} + */ function createTransferRequestBatch(address[] memory tos, uint256[] memory values) public{ if(tos.length == 0){ revert RuleConditionalTransfer_EmptyArray(); diff --git a/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol b/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol index dc4e4f3..04c40e2 100644 --- a/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol +++ b/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol @@ -6,22 +6,36 @@ import "OZ/token/ERC20/IERC20.sol"; import "../../validation/abstract/RuleCommonInvariantStorage.sol"; import "src/rules/validation/RuleWhitelist.sol"; abstract contract RuleConditionalTransferInvariantStorage is RuleCommonInvariantStorage { + /** + * 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; } diff --git a/src/rules/operation/abstract/RuleConditionalTransferOperator.sol b/src/rules/operation/abstract/RuleConditionalTransferOperator.sol index cd17779..5a8497f 100644 --- a/src/rules/operation/abstract/RuleConditionalTransferOperator.sol +++ b/src/rules/operation/abstract/RuleConditionalTransferOperator.sol @@ -6,27 +6,30 @@ import "OZ/access/AccessControl.sol"; import "./RuleConditionalTransferInvariantStorage.sol"; import "OZ/token/ERC20/utils/SafeERC20.sol"; /** -* @title a RuleConditionalTransfer manager +* @title Restricted functions */ - abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditionalTransferInvariantStorage { // Security using SafeERC20 for IERC20; - OPTION internal options; - - - // Getter + // public variable with automatic Getter + OPTION public options; uint256 public requestId; mapping(uint256 => bytes32) public IdToKey; mapping(bytes32 => TransferRequest) public transferRequests; RuleWhitelist public whitelistConditionalTransfer; + /** + * @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); } + /** + 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; @@ -36,6 +39,11 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio } } + /** + * @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; @@ -48,7 +56,8 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio /** * @notice set time limit for new requests (Approval and transfer) - * Don't affect already created requests + * 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){ @@ -58,7 +67,11 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio 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; @@ -68,7 +81,9 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio } } - + /** + * @notice create a transfer request directly approved + */ function createTransferRequestWithApproval( TransferRequestKeyElement calldata keyElement ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ @@ -76,27 +91,33 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio } /** + @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 + @param isApproved approved (true) or refused (false). Put true if you use partialApproval */ function approveTransferRequest( - TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved_ + TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - _approveTransferRequestKeyElement(keyElement, partialValue, isApproved_); + _approveTransferRequestKeyElement(keyElement, partialValue, isApproved); } + /** + * @notice approve a transferRequestby using its id + */ function approveTransferRequestWithId( - uint256 requestId_, bool isApproved_ + 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_); + _approveRequest(transferRequest, isApproved); } - + /** + * @notice reset to None the status of a request + */ function resetRequestStatus( uint256 requestId_ ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ @@ -108,14 +129,16 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio } /***** Batch function */ - + /** + * @notice Batch version of {approveTransferRequestWithId} + */ function approveTransferRequestBatchWithId( - uint256[] calldata requestId_, bool[] calldata isApproved_ + 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){ + if(requestId_.length != isApproved.length){ revert RuleConditionalTransfer_InvalidLengthArray(); } // Check id validity before performing actions @@ -126,26 +149,30 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio } for(uint256 i = 0; i < requestId_.length; ++i){ TransferRequest memory transferRequest = transferRequests[IdToKey[requestId_[i]]]; - _approveRequest(transferRequest, isApproved_[i]); + _approveRequest(transferRequest, isApproved[i]); } } - + /** + * @notice Batch version of {approveTransferRequest} + */ function approveTransferRequestBatch( - TransferRequestKeyElement[] calldata keyElements, uint256[] calldata partialValues, bool[] calldata isApproved_ + 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)){ + 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]); + _approveTransferRequestKeyElement(keyElements[i], partialValues[i], isApproved[i]); } } - + /** + * @notice Batch version of {createTransferRequestWithApproval} + */ function createTransferRequestWithApprovalBatch( TransferRequestKeyElement[] calldata keyElements ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ @@ -157,7 +184,9 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio } } - + /** + * @notice Batch version of {resetRequestStatus} + */ function resetRequestStatusBatch( uint256[] memory requestIds ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ @@ -178,9 +207,8 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio /*** Internal functions ****/ - function _approveTransferRequestKeyElement( - TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved_ + TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved ) internal { if(partialValue > keyElement.value){ revert RuleConditionalTransfer_InvalidValueApproved(); @@ -188,7 +216,7 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio bytes32 key = keccak256(abi.encode(keyElement.from, keyElement.to, keyElement.value)); TransferRequest memory transferRequest = transferRequests[key]; if(partialValue > 0 ){ - if(! isApproved_){ + if(! isApproved){ revert RuleConditionalTransfer_CannotDeniedPartially(); } // Denied the first request @@ -196,7 +224,7 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio // Create new request _createTransferRequestWithApproval(TransferRequestKeyElement({from: keyElement.from, to: keyElement.to, value: partialValue})); }else{ - _approveRequest(transferRequest, isApproved_); + _approveRequest(transferRequest, isApproved); } } @@ -207,7 +235,6 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio // APPROVED => will overwrite previous status with a new delay // DENIED => will overwrite bytes32 key = keccak256(abi.encode(keyElement.from, keyElement.to, keyElement.value)); - // Status NONE not enough because reset is possible if(_checkRequestStatus(key)){ TransferRequest memory newTransferApproval = TransferRequest({ key: key, @@ -239,15 +266,16 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio } 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{ + function _approveRequest(TransferRequest memory transferRequest , bool isApproved) internal{ // status if(transferRequest.status != STATUS.WAIT){ revert RuleConditionalTransfer_Wrong_Status(); } - if(isApproved_){ + if(isApproved){ // Time if(block.timestamp > (transferRequest.askTime + options.timeLimit.timeLimitToApprove)){ revert RuleConditionalTransfer_timeExceeded(); @@ -261,7 +289,6 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio // Transfer with approval // External call if(options.automaticTransfer.cmtat.allowance(transferRequest.from, address(this)) >= transferRequest.value){ - //_updateProcessedTransfer(transferRequest.key); // Will call the ruleEngine and the rule again... options.automaticTransfer.cmtat.safeTransferFrom(transferRequest.from, transferRequest.to, transferRequest.value); } @@ -272,6 +299,9 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio } } + /** + * @notice update the request during a transfer + */ function _updateProcessedTransfer(bytes32 key) internal { // Reset to zero transferRequests[key].maxTime = 0; diff --git a/test/RuleConditionalTransfer/CMTATIntegrationWhitelist.t .sol b/test/RuleConditionalTransfer/CMTATIntegrationWhitelist.t .sol new file mode 100644 index 0000000..64f5664 --- /dev/null +++ b/test/RuleConditionalTransfer/CMTATIntegrationWhitelist.t .sol @@ -0,0 +1,518 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import "forge-std/Test.sol"; +import "CMTAT/CMTAT_STANDALONE.sol"; +import "../HelperContract.sol"; +import "src/RuleEngine.sol"; + +/** +* @title Integration test with the CMTAT +*/ +contract CMTATIntegrationConditionalTransfer is Test, HelperContract { + // Defined in CMTAT.sol + uint8 constant TRANSFER_OK = 0; + string constant TEXT_TRANSFER_OK = "No restriction"; + + RuleEngine ruleEngineMock; + uint256 resUint256; + bool resBool; + + 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 + }); + + + + // 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 + uint8 decimals = 0; + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT = new CMTAT_STANDALONE( + ZERO_ADDRESS, + DEFAULT_ADMIN_ADDRESS, + IAuthorizationEngine(address(0)), + "CMTA Token", + "CMTAT", + decimals, + "CMTAT_ISIN", + "https://cmta.ch", + IRuleEngine(address(0)), + "CMTAT_info", + FLAG + ); + + + // 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(Errors.CMTAT_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(Errors.CMTAT_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(Errors.CMTAT_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 { + // Arrange + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21)); + // Act + CMTAT_CONTRACT.transfer(ADDRESS2, 21); + } + + function testCanMakeATransferIfApproved() public { + // 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 testCanMakeAPartialTransferIfPartiallyApproved() 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 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 testCannotMakeAWholeTransferIfPartiallyApproved() 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 transferApproved(key, ADDRESS1, ADDRESS2, partialValue, 1); + emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); + ruleConditionalTransfer.approveTransferRequest(transferRequestInput, partialValue, true); + + // Act + vm.expectRevert( + abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, defaultValue)); + vm.prank(ADDRESS1); + CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); + } + + + function testCannotMakeATransferIfDelayExceeded() public { + // 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); + + // +30 days and one second + vm.warp(block.timestamp + 2592001); + // Act + vm.expectRevert( + abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2,defaultValue)); + vm.prank(ADDRESS1); + CMTAT_CONTRACT.transfer(ADDRESS2,defaultValue); + } + + function testCannotMakeATransferIfDelayJustInTime() 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); + // 30 days + vm.warp(block.timestamp + 2592000); + // Act + vm.prank(ADDRESS1); + CMTAT_CONTRACT.transfer(ADDRESS2,defaultValue); + } + + function testCanSetTimeLimitWithTransferExceeded() public { + TIME_LIMIT memory timeLimit_ = TIME_LIMIT({ + timeLimitToApprove: 1 days, + timeLimitToTransfer: 1 days + }); + // Act + vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + ruleConditionalTransfer.setTimeLimit(timeLimit_); + // Arrange + _createTransferRequest(); + vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0,true); + + + // Assert + // Timeout + // >1 days + vm.warp(block.timestamp + 1 days + 1 seconds); + + vm.expectRevert( + abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2,defaultValue)); + vm.prank(ADDRESS1); + CMTAT_CONTRACT.transfer(ADDRESS2,defaultValue); + + } + + function testCanMintWithoutApproval() 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 testCanBurnWithoutApproval() public { + // Act + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT.burn(ADDRESS1,defaultValue, "test"); + + // Assert + resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); + assertEq(resUint256, ADDRESS1_BALANCE_INIT - defaultValue); + } + + function testCannotMintWithoutApproval() public { + 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(Errors.CMTAT_InvalidTransfer.selector, ZERO_ADDRESS , ADDRESS1, 11)); + CMTAT_CONTRACT.mint(ADDRESS1, 11); + } + + function testCannotBurnWithoutApproval() public { + 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(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ZERO_ADDRESS, defaultValue)); + CMTAT_CONTRACT.burn(ADDRESS1,defaultValue, "test"); + } + + function testAutomaticTransferIfOptionsSet() public { + AUTOMATIC_TRANSFER memory automaticTransferTest = AUTOMATIC_TRANSFER({ + isActivate:true, + cmtat: CMTAT_CONTRACT + }); + vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + ruleConditionalTransfer.setAutomaticTransfer(automaticTransferTest); + + // Aproval + vm.prank(ADDRESS1); + CMTAT_CONTRACT.approve(address(ruleConditionalTransfer), defaultValue); + + // Arrange + _createTransferRequest(); + + // 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 testCanTransferIfAutomaticApprovalSetAndTimeExceeds() public { + AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ + isActivate: true, + timeLimitBeforeAutomaticApproval: 90 days + }); + vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + ruleConditionalTransfer.setAutomaticApproval(automaticApproval_); + + // Arrange + _createTransferRequest(); + + vm.warp(block.timestamp + 90 days); + // Act + vm.prank(ADDRESS1); + vm.expectEmit(true, true, true, true); + emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2,defaultValue, 0); + CMTAT_CONTRACT.transfer(ADDRESS2,defaultValue); + } + + function testCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds() public { + AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ + isActivate: true, + timeLimitBeforeAutomaticApproval: 90 days + }); + vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + ruleConditionalTransfer.setAutomaticApproval(automaticApproval_); + + // Arrange + _createTransferRequest(); + + + vm.warp(block.timestamp + 92 days); + // Act + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, defaultValue)); + CMTAT_CONTRACT.transfer(ADDRESS2,defaultValue); + } +} diff --git a/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol index fee118a..f9a18c7 100644 --- a/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol +++ b/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol @@ -100,6 +100,24 @@ contract RuleConditionalTransferAccessControl is Test, HelperContract { 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); @@ -112,20 +130,31 @@ contract RuleConditionalTransferAccessControl is Test, HelperContract { ruleConditionalTransfer.approveTransferRequestBatchWithId(ids, isApproveds); } - function testCannotAttackerResetARequest() public { - _createTransferRequest(); - + 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.resetRequestStatus(0); + ruleConditionalTransfer.approveTransferRequestBatch(keyElements, partialValues, boolIsApproved); } - function testCannotAttackerCreateTransferRequestWithApproval() public { + 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.createTransferRequestWithApproval(transferRequestInput); + 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 *********/ diff --git a/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol index e7c80fa..5083279 100644 --- a/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol +++ b/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol @@ -158,6 +158,20 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { 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 { @@ -282,6 +296,14 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { assertEq(transferRequest.to, ADDRESS2); assertEq(transferRequest.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 {