diff --git a/.gitignore b/.gitignore index 603dabe..e13c4e7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ node_modules/ broadcast/ lib/ out/ +docOut/ cache/ .~lock.test.odt# nethereum-gen.settings @@ -12,4 +13,4 @@ artifacts/ cache_hardhat/ #drawio *.bkp -*.dtmp \ No newline at end of file +*.dtmp diff --git a/CHANGELOG.md b/CHANGELOG.md index 88be8b9..6881c8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ Please follow [https://changelog.md/](https://changelog.md/) conventions. +## v2.0.1 + +- Add a new rule WhitelistWrapper + +This rule can be used to restrict transfers from/to only addresses inside a group of whitelist rules managed by different operators. + ## v2.0.0 - Implement the new architecture for the RuleEngine, with ValidationRule and OperationRule diff --git a/README.md b/README.md index b8e812e..6dc2108 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ The following rules are available: | Rule | Type | Description | Doc | | ------------------------------------------------------------ | -------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | [RuleWhitelist](src/rules/validation/RuleWhitelist.sol) | RuleValidation | This rule can be used to restrict transfers from/to only addresses inside a whitelist. | [RuleWhitelist.md](./doc/technical/RuleWhitelist.md)
[surya-report](./doc/surya/surya_report/surya_report_RuleWhitelist.sol.md) | +| [RuleWhitelistWrapper](src/rules/validation/RuleWhitelistWrapper.sol) | RuleValidation | This rule can be used to restrict transfers from/to only addresses inside a group of whitelist rules managed by different operators. | [RuleWhitelistWrapper.md](./doc/technical/RuleWhitelistWrapper.md)
[surya-report](./doc/surya/surya_report/surya_report_RuleWhitelistWrapper.sol.md) | | [RuleBlacklist](src/rules/validation/RuleBlacklist.sol) | RuleValidation | This rule can be used to forbid transfer from/to addresses in the blacklist | [RuleBlacklist.md](./doc/technical/RuleBlacklist.md)
[surya-report](./doc/surya/surya_report/surya_report_RuleBlacklist.sol.md) | | [RuleSanctionList](src/rules/validation/RuleSanctionList.sol) | RuleValidation | The purpose of this contract is to use the oracle contract from Chainalysis to forbid transfer from/to an address included in a sanctions designation (US, EU, or UN). | [RuleSanctionList.md](./doc/technical/RuleSanctionList.md)
[surya-report](./doc/surya/surya_report/surya_report_RuleSanctionList.sol.md) | | [RuleConditionalTransfer](src/rules/operation/RuleConditionalTransfer.sol) | RuleOperation | This page describes a Conditional Transfer implementation. This rule requires that transfers have to be approved before being executed by the token holders. | [RuleConditionalTransfer.md](./doc/technical/RuleConditionalTransfer.md)
[surya-report](./doc/surya/surya_report/surya_report_RuleConditionalTransfer.sol.md) | diff --git a/doc/schema/rule/ruleWhitelistWrapper.drawio b/doc/schema/rule/ruleWhitelistWrapper.drawio new file mode 100644 index 0000000..695db2b --- /dev/null +++ b/doc/schema/rule/ruleWhitelistWrapper.drawio @@ -0,0 +1 @@ +7VrLcpswFP0als3whizj2Eln2k4zzSJJdwrIoKmMPEJ+5esrjMBIsmPsxpgk3STcowfo3MO90sWGcz1Z3lIwTX+QGGLDNuOl4QwN2w4vTf63AFYl4PthCSQUxSVkbYB79AIFKMYlMxTDXOrICMEMTWUwIlkGIyZhgFKykLuNCZbvOgUJ1ID7CGAdfUAxS0vUdhx/0/AVoiStbu17btkyAVVvsZQ8BTFZNCBnZDjXlBBWXk2W1xAX5FXElONudrTWT0ZhxtoMYDcvz7d+bOY2+j0fWZgFafrFLmeZAzwTK/41w3CUJSiD4rHZqiIjX6AJBrzBGSxSxOD9FERF04K7nmMpm2BuWfxyTDImnGmF3NafVTz+HFIGlw1IPPstJBPI6Ip3qaQkaBRCcipaFw23mAJLGx6pQSCkkNRTb8jiF4KvA7hzNO4eClYwytkDZ2QKad4vCl23dxy6uznkMOVa5P+sftEYWjKN4dlZ9DQWFzqLdr9Z7IEY/TY0Zv2m0XfPTmOg0ahRBrP4qsjO3IowyHMUyURRMstiWNzE5BZcIvYoWorrpwK/8IQ1XDa6DVeVkfGlPDaNxqjC3AxbW9W41i7KyYxGcH9qZYAmkO1PIzCWdiK6wxsO9bb4s8IoxIChubx/2eZjcYc7gjK20ZPjy3pyPUUm5brFqOZ2Q5nIVYTpqnoridEmWkuuXvbxKgy7UaF9nAzt7nTotNSh2ysdBmp6cI/UYaAI2r7sVoeX/6PhISr0+qVCRwliqnhaq1A5vriqnE+swuptOq0MrQ8iQr9XIvQ9ZYvnHCtCU57ICzsWoV5teCMRmlIsDF4Phm+np36lTH/X8f5QnWgTdZwyLb2yYgQDRrlh8xnNMcA5NIKhLh7uiO/gGWJZMwCjJCsExR0MKQeK4xWKAL4SDRMUx8UcAwpz9AKe1/MVUpkWS1wv2hsY3rCVeF6Xvnqwq0uX4q5Gszi47cBnXlhB6Mn++Tf5VF3IeJzD0zhUL/Oc48WvE5AlJ6CguwzktcxA/ToUhrayhz52M66msq4PhZZeKXv3kaV6tz5nZNFrdmeNLM1gUu+IO4ks/oeILK66JT12z+JZHUeWLVXP9x5Zqnfrc0aWwwqIGVl/AIhBnq5DiSW7s8DvAOOuzNaIbToczRklf+oPy/buWFSXd56a0WdfKOp5JOpXqScM9hyO20aiSyWkeepx/dSRaEvFMRj8/MYhQgu+uWLp+h2O9U/8n2MX3rYOZPdKoY63J8W1/jSj1IFc/60Uys3ND1rK7pufBTmjvw== \ No newline at end of file diff --git a/doc/schema/rule/ruleWhitelistWrapper.drawio.png b/doc/schema/rule/ruleWhitelistWrapper.drawio.png new file mode 100644 index 0000000..0cadf5d Binary files /dev/null and b/doc/schema/rule/ruleWhitelistWrapper.drawio.png differ diff --git a/doc/surya/surya_graph/surya_graph_IRuleEngineValidation.sol.png b/doc/surya/surya_graph/surya_graph_IRuleEngineValidation.sol.png index 87de24a..f24db03 100644 Binary files a/doc/surya/surya_graph/surya_graph_IRuleEngineValidation.sol.png and b/doc/surya/surya_graph/surya_graph_IRuleEngineValidation.sol.png differ diff --git a/doc/surya/surya_graph/surya_graph_RuleAddressList.sol.png b/doc/surya/surya_graph/surya_graph_RuleAddressList.sol.png index e6e0743..484142b 100644 Binary files a/doc/surya/surya_graph/surya_graph_RuleAddressList.sol.png and b/doc/surya/surya_graph/surya_graph_RuleAddressList.sol.png differ diff --git a/doc/surya/surya_graph/surya_graph_RuleEngineValidation.sol.png b/doc/surya/surya_graph/surya_graph_RuleEngineValidation.sol.png index 6f11d4b..334417a 100644 Binary files a/doc/surya/surya_graph/surya_graph_RuleEngineValidation.sol.png and b/doc/surya/surya_graph/surya_graph_RuleEngineValidation.sol.png differ diff --git a/doc/surya/surya_graph/surya_graph_RuleEngineValidationCommon.sol.png b/doc/surya/surya_graph/surya_graph_RuleEngineValidationCommon.sol.png new file mode 100644 index 0000000..8f9337d Binary files /dev/null and b/doc/surya/surya_graph/surya_graph_RuleEngineValidationCommon.sol.png differ diff --git a/doc/surya/surya_graph/surya_graph_RuleWhitelistWrapper.sol.png b/doc/surya/surya_graph/surya_graph_RuleWhitelistWrapper.sol.png new file mode 100644 index 0000000..2a33926 Binary files /dev/null and b/doc/surya/surya_graph/surya_graph_RuleWhitelistWrapper.sol.png differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_IRuleEngineValidation.sol.png b/doc/surya/surya_inheritance/surya_inheritance_IRuleEngineValidation.sol.png index 0036d33..d7954ab 100644 Binary files a/doc/surya/surya_inheritance/surya_inheritance_IRuleEngineValidation.sol.png and b/doc/surya/surya_inheritance/surya_inheritance_IRuleEngineValidation.sol.png differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleEngineValidation.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleEngineValidation.sol.png index 0d8dc7f..4ed4e87 100644 Binary files a/doc/surya/surya_inheritance/surya_inheritance_RuleEngineValidation.sol.png and b/doc/surya/surya_inheritance/surya_inheritance_RuleEngineValidation.sol.png differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleEngineValidationCommon.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleEngineValidationCommon.sol.png new file mode 100644 index 0000000..e2569bd Binary files /dev/null and b/doc/surya/surya_inheritance/surya_inheritance_RuleEngineValidationCommon.sol.png differ diff --git a/doc/surya/surya_inheritance/surya_inheritance_RuleWhitelistWrapper.sol.png b/doc/surya/surya_inheritance/surya_inheritance_RuleWhitelistWrapper.sol.png new file mode 100644 index 0000000..fd9f2ac Binary files /dev/null and b/doc/surya/surya_inheritance/surya_inheritance_RuleWhitelistWrapper.sol.png differ diff --git a/doc/surya/surya_report/surya_report_IRuleEngineValidation.sol.md b/doc/surya/surya_report/surya_report_IRuleEngineValidation.sol.md index 421450b..81d8773 100644 --- a/doc/surya/surya_report/surya_report_IRuleEngineValidation.sol.md +++ b/doc/surya/surya_report/surya_report_IRuleEngineValidation.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./interfaces/IRuleEngineValidation.sol | 79955886291ed983850b8b82060b7c2b0b90e4f7 | +| ./interfaces/IRuleEngineValidation.sol | 11118806381880ade78b3dbba1cea694c9a8014e | ### Contracts Description Table @@ -16,12 +16,14 @@ | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| | **IRuleEngineValidation** | Interface | ||| +| └ | detectTransferRestrictionValidation | External ❗️ | |NO❗️ | +| └ | validateTransferValidation | External ❗️ | |NO❗️ | +|||||| +| **IRuleEngineValidationCommon** | Interface | ||| | └ | setRulesValidation | External ❗️ | 🛑 |NO❗️ | | └ | rulesCountValidation | External ❗️ | |NO❗️ | | └ | ruleValidation | External ❗️ | |NO❗️ | | └ | rulesValidation | External ❗️ | |NO❗️ | -| └ | detectTransferRestrictionValidation | External ❗️ | |NO❗️ | -| └ | validateTransferValidation | External ❗️ | |NO❗️ | ### Legend diff --git a/doc/surya/surya_report/surya_report_RuleAddressList.sol.md b/doc/surya/surya_report/surya_report_RuleAddressList.sol.md index e4c8b91..ce6420b 100644 --- a/doc/surya/surya_report/surya_report_RuleAddressList.sol.md +++ b/doc/surya/surya_report/surya_report_RuleAddressList.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/abstract/RuleAddressList/RuleAddressList.sol | daf3fa53f0f864274951e68bb9c8e6b44eba5fa0 | +| ./rules/validation/abstract/RuleAddressList/RuleAddressList.sol | 5cbdfeb513dd3181dd8654b57e32bd0f4b49f981 | ### Contracts Description Table @@ -23,6 +23,7 @@ | └ | removeAddressFromTheList | Public ❗️ | 🛑 | onlyRole | | └ | numberListedAddress | Public ❗️ | |NO❗️ | | └ | addressIsListed | Public ❗️ | |NO❗️ | +| └ | addressIsListedBatch | Public ❗️ | |NO❗️ | | └ | _msgSender | Internal 🔒 | | | | └ | _msgData | Internal 🔒 | | | | └ | _contextSuffixLength | Internal 🔒 | | | diff --git a/doc/surya/surya_report/surya_report_RuleAddressListInvariantStorage.sol.md b/doc/surya/surya_report/surya_report_RuleAddressListInvariantStorage.sol.md index 3ac5906..62de3eb 100644 --- a/doc/surya/surya_report/surya_report_RuleAddressListInvariantStorage.sol.md +++ b/doc/surya/surya_report/surya_report_RuleAddressListInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/abstract/RuleAddressList/RuleAddressListInvariantStorage.sol | f9927d2adb13a39b3f83b0c810f3fa559272c341 | +| ./rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol | f9927d2adb13a39b3f83b0c810f3fa559272c341 | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleBlacklist.sol.md b/doc/surya/surya_report/surya_report_RuleBlacklist.sol.md index 038ddfe..d22d5db 100644 --- a/doc/surya/surya_report/surya_report_RuleBlacklist.sol.md +++ b/doc/surya/surya_report/surya_report_RuleBlacklist.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/RuleBlacklist.sol | 831a76a89cf2f6148bdd911e6e1ec5be4e1c1a27 | +| ./rules/validation/RuleBlacklist.sol | 9bf4aefed66c48ac2b68bad9c56b9f3e01e8da24 | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleBlacklistInvariantStorage.sol.md b/doc/surya/surya_report/surya_report_RuleBlacklistInvariantStorage.sol.md index e1995b3..ca7c79c 100644 --- a/doc/surya/surya_report/surya_report_RuleBlacklistInvariantStorage.sol.md +++ b/doc/surya/surya_report/surya_report_RuleBlacklistInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/abstract/RuleAddressList/RuleBlacklistInvariantStorage.sol | ff8b14ed50b470a70389498956f621cd828816ed | +| ./rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol | cf47d03ede24ba35080106f8d4380bb651e92c39 | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleEngine.sol.md b/doc/surya/surya_report/surya_report_RuleEngine.sol.md index d0812d9..4cc45b2 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 | 0fc418971885c84c32fab8ba76462a7ae5c77b77 | +| ./RuleEngine.sol | 9ac4a4a50634a369d5b88418fc8d1af7a3b1df77 | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleEngineInvariantStorage.sol.md b/doc/surya/surya_report/surya_report_RuleEngineInvariantStorage.sol.md index 70e3623..ddf1dc5 100644 --- a/doc/surya/surya_report/surya_report_RuleEngineInvariantStorage.sol.md +++ b/doc/surya/surya_report/surya_report_RuleEngineInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/RuleEngineInvariantStorage.sol | c733563e242d5ffa42e9e5c8140a4cbbd6267f93 | +| ./modules/RuleEngineInvariantStorage.sol | 824864b8a40f1f4ff47cc91e3226d6cd92b9ed3c | ### 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 9823a14..0243375 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 | a511cf11774bebce822a8b277f0d33a71d6df492 | +| ./modules/RuleEngineOperation.sol | 428f410167252dbe376f484fccaa796cb1309851 | ### 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 fe3ac20..7b9b7c5 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 | 389f8e6a721d981e7704f67c608138af0b3bed97 | +| ./modules/RuleEngineValidation.sol | 6b65517a26ad9ef8bfc88dad98a35bd8b29fcca4 | ### Contracts Description Table @@ -15,17 +15,7 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleEngineValidation** | Implementation | AccessControl, RuleInternal, IRuleEngineValidation, IERC1404EnumCode ||| -| └ | setRulesValidation | Public ❗️ | 🛑 | onlyRole | -| └ | clearRulesValidation | Public ❗️ | 🛑 | onlyRole | -| └ | _clearRulesValidation | Internal 🔒 | 🛑 | | -| └ | addRuleValidation | Public ❗️ | 🛑 | onlyRole | -| └ | removeRuleValidation | Public ❗️ | 🛑 | onlyRole | -| └ | _removeRuleValidation | Internal 🔒 | 🛑 | | -| └ | rulesCountValidation | External ❗️ | |NO❗️ | -| └ | getRuleIndexValidation | External ❗️ | |NO❗️ | -| └ | ruleValidation | External ❗️ | |NO❗️ | -| └ | rulesValidation | External ❗️ | |NO❗️ | +| **RuleEngineValidation** | Implementation | AccessControl, RuleInternal, RuleEngineValidationCommon, IRuleEngineValidation, IERC1404EnumCode ||| | └ | detectTransferRestrictionValidation | Public ❗️ | |NO❗️ | | └ | validateTransferValidation | Public ❗️ | |NO❗️ | diff --git a/doc/surya/surya_report/surya_report_RuleEngineValidationCommon.sol.md b/doc/surya/surya_report/surya_report_RuleEngineValidationCommon.sol.md new file mode 100644 index 0000000..b1d05aa --- /dev/null +++ b/doc/surya/surya_report/surya_report_RuleEngineValidationCommon.sol.md @@ -0,0 +1,36 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./modules/RuleEngineValidationCommon.sol | 9c992d27ccef264c7cb0c3137f384541590f9bfd | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **RuleEngineValidationCommon** | Implementation | AccessControl, RuleInternal, IRuleEngineValidationCommon ||| +| └ | setRulesValidation | Public ❗️ | 🛑 | onlyRole | +| └ | clearRulesValidation | Public ❗️ | 🛑 | onlyRole | +| └ | _clearRulesValidation | Internal 🔒 | 🛑 | | +| └ | addRuleValidation | Public ❗️ | 🛑 | onlyRole | +| └ | removeRuleValidation | Public ❗️ | 🛑 | onlyRole | +| └ | _removeRuleValidation | Internal 🔒 | 🛑 | | +| └ | rulesCountValidation | External ❗️ | |NO❗️ | +| └ | getRuleIndexValidation | External ❗️ | |NO❗️ | +| └ | ruleValidation | External ❗️ | |NO❗️ | +| └ | rulesValidation | External ❗️ | |NO❗️ | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/surya/surya_report/surya_report_RuleWhitelist.sol.md b/doc/surya/surya_report/surya_report_RuleWhitelist.sol.md index dcae5ae..f92ec99 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 | 721bc822979b9948547c0d499ccb831ee6083775 | +| ./rules/validation/RuleWhitelist.sol | 95fbe2f3831b9a71b1b332868ca5594f4b3d4332 | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleWhitelistInvariantStorage.sol.md b/doc/surya/surya_report/surya_report_RuleWhitelistInvariantStorage.sol.md index ffa665e..8fab71d 100644 --- a/doc/surya/surya_report/surya_report_RuleWhitelistInvariantStorage.sol.md +++ b/doc/surya/surya_report/surya_report_RuleWhitelistInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./rules/validation/abstract/RuleAddressList/RuleWhitelistInvariantStorage.sol | 539fc229948771c41225df414fbe1eb050fd75f9 | +| ./rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol | fd28dfca118991fc5956bb5638de59a5a082ccbf | ### Contracts Description Table diff --git a/doc/surya/surya_report/surya_report_RuleWhitelistWrapper.sol.md b/doc/surya/surya_report/surya_report_RuleWhitelistWrapper.sol.md new file mode 100644 index 0000000..47a0301 --- /dev/null +++ b/doc/surya/surya_report/surya_report_RuleWhitelistWrapper.sol.md @@ -0,0 +1,33 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./rules/validation/RuleWhitelistWrapper.sol | bf329dec00b1249add78824aa85a9dcdd49a8342 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **RuleWhitelistWrapper** | Implementation | RuleEngineValidationCommon, MetaTxModuleStandalone, RuleValidateTransfer, RuleWhitelistInvariantStorage ||| +| └ | | Public ❗️ | 🛑 | MetaTxModuleStandalone | +| └ | detectTransferRestriction | Public ❗️ | |NO❗️ | +| └ | canReturnTransferRestrictionCode | External ❗️ | |NO❗️ | +| └ | messageForTransferRestriction | External ❗️ | |NO❗️ | +| └ | _msgSender | Internal 🔒 | | | +| └ | _msgData | Internal 🔒 | | | +| └ | _contextSuffixLength | Internal 🔒 | | | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/technical/RuleBlacklist.md b/doc/technical/RuleBlacklist.md index 6028c04..59ebb3c 100644 --- a/doc/technical/RuleBlacklist.md +++ b/doc/technical/RuleBlacklist.md @@ -11,7 +11,9 @@ A part of the code is shared with Rule Whitelist ![surya_graph_Blacklist](../surya/surya_graph/surya_graph_RuleBlacklist.sol.png) +### Inheritance +![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleBlacklist.sol.png) ## Access Control diff --git a/doc/technical/RuleConditionalTransfer.md b/doc/technical/RuleConditionalTransfer.md index a9f1d85..fcea617 100644 --- a/doc/technical/RuleConditionalTransfer.md +++ b/doc/technical/RuleConditionalTransfer.md @@ -71,7 +71,9 @@ To perform the transfer, the token holder has to `approve` the rule to spend tok ![surya_graph_Blacklist](../surya/surya_graph/surya_graph_RuleConditionalTransfer.sol.png) +### Inheritance +![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleConditionalTransfer.sol.png) ### Workflow diff --git a/doc/technical/RuleSanctionList.md b/doc/technical/RuleSanctionList.md index 06fb607..3ce697e 100644 --- a/doc/technical/RuleSanctionList.md +++ b/doc/technical/RuleSanctionList.md @@ -18,6 +18,10 @@ The documentation and the contracts addresses are available here: [Chainalysis o ![surya_graph_Whitelist](../surya/surya_graph/surya_graph_RuleSanctionList.sol.png) +### Inheritance + +![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleSanctionList.sol.png) + ## Access Control ### Admin diff --git a/doc/technical/RuleWhitelist.md b/doc/technical/RuleWhitelist.md index 5360520..d74b8aa 100644 --- a/doc/technical/RuleWhitelist.md +++ b/doc/technical/RuleWhitelist.md @@ -10,7 +10,9 @@ This rule can be used to restrict transfers from/to only addresses inside a whit ![surya_graph_Whitelist](../surya/surya_graph/surya_graph_RuleWhitelist.sol.png) +### Inheritance +![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleWhitelist.sol.png) ## Access Control @@ -21,7 +23,7 @@ The default admin is the address put in argument(`admin`) inside the constructor ### Schema Here a schema of the Access Control. -![alt text](../accessControl/access-control-RuleWhitelist.png) +![alt text](../security/accessControl/access-control-RuleWhitelist.png) diff --git a/doc/technical/RuleWhitelistWrapper.md b/doc/technical/RuleWhitelistWrapper.md new file mode 100644 index 0000000..4895bf1 --- /dev/null +++ b/doc/technical/RuleWhitelistWrapper.md @@ -0,0 +1,32 @@ +# Rule Whitelist Wrapper + +[TOC] + +This rule allows to have several different whitelist rules, managed by different operators. + +The rule will call each whitelist rule to know if during a transfer the address `from`or the address `to`is in the whitelist. +If this is the case, the rule return 0 (transfer valid) or an error otherwise. + +## Schema + +### Architecture + +![ruleWhitelistWrapper.drawio](../schema/rule/ruleWhitelistWrapper.drawio.png) + +### Graph + +![surya_graph_Whitelist](../surya/surya_graph/surya_graph_RuleWhitelistWrapper.sol.png) + +### Inheritance + +![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleWhitelistWrapper.sol.png) + +## Details + +### Architecture + +This rule inherits from `RuleEngineValidationCommon`. Thus the whitelist rules are managed with the same architecture and code than for the ruleEngine. For example, rules are added with the functions `setRulesValidation` or `addRuleValidation`. + +### Admin + +The default admin is the address put in argument(`admin`) inside the constructor. It is set in the constructor when the contract is deployed. diff --git a/doc/test/coverage/index-sort-b.html b/doc/test/coverage/index-sort-b.html index a8ed6d6..922799d 100644 --- a/doc/test/coverage/index-sort-b.html +++ b/doc/test/coverage/index-sort-b.html @@ -31,27 +31,27 @@ lcov.info Lines: - 364 - 396 - 91.9 % + 402 + 436 + 92.2 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 95 - 103 - 92.2 % + 101 + 110 + 91.8 % Branches: - 154 - 166 - 92.8 % + 163 + 178 + 91.6 % @@ -96,22 +96,22 @@ src/rules/validation/abstract/RuleAddressList -
96.8%96.8%
+
97.1%97.1%
- 96.8 % - 30 / 31 - 93.3 % - 14 / 15 + 97.1 % + 34 / 35 + 93.8 % + 15 / 16 75.0 % 6 / 8 src -
96.3%96.3%
+
96.6%96.6%
- 96.3 % - 26 / 27 + 96.6 % + 28 / 29 85.7 % 6 / 7 80.0 % @@ -123,19 +123,31 @@
98.8%98.8%
98.8 % - 84 / 85 + 85 / 86 93.8 % 15 / 16 90.5 % 38 / 42 + + src/rules/validation + +
95.8%95.8%
+ + 95.8 % + 69 / 72 + 89.5 % + 17 / 19 + 92.1 % + 35 / 38 + src/modules
100.0%
100.0 % - 80 / 80 + 82 / 82 100.0 % 27 / 27 95.8 % @@ -147,7 +159,7 @@
100.0%
100.0 % - 96 / 96 + 99 / 99 94.7 % 18 / 19 98.1 % @@ -177,18 +189,6 @@ - 0 / 0 - - src/rules/validation - -
97.7%97.7%
- - 97.7 % - 43 / 44 - 92.3 % - 12 / 13 - 100.0 % - 26 / 26 -
diff --git a/doc/test/coverage/index-sort-f.html b/doc/test/coverage/index-sort-f.html index 6d4fae1..d45e811 100644 --- a/doc/test/coverage/index-sort-f.html +++ b/doc/test/coverage/index-sort-f.html @@ -31,27 +31,27 @@ lcov.info Lines: - 364 - 396 - 91.9 % + 402 + 436 + 92.2 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 95 - 103 - 92.2 % + 101 + 110 + 91.8 % Branches: - 154 - 166 - 92.8 % + 163 + 178 + 91.6 % @@ -108,10 +108,10 @@ src -
96.3%96.3%
+
96.6%96.6%
- 96.3 % - 26 / 27 + 96.6 % + 28 / 29 85.7 % 6 / 7 80.0 % @@ -120,24 +120,24 @@ src/rules/validation -
97.7%97.7%
+
95.8%95.8%
- 97.7 % - 43 / 44 - 92.3 % - 12 / 13 - 100.0 % - 26 / 26 + 95.8 % + 69 / 72 + 89.5 % + 17 / 19 + 92.1 % + 35 / 38 src/rules/validation/abstract/RuleAddressList -
96.8%96.8%
+
97.1%97.1%
- 96.8 % - 30 / 31 - 93.3 % - 14 / 15 + 97.1 % + 34 / 35 + 93.8 % + 15 / 16 75.0 % 6 / 8 @@ -147,7 +147,7 @@
98.8%98.8%
98.8 % - 84 / 85 + 85 / 86 93.8 % 15 / 16 90.5 % @@ -159,7 +159,7 @@
100.0%
100.0 % - 96 / 96 + 99 / 99 94.7 % 18 / 19 98.1 % @@ -183,7 +183,7 @@
100.0%
100.0 % - 80 / 80 + 82 / 82 100.0 % 27 / 27 95.8 % diff --git a/doc/test/coverage/index-sort-l.html b/doc/test/coverage/index-sort-l.html index c955df1..608336a 100644 --- a/doc/test/coverage/index-sort-l.html +++ b/doc/test/coverage/index-sort-l.html @@ -31,27 +31,27 @@ lcov.info Lines: - 364 - 396 - 91.9 % + 402 + 436 + 92.2 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 95 - 103 - 92.2 % + 101 + 110 + 91.8 % Branches: - 154 - 166 - 92.8 % + 163 + 178 + 91.6 % @@ -105,13 +105,25 @@ - 0 / 0 + + src/rules/validation + +
95.8%95.8%
+ + 95.8 % + 69 / 72 + 89.5 % + 17 / 19 + 92.1 % + 35 / 38 + src -
96.3%96.3%
+
96.6%96.6%
- 96.3 % - 26 / 27 + 96.6 % + 28 / 29 85.7 % 6 / 7 80.0 % @@ -120,34 +132,22 @@ src/rules/validation/abstract/RuleAddressList -
96.8%96.8%
+
97.1%97.1%
- 96.8 % - 30 / 31 - 93.3 % - 14 / 15 + 97.1 % + 34 / 35 + 93.8 % + 15 / 16 75.0 % 6 / 8 - - src/rules/validation - -
97.7%97.7%
- - 97.7 % - 43 / 44 - 92.3 % - 12 / 13 - 100.0 % - 26 / 26 - src/rules/operation
98.8%98.8%
98.8 % - 84 / 85 + 85 / 86 93.8 % 15 / 16 90.5 % @@ -171,7 +171,7 @@
100.0%
100.0 % - 80 / 80 + 82 / 82 100.0 % 27 / 27 95.8 % @@ -183,7 +183,7 @@
100.0%
100.0 % - 96 / 96 + 99 / 99 94.7 % 18 / 19 98.1 % diff --git a/doc/test/coverage/index.html b/doc/test/coverage/index.html index 960324e..db93b03 100644 --- a/doc/test/coverage/index.html +++ b/doc/test/coverage/index.html @@ -31,27 +31,27 @@ lcov.info Lines: - 364 - 396 - 91.9 % + 402 + 436 + 92.2 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 95 - 103 - 92.2 % + 101 + 110 + 91.8 % Branches: - 154 - 166 - 92.8 % + 163 + 178 + 91.6 % @@ -96,10 +96,10 @@ src -
96.3%96.3%
+
96.6%96.6%
- 96.3 % - 26 / 27 + 96.6 % + 28 / 29 85.7 % 6 / 7 80.0 % @@ -111,7 +111,7 @@
100.0%
100.0 % - 80 / 80 + 82 / 82 100.0 % 27 / 27 95.8 % @@ -123,7 +123,7 @@
98.8%98.8%
98.8 % - 84 / 85 + 85 / 86 93.8 % 15 / 16 90.5 % @@ -135,7 +135,7 @@
100.0%
100.0 % - 96 / 96 + 99 / 99 94.7 % 18 / 19 98.1 % @@ -144,14 +144,14 @@ src/rules/validation -
97.7%97.7%
+
95.8%95.8%
- 97.7 % - 43 / 44 - 92.3 % - 12 / 13 - 100.0 % - 26 / 26 + 95.8 % + 69 / 72 + 89.5 % + 17 / 19 + 92.1 % + 35 / 38 src/rules/validation/abstract @@ -168,12 +168,12 @@ src/rules/validation/abstract/RuleAddressList -
96.8%96.8%
+
97.1%97.1%
- 96.8 % - 30 / 31 - 93.3 % - 14 / 15 + 97.1 % + 34 / 35 + 93.8 % + 15 / 16 75.0 % 6 / 8 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 104e111..78d135d 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 0 @@ -69,7 +69,7 @@ Hit count Sort by hit count - CMTATWithRuleEngineScript.run + CMTATWithRuleEngineScript.run 0 diff --git a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html index 6955f40..7974e50 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 0 @@ -69,7 +69,7 @@ Hit count Sort by hit count - CMTATWithRuleEngineScript.run + CMTATWithRuleEngineScript.run 0 diff --git a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html index fd8f994..f3ff3ee 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 0 @@ -78,48 +78,53 @@ 7 : : import "CMTAT/CMTAT_STANDALONE.sol"; 8 : : import "src/RuleEngine.sol"; 9 : : import "src/rules/validation/RuleWhitelist.sol"; - 10 : : /** - 11 : : @title Deploy a CMTAT, a RuleWhitelist and a RuleEngine - 12 : : */ - 13 : : contract CMTATWithRuleEngineScript is Script { - 14 : : function run() external { - 15 : : // Get env variable - 16 : 0 : uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); - 17 : 0 : address ADMIN = vm.addr(deployerPrivateKey); - 18 : 0 : address trustedForwarder = address(0x0); - 19 : 0 : vm.startBroadcast(deployerPrivateKey); - 20 : 0 : uint256 flag = 5; - 21 : 0 : uint8 decimals = 0; - 22 : : // CMTAT - 23 : 0 : CMTAT_STANDALONE CMTAT_CONTRACT = new CMTAT_STANDALONE( - 24 : : trustedForwarder, - 25 : : ADMIN, - 26 : : IAuthorizationEngine(address(0)), - 27 : : "CMTA Token", - 28 : : "CMTAT", - 29 : : decimals, - 30 : : "CMTAT_ISIN", - 31 : : "https://cmta.ch", - 32 : : IRuleEngine(address(0)), - 33 : : "CMTAT_info", - 34 : : flag - 35 : : ); - 36 : 0 : console.log("CMTAT CMTAT_CONTRACT : ", address(CMTAT_CONTRACT)); - 37 : : // whitelist - 38 : 0 : RuleWhitelist ruleWhitelist = new RuleWhitelist( - 39 : : ADMIN, - 40 : : trustedForwarder - 41 : : ); - 42 : 0 : console.log("whitelist: ", address(ruleWhitelist)); - 43 : : // ruleEngine - 44 : 0 : RuleEngine RULE_ENGINE = new RuleEngine(ADMIN, trustedForwarder, address(CMTAT_CONTRACT)); - 45 : 0 : console.log("RuleEngine : ", address(RULE_ENGINE)); - 46 : 0 : RULE_ENGINE.addRuleValidation(ruleWhitelist); - 47 : 0 : CMTAT_CONTRACT.setRuleEngine(RULE_ENGINE); - 48 : : - 49 : 0 : vm.stopBroadcast(); - 50 : : } - 51 : : } + 10 : : + 11 : : /** + 12 : : @title Deploy a CMTAT, a RuleWhitelist and a RuleEngine + 13 : : */ + 14 : : contract CMTATWithRuleEngineScript is Script { + 15 : : function run() external { + 16 : : // Get env variable + 17 : 0 : uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + 18 : 0 : address ADMIN = vm.addr(deployerPrivateKey); + 19 : 0 : address trustedForwarder = address(0x0); + 20 : 0 : vm.startBroadcast(deployerPrivateKey); + 21 : 0 : uint256 flag = 5; + 22 : 0 : uint8 decimals = 0; + 23 : : // CMTAT + 24 : 0 : CMTAT_STANDALONE CMTAT_CONTRACT = new CMTAT_STANDALONE( + 25 : : trustedForwarder, + 26 : : ADMIN, + 27 : : IAuthorizationEngine(address(0)), + 28 : : "CMTA Token", + 29 : : "CMTAT", + 30 : : decimals, + 31 : : "CMTAT_ISIN", + 32 : : "https://cmta.ch", + 33 : : IRuleEngine(address(0)), + 34 : : "CMTAT_info", + 35 : : flag + 36 : : ); + 37 : 0 : console.log("CMTAT CMTAT_CONTRACT : ", address(CMTAT_CONTRACT)); + 38 : : // whitelist + 39 : 0 : RuleWhitelist ruleWhitelist = new RuleWhitelist( + 40 : : ADMIN, + 41 : : trustedForwarder + 42 : : ); + 43 : 0 : console.log("whitelist: ", address(ruleWhitelist)); + 44 : : // ruleEngine + 45 : 0 : RuleEngine RULE_ENGINE = new RuleEngine( + 46 : : ADMIN, + 47 : : trustedForwarder, + 48 : : address(CMTAT_CONTRACT) + 49 : : ); + 50 : 0 : console.log("RuleEngine : ", address(RULE_ENGINE)); + 51 : 0 : RULE_ENGINE.addRuleValidation(ruleWhitelist); + 52 : 0 : CMTAT_CONTRACT.setRuleEngine(RULE_ENGINE); + 53 : : + 54 : 0 : vm.stopBroadcast(); + 55 : : } + 56 : : } 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 0be87b7..959b08b 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-15 12:20:21 + 2024-06-11 10:19:24 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 f91ca3b..0433035 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-15 12:20:21 + 2024-06-11 10:19:24 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 4eb457e..48afae6 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 0 diff --git a/doc/test/coverage/script/index-sort-b.html b/doc/test/coverage/script/index-sort-b.html index 7e3a773..4495e7c 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 0 diff --git a/doc/test/coverage/script/index-sort-f.html b/doc/test/coverage/script/index-sort-f.html index afd417e..12cfb5b 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 0 @@ -82,28 +82,28 @@ Branches Sort by branch coverage - RuleEngineScript.s.sol + CMTATWithRuleEngineScript.s.sol
0.0%
0.0 % - 0 / 12 + 0 / 15 0.0 % 0 / 1 - 0.0 % - 0 / 2 + - + 0 / 0 - CMTATWithRuleEngineScript.s.sol + RuleEngineScript.s.sol
0.0%
0.0 % - 0 / 15 + 0 / 12 0.0 % 0 / 1 - - - 0 / 0 + 0.0 % + 0 / 2 diff --git a/doc/test/coverage/script/index-sort-l.html b/doc/test/coverage/script/index-sort-l.html index 0366127..a1602b6 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 0 diff --git a/doc/test/coverage/script/index.html b/doc/test/coverage/script/index.html index 38a89dc..647bf4f 100644 --- a/doc/test/coverage/script/index.html +++ b/doc/test/coverage/script/index.html @@ -37,7 +37,7 @@ Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 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 a8539b5..405200a 100644 --- a/doc/test/coverage/src/RuleEngine.sol.func-sort-c.html +++ b/doc/test/coverage/src/RuleEngine.sol.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 26 - 27 - 96.3 % + 28 + 29 + 96.6 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 6 @@ -69,32 +69,32 @@ Hit count Sort by hit count - RuleEngine._msgData + RuleEngine._msgData 0 - RuleEngine.validateTransfer + RuleEngine.validateTransfer 9 - RuleEngine.detectTransferRestriction - 13 + RuleEngine.detectTransferRestriction + 17 - RuleEngine.messageForTransferRestriction - 14 + RuleEngine.messageForTransferRestriction + 18 - RuleEngine.operateOnTransfer - 45 + RuleEngine.operateOnTransfer + 52 - RuleEngine._contextSuffixLength - 244 + RuleEngine._contextSuffixLength + 263 - RuleEngine._msgSender - 244 + RuleEngine._msgSender + 263
diff --git a/doc/test/coverage/src/RuleEngine.sol.func.html b/doc/test/coverage/src/RuleEngine.sol.func.html index 2250ee1..fe0b6bf 100644 --- a/doc/test/coverage/src/RuleEngine.sol.func.html +++ b/doc/test/coverage/src/RuleEngine.sol.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 26 - 27 - 96.3 % + 28 + 29 + 96.6 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 6 @@ -69,31 +69,31 @@ Hit count Sort by hit count - RuleEngine._contextSuffixLength - 244 + RuleEngine._contextSuffixLength + 263 - RuleEngine._msgData + RuleEngine._msgData 0 - RuleEngine._msgSender - 244 + RuleEngine._msgSender + 263 - RuleEngine.detectTransferRestriction - 13 + RuleEngine.detectTransferRestriction + 17 - RuleEngine.messageForTransferRestriction - 14 + RuleEngine.messageForTransferRestriction + 18 - RuleEngine.operateOnTransfer - 45 + RuleEngine.operateOnTransfer + 52 - RuleEngine.validateTransfer + RuleEngine.validateTransfer 9 diff --git a/doc/test/coverage/src/RuleEngine.sol.gcov.html b/doc/test/coverage/src/RuleEngine.sol.gcov.html index a5ae197..4d28c47 100644 --- a/doc/test/coverage/src/RuleEngine.sol.gcov.html +++ b/doc/test/coverage/src/RuleEngine.sol.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 26 - 27 - 96.3 % + 28 + 29 + 96.6 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 6 @@ -78,152 +78,177 @@ 7 : : import "./modules/RuleEngineOperation.sol"; 8 : : import "./modules/RuleEngineValidation.sol"; 9 : : - 10 : : - 11 : : /** - 12 : : * @title Implementation of a ruleEngine as defined by the CMTAT - 13 : : */ - 14 : : contract RuleEngine is IRuleEngine, RuleEngineOperation, RuleEngineValidation, MetaTxModuleStandalone { - 15 : : error RuleEngine_TransferInvalid(); - 16 : : /** - 17 : : * @param admin Address of the contract (Access Control) - 18 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - 19 : : */ - 20 : : constructor( - 21 : : address admin, - 22 : : address forwarderIrrevocable, - 23 : : address tokenContract - 24 : : ) MetaTxModuleStandalone(forwarderIrrevocable) { - 25 : : if(admin == address(0)) - 26 : : { - 27 : : revert RuleEngine_AdminWithAddressZeroNotAllowed(); - 28 : : } - 29 : : if(tokenContract != address(0)){ - 30 : : _grantRole(TOKEN_CONTRACT_ROLE, tokenContract); - 31 : : } - 32 : : _grantRole(DEFAULT_ADMIN_ROLE, admin); - 33 : : _grantRole(RULE_ENGINE_ROLE, admin); - 34 : : } - 35 : : - 36 : : - 37 : : /** - 38 : : * @notice Go through all the rule to know if a restriction exists on the transfer - 39 : : * @param _from the origin address - 40 : : * @param _to the destination address - 41 : : * @param _amount to transfer - 42 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - 43 : : **/ - 44 : : function detectTransferRestriction( - 45 : : address _from, - 46 : : address _to, - 47 : : uint256 _amount - 48 : : ) public view override returns (uint8) { - 49 : : // Validation - 50 : 66 : uint8 code = RuleEngineValidation.detectTransferRestrictionValidation(_from, _to, _amount); - 51 [ + + ]: 66 : if(code != uint8(REJECTED_CODE_BASE.TRANSFER_OK) ){ - 52 : 24 : return code; - 53 : : } - 54 : : - 55 : : // Operation - 56 : 20 : uint256 rulesLength = _rulesOperation.length; - 57 : 32 : for (uint256 i = 0; i < rulesLength; ++i ) { - 58 : 18 : uint8 restriction = IRuleValidation(_rulesOperation[i]).detectTransferRestriction( - 59 : : _from, - 60 : : _to, - 61 : : _amount - 62 : : ); - 63 [ + + ]: 12 : if (restriction > 0) { - 64 : 10 : return restriction; - 65 : : } - 66 : : } - 67 : : - 68 : 15 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 69 : : } - 70 : : - 71 : : /** - 72 : : * @notice Validate a transfer - 73 : : * @param _from the origin address - 74 : : * @param _to the destination address - 75 : : * @param _amount to transfer - 76 : : * @return True if the transfer is valid, false otherwise - 77 : : **/ - 78 : : function validateTransfer( - 79 : : address _from, - 80 : : address _to, - 81 : : uint256 _amount - 82 : : ) public view override returns (bool) { - 83 : 45 : return detectTransferRestriction(_from, _to, _amount) == uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 84 : : } - 85 : : - 86 : : /** - 87 : : * @notice Return the message corresponding to the code - 88 : : * @param _restrictionCode The target restriction code - 89 : : * @return True if the transfer is valid, false otherwise - 90 : : **/ - 91 : : function messageForTransferRestriction( - 92 : : uint8 _restrictionCode - 93 : : ) external view override returns (string memory) { - 94 : : // Validation - 95 : 28 : uint256 rulesLength = _rulesValidation.length; - 96 : 46 : for (uint256 i = 0; i < rulesLength; ++i) { - 97 [ # + ]: 18 : if (IRuleValidation(_rulesValidation[i]).canReturnTransferRestrictionCode(_restrictionCode)) { - 98 : 14 : return - 99 : 14 : IRuleValidation(_rulesValidation[i]).messageForTransferRestriction(_restrictionCode); - 100 : : } - 101 : : } - 102 : : // operation - 103 : 14 : rulesLength = _rulesOperation.length; - 104 : 23 : for (uint256 i = 0; i < rulesLength; ++i) { - 105 [ # + ]: 4 : if (IRuleValidation(_rulesOperation[i]).canReturnTransferRestrictionCode(_restrictionCode)) { - 106 : 2 : return - 107 : 2 : IRuleValidation(_rulesOperation[i]).messageForTransferRestriction(_restrictionCode); - 108 : : } - 109 : : } - 110 : 12 : return "Unknown restriction code"; - 111 : : } - 112 : : - 113 : : /* - 114 : : * @notice function protected by access control - 115 : : */ - 116 : : function operateOnTransfer(address from, address to, uint256 amount) external override onlyRole(TOKEN_CONTRACT_ROLE) returns (bool isValid) { - 117 : : // Validate the transfer - 118 [ + + ]: 88 : if(!RuleEngineValidation.validateTransferValidation(from, to, amount)){ - 119 : 14 : return false; - 120 : : } - 121 : : // Apply operation on RuleEngine - 122 : 111 : return RuleEngineOperation._operateOnTransfer(from, to, amount); - 123 : : } - 124 : : - 125 : : /** - 126 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 127 : : */ - 128 : : function _msgSender() - 129 : : internal - 130 : : view - 131 : : override(ERC2771Context, Context) - 132 : : returns (address sender) - 133 : : { - 134 : 732 : return ERC2771Context._msgSender(); - 135 : : } - 136 : : - 137 : : /** - 138 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 139 : : */ - 140 : : function _msgData() - 141 : : internal - 142 : : view - 143 : : override(ERC2771Context, Context) - 144 : : returns (bytes calldata) - 145 : : { - 146 : 0 : return ERC2771Context._msgData(); - 147 : : } - 148 : : - 149 : : /** - 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 : 732 : return ERC2771Context._contextSuffixLength(); - 154 : : } - 155 : : } + 10 : : /** + 11 : : * @title Implementation of a ruleEngine as defined by the CMTAT + 12 : : */ + 13 : : contract RuleEngine is + 14 : : IRuleEngine, + 15 : : RuleEngineOperation, + 16 : : RuleEngineValidation, + 17 : : MetaTxModuleStandalone + 18 : : { + 19 : : error RuleEngine_TransferInvalid(); + 20 : : + 21 : : /** + 22 : : * @param admin Address of the contract (Access Control) + 23 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + 24 : : */ + 25 : : constructor( + 26 : : address admin, + 27 : : address forwarderIrrevocable, + 28 : : address tokenContract + 29 : : ) MetaTxModuleStandalone(forwarderIrrevocable) { + 30 : : if (admin == address(0)) { + 31 : : revert RuleEngine_AdminWithAddressZeroNotAllowed(); + 32 : : } + 33 : : if (tokenContract != address(0)) { + 34 : : _grantRole(TOKEN_CONTRACT_ROLE, tokenContract); + 35 : : } + 36 : : _grantRole(DEFAULT_ADMIN_ROLE, admin); + 37 : : _grantRole(RULE_ENGINE_OPERATOR_ROLE, admin); + 38 : : } + 39 : : + 40 : : /** + 41 : : * @notice Go through all the rule to know if a restriction exists on the transfer + 42 : : * @param _from the origin address + 43 : : * @param _to the destination address + 44 : : * @param _amount to transfer + 45 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + 46 : : **/ + 47 : : function detectTransferRestriction( + 48 : : address _from, + 49 : : address _to, + 50 : : uint256 _amount + 51 : : ) public view override returns (uint8) { + 52 : : // Validation + 53 : 78 : uint8 code = RuleEngineValidation.detectTransferRestrictionValidation( + 54 : : _from, + 55 : : _to, + 56 : : _amount + 57 : : ); + 58 [ + + ]: 78 : if (code != uint8(REJECTED_CODE_BASE.TRANSFER_OK)) { + 59 : 30 : return code; + 60 : : } + 61 : : + 62 : : // Operation + 63 : 22 : uint256 rulesLength = _rulesOperation.length; + 64 : 35 : for (uint256 i = 0; i < rulesLength; ++i) { + 65 : 18 : uint8 restriction = IRuleValidation(_rulesOperation[i]) + 66 : : .detectTransferRestriction(_from, _to, _amount); + 67 [ + + ]: 12 : if (restriction > 0) { + 68 : 10 : return restriction; + 69 : : } + 70 : : } + 71 : : + 72 : 18 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 73 : : } + 74 : : + 75 : : /** + 76 : : * @notice Validate a transfer + 77 : : * @param _from the origin address + 78 : : * @param _to the destination address + 79 : : * @param _amount to transfer + 80 : : * @return True if the transfer is valid, false otherwise + 81 : : **/ + 82 : : function validateTransfer( + 83 : : address _from, + 84 : : address _to, + 85 : : uint256 _amount + 86 : : ) public view override returns (bool) { + 87 : 18 : return + 88 : 27 : detectTransferRestriction(_from, _to, _amount) == + 89 : 18 : uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 90 : : } + 91 : : + 92 : : /** + 93 : : * @notice Return the message corresponding to the code + 94 : : * @param _restrictionCode The target restriction code + 95 : : * @return True if the transfer is valid, false otherwise + 96 : : **/ + 97 : : function messageForTransferRestriction( + 98 : : uint8 _restrictionCode + 99 : : ) external view override returns (string memory) { + 100 : : // Validation + 101 : 36 : uint256 rulesLength = _rulesValidation.length; + 102 : 60 : for (uint256 i = 0; i < rulesLength; ++i) { + 103 [ # + ]: : if ( + 104 : 26 : IRuleValidation(_rulesValidation[i]) + 105 : : .canReturnTransferRestrictionCode(_restrictionCode) + 106 : : ) { + 107 : 20 : return + 108 : 20 : IRuleValidation(_rulesValidation[i]) + 109 : : .messageForTransferRestriction(_restrictionCode); + 110 : : } + 111 : : } + 112 : : // operation + 113 : 16 : rulesLength = _rulesOperation.length; + 114 : 26 : for (uint256 i = 0; i < rulesLength; ++i) { + 115 [ # + ]: : if ( + 116 : 4 : IRuleValidation(_rulesOperation[i]) + 117 : : .canReturnTransferRestrictionCode(_restrictionCode) + 118 : : ) { + 119 : 2 : return + 120 : 2 : IRuleValidation(_rulesOperation[i]) + 121 : : .messageForTransferRestriction(_restrictionCode); + 122 : : } + 123 : : } + 124 : 14 : return "Unknown restriction code"; + 125 : : } + 126 : : + 127 : : /* + 128 : : * @notice function protected by access control + 129 : : */ + 130 : : function operateOnTransfer( + 131 : : address from, + 132 : : address to, + 133 : : uint256 amount + 134 : : ) external override onlyRole(TOKEN_CONTRACT_ROLE) returns (bool isValid) { + 135 : : // Validate the transfer + 136 [ + + ]: : if ( + 137 : 102 : !RuleEngineValidation.validateTransferValidation(from, to, amount) + 138 : : ) { + 139 : 20 : return false; + 140 : : } + 141 : : // Apply operation on RuleEngine + 142 : 123 : return RuleEngineOperation._operateOnTransfer(from, to, amount); + 143 : : } + 144 : : + 145 : : /** + 146 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 147 : : */ + 148 : : function _msgSender() + 149 : : internal + 150 : : view + 151 : : override(ERC2771Context, Context) + 152 : : returns (address sender) + 153 : : { + 154 : 789 : return ERC2771Context._msgSender(); + 155 : : } + 156 : : + 157 : : /** + 158 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 159 : : */ + 160 : : function _msgData() + 161 : : internal + 162 : : view + 163 : : override(ERC2771Context, Context) + 164 : : returns (bytes calldata) + 165 : : { + 166 : 0 : return ERC2771Context._msgData(); + 167 : : } + 168 : : + 169 : : /** + 170 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 171 : : */ + 172 : : function _contextSuffixLength() + 173 : : internal + 174 : : view + 175 : : override(ERC2771Context, Context) + 176 : : returns (uint256) + 177 : : { + 178 : 789 : return ERC2771Context._contextSuffixLength(); + 179 : : } + 180 : : } diff --git a/doc/test/coverage/src/index-sort-b.html b/doc/test/coverage/src/index-sort-b.html index 7c7d1c2..69c094d 100644 --- a/doc/test/coverage/src/index-sort-b.html +++ b/doc/test/coverage/src/index-sort-b.html @@ -31,13 +31,13 @@ lcov.info Lines: - 26 - 27 - 96.3 % + 28 + 29 + 96.6 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 6 @@ -84,10 +84,10 @@ RuleEngine.sol -
96.3%96.3%
+
96.6%96.6%
- 96.3 % - 26 / 27 + 96.6 % + 28 / 29 85.7 % 6 / 7 80.0 % diff --git a/doc/test/coverage/src/index-sort-f.html b/doc/test/coverage/src/index-sort-f.html index 6a6bcc1..a0c5e56 100644 --- a/doc/test/coverage/src/index-sort-f.html +++ b/doc/test/coverage/src/index-sort-f.html @@ -31,13 +31,13 @@ lcov.info Lines: - 26 - 27 - 96.3 % + 28 + 29 + 96.6 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 6 @@ -84,10 +84,10 @@ RuleEngine.sol -
96.3%96.3%
+
96.6%96.6%
- 96.3 % - 26 / 27 + 96.6 % + 28 / 29 85.7 % 6 / 7 80.0 % diff --git a/doc/test/coverage/src/index-sort-l.html b/doc/test/coverage/src/index-sort-l.html index 876daf1..7392b50 100644 --- a/doc/test/coverage/src/index-sort-l.html +++ b/doc/test/coverage/src/index-sort-l.html @@ -31,13 +31,13 @@ lcov.info Lines: - 26 - 27 - 96.3 % + 28 + 29 + 96.6 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 6 @@ -84,10 +84,10 @@ RuleEngine.sol -
96.3%96.3%
+
96.6%96.6%
- 96.3 % - 26 / 27 + 96.6 % + 28 / 29 85.7 % 6 / 7 80.0 % diff --git a/doc/test/coverage/src/index.html b/doc/test/coverage/src/index.html index 3326585..c192026 100644 --- a/doc/test/coverage/src/index.html +++ b/doc/test/coverage/src/index.html @@ -31,13 +31,13 @@ lcov.info Lines: - 26 - 27 - 96.3 % + 28 + 29 + 96.6 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 6 @@ -84,10 +84,10 @@ RuleEngine.sol -
96.3%96.3%
+
96.6%96.6%
- 96.3 % - 26 / 27 + 96.6 % + 28 / 29 85.7 % 6 / 7 80.0 % 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 60b6676..0fd50ed 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 11 @@ -69,47 +69,47 @@ Hit count Sort by hit count - RuleEngineOperation.ruleOperation + RuleEngineOperation.ruleOperation 1 - RuleEngineOperation.getRuleIndexOperation + RuleEngineOperation.getRuleIndexOperation 3 - RuleEngineOperation.clearRulesOperation + RuleEngineOperation.clearRulesOperation 4 - RuleEngineOperation.removeRuleOperation + RuleEngineOperation.removeRuleOperation 5 - RuleEngineOperation.rulesOperation + RuleEngineOperation.rulesOperation 5 - RuleEngineOperation.setRulesOperation + RuleEngineOperation.setRulesOperation 11 - RuleEngineOperation._clearRulesOperation + RuleEngineOperation._clearRulesOperation 14 - RuleEngineOperation._removeRuleOperation + RuleEngineOperation._removeRuleOperation 22 - RuleEngineOperation._operateOnTransfer - 37 + RuleEngineOperation._operateOnTransfer + 41 - RuleEngineOperation.rulesCountOperation + RuleEngineOperation.rulesCountOperation 41 - RuleEngineOperation.addRuleOperation + RuleEngineOperation.addRuleOperation 68 diff --git a/doc/test/coverage/src/modules/RuleEngineOperation.sol.func.html b/doc/test/coverage/src/modules/RuleEngineOperation.sol.func.html index d1a961d..4034157 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 11 @@ -69,47 +69,47 @@ Hit count Sort by hit count - RuleEngineOperation._clearRulesOperation + RuleEngineOperation._clearRulesOperation 14 - RuleEngineOperation._operateOnTransfer - 37 + RuleEngineOperation._operateOnTransfer + 41 - RuleEngineOperation._removeRuleOperation + RuleEngineOperation._removeRuleOperation 22 - RuleEngineOperation.addRuleOperation + RuleEngineOperation.addRuleOperation 68 - RuleEngineOperation.clearRulesOperation + RuleEngineOperation.clearRulesOperation 4 - RuleEngineOperation.getRuleIndexOperation + RuleEngineOperation.getRuleIndexOperation 3 - RuleEngineOperation.removeRuleOperation + RuleEngineOperation.removeRuleOperation 5 - RuleEngineOperation.ruleOperation + RuleEngineOperation.ruleOperation 1 - RuleEngineOperation.rulesCountOperation + RuleEngineOperation.rulesCountOperation 41 - RuleEngineOperation.rulesOperation + RuleEngineOperation.rulesOperation 5 - RuleEngineOperation.setRulesOperation + RuleEngineOperation.setRulesOperation 11 diff --git a/doc/test/coverage/src/modules/RuleEngineOperation.sol.gcov.html b/doc/test/coverage/src/modules/RuleEngineOperation.sol.gcov.html index 157fff9..4a3b270 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 11 @@ -77,156 +77,168 @@ 6 : : import "../interfaces/IRuleEngineOperation.sol"; 7 : : import "../interfaces/IRuleOperation.sol"; 8 : : import "OZ/access/AccessControl.sol"; - 9 : : /** - 10 : : * @title Implementation of a ruleEngine defined by the CMTAT - 11 : : */ - 12 : : abstract contract RuleEngineOperation is AccessControl, RuleInternal, IRuleEngineOperation { - 13 : : /// @dev Array of rules - 14 : : address[] internal _rulesOperation; - 15 : : - 16 : : /** - 17 : : * @notice Set all the rules, will overwrite all the previous rules. \n - 18 : : * Revert if one rule is a zero address or if the rule is already present - 19 : : * - 20 : : */ - 21 : : function setRulesOperation( - 22 : : address[] calldata rules_ - 23 : : ) public onlyRole(RULE_ENGINE_ROLE) { - 24 [ + + ]: 22 : if(_rulesOperation.length > 0){ - 25 : 20 : _clearRulesOperation(); - 26 : : } - 27 : 22 : _setRules(rules_); - 28 : 16 : _rulesOperation = rules_; - 29 : : } - 30 : : - 31 : : /** - 32 : : * @notice Clear all the rules of the array of rules - 33 : : * - 34 : : */ - 35 : : function clearRulesOperation() public onlyRole(RULE_ENGINE_ROLE) { - 36 : 8 : _clearRulesOperation(); - 37 : : } - 38 : : - 39 : : /** - 40 : : * @notice Clear all the rules of the array of rules - 41 : : * - 42 : : */ - 43 : : function _clearRulesOperation() internal { - 44 : 28 : uint256 index; - 45 : : // we remove the last element first since it is more optimized. - 46 : 76 : for(uint256 i = _rulesOperation.length; i > 0; --i){ - 47 : : unchecked { - 48 : : // don't underflow since i > 0 - 49 : 34 : index = i - 1; - 50 : : } - 51 : 34 : _removeRuleOperation(_rulesOperation[index], index); - 52 : : } - 53 : 28 : emit ClearRules(_rulesOperation); - 54 : : } - 55 : : - 56 : : /** - 57 : : * @notice Add a rule to the array of rules - 58 : : * Revert if one rule is a zero address or if the rule is already present - 59 : : * - 60 : : */ - 61 : : function addRuleOperation(IRuleOperation rule_) public onlyRole(RULE_ENGINE_ROLE) { - 62 : 136 : RuleInternal._addRule( _rulesOperation, address(rule_)); - 63 : 132 : emit AddRule(address(rule_)); - 64 : : } - 65 : : - 66 : : /** - 67 : : * @notice Remove a rule from the array of rules - 68 : : * Revert if the rule found at the specified index does not match the rule in argument - 69 : : * @param rule_ address of the target rule - 70 : : * @param index the position inside the array of rule - 71 : : * @dev To reduce the array size, the last rule is moved to the location occupied - 72 : : * by the rule to remove - 73 : : * - 74 : : * - 75 : : */ - 76 : : function removeRuleOperation( - 77 : : IRuleOperation rule_, - 78 : : uint256 index - 79 : : ) public onlyRole(RULE_ENGINE_ROLE) { - 80 : 10 : _removeRuleOperation(address(rule_), index); - 81 : : } - 82 : : - 83 : : /** - 84 : : * @notice Remove a rule from the array of rules - 85 : : * Revert if the rule found at the specified index does not match the rule in argument - 86 : : * @param rule_ address of the target rule - 87 : : * @param index the position inside the array of rule - 88 : : * @dev To reduce the array size, the last rule is moved to the location occupied - 89 : : * by the rule to remove - 90 : : * - 91 : : * - 92 : : */ - 93 : : function _removeRuleOperation( - 94 : : address rule_, - 95 : : uint256 index - 96 : : ) internal { - 97 : 44 : RuleInternal._removeRule(_rulesOperation, rule_, index); - 98 : 42 : emit RemoveRule(address(rule_)); - 99 : : } - 100 : : - 101 : : /** - 102 : : * @return The number of rules inside the array - 103 : : */ - 104 : : function rulesCountOperation() external view override returns (uint256) { - 105 : 82 : return _rulesOperation.length; - 106 : : } - 107 : : - 108 : : /** - 109 : : * @notice Get the index of a rule inside the list - 110 : : * @return index if the rule is found, _rulesOperation.length otherwise - 111 : : */ - 112 : : function getRuleIndexOperation(IRuleOperation rule_) external view returns (uint256 index) { - 113 : 9 : return RuleInternal.getRuleIndex(_rulesOperation, address(rule_)); - 114 : : } - 115 : : - 116 : : /** - 117 : : * @notice Get the rule at the position specified by ruleId - 118 : : * @param ruleId index of the rule - 119 : : * @return a rule address - 120 : : */ - 121 : : function ruleOperation(uint256 ruleId) external view override returns (address) { - 122 : 2 : return _rulesOperation[ruleId]; - 123 : : } - 124 : : - 125 : : /** - 126 : : * @notice Get all the rules - 127 : : * @return An array of rules - 128 : : */ - 129 : : function rulesOperation() external view override returns (address[] memory) { - 130 : 10 : return _rulesOperation; + 9 : : + 10 : : /** + 11 : : * @title Implementation of a ruleEngine defined by the CMTAT + 12 : : */ + 13 : : abstract contract RuleEngineOperation is + 14 : : AccessControl, + 15 : : RuleInternal, + 16 : : IRuleEngineOperation + 17 : : { + 18 : : /// @dev Array of rules + 19 : : address[] internal _rulesOperation; + 20 : : + 21 : : /** + 22 : : * @notice Set all the rules, will overwrite all the previous rules. \n + 23 : : * Revert if one rule is a zero address or if the rule is already present + 24 : : * + 25 : : */ + 26 : : function setRulesOperation( + 27 : : address[] calldata rules_ + 28 : : ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { + 29 [ + + ]: 22 : if (_rulesOperation.length > 0) { + 30 : 20 : _clearRulesOperation(); + 31 : : } + 32 : 22 : _setRules(rules_); + 33 : 16 : _rulesOperation = rules_; + 34 : : } + 35 : : + 36 : : /** + 37 : : * @notice Clear all the rules of the array of rules + 38 : : * + 39 : : */ + 40 : : function clearRulesOperation() public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { + 41 : 8 : _clearRulesOperation(); + 42 : : } + 43 : : + 44 : : /** + 45 : : * @notice Clear all the rules of the array of rules + 46 : : * + 47 : : */ + 48 : : function _clearRulesOperation() internal { + 49 : 28 : uint256 index; + 50 : : // we remove the last element first since it is more optimized. + 51 : 76 : for (uint256 i = _rulesOperation.length; i > 0; --i) { + 52 : : unchecked { + 53 : : // don't underflow since i > 0 + 54 : 34 : index = i - 1; + 55 : : } + 56 : 34 : _removeRuleOperation(_rulesOperation[index], index); + 57 : : } + 58 : 28 : emit ClearRules(_rulesOperation); + 59 : : } + 60 : : + 61 : : /** + 62 : : * @notice Add a rule to the array of rules + 63 : : * Revert if one rule is a zero address or if the rule is already present + 64 : : * + 65 : : */ + 66 : : function addRuleOperation( + 67 : : IRuleOperation rule_ + 68 : : ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { + 69 : 136 : RuleInternal._addRule(_rulesOperation, address(rule_)); + 70 : 132 : emit AddRule(address(rule_)); + 71 : : } + 72 : : + 73 : : /** + 74 : : * @notice Remove a rule from the array of rules + 75 : : * Revert if the rule found at the specified index does not match the rule in argument + 76 : : * @param rule_ address of the target rule + 77 : : * @param index the position inside the array of rule + 78 : : * @dev To reduce the array size, the last rule is moved to the location occupied + 79 : : * by the rule to remove + 80 : : * + 81 : : * + 82 : : */ + 83 : : function removeRuleOperation( + 84 : : IRuleOperation rule_, + 85 : : uint256 index + 86 : : ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { + 87 : 10 : _removeRuleOperation(address(rule_), index); + 88 : : } + 89 : : + 90 : : /** + 91 : : * @notice Remove a rule from the array of rules + 92 : : * Revert if the rule found at the specified index does not match the rule in argument + 93 : : * @param rule_ address of the target rule + 94 : : * @param index the position inside the array of rule + 95 : : * @dev To reduce the array size, the last rule is moved to the location occupied + 96 : : * by the rule to remove + 97 : : * + 98 : : * + 99 : : */ + 100 : : function _removeRuleOperation(address rule_, uint256 index) internal { + 101 : 44 : RuleInternal._removeRule(_rulesOperation, rule_, index); + 102 : 42 : emit RemoveRule(address(rule_)); + 103 : : } + 104 : : + 105 : : /** + 106 : : * @return The number of rules inside the array + 107 : : */ + 108 : : function rulesCountOperation() external view override returns (uint256) { + 109 : 82 : return _rulesOperation.length; + 110 : : } + 111 : : + 112 : : /** + 113 : : * @notice Get the index of a rule inside the list + 114 : : * @return index if the rule is found, _rulesOperation.length otherwise + 115 : : */ + 116 : : function getRuleIndexOperation( + 117 : : IRuleOperation rule_ + 118 : : ) external view returns (uint256 index) { + 119 : 9 : return RuleInternal.getRuleIndex(_rulesOperation, address(rule_)); + 120 : : } + 121 : : + 122 : : /** + 123 : : * @notice Get the rule at the position specified by ruleId + 124 : : * @param ruleId index of the rule + 125 : : * @return a rule address + 126 : : */ + 127 : : function ruleOperation( + 128 : : uint256 ruleId + 129 : : ) external view override returns (address) { + 130 : 2 : return _rulesOperation[ruleId]; 131 : : } 132 : : - 133 : : - 134 : : /** - 135 : : * @notice Go through all the rule to know if a restriction exists on the transfer - 136 : : * @param _from the origin address - 137 : : * @param _to the destination address - 138 : : * @param _amount to transfer - 139 : : **/ - 140 : : function _operateOnTransfer( - 141 : : address _from, - 142 : : address _to, - 143 : : uint256 _amount - 144 : : ) internal returns (bool isValid){ - 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 [ + + ]: 66 : if(!result){ - 153 : 34 : return false; - 154 : : } - 155 : : } - 156 : 40 : return true; - 157 : : } - 158 : : } + 133 : : /** + 134 : : * @notice Get all the rules + 135 : : * @return An array of rules + 136 : : */ + 137 : : function rulesOperation() + 138 : : external + 139 : : view + 140 : : override + 141 : : returns (address[] memory) + 142 : : { + 143 : 10 : return _rulesOperation; + 144 : : } + 145 : : + 146 : : /** + 147 : : * @notice Go through all the rule to know if a restriction exists on the transfer + 148 : : * @param _from the origin address + 149 : : * @param _to the destination address + 150 : : * @param _amount to transfer + 151 : : **/ + 152 : : function _operateOnTransfer( + 153 : : address _from, + 154 : : address _to, + 155 : : uint256 _amount + 156 : : ) internal returns (bool isValid) { + 157 : 82 : uint256 rulesLength = _rulesOperation.length; + 158 : 155 : for (uint256 i = 0; i < rulesLength; ++i) { + 159 : 99 : bool result = IRuleOperation(_rulesOperation[i]).operateOnTransfer( + 160 : : _from, + 161 : : _to, + 162 : : _amount + 163 : : ); + 164 [ + + ]: 66 : if (!result) { + 165 : 34 : return false; + 166 : : } + 167 : : } + 168 : 48 : return true; + 169 : : } + 170 : : } 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 25488e0..ab7d535 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 @@ -31,17 +31,17 @@ lcov.info Lines: - 26 - 26 + 9 + 9 100.0 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 12 - 12 + 2 + 2 100.0 % @@ -49,8 +49,8 @@ Branches: - 4 - 4 + 2 + 2 100.0 % @@ -69,53 +69,13 @@ Hit count Sort by hit count - RuleEngineValidation.ruleValidation - 1 - - - RuleEngineValidation.validateTransferValidation + RuleEngineValidation.validateTransferValidation 2 - RuleEngineValidation.detectTransferRestrictionValidation - 3 - - - RuleEngineValidation.getRuleIndexValidation + RuleEngineValidation.detectTransferRestrictionValidation 3 - - RuleEngineValidation.rulesValidation - 5 - - - RuleEngineValidation.clearRulesValidation - 6 - - - RuleEngineValidation.removeRuleValidation - 6 - - - RuleEngineValidation.setRulesValidation - 22 - - - RuleEngineValidation._clearRulesValidation - 25 - - - RuleEngineValidation._removeRuleValidation - 33 - - - RuleEngineValidation.addRuleValidation - 67 - - - RuleEngineValidation.rulesCountValidation - 69 -
diff --git a/doc/test/coverage/src/modules/RuleEngineValidation.sol.func.html b/doc/test/coverage/src/modules/RuleEngineValidation.sol.func.html index 0e25146..9008852 100644 --- a/doc/test/coverage/src/modules/RuleEngineValidation.sol.func.html +++ b/doc/test/coverage/src/modules/RuleEngineValidation.sol.func.html @@ -31,17 +31,17 @@ lcov.info Lines: - 26 - 26 + 9 + 9 100.0 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 12 - 12 + 2 + 2 100.0 % @@ -49,8 +49,8 @@ Branches: - 4 - 4 + 2 + 2 100.0 % @@ -69,51 +69,11 @@ Hit count Sort by hit count - RuleEngineValidation._clearRulesValidation - 25 - - - RuleEngineValidation._removeRuleValidation - 33 - - - RuleEngineValidation.addRuleValidation - 67 - - - RuleEngineValidation.clearRulesValidation - 6 - - - RuleEngineValidation.detectTransferRestrictionValidation - 3 - - - RuleEngineValidation.getRuleIndexValidation + RuleEngineValidation.detectTransferRestrictionValidation 3 - RuleEngineValidation.removeRuleValidation - 6 - - - RuleEngineValidation.ruleValidation - 1 - - - RuleEngineValidation.rulesCountValidation - 69 - - - RuleEngineValidation.rulesValidation - 5 - - - RuleEngineValidation.setRulesValidation - 22 - - - RuleEngineValidation.validateTransferValidation + RuleEngineValidation.validateTransferValidation 2 diff --git a/doc/test/coverage/src/modules/RuleEngineValidation.sol.gcov.html b/doc/test/coverage/src/modules/RuleEngineValidation.sol.gcov.html index d78351a..6a7a5f3 100644 --- a/doc/test/coverage/src/modules/RuleEngineValidation.sol.gcov.html +++ b/doc/test/coverage/src/modules/RuleEngineValidation.sol.gcov.html @@ -31,17 +31,17 @@ lcov.info Lines: - 26 - 26 + 9 + 9 100.0 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 12 - 12 + 2 + 2 100.0 % @@ -49,8 +49,8 @@ Branches: - 4 - 4 + 2 + 2 100.0 % @@ -75,177 +75,62 @@ 4 : : 5 : : import "OZ/access/AccessControl.sol"; 6 : : import "./RuleInternal.sol"; - 7 : : import "../interfaces/IRuleEngineValidation.sol"; - 8 : : import "../interfaces/IRuleValidation.sol"; - 9 : : import "CMTAT/interfaces/draft-IERC1404/draft-IERC1404EnumCode.sol"; - 10 : : /** - 11 : : * @title Implementation of a ruleEngine defined by the CMTAT - 12 : : */ - 13 : : abstract contract RuleEngineValidation is AccessControl, RuleInternal, IRuleEngineValidation, IERC1404EnumCode { - 14 : : /// @dev Array of rules - 15 : : address[] internal _rulesValidation; - 16 : : - 17 : : - 18 : : /** - 19 : : * @notice Set all the rules, will overwrite all the previous rules. \n - 20 : : * Revert if one rule is a zero address or if the rule is already present - 21 : : * @dev take address[] instead of IRuleEngineValidation[] since it is not possible to cast IRuleEngineValidation[] -> address[] - 22 : : * - 23 : : */ - 24 : : function setRulesValidation( - 25 : : address[] calldata rules_ - 26 : : ) public override onlyRole(RULE_ENGINE_ROLE) { - 27 [ + + ]: 42 : if(_rulesValidation.length > 0){ - 28 : 40 : _clearRulesValidation(); - 29 : : } - 30 : 42 : _setRules(rules_); - 31 : 36 : _rulesValidation = rules_; - 32 : : } - 33 : : - 34 : : /** - 35 : : * @notice Clear all the rules of the array of rules - 36 : : * - 37 : : */ - 38 : : function clearRulesValidation() public onlyRole(RULE_ENGINE_ROLE) { - 39 : 10 : _clearRulesValidation(); - 40 : : } - 41 : : - 42 : : /** - 43 : : * @notice Clear all the rules of the array of rules - 44 : : * - 45 : : */ - 46 : : function _clearRulesValidation() internal { - 47 : 50 : uint256 index; - 48 : : // we remove the last element first since it is more optimized. - 49 : 131 : for(uint256 i = _rulesValidation.length; i > 0; --i){ - 50 : : unchecked { - 51 : : // don't underflow since i > 0 - 52 : 56 : index = i - 1; - 53 : : } - 54 : 56 : _removeRuleValidation(_rulesValidation[index], index); - 55 : : } - 56 : 50 : emit ClearRules(_rulesValidation); - 57 : : } - 58 : : - 59 : : /** - 60 : : * @notice Add a rule to the array of rules - 61 : : * Revert if one rule is a zero address or if the rule is already present - 62 : : * - 63 : : */ - 64 : : function addRuleValidation(IRuleValidation rule_) public onlyRole(RULE_ENGINE_ROLE) { - 65 : 132 : RuleInternal._addRule( _rulesValidation, address(rule_)); - 66 : 128 : emit AddRule(address(rule_)); - 67 : : } - 68 : : - 69 : : /** - 70 : : * @notice Remove a rule from the array of rules - 71 : : * Revert if the rule found at the specified index does not match the rule in argument - 72 : : * @param rule_ address of the target rule - 73 : : * @param index the position inside the array of rule - 74 : : * @dev To reduce the array size, the last rule is moved to the location occupied - 75 : : * by the rule to remove - 76 : : * - 77 : : * - 78 : : */ - 79 : : function removeRuleValidation( - 80 : : IRuleValidation rule_, - 81 : : uint256 index - 82 : : ) public onlyRole(RULE_ENGINE_ROLE) { - 83 : 10 : _removeRuleValidation(address(rule_), index); - 84 : : } - 85 : : - 86 : : /** - 87 : : * @notice Remove a rule from the array of rules - 88 : : * Revert if the rule found at the specified index does not match the rule in argument - 89 : : * @param rule_ address of the target rule - 90 : : * @param index the position inside the array of rule - 91 : : * @dev To reduce the array size, the last rule is moved to the location occupied - 92 : : * by the rule to remove - 93 : : * - 94 : : * - 95 : : */ - 96 : : function _removeRuleValidation( - 97 : : address rule_, - 98 : : uint256 index - 99 : : ) internal { - 100 : 66 : RuleInternal._removeRule(_rulesValidation, rule_, index); - 101 : 64 : emit RemoveRule(address(rule_)); - 102 : : } - 103 : : - 104 : : /** - 105 : : * @return The number of rules inside the array - 106 : : */ - 107 : : function rulesCountValidation() external view override returns (uint256) { - 108 : 138 : return _rulesValidation.length; - 109 : : } - 110 : : - 111 : : /** - 112 : : * @notice Get the index of a rule inside the list - 113 : : * @return index if the rule is found, _rulesValidation.length otherwise - 114 : : */ - 115 : : function getRuleIndexValidation(IRuleValidation rule_) external view returns (uint256 index) { - 116 : 9 : return RuleInternal.getRuleIndex(_rulesValidation, address(rule_)); - 117 : : } - 118 : : - 119 : : /** - 120 : : * @notice Get the rule at the position specified by ruleId - 121 : : * @param ruleId index of the rule - 122 : : * @return a rule address - 123 : : */ - 124 : : function ruleValidation(uint256 ruleId) external view override returns (address) { - 125 : 2 : return _rulesValidation[ruleId]; - 126 : : } - 127 : : - 128 : : /** - 129 : : * @notice Get all the rules - 130 : : * @return An array of rules - 131 : : */ - 132 : : function rulesValidation() external view override returns (address[] memory) { - 133 : 10 : return _rulesValidation; - 134 : : } - 135 : : - 136 : : /** - 137 : : * @notice Go through all the rule to know if a restriction exists on the transfer - 138 : : * @param _from the origin address - 139 : : * @param _to the destination address - 140 : : * @param _amount to transfer - 141 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - 142 : : **/ - 143 : : function detectTransferRestrictionValidation( - 144 : : address _from, - 145 : : address _to, - 146 : : uint256 _amount - 147 : : ) public view override returns (uint8) { - 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, - 153 : : _amount - 154 : : ); - 155 [ + + ]: 64 : if (restriction > 0) { - 156 : 44 : return restriction; - 157 : : } - 158 : : } - 159 : : - 160 : 147 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 161 : : } - 162 : : - 163 : : /** - 164 : : * @notice Validate a transfer - 165 : : * @param _from the origin address - 166 : : * @param _to the destination address - 167 : : * @param _amount to transfer - 168 : : * @return True if the transfer is valid, false otherwise - 169 : : **/ - 170 : : function validateTransferValidation( - 171 : : address _from, - 172 : : address _to, - 173 : : uint256 _amount - 174 : : ) public view override returns (bool) { - 175 : 230 : return detectTransferRestrictionValidation(_from, _to, _amount) == uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 176 : : } - 177 : : } + 7 : : import "./RuleEngineValidationCommon.sol"; + 8 : : import "../interfaces/IRuleEngineValidation.sol"; + 9 : : import "../interfaces/IRuleValidation.sol"; + 10 : : import "CMTAT/interfaces/draft-IERC1404/draft-IERC1404EnumCode.sol"; + 11 : : + 12 : : /** + 13 : : * @title Implementation of a ruleEngine defined by the CMTAT + 14 : : */ + 15 : : abstract contract RuleEngineValidation is + 16 : : AccessControl, + 17 : : RuleInternal, + 18 : : RuleEngineValidationCommon, + 19 : : IRuleEngineValidation, + 20 : : IERC1404EnumCode + 21 : : { + 22 : : /** + 23 : : * @notice Go through all the rule to know if a restriction exists on the transfer + 24 : : * @param _from the origin address + 25 : : * @param _to the destination address + 26 : : * @param _amount to transfer + 27 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + 28 : : **/ + 29 : : function detectTransferRestrictionValidation( + 30 : : address _from, + 31 : : address _to, + 32 : : uint256 _amount + 33 : : ) public view override returns (uint8) { + 34 : 164 : uint256 rulesLength = _rulesValidation.length; + 35 : 276 : for (uint256 i = 0; i < rulesLength; ++i) { + 36 : 129 : uint8 restriction = IRuleValidation(_rulesValidation[i]) + 37 : : .detectTransferRestriction(_from, _to, _amount); + 38 [ + + ]: 86 : if (restriction > 0) { + 39 : 56 : return restriction; + 40 : : } + 41 : : } + 42 : : + 43 : 162 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 44 : : } + 45 : : + 46 : : /** + 47 : : * @notice Validate a transfer + 48 : : * @param _from the origin address + 49 : : * @param _to the destination address + 50 : : * @param _amount to transfer + 51 : : * @return True if the transfer is valid, false otherwise + 52 : : **/ + 53 : : function validateTransferValidation( + 54 : : address _from, + 55 : : address _to, + 56 : : uint256 _amount + 57 : : ) public view override returns (bool) { + 58 : 106 : return + 59 : 159 : detectTransferRestrictionValidation(_from, _to, _amount) == + 60 : 106 : uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 61 : : } + 62 : : } diff --git a/doc/test/coverage/src/modules/RuleEngineValidationCommon.sol.func-sort-c.html b/doc/test/coverage/src/modules/RuleEngineValidationCommon.sol.func-sort-c.html new file mode 100644 index 0000000..2cc84b0 --- /dev/null +++ b/doc/test/coverage/src/modules/RuleEngineValidationCommon.sol.func-sort-c.html @@ -0,0 +1,121 @@ + + + + + + + LCOV - lcov.info - src/modules/RuleEngineValidationCommon.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/modules - RuleEngineValidationCommon.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1919100.0 %
Date:2024-06-11 10:19:24Functions:1010100.0 %
Branches:22100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleEngineValidationCommon.ruleValidation1
RuleEngineValidationCommon.getRuleIndexValidation3
RuleEngineValidationCommon.rulesValidation5
RuleEngineValidationCommon.clearRulesValidation6
RuleEngineValidationCommon.removeRuleValidation6
RuleEngineValidationCommon.setRulesValidation22
RuleEngineValidationCommon._clearRulesValidation25
RuleEngineValidationCommon._removeRuleValidation33
RuleEngineValidationCommon.rulesCountValidation69
RuleEngineValidationCommon.addRuleValidation115
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/modules/RuleEngineValidationCommon.sol.func.html b/doc/test/coverage/src/modules/RuleEngineValidationCommon.sol.func.html new file mode 100644 index 0000000..cc2d19e --- /dev/null +++ b/doc/test/coverage/src/modules/RuleEngineValidationCommon.sol.func.html @@ -0,0 +1,121 @@ + + + + + + + LCOV - lcov.info - src/modules/RuleEngineValidationCommon.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/modules - RuleEngineValidationCommon.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1919100.0 %
Date:2024-06-11 10:19:24Functions:1010100.0 %
Branches:22100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleEngineValidationCommon._clearRulesValidation25
RuleEngineValidationCommon._removeRuleValidation33
RuleEngineValidationCommon.addRuleValidation115
RuleEngineValidationCommon.clearRulesValidation6
RuleEngineValidationCommon.getRuleIndexValidation3
RuleEngineValidationCommon.removeRuleValidation6
RuleEngineValidationCommon.ruleValidation1
RuleEngineValidationCommon.rulesCountValidation69
RuleEngineValidationCommon.rulesValidation5
RuleEngineValidationCommon.setRulesValidation22
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/modules/RuleEngineValidationCommon.sol.gcov.html b/doc/test/coverage/src/modules/RuleEngineValidationCommon.sol.gcov.html new file mode 100644 index 0000000..c291df0 --- /dev/null +++ b/doc/test/coverage/src/modules/RuleEngineValidationCommon.sol.gcov.html @@ -0,0 +1,231 @@ + + + + + + + LCOV - lcov.info - src/modules/RuleEngineValidationCommon.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/modules - RuleEngineValidationCommon.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1919100.0 %
Date:2024-06-11 10:19:24Functions:1010100.0 %
Branches:22100.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : 
+       3                 :            : pragma solidity ^0.8.20;
+       4                 :            : 
+       5                 :            : import "OZ/access/AccessControl.sol";
+       6                 :            : import "./RuleInternal.sol";
+       7                 :            : import "../interfaces/IRuleEngineValidation.sol";
+       8                 :            : import "../interfaces/IRuleValidation.sol";
+       9                 :            : 
+      10                 :            : /**
+      11                 :            :  * @title Implementation of a ruleEngine defined by the CMTAT
+      12                 :            :  */
+      13                 :            : abstract contract RuleEngineValidationCommon is
+      14                 :            :     AccessControl,
+      15                 :            :     RuleInternal,
+      16                 :            :     IRuleEngineValidationCommon
+      17                 :            : {
+      18                 :            :     /// @dev Array of rules
+      19                 :            :     address[] internal _rulesValidation;
+      20                 :            : 
+      21                 :            :     /**
+      22                 :            :      * @notice Set all the rules, will overwrite all the previous rules. \n
+      23                 :            :      * Revert if one rule is a zero address or if the rule is already present
+      24                 :            :      * @dev take address[] instead of IRuleEngineValidation[] since it is not possible to cast IRuleEngineValidation[] -> address[]
+      25                 :            :      *
+      26                 :            :      */
+      27                 :            :     function setRulesValidation(
+      28                 :            :         address[] calldata rules_
+      29                 :            :     ) public override onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
+      30         [ +  + ]:         42 :         if (_rulesValidation.length > 0) {
+      31                 :         40 :             _clearRulesValidation();
+      32                 :            :         }
+      33                 :         42 :         _setRules(rules_);
+      34                 :         36 :         _rulesValidation = rules_;
+      35                 :            :     }
+      36                 :            : 
+      37                 :            :     /**
+      38                 :            :      * @notice Clear all the rules of the array of rules
+      39                 :            :      *
+      40                 :            :      */
+      41                 :            :     function clearRulesValidation() public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
+      42                 :         10 :         _clearRulesValidation();
+      43                 :            :     }
+      44                 :            : 
+      45                 :            :     /**
+      46                 :            :      * @notice Clear all the rules of the array of rules
+      47                 :            :      *
+      48                 :            :      */
+      49                 :            :     function _clearRulesValidation() internal {
+      50                 :         50 :         uint256 index;
+      51                 :            :         // we remove the last element first since it is more optimized.
+      52                 :        131 :         for (uint256 i = _rulesValidation.length; i > 0; --i) {
+      53                 :            :             unchecked {
+      54                 :            :                 // don't underflow since i > 0
+      55                 :         56 :                 index = i - 1;
+      56                 :            :             }
+      57                 :         56 :             _removeRuleValidation(_rulesValidation[index], index);
+      58                 :            :         }
+      59                 :         50 :         emit ClearRules(_rulesValidation);
+      60                 :            :     }
+      61                 :            : 
+      62                 :            :     /**
+      63                 :            :      * @notice Add a rule to the array of rules
+      64                 :            :      * Revert if one rule is a zero address or if the rule is already present
+      65                 :            :      *
+      66                 :            :      */
+      67                 :            :     function addRuleValidation(
+      68                 :            :         IRuleValidation rule_
+      69                 :            :     ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
+      70                 :        228 :         RuleInternal._addRule(_rulesValidation, address(rule_));
+      71                 :        224 :         emit AddRule(address(rule_));
+      72                 :            :     }
+      73                 :            : 
+      74                 :            :     /**
+      75                 :            :      * @notice Remove a rule from the array of rules
+      76                 :            :      * Revert if the rule found at the specified index does not match the rule in argument
+      77                 :            :      * @param rule_ address of the target rule
+      78                 :            :      * @param index the position inside the array of rule
+      79                 :            :      * @dev To reduce the array size, the last rule is moved to the location occupied
+      80                 :            :      * by the rule to remove
+      81                 :            :      *
+      82                 :            :      *
+      83                 :            :      */
+      84                 :            :     function removeRuleValidation(
+      85                 :            :         IRuleValidation rule_,
+      86                 :            :         uint256 index
+      87                 :            :     ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
+      88                 :         10 :         _removeRuleValidation(address(rule_), index);
+      89                 :            :     }
+      90                 :            : 
+      91                 :            :     /**
+      92                 :            :      * @notice Remove a rule from the array of rules
+      93                 :            :      * Revert if the rule found at the specified index does not match the rule in argument
+      94                 :            :      * @param rule_ address of the target rule
+      95                 :            :      * @param index the position inside the array of rule
+      96                 :            :      * @dev To reduce the array size, the last rule is moved to the location occupied
+      97                 :            :      * by the rule to remove
+      98                 :            :      *
+      99                 :            :      *
+     100                 :            :      */
+     101                 :            :     function _removeRuleValidation(address rule_, uint256 index) internal {
+     102                 :         66 :         RuleInternal._removeRule(_rulesValidation, rule_, index);
+     103                 :         64 :         emit RemoveRule(address(rule_));
+     104                 :            :     }
+     105                 :            : 
+     106                 :            :     /**
+     107                 :            :      * @return The number of rules inside the array
+     108                 :            :      */
+     109                 :            :     function rulesCountValidation() external view override returns (uint256) {
+     110                 :        138 :         return _rulesValidation.length;
+     111                 :            :     }
+     112                 :            : 
+     113                 :            :     /**
+     114                 :            :      * @notice Get the index of a rule inside the list
+     115                 :            :      * @return index if the rule is found, _rulesValidation.length otherwise
+     116                 :            :      */
+     117                 :            :     function getRuleIndexValidation(
+     118                 :            :         IRuleValidation rule_
+     119                 :            :     ) external view returns (uint256 index) {
+     120                 :          9 :         return RuleInternal.getRuleIndex(_rulesValidation, address(rule_));
+     121                 :            :     }
+     122                 :            : 
+     123                 :            :     /**
+     124                 :            :      * @notice Get the rule at the position specified by ruleId
+     125                 :            :      * @param ruleId index of the rule
+     126                 :            :      * @return a rule address
+     127                 :            :      */
+     128                 :            :     function ruleValidation(
+     129                 :            :         uint256 ruleId
+     130                 :            :     ) external view override returns (address) {
+     131                 :          2 :         return _rulesValidation[ruleId];
+     132                 :            :     }
+     133                 :            : 
+     134                 :            :     /**
+     135                 :            :      * @notice Get all the rules
+     136                 :            :      * @return An array of rules
+     137                 :            :      */
+     138                 :            :     function rulesValidation()
+     139                 :            :         external
+     140                 :            :         view
+     141                 :            :         override
+     142                 :            :         returns (address[] memory)
+     143                 :            :     {
+     144                 :         10 :         return _rulesValidation;
+     145                 :            :     }
+     146                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + 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 7f87299..388b450 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 4 @@ -69,20 +69,20 @@ Hit count Sort by hit count - RuleInternal.getRuleIndex + RuleInternal.getRuleIndex 6 - RuleInternal._setRules + RuleInternal._setRules 32 - RuleInternal._removeRule + RuleInternal._removeRule 55 - RuleInternal._addRule - 134 + RuleInternal._addRule + 182
diff --git a/doc/test/coverage/src/modules/RuleInternal.sol.func.html b/doc/test/coverage/src/modules/RuleInternal.sol.func.html index 3682d83..c96cc29 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 4 @@ -69,19 +69,19 @@ Hit count Sort by hit count - RuleInternal._addRule - 134 + RuleInternal._addRule + 182 - RuleInternal._removeRule + RuleInternal._removeRule 55 - RuleInternal._setRules + RuleInternal._setRules 32 - RuleInternal.getRuleIndex + RuleInternal.getRuleIndex 6 diff --git a/doc/test/coverage/src/modules/RuleInternal.sol.gcov.html b/doc/test/coverage/src/modules/RuleInternal.sol.gcov.html index 56428d7..c533201 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 4 @@ -75,102 +75,99 @@ 4 : : import "./RuleEngineInvariantStorage.sol"; 5 : : 6 : : /** - 7 : : * @title Implementation of a ruleEngine defined by the CMTAT - 8 : : */ + 7 : : * @title Implementation of a ruleEngine defined by the CMTAT + 8 : : */ 9 : : abstract contract RuleInternal is RuleEngineInvariantStorage { - 10 : : - 11 : : /// @dev Indicate if a rule already exists - 12 : : // Can be shared betwen RuleOperation and RuleValidation since it is a mapping - 13 : : mapping(address => bool) _ruleIsPresent; - 14 : : - 15 : : /** - 16 : : * @notice Set all the rules, will overwrite all the previous rules. \n - 17 : : * Revert if one rule is a zero address or if the rule is already present - 18 : : * - 19 : : */ - 20 : : function _setRules( - 21 : : address[] calldata rules_ - 22 : : ) internal { - 23 [ + + ]: 64 : if(rules_.length == 0){ - 24 : 4 : revert RuleEngine_ArrayIsEmpty(); - 25 : : } - 26 : 134 : for (uint256 i = 0; i < rules_.length; ) { - 27 [ + + ]: 192 : if( address(rules_[i]) == address(0x0)){ - 28 : 4 : revert RuleEngine_RuleAddressZeroNotAllowed(); + 10 : : /// @dev Indicate if a rule already exists + 11 : : // Can be shared betwen RuleOperation and RuleValidation since it is a mapping + 12 : : mapping(address => bool) _ruleIsPresent; + 13 : : + 14 : : /** + 15 : : * @notice Set all the rules, will overwrite all the previous rules. \n + 16 : : * Revert if one rule is a zero address or if the rule is already present + 17 : : * + 18 : : */ + 19 : : function _setRules(address[] calldata rules_) internal { + 20 [ + + ]: 64 : if (rules_.length == 0) { + 21 : 4 : revert RuleEngine_ArrayIsEmpty(); + 22 : : } + 23 : 134 : for (uint256 i = 0; i < rules_.length; ) { + 24 [ + + ]: 192 : if (address(rules_[i]) == address(0x0)) { + 25 : 4 : revert RuleEngine_RuleAddressZeroNotAllowed(); + 26 : : } + 27 [ + + ]: 46 : if (_ruleIsPresent[rules_[i]]) { + 28 : 4 : revert RuleEngine_RuleAlreadyExists(); 29 : : } - 30 [ + + ]: 46 : if(_ruleIsPresent[rules_[i]]){ - 31 : 4 : revert RuleEngine_RuleAlreadyExists(); - 32 : : } - 33 : 88 : _ruleIsPresent[rules_[i]] = true; - 34 : 88 : emit AddRule(rules_[i]); - 35 : : unchecked { - 36 : 88 : ++i; - 37 : : } - 38 : : } - 39 : : } - 40 : : - 41 : : /** - 42 : : * @notice Add a rule to the array of rules - 43 : : * Revert if one rule is a zero address or if the rule is already present - 44 : : * - 45 : : */ - 46 : : function _addRule(address[] storage _rules, address rule_) internal { - 47 [ + + ]: 536 : if( address(rule_) == address(0x0)) - 48 : : { - 49 : 4 : revert RuleEngine_RuleAddressZeroNotAllowed(); - 50 : : } - 51 [ + + ]: 132 : if( _ruleIsPresent[rule_]) - 52 : : { - 53 : 4 : revert RuleEngine_RuleAlreadyExists(); - 54 : : } - 55 : 260 : _rules.push(rule_); - 56 : 260 : _ruleIsPresent[rule_] = true; - 57 : : } - 58 : : - 59 : : /** - 60 : : * @notice Remove a rule from the array of rules - 61 : : * Revert if the rule found at the specified index does not match the rule in argument - 62 : : * @param rule_ address of the target rule - 63 : : * @param index the position inside the array of rule - 64 : : * @dev To reduce the array size, the last rule is moved to the location occupied - 65 : : * by the rule to remove - 66 : : * - 67 : : * - 68 : : */ - 69 : : function _removeRule( - 70 : : address[] storage _rules, - 71 : : address rule_, - 72 : : uint256 index - 73 : : ) internal { - 74 [ + + ]: 110 : if(_rules[index] != rule_) - 75 : : { - 76 : 4 : revert RuleEngine_RuleDoNotMatch(); - 77 : : } - 78 [ # + ]: 159 : if (index != _rules.length - 1) { - 79 : 8 : _rules[index] = _rules[_rules.length - 1]; - 80 : : } - 81 : 106 : _rules.pop(); - 82 : 106 : _ruleIsPresent[rule_] = false; - 83 : 106 : emit RemoveRule(rule_); - 84 : : } - 85 : : - 86 : : /** - 87 : : * @notice Get the index of a rule inside the list - 88 : : * @return index if the rule is found, _rules.length otherwise - 89 : : */ - 90 : : function getRuleIndex(address[] storage _rules, address rule_) internal view returns (uint256 index) { - 91 : 12 : uint256 rulesLength = _rules.length; - 92 : 24 : for (index = 0; index < rulesLength;) { - 93 [ + + ]: 20 : if (_rules[index] == rule_) { - 94 : 8 : return index; + 30 : 88 : _ruleIsPresent[rules_[i]] = true; + 31 : 88 : emit AddRule(rules_[i]); + 32 : : unchecked { + 33 : 88 : ++i; + 34 : : } + 35 : : } + 36 : : } + 37 : : + 38 : : /** + 39 : : * @notice Add a rule to the array of rules + 40 : : * Revert if one rule is a zero address or if the rule is already present + 41 : : * + 42 : : */ + 43 : : function _addRule(address[] storage _rules, address rule_) internal { + 44 [ + + ]: 728 : if (address(rule_) == address(0x0)) { + 45 : 4 : revert RuleEngine_RuleAddressZeroNotAllowed(); + 46 : : } + 47 [ + + ]: 180 : if (_ruleIsPresent[rule_]) { + 48 : 4 : revert RuleEngine_RuleAlreadyExists(); + 49 : : } + 50 : 356 : _rules.push(rule_); + 51 : 356 : _ruleIsPresent[rule_] = true; + 52 : : } + 53 : : + 54 : : /** + 55 : : * @notice Remove a rule from the array of rules + 56 : : * Revert if the rule found at the specified index does not match the rule in argument + 57 : : * @param rule_ address of the target rule + 58 : : * @param index the position inside the array of rule + 59 : : * @dev To reduce the array size, the last rule is moved to the location occupied + 60 : : * by the rule to remove + 61 : : * + 62 : : * + 63 : : */ + 64 : : function _removeRule( + 65 : : address[] storage _rules, + 66 : : address rule_, + 67 : : uint256 index + 68 : : ) internal { + 69 [ + + ]: 110 : if (_rules[index] != rule_) { + 70 : 4 : revert RuleEngine_RuleDoNotMatch(); + 71 : : } + 72 [ # + ]: 159 : if (index != _rules.length - 1) { + 73 : 8 : _rules[index] = _rules[_rules.length - 1]; + 74 : : } + 75 : 106 : _rules.pop(); + 76 : 106 : _ruleIsPresent[rule_] = false; + 77 : 106 : emit RemoveRule(rule_); + 78 : : } + 79 : : + 80 : : /** + 81 : : * @notice Get the index of a rule inside the list + 82 : : * @return index if the rule is found, _rules.length otherwise + 83 : : */ + 84 : : function getRuleIndex( + 85 : : address[] storage _rules, + 86 : : address rule_ + 87 : : ) internal view returns (uint256 index) { + 88 : 12 : uint256 rulesLength = _rules.length; + 89 : 24 : for (index = 0; index < rulesLength; ) { + 90 [ + + ]: 20 : if (_rules[index] == rule_) { + 91 : 8 : return index; + 92 : : } + 93 : : unchecked { + 94 : 12 : ++index; 95 : : } - 96 : : unchecked { - 97 : 12 : ++index; - 98 : : } - 99 : : } - 100 : 4 : return _rules.length; - 101 : : } - 102 : : } + 96 : : } + 97 : 4 : return _rules.length; + 98 : : } + 99 : : } diff --git a/doc/test/coverage/src/modules/index-sort-b.html b/doc/test/coverage/src/modules/index-sort-b.html index 85bb87e..014db42 100644 --- a/doc/test/coverage/src/modules/index-sort-b.html +++ b/doc/test/coverage/src/modules/index-sort-b.html @@ -31,13 +31,13 @@ lcov.info Lines: - 80 - 80 + 82 + 82 100.0 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 27 @@ -93,17 +93,29 @@ 93.8 % 15 / 16 + + RuleEngineValidationCommon.sol + +
100.0%
+ + 100.0 % + 19 / 19 + 100.0 % + 10 / 10 + 100.0 % + 2 / 2 + RuleEngineValidation.sol
100.0%
100.0 % - 26 / 26 + 9 / 9 100.0 % - 12 / 12 + 2 / 2 100.0 % - 4 / 4 + 2 / 2 RuleEngineOperation.sol diff --git a/doc/test/coverage/src/modules/index-sort-f.html b/doc/test/coverage/src/modules/index-sort-f.html index a84ef03..4e1c5fa 100644 --- a/doc/test/coverage/src/modules/index-sort-f.html +++ b/doc/test/coverage/src/modules/index-sort-f.html @@ -31,13 +31,13 @@ lcov.info Lines: - 80 - 80 + 82 + 82 100.0 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 27 @@ -81,6 +81,18 @@ Functions Sort by function coverage Branches Sort by branch coverage + + RuleEngineValidation.sol + +
100.0%
+ + 100.0 % + 9 / 9 + 100.0 % + 2 / 2 + 100.0 % + 2 / 2 + RuleInternal.sol @@ -94,26 +106,26 @@ 15 / 16 - RuleEngineOperation.sol + RuleEngineValidationCommon.sol
100.0%
100.0 % - 25 / 25 + 19 / 19 100.0 % - 11 / 11 + 10 / 10 100.0 % - 4 / 4 + 2 / 2 - RuleEngineValidation.sol + RuleEngineOperation.sol
100.0%
100.0 % - 26 / 26 + 25 / 25 100.0 % - 12 / 12 + 11 / 11 100.0 % 4 / 4 diff --git a/doc/test/coverage/src/modules/index-sort-l.html b/doc/test/coverage/src/modules/index-sort-l.html index 49f111f..4306ce9 100644 --- a/doc/test/coverage/src/modules/index-sort-l.html +++ b/doc/test/coverage/src/modules/index-sort-l.html @@ -31,13 +31,13 @@ lcov.info Lines: - 80 - 80 + 82 + 82 100.0 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 27 @@ -82,26 +82,38 @@ Branches Sort by branch coverage - RuleEngineOperation.sol + RuleEngineValidation.sol
100.0%
100.0 % - 25 / 25 + 9 / 9 100.0 % - 11 / 11 + 2 / 2 100.0 % - 4 / 4 + 2 / 2 - RuleEngineValidation.sol + RuleEngineValidationCommon.sol
100.0%
100.0 % - 26 / 26 + 19 / 19 + 100.0 % + 10 / 10 100.0 % - 12 / 12 + 2 / 2 + + + RuleEngineOperation.sol + +
100.0%
+ + 100.0 % + 25 / 25 + 100.0 % + 11 / 11 100.0 % 4 / 4 diff --git a/doc/test/coverage/src/modules/index.html b/doc/test/coverage/src/modules/index.html index 373a764..953d36c 100644 --- a/doc/test/coverage/src/modules/index.html +++ b/doc/test/coverage/src/modules/index.html @@ -31,13 +31,13 @@ lcov.info Lines: - 80 - 80 + 82 + 82 100.0 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 27 @@ -99,11 +99,23 @@
100.0%
100.0 % - 26 / 26 + 9 / 9 100.0 % - 12 / 12 + 2 / 2 100.0 % - 4 / 4 + 2 / 2 + + + RuleEngineValidationCommon.sol + +
100.0%
+ + 100.0 % + 19 / 19 + 100.0 % + 10 / 10 + 100.0 % + 2 / 2 RuleInternal.sol 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 6760052..5abe2e2 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: - 84 85 + 86 98.8 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 15 @@ -69,67 +69,67 @@ 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 + RuleConditionalTransfer.cancelTransferRequest 6 - RuleConditionalTransfer._cancelTransferRequest + RuleConditionalTransfer._cancelTransferRequest 9 - RuleConditionalTransfer.detectTransferRestriction + RuleConditionalTransfer.detectTransferRestriction 11 - RuleConditionalTransfer.operateOnTransfer + RuleConditionalTransfer.operateOnTransfer 33 - RuleConditionalTransfer.getRequestByStatus + RuleConditionalTransfer.getRequestByStatus 35 - RuleConditionalTransfer._validateApproval + RuleConditionalTransfer._validateApproval 37 - RuleConditionalTransfer._validateBurnMint + RuleConditionalTransfer._validateBurnMint 41 - RuleConditionalTransfer.getRequestTrade + RuleConditionalTransfer.getRequestTrade 57 - RuleConditionalTransfer.createTransferRequest + RuleConditionalTransfer.createTransferRequest 102 - RuleConditionalTransfer._contextSuffixLength + RuleConditionalTransfer._contextSuffixLength 452 - RuleConditionalTransfer._msgSender + 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 4bb3fe2..9fa83d8 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: - 84 85 + 86 98.8 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 15 @@ -69,67 +69,67 @@ Hit count Sort by hit count - RuleConditionalTransfer._cancelTransferRequest + RuleConditionalTransfer._cancelTransferRequest 9 - RuleConditionalTransfer._contextSuffixLength + RuleConditionalTransfer._contextSuffixLength 452 - RuleConditionalTransfer._msgData + RuleConditionalTransfer._msgData 0 - RuleConditionalTransfer._msgSender + RuleConditionalTransfer._msgSender 452 - RuleConditionalTransfer._validateApproval + RuleConditionalTransfer._validateApproval 37 - RuleConditionalTransfer._validateBurnMint + RuleConditionalTransfer._validateBurnMint 41 - RuleConditionalTransfer.canReturnTransferRestrictionCode + RuleConditionalTransfer.canReturnTransferRestrictionCode 2 - RuleConditionalTransfer.cancelTransferRequest + RuleConditionalTransfer.cancelTransferRequest 6 - RuleConditionalTransfer.cancelTransferRequestBatch + RuleConditionalTransfer.cancelTransferRequestBatch 3 - RuleConditionalTransfer.createTransferRequest + RuleConditionalTransfer.createTransferRequest 102 - RuleConditionalTransfer.createTransferRequestBatch + RuleConditionalTransfer.createTransferRequestBatch 3 - RuleConditionalTransfer.detectTransferRestriction + RuleConditionalTransfer.detectTransferRestriction 11 - RuleConditionalTransfer.getRequestByStatus + RuleConditionalTransfer.getRequestByStatus 35 - RuleConditionalTransfer.getRequestTrade + RuleConditionalTransfer.getRequestTrade 57 - RuleConditionalTransfer.messageForTransferRestriction + RuleConditionalTransfer.messageForTransferRestriction 3 - RuleConditionalTransfer.operateOnTransfer + 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 d822f2b..9ad4604 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: - 84 85 + 86 98.8 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 15 @@ -75,342 +75,375 @@ 4 : : 5 : : import "OZ/access/AccessControl.sol"; 6 : : import "../../interfaces/IRuleOperation.sol"; - 7 : : import "./../../modules/MetaTxModuleStandalone.sol"; + 7 : : import "./../../modules/MetaTxModuleStandalone.sol"; 8 : : import "./abstract/RuleConditionalTransferInvariantStorage.sol"; 9 : : import "./abstract/RuleConditionalTransferOperator.sol"; 10 : : import "../validation/abstract/RuleValidateTransfer.sol"; 11 : : import "CMTAT/interfaces/engine/IRuleEngine.sol"; 12 : : 13 : : /** - 14 : : * @title a whitelist manager - 15 : : */ + 14 : : * @title a whitelist manager + 15 : : */ 16 : : - 17 : : contract RuleConditionalTransfer is RuleValidateTransfer, IRuleOperation, RuleConditionalTransferOperator, MetaTxModuleStandalone { - 18 : : /** - 19 : : * @param admin Address of the contract (Access Control) - 20 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - 21 : : */ - 22 : : constructor( - 23 : : address admin, - 24 : : address forwarderIrrevocable, - 25 : : IRuleEngine ruleEngineContract, - 26 : : OPTION memory options_ - 27 : : ) MetaTxModuleStandalone(forwarderIrrevocable) { - 28 : : if(admin == address(0)){ - 29 : : revert RuleConditionalTransfer_AdminWithAddressZeroNotAllowed(); - 30 : : } - 31 : : _grantRole(DEFAULT_ADMIN_ROLE, admin); - 32 : : _grantRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, admin); - 33 : : if(address(ruleEngineContract) != address(0x0)){ - 34 : : _grantRole(RULE_ENGINE_CONTRACT_ROLE, address(ruleEngineContract)); + 17 : : contract RuleConditionalTransfer is + 18 : : RuleValidateTransfer, + 19 : : IRuleOperation, + 20 : : RuleConditionalTransferOperator, + 21 : : MetaTxModuleStandalone + 22 : : { + 23 : : /** + 24 : : * @param admin Address of the contract (Access Control) + 25 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + 26 : : */ + 27 : : constructor( + 28 : : address admin, + 29 : : address forwarderIrrevocable, + 30 : : IRuleEngine ruleEngineContract, + 31 : : OPTION memory options_ + 32 : : ) MetaTxModuleStandalone(forwarderIrrevocable) { + 33 : : if (admin == address(0)) { + 34 : : revert RuleConditionalTransfer_AdminWithAddressZeroNotAllowed(); 35 : : } - 36 : : if(options_.timeLimit.timeLimitToApprove == 0){ - 37 : : options_.timeLimit.timeLimitToApprove = type(uint64).max; - 38 : : } - 39 : : if(options_.timeLimit.timeLimitToTransfer == 0){ - 40 : : options_.timeLimit.timeLimitToTransfer = type(uint64).max; - 41 : : } - 42 : : options = options_; - 43 : : } - 44 : : - 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 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); + 36 : : _grantRole(DEFAULT_ADMIN_ROLE, admin); + 37 : : _grantRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, admin); + 38 : : if (address(ruleEngineContract) != address(0x0)) { + 39 : : _grantRole(RULE_ENGINE_CONTRACT_ROLE, address(ruleEngineContract)); + 40 : : } + 41 : : if (options_.timeLimit.timeLimitToApprove == 0) { + 42 : : options_.timeLimit.timeLimitToApprove = type(uint64).max; + 43 : : } + 44 : : if (options_.timeLimit.timeLimitToTransfer == 0) { + 45 : : options_.timeLimit.timeLimitToTransfer = type(uint64).max; + 46 : : } + 47 : : options = options_; + 48 : : } + 49 : : + 50 : : /** + 51 : : * @notice Create a request of transfer for yourselves + 52 : : * @param to recipient of tokens + 53 : : * @param value amount of tokens to transfer + 54 : : */ + 55 : : function createTransferRequest(address to, uint256 value) public { + 56 : : // WAIT => Will set a new delay to approve + 57 : : // APPROVED => will overwrite previous status + 58 : : // DENIED => reject + 59 : 315 : address from = _msgSender(); + 60 : 315 : bytes32 key = keccak256(abi.encode(from, to, value)); + 61 [ + + ]: 210 : if (transferRequests[key].status == STATUS.DENIED) { + 62 : 2 : revert RuleConditionalTransfer_TransferDenied(); + 63 : : } + 64 [ # + ]: 208 : if (_checkRequestStatus(key)) { + 65 : 202 : uint256 requestIdLocal = requestId; + 66 : 303 : TransferRequest memory newTransferApproval = TransferRequest({ + 67 : : key: key, + 68 : : id: requestIdLocal, + 69 : : from: from, + 70 : : to: to, + 71 : : value: value, + 72 : : askTime: block.timestamp, + 73 : : maxTime: 0, + 74 : : status: STATUS.WAIT + 75 : : }); + 76 : 202 : transferRequests[key] = newTransferApproval; + 77 : 202 : IdToKey[requestIdLocal] = key; + 78 : 202 : emit transferWaiting(key, from, to, value, requestId); + 79 : 202 : ++requestId; + 80 : : } else { + 81 : : // Overwrite previous approval + 82 : 6 : transferRequests[key].askTime = block.timestamp; + 83 : 6 : transferRequests[key].status = STATUS.WAIT; + 84 : 6 : emit transferWaiting( + 85 : : key, + 86 : : from, + 87 : : to, + 88 : : value, + 89 : : transferRequests[key].id + 90 : : ); + 91 : : } + 92 : : } + 93 : : + 94 : : /** + 95 : : * @notice Batch version of {createTransferRequest} + 96 : : */ + 97 : : function createTransferRequestBatch( + 98 : : address[] memory tos, + 99 : : uint256[] memory values + 100 : : ) public { + 101 [ + + ]: 6 : if (tos.length == 0) { + 102 : 2 : revert RuleConditionalTransfer_EmptyArray(); + 103 : : } + 104 [ + + ]: 4 : if (tos.length != values.length) { + 105 : 2 : revert RuleConditionalTransfer_InvalidLengthArray(); + 106 : : } + 107 : 9 : for (uint256 i = 0; i < tos.length; ++i) { + 108 : 6 : createTransferRequest(tos[i], values[i]); + 109 : : } + 110 : : } + 111 : : + 112 : : /** + 113 : : * @notice allow a token holder to cancel/reset his own request + 114 : : */ + 115 : : function cancelTransferRequest(uint256 requestId_) public { + 116 : 12 : _cancelTransferRequest(requestId_); + 117 : : } + 118 : : + 119 : : /** + 120 : : * @notice allow a token holder to cancel/reset his own request + 121 : : */ + 122 : : function cancelTransferRequestBatch(uint256[] memory requestIds) public { + 123 [ + + ]: 6 : if (requestIds.length == 0) { + 124 : 2 : revert RuleConditionalTransfer_EmptyArray(); + 125 : : } + 126 : : // Check id validity before performing actions + 127 : 14 : for (uint256 i = 0; i < requestIds.length; ++i) { + 128 [ + + ]: 15 : if (requestIds[i] + 1 > requestId) { + 129 : 2 : revert RuleConditionalTransfer_InvalidId(); + 130 : : } + 131 : : } + 132 : 9 : for (uint256 i = 0; i < requestIds.length; ++i) { + 133 : 6 : _cancelTransferRequest(requestIds[i]); + 134 : : } + 135 : : } + 136 : : + 137 : : function _cancelTransferRequest(uint256 requestId_) internal { + 138 [ + + ]: 27 : if (requestId_ + 1 > requestId) { + 139 : 2 : revert RuleConditionalTransfer_InvalidId(); + 140 : : } + 141 : 16 : bytes32 key = IdToKey[requestId_]; + 142 : : // Check Sender + 143 [ + + ]: 24 : if (transferRequests[key].from != _msgSender()) { + 144 : 2 : revert RuleConditionalTransfer_InvalidSender(); + 145 : : } + 146 : : // Check status + 147 [ + + ]: : if ( + 148 : 21 : transferRequests[key].status != STATUS.WAIT && + 149 : 4 : transferRequests[key].status != STATUS.APPROVED + 150 : : ) { + 151 : 2 : revert RuleConditionalTransfer_Wrong_Status(); + 152 : : } + 153 : 12 : _resetRequestStatus(key); + 154 : : } + 155 : : + 156 : : function getRequestTrade( + 157 : : address from, + 158 : : address to, + 159 : : uint256 value + 160 : : ) public view returns (TransferRequest memory) { + 161 : 171 : bytes32 key = keccak256(abi.encode(from, to, value)); + 162 : 114 : return transferRequests[key]; + 163 : : } + 164 : : + 165 : : /** + 166 : : * @notice get Trade by status + 167 : : * @param _targetStatus The status of the transactions you want to retrieve + 168 : : * @return array with corresponding transactions + 169 : : */ + 170 : : function getRequestByStatus( + 171 : : STATUS _targetStatus + 172 : : ) public view returns (TransferRequest[] memory) { + 173 : 70 : uint totalRequestCount = requestId; + 174 : 70 : uint requestCount = 0; + 175 : 70 : uint currentIndex = 0; 176 : : - 177 : : // We create an array with the list of trade + 177 : : // We count the number of requests matching the criteria 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 : : } - 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 _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; + 179 [ + + ]: 76 : if (transferRequests[IdToKey[i]].status == _targetStatus) { + 180 : 72 : requestCount += 1; + 181 : : } + 182 : : } + 183 : : + 184 : : // We reserve the memory to store the trade + 185 : 105 : TransferRequest[] memory requests = new TransferRequest[](requestCount); + 186 : : + 187 : : // We create an array with the list of trade + 188 : 181 : for (uint i = 0; i < totalRequestCount; ++i) { + 189 [ # + ]: 76 : if (transferRequests[IdToKey[i]].status == _targetStatus) { + 190 : : //uint currentId = i + 1; + 191 : 72 : TransferRequest memory currentRequest = transferRequests[ + 192 : : IdToKey[i] + 193 : : ]; + 194 : 72 : requests[currentIndex] = currentRequest; + 195 : 72 : currentIndex += 1; + 196 : : } + 197 : : } + 198 : 70 : return requests; + 199 : : } + 200 : : + 201 : : /** + 202 : : * @dev Returns true if the transfer is valid, and false otherwise. + 203 : : * Add access control with the RuleEngine + 204 : : */ + 205 : : function operateOnTransfer( + 206 : : address _from, + 207 : : address _to, + 208 : : uint256 _amount + 209 : : ) + 210 : : public + 211 : : override + 212 : : onlyRole(RULE_ENGINE_CONTRACT_ROLE) + 213 : : returns (bool isValid) + 214 : : { + 215 : : // No need of approval if from and to are in the whitelist + 216 [ + + ]: 132 : if (address(whitelistConditionalTransfer) != address(0)) { + 217 [ + + ]: : if ( + 218 : 54 : whitelistConditionalTransfer.addressIsListed(_from) && + 219 : 6 : whitelistConditionalTransfer.addressIsListed(_to) + 220 : : ) { + 221 : 4 : return true; + 222 : : } + 223 : : } + 224 : : + 225 : : // Mint & Burn + 226 [ + + ]: 62 : if (_validateBurnMint(_from, _to)) { + 227 : 8 : return true; + 228 : : } + 229 : 81 : bytes32 key = keccak256(abi.encode(_from, _to, _amount)); + 230 [ + + ]: 54 : if (_validateApproval(key)) { + 231 : 20 : _updateProcessedTransfer(key); + 232 : 20 : return true; + 233 : : } else { + 234 : 34 : return false; + 235 : : } + 236 : : } + 237 : : + 238 : : /** + 239 : : * @notice Check if the transfer is valid + 240 : : * @param _from the origin address + 241 : : * @param _to the destination address + 242 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + 243 : : **/ + 244 : : function detectTransferRestriction( + 245 : : address _from, + 246 : : address _to, + 247 : : uint256 _amount + 248 : : ) public view override returns (uint8) { + 249 : : // No need of approval if from and to are in the whitelist + 250 [ # + ]: 44 : if (address(whitelistConditionalTransfer) != address(0)) { + 251 [ # + ]: : if ( + 252 : 9 : whitelistConditionalTransfer.addressIsListed(_from) && + 253 : 4 : whitelistConditionalTransfer.addressIsListed(_to) + 254 : : ) { + 255 : 3 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 256 : : } + 257 : : } + 258 : 30 : bytes32 key = keccak256(abi.encode(_from, _to, _amount)); + 259 [ + + ]: 40 : if (!_validateBurnMint(_from, _to) && !_validateApproval(key)) { + 260 : 16 : return CODE_TRANSFER_REQUEST_NOT_APPROVED; + 261 : : } else { + 262 : 6 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 263 : : } + 264 : : } + 265 : : + 266 : : /** + 267 : : * @notice To know if the restriction code is valid for this rule or not. + 268 : : * @param _restrictionCode The target restriction code + 269 : : * @return true if the restriction code is known, false otherwise + 270 : : **/ + 271 : : function canReturnTransferRestrictionCode( + 272 : : uint8 _restrictionCode + 273 : : ) external pure override returns (bool) { + 274 : 6 : return _restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED; + 275 : : } + 276 : : + 277 : : /** + 278 : : * @notice Return the corresponding message + 279 : : * @param _restrictionCode The target restriction code + 280 : : * @return true if the transfer is valid, false otherwise + 281 : : **/ + 282 : : function messageForTransferRestriction( + 283 : : uint8 _restrictionCode + 284 : : ) external pure override returns (string memory) { + 285 [ + + ]: 6 : if (_restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED) { + 286 : 4 : return TEXT_TRANSFER_REQUEST_NOT_APPROVED; + 287 : : } else { + 288 : 2 : return TEXT_CODE_NOT_FOUND; + 289 : : } 290 : : } 291 : : 292 : : /** - 293 : : * - 294 : : * @dev - 295 : : * Test transfer approval condition + 293 : : * + 294 : : * @dev + 295 : : * Test burn and mint 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 : : } + 297 : : * + 298 : : */ + 299 : : function _validateBurnMint( + 300 : : address _from, + 301 : : address _to + 302 : : ) internal view returns (bool isValid) { + 303 : : // Mint & Burn + 304 [ + + ]: : if ( + 305 : 82 : (_from == address(0) && + 306 : : options.issuance.authorizedMintWithoutApproval) || + 307 : : (_to == address(0) && + 308 : : options.issuance.authorizedBurnWithoutApproval) + 309 : : ) { + 310 : 8 : return true; + 311 : : } + 312 : 74 : return false; + 313 : : } + 314 : : + 315 : : /** + 316 : : * + 317 : : * @dev + 318 : : * Test transfer approval condition + 319 : : * Returns true if the transfer is valid, and false otherwise. + 320 : : */ + 321 : : function _validateApproval( + 322 : : bytes32 key + 323 : : ) internal view returns (bool isValid) { + 324 : 111 : bool automaticApprovalCondition = options + 325 : : .automaticApproval + 326 : : .isActivate && + 327 : : ((transferRequests[key].askTime + + 328 : : options.automaticApproval.timeLimitBeforeAutomaticApproval) >= + 329 : : block.timestamp); + 330 : 111 : bool isTransferApproved = (transferRequests[key].status == + 331 : : STATUS.APPROVED) && + 332 : : (transferRequests[key].maxTime >= block.timestamp); + 333 [ + + ]: 74 : if (automaticApprovalCondition || isTransferApproved) { + 334 : 24 : return true; + 335 : : } else { + 336 : 50 : return false; + 337 : : } + 338 : : } + 339 : : + 340 : : /** + 341 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 342 : : */ + 343 : : function _msgSender() + 344 : : internal + 345 : : view + 346 : : override(ERC2771Context, Context) + 347 : : returns (address sender) + 348 : : { + 349 : 1356 : return ERC2771Context._msgSender(); + 350 : : } + 351 : : + 352 : : /** + 353 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 354 : : */ + 355 : : function _msgData() + 356 : : internal + 357 : : view + 358 : : override(ERC2771Context, Context) + 359 : : returns (bytes calldata) + 360 : : { + 361 : 0 : return ERC2771Context._msgData(); + 362 : : } + 363 : : + 364 : : /** + 365 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 366 : : */ + 367 : : function _contextSuffixLength() + 368 : : internal + 369 : : view + 370 : : override(ERC2771Context, Context) + 371 : : returns (uint256) + 372 : : { + 373 : 1356 : return ERC2771Context._contextSuffixLength(); + 374 : : } + 375 : : } 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 b1117d6..37c914c 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,13 +31,13 @@ lcov.info Lines: - 96 - 96 + 99 + 99 100.0 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 18 @@ -69,79 +69,79 @@ Hit count Sort by hit count - RuleConditionalTransferOperator._createTransferRequestWithApproval + RuleConditionalTransferOperator._createTransferRequestWithApproval 0 - RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch + RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch 3 - RuleConditionalTransferOperator.resetRequestStatus + RuleConditionalTransferOperator.resetRequestStatus 3 - RuleConditionalTransferOperator.resetRequestStatusBatch + RuleConditionalTransferOperator.resetRequestStatusBatch 3 - RuleConditionalTransferOperator.setAutomaticTransfer + RuleConditionalTransferOperator.setAutomaticTransfer 3 - RuleConditionalTransferOperator.setTimeLimit + RuleConditionalTransferOperator.setTimeLimit 4 - RuleConditionalTransferOperator.approveTransferRequestWithId + RuleConditionalTransferOperator.approveTransferRequestWithId 5 - RuleConditionalTransferOperator.setAutomaticApproval + RuleConditionalTransferOperator.setAutomaticApproval 5 - RuleConditionalTransferOperator.setIssuanceOptions + RuleConditionalTransferOperator.setIssuanceOptions 5 - RuleConditionalTransferOperator.createTransferRequestWithApproval + RuleConditionalTransferOperator.createTransferRequestWithApproval 6 - RuleConditionalTransferOperator.approveTransferRequestBatch + RuleConditionalTransferOperator.approveTransferRequestBatch 7 - RuleConditionalTransferOperator.approveTransferRequestBatchWithId + RuleConditionalTransferOperator.approveTransferRequestBatchWithId 7 - RuleConditionalTransferOperator._resetRequestStatus + RuleConditionalTransferOperator._resetRequestStatus 10 - RuleConditionalTransferOperator._updateProcessedTransfer + RuleConditionalTransferOperator._updateProcessedTransfer 10 - RuleConditionalTransferOperator.setConditionalWhitelist + RuleConditionalTransferOperator.setConditionalWhitelist 25 - RuleConditionalTransferOperator.approveTransferRequest + RuleConditionalTransferOperator.approveTransferRequest 33 - RuleConditionalTransferOperator._approveTransferRequestKeyElement + RuleConditionalTransferOperator._approveTransferRequestKeyElement 41 - RuleConditionalTransferOperator._approveRequest + RuleConditionalTransferOperator._approveRequest 46 - RuleConditionalTransferOperator._checkRequestStatus + 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 7f4ac9d..dc88726 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,13 +31,13 @@ lcov.info Lines: - 96 - 96 + 99 + 99 100.0 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 18 @@ -69,79 +69,79 @@ Hit count Sort by hit count - RuleConditionalTransferOperator._approveRequest + RuleConditionalTransferOperator._approveRequest 46 - RuleConditionalTransferOperator._approveTransferRequestKeyElement + RuleConditionalTransferOperator._approveTransferRequestKeyElement 41 - RuleConditionalTransferOperator._checkRequestStatus + RuleConditionalTransferOperator._checkRequestStatus 119 - RuleConditionalTransferOperator._createTransferRequestWithApproval + RuleConditionalTransferOperator._createTransferRequestWithApproval 0 - RuleConditionalTransferOperator._resetRequestStatus + RuleConditionalTransferOperator._resetRequestStatus 10 - RuleConditionalTransferOperator._updateProcessedTransfer + RuleConditionalTransferOperator._updateProcessedTransfer 10 - RuleConditionalTransferOperator.approveTransferRequest + RuleConditionalTransferOperator.approveTransferRequest 33 - RuleConditionalTransferOperator.approveTransferRequestBatch + RuleConditionalTransferOperator.approveTransferRequestBatch 7 - RuleConditionalTransferOperator.approveTransferRequestBatchWithId + RuleConditionalTransferOperator.approveTransferRequestBatchWithId 7 - RuleConditionalTransferOperator.approveTransferRequestWithId + RuleConditionalTransferOperator.approveTransferRequestWithId 5 - RuleConditionalTransferOperator.createTransferRequestWithApproval + RuleConditionalTransferOperator.createTransferRequestWithApproval 6 - RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch + RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch 3 - RuleConditionalTransferOperator.resetRequestStatus + RuleConditionalTransferOperator.resetRequestStatus 3 - RuleConditionalTransferOperator.resetRequestStatusBatch + RuleConditionalTransferOperator.resetRequestStatusBatch 3 - RuleConditionalTransferOperator.setAutomaticApproval + RuleConditionalTransferOperator.setAutomaticApproval 5 - RuleConditionalTransferOperator.setAutomaticTransfer + RuleConditionalTransferOperator.setAutomaticTransfer 3 - RuleConditionalTransferOperator.setConditionalWhitelist + RuleConditionalTransferOperator.setConditionalWhitelist 25 - RuleConditionalTransferOperator.setIssuanceOptions + RuleConditionalTransferOperator.setIssuanceOptions 5 - RuleConditionalTransferOperator.setTimeLimit + 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 0c436a8..f764155 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,13 +31,13 @@ lcov.info Lines: - 96 - 96 + 99 + 99 100.0 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 18 @@ -75,314 +75,449 @@ 4 : : 5 : : import "OZ/access/AccessControl.sol"; 6 : : import "./RuleConditionalTransferInvariantStorage.sol"; - 7 : : import "OZ/token/ERC20/utils/SafeERC20.sol"; - 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 [ + + ]: 12 : if(requestId_ + 1 > requestId) { - 112 : 4 : revert RuleConditionalTransfer_InvalidId(); - 113 : : } - 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 : 2 : bytes32 key = IdToKey[requestId_]; - 128 : 2 : _resetRequestStatus(key); - 129 : : } - 130 : : - 131 : : /***** Batch function */ + 7 : : import "OZ/token/ERC20/utils/SafeERC20.sol"; + 8 : : + 9 : : /** + 10 : : * @title Restricted functions + 11 : : */ + 12 : : abstract contract RuleConditionalTransferOperator is + 13 : : AccessControl, + 14 : : RuleConditionalTransferInvariantStorage + 15 : : { + 16 : : // Security + 17 : : using SafeERC20 for IERC20; + 18 : : + 19 : : // public variable with automatic Getter + 20 : : OPTION public options; + 21 : : uint256 public requestId; + 22 : : mapping(uint256 => bytes32) public IdToKey; + 23 : : mapping(bytes32 => TransferRequest) public transferRequests; + 24 : : RuleWhitelist public whitelistConditionalTransfer; + 25 : : + 26 : : /** + 27 : : * @notice set a whitelist. A transfer does not need of an approved request if from and to are in the whitelist + 28 : : */ + 29 : : function setConditionalWhitelist( + 30 : : RuleWhitelist newWhitelistConditionalTransfer + 31 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + 32 : 50 : whitelistConditionalTransfer = newWhitelistConditionalTransfer; + 33 : 50 : emit WhitelistConditionalTransfer(newWhitelistConditionalTransfer); + 34 : : } + 35 : : + 36 : : /** + 37 : : set/unset the issuance options (mint & burn) + 38 : : */ + 39 : : function setIssuanceOptions( + 40 : : ISSUANCE calldata issuance_ + 41 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + 42 [ + + ]: : if ( + 43 : 8 : options.issuance.authorizedMintWithoutApproval != + 44 : : issuance_.authorizedMintWithoutApproval + 45 : : ) { + 46 : 4 : options.issuance.authorizedMintWithoutApproval = issuance_ + 47 : : .authorizedMintWithoutApproval; + 48 : : } + 49 [ + + ]: : if ( + 50 : 8 : options.issuance.authorizedBurnWithoutApproval != + 51 : : issuance_.authorizedBurnWithoutApproval + 52 : : ) { + 53 : 4 : options.issuance.authorizedBurnWithoutApproval = issuance_ + 54 : : .authorizedBurnWithoutApproval; + 55 : : } + 56 : : } + 57 : : + 58 : : /** + 59 : : * @notice set/unset the option to perform the transfer if the request is approved by the rule operator. + 60 : : * To perform the transfer, the token holder has to approve the rule to spend tokens on his behalf (standard ERC-20 approval). + 61 : : * If the allowance is not sufficient, the request will be approved, but without performing the transfer. + 62 : : */ + 63 : : function setAutomaticTransfer( + 64 : : AUTOMATIC_TRANSFER calldata automaticTransfer_ + 65 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + 66 [ + + ]: : if ( + 67 : 4 : automaticTransfer_.isActivate != + 68 : : options.automaticTransfer.isActivate + 69 : : ) { + 70 : 4 : options.automaticTransfer.isActivate = automaticTransfer_ + 71 : : .isActivate; + 72 : : } + 73 : : // No need to put the cmtat to zero to deactivate automaticTransfer + 74 [ + + ]: : if ( + 75 : 6 : address(automaticTransfer_.cmtat) != + 76 : 4 : address(options.automaticTransfer.cmtat) + 77 : : ) { + 78 : 4 : options.automaticTransfer.cmtat = automaticTransfer_.cmtat; + 79 : : } + 80 : : } + 81 : : + 82 : : /** + 83 : : * @notice set time limit for new requests (Approval and transfer) + 84 : : * timeLimitToApprove: time limit for an operator to approve a request + 85 : : * timeLimitToTransfer: once a request is approved, time limit for the token holder to perform the transfer + 86 : : */ + 87 : : function setTimeLimit( + 88 : : TIME_LIMIT memory timeLimit_ + 89 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + 90 [ + + ]: : if ( + 91 : 6 : options.timeLimit.timeLimitToApprove != + 92 : : timeLimit_.timeLimitToApprove + 93 : : ) { + 94 : 6 : options.timeLimit.timeLimitToApprove = timeLimit_ + 95 : : .timeLimitToApprove; + 96 : : } + 97 [ + + ]: : if ( + 98 : 6 : options.timeLimit.timeLimitToTransfer != + 99 : : timeLimit_.timeLimitToTransfer + 100 : : ) { + 101 : 6 : options.timeLimit.timeLimitToTransfer = timeLimit_ + 102 : : .timeLimitToTransfer; + 103 : : } + 104 : : } + 105 : : + 106 : : /** + 107 : : * @notice If the transfer is not approved or denied within {timeLimitBeforeAutomaticApproval}, + 108 : : * the request is considered as approved during a transfer. + 109 : : * + 110 : : */ + 111 : : function setAutomaticApproval( + 112 : : AUTOMATIC_APPROVAL memory automaticApproval_ + 113 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + 114 [ + + ]: : if ( + 115 : 8 : options.automaticApproval.isActivate != + 116 : : automaticApproval_.isActivate + 117 : : ) { + 118 : 8 : options.automaticApproval.isActivate = automaticApproval_ + 119 : : .isActivate; + 120 : : } + 121 [ + + ]: : if ( + 122 : 8 : options.automaticApproval.timeLimitBeforeAutomaticApproval != + 123 : : automaticApproval_.timeLimitBeforeAutomaticApproval + 124 : : ) { + 125 : 8 : options + 126 : : .automaticApproval + 127 : : .timeLimitBeforeAutomaticApproval = automaticApproval_ + 128 : : .timeLimitBeforeAutomaticApproval; + 129 : : } + 130 : : } + 131 : : 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 : : * @notice Batch version of {approveTransferRequest} - 158 : : */ - 159 : : function approveTransferRequestBatch( - 160 : : TransferRequestKeyElement[] calldata keyElements, uint256[] calldata partialValues, bool[] calldata isApproved + 133 : : * @notice create a transfer request directly approved + 134 : : */ + 135 : : function createTransferRequestWithApproval( + 136 : : TransferRequestKeyElement calldata keyElement + 137 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + 138 : 10 : _createTransferRequestWithApproval(keyElement); + 139 : : } + 140 : : + 141 : : /** + 142 : : @notice approve a transferRequest + 143 : : @param keyElement contains from, to, value + 144 : : @param partialValue amount approved. Put 0 if all the amount specified by value is approved. + 145 : : @param isApproved approved (true) or refused (false). Put true if you use partialApproval + 146 : : */ + 147 : : function approveTransferRequest( + 148 : : TransferRequestKeyElement calldata keyElement, + 149 : : uint256 partialValue, + 150 : : bool isApproved + 151 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + 152 : 64 : _approveTransferRequestKeyElement(keyElement, partialValue, isApproved); + 153 : : } + 154 : : + 155 : : /** + 156 : : * @notice approve a transferRequestby using its id + 157 : : */ + 158 : : function approveTransferRequestWithId( + 159 : : uint256 requestId_, + 160 : : bool isApproved 161 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { - 162 [ + + ]: 12 : if(keyElements.length == 0){ - 163 : 2 : revert RuleConditionalTransfer_EmptyArray(); + 162 [ + + ]: 12 : if (requestId_ + 1 > requestId) { + 163 : 4 : revert RuleConditionalTransfer_InvalidId(); 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); + 165 : 4 : TransferRequest memory transferRequest = transferRequests[ + 166 : : IdToKey[requestId_] + 167 : : ]; + 168 : 4 : _approveRequest(transferRequest, isApproved); + 169 : : } + 170 : : + 171 : : /** + 172 : : * @notice reset to None the status of a request + 173 : : */ + 174 : : function resetRequestStatus( + 175 : : uint256 requestId_ + 176 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + 177 [ + + ]: 6 : if (requestId_ + 1 > requestId) { + 178 : 2 : revert RuleConditionalTransfer_InvalidId(); + 179 : : } + 180 : 2 : bytes32 key = IdToKey[requestId_]; + 181 : 2 : _resetRequestStatus(key); + 182 : : } + 183 : : + 184 : : /***** Batch function */ + 185 : : /** + 186 : : * @notice Batch version of {approveTransferRequestWithId} + 187 : : */ + 188 : : function approveTransferRequestBatchWithId( + 189 : : uint256[] calldata requestId_, + 190 : : bool[] calldata isApproved + 191 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + 192 [ + + ]: 10 : if (requestId_.length == 0) { + 193 : 2 : revert RuleConditionalTransfer_EmptyArray(); + 194 : : } + 195 [ + + ]: 8 : if (requestId_.length != isApproved.length) { + 196 : 2 : revert RuleConditionalTransfer_InvalidLengthArray(); + 197 : : } + 198 : : // Check id validity before performing actions + 199 : 29 : for (uint256 i = 0; i < requestId_.length; ++i) { + 200 [ + + ]: 33 : if (requestId_[i] + 1 > requestId) { + 201 : 2 : revert RuleConditionalTransfer_InvalidId(); + 202 : : } + 203 : : } + 204 : 14 : for (uint256 i = 0; i < requestId_.length; ++i) { + 205 : 10 : TransferRequest memory transferRequest = transferRequests[ + 206 : : IdToKey[requestId_[i]] + 207 : : ]; + 208 : 10 : _approveRequest(transferRequest, isApproved[i]); + 209 : : } + 210 : : } + 211 : : + 212 : : /** + 213 : : * @notice Batch version of {approveTransferRequest} + 214 : : */ + 215 : : function approveTransferRequestBatch( + 216 : : TransferRequestKeyElement[] calldata keyElements, + 217 : : uint256[] calldata partialValues, + 218 : : bool[] calldata isApproved + 219 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + 220 [ + + ]: 12 : if (keyElements.length == 0) { + 221 : 2 : revert RuleConditionalTransfer_EmptyArray(); + 222 : : } + 223 [ + + ]: : if ( + 224 : 10 : (keyElements.length != partialValues.length) || + 225 : : (partialValues.length != isApproved.length) + 226 : : ) { + 227 : 6 : revert RuleConditionalTransfer_InvalidLengthArray(); 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); + 229 : 24 : for (uint256 i = 0; i < keyElements.length; ++i) { + 230 : 18 : _approveTransferRequestKeyElement( + 231 : : keyElements[i], + 232 : : partialValues[i], + 233 : : isApproved[i] + 234 : : ); + 235 : : } + 236 : : } + 237 : : + 238 : : /** + 239 : : * @notice Batch version of {createTransferRequestWithApproval} + 240 : : */ + 241 : : function createTransferRequestWithApprovalBatch( + 242 : : TransferRequestKeyElement[] calldata keyElements + 243 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + 244 [ + + ]: 4 : if (keyElements.length == 0) { + 245 : 2 : revert RuleConditionalTransfer_EmptyArray(); + 246 : : } + 247 : 11 : for (uint256 i = 0; i < keyElements.length; ++i) { + 248 : 8 : _createTransferRequestWithApproval(keyElements[i]); + 249 : : } + 250 : : } + 251 : : + 252 : : /** + 253 : : * @notice Batch version of {resetRequestStatus} + 254 : : */ + 255 : : function resetRequestStatusBatch( + 256 : : uint256[] memory requestIds + 257 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + 258 [ + + ]: 6 : if (requestIds.length == 0) { + 259 : 2 : revert RuleConditionalTransfer_EmptyArray(); + 260 : : } + 261 : : // Check id validity before performing actions + 262 : 12 : for (uint256 i = 0; i < requestIds.length; ++i) { + 263 [ + + ]: 12 : if (requestIds[i] + 1 > requestId) { + 264 : 2 : revert RuleConditionalTransfer_InvalidId(); + 265 : : } + 266 : : } + 267 : 9 : for (uint256 i = 0; i < requestIds.length; ++i) { + 268 : 6 : bytes32 key = IdToKey[requestIds[i]]; + 269 : 6 : _resetRequestStatus(key); + 270 : : } 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 : : } + 273 : : /*** Internal functions ****/ + 274 : : function _approveTransferRequestKeyElement( + 275 : : TransferRequestKeyElement calldata keyElement, + 276 : : uint256 partialValue, + 277 : : bool isApproved + 278 : : ) internal { + 279 [ + + ]: 82 : if (partialValue > keyElement.value) { + 280 : 2 : revert RuleConditionalTransfer_InvalidValueApproved(); + 281 : : } + 282 : 120 : bytes32 key = keccak256( + 283 : : abi.encode(keyElement.from, keyElement.to, keyElement.value) + 284 : : ); + 285 : 80 : TransferRequest memory transferRequest = transferRequests[key]; + 286 [ + + ]: 80 : if (partialValue > 0) { + 287 [ + + ]: 14 : if (!isApproved) { + 288 : 2 : revert RuleConditionalTransfer_CannotDeniedPartially(); + 289 : : } + 290 : : // Denied the first request + 291 : 12 : _approveRequest(transferRequest, false); + 292 : : // Create new request + 293 : 12 : _createTransferRequestWithApproval( + 294 : : TransferRequestKeyElement({ + 295 : : from: keyElement.from, + 296 : : to: keyElement.to, + 297 : : value: partialValue + 298 : : }) + 299 : : ); + 300 : : } else { + 301 : 66 : _approveRequest(transferRequest, isApproved); + 302 : : } + 303 : : } + 304 : : + 305 : : function _createTransferRequestWithApproval( + 306 : : TransferRequestKeyElement memory keyElement + 307 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + 308 : : // WAIT => Will overwrite + 309 : : // APPROVED => will overwrite previous status with a new delay + 310 : : // DENIED => will overwrite + 311 : 45 : bytes32 key = keccak256( + 312 : : abi.encode(keyElement.from, keyElement.to, keyElement.value) + 313 : : ); + 314 [ # + ]: 30 : if (_checkRequestStatus(key)) { + 315 : 42 : TransferRequest memory newTransferApproval = TransferRequest({ + 316 : : key: key, + 317 : : id: requestId, + 318 : : from: keyElement.from, + 319 : : to: keyElement.to, + 320 : : value: keyElement.value, + 321 : : askTime: 0, + 322 : : maxTime: block.timestamp + + 323 : : options.timeLimit.timeLimitToTransfer, + 324 : : status: STATUS.APPROVED + 325 : : }); + 326 : 28 : transferRequests[key] = newTransferApproval; + 327 : 28 : IdToKey[requestId] = key; + 328 : 28 : emit transferApproved( + 329 : : key, + 330 : : keyElement.from, + 331 : : keyElement.to, + 332 : : keyElement.value, + 333 : : requestId + 334 : : ); + 335 : 28 : ++requestId; + 336 : : } else { + 337 : : // Overwrite previous approval + 338 : 2 : transferRequests[key].maxTime = + 339 : : block.timestamp + + 340 : : options.timeLimit.timeLimitToTransfer; + 341 : 2 : transferRequests[key].status = STATUS.APPROVED; + 342 : 2 : emit transferApproved( + 343 : : key, + 344 : : keyElement.from, + 345 : : keyElement.to, + 346 : : keyElement.value, + 347 : : transferRequests[key].id + 348 : : ); + 349 : : } + 350 : : } + 351 : : + 352 : : function _resetRequestStatus(bytes32 key) internal { + 353 : 20 : transferRequests[key].status = STATUS.NONE; + 354 : 20 : emit transferReset( + 355 : : key, + 356 : : transferRequests[key].from, + 357 : : transferRequests[key].to, + 358 : : transferRequests[key].value, + 359 : : transferRequests[key].id + 360 : : ); + 361 : : } + 362 : : + 363 : : function _checkRequestStatus(bytes32 key) internal view returns (bool) { + 364 : : // Status NONE not enough because reset is possible + 365 : 238 : return + 366 : 238 : (transferRequests[key].status == STATUS.NONE) && + 367 : : (transferRequests[key].key == 0x0); + 368 : : } + 369 : : + 370 : : function _approveRequest( + 371 : : TransferRequest memory transferRequest, + 372 : : bool isApproved + 373 : : ) internal { + 374 : : // status + 375 [ + + ]: 92 : if (transferRequest.status != STATUS.WAIT) { + 376 : 2 : revert RuleConditionalTransfer_Wrong_Status(); + 377 : : } + 378 [ + + ]: 45 : if (isApproved) { + 379 : : // Time + 380 [ + + ]: : if ( + 381 : 54 : block.timestamp > + 382 : : (transferRequest.askTime + options.timeLimit.timeLimitToApprove) + 383 : : ) { + 384 : 6 : revert RuleConditionalTransfer_timeExceeded(); + 385 : : } + 386 : : // Set status + 387 : 48 : transferRequests[transferRequest.key].status = STATUS.APPROVED; + 388 : : // Set max time + 389 : 48 : transferRequests[transferRequest.key].maxTime = + 390 : : block.timestamp + + 391 : : options.timeLimit.timeLimitToTransfer; + 392 : 48 : emit transferApproved( + 393 : : transferRequest.key, + 394 : : transferRequest.from, + 395 : : transferRequest.to, + 396 : : transferRequest.value, + 397 : : transferRequests[transferRequest.key].id + 398 : : ); + 399 [ + + ]: : if ( + 400 : 48 : options.automaticTransfer.isActivate && + 401 : 8 : address(options.automaticTransfer.cmtat) != address(0) + 402 : : ) { + 403 : : // Transfer with approval + 404 : : // External call + 405 [ + + ]: : if ( + 406 : 6 : options.automaticTransfer.cmtat.allowance( + 407 : : transferRequest.from, + 408 : : address(this) + 409 : : ) >= transferRequest.value + 410 : : ) { + 411 : : // Will call the ruleEngine and the rule again... + 412 : 4 : options.automaticTransfer.cmtat.safeTransferFrom( + 413 : : transferRequest.from, + 414 : : transferRequest.to, + 415 : : transferRequest.value + 416 : : ); + 417 : : } + 418 : : } + 419 : : } else { + 420 : 36 : transferRequests[transferRequest.key].status = STATUS.DENIED; + 421 : 36 : emit transferDenied( + 422 : : transferRequest.key, + 423 : : transferRequest.from, + 424 : : transferRequest.to, + 425 : : transferRequest.value, + 426 : : transferRequests[transferRequest.key].id + 427 : : ); + 428 : : } + 429 : : } + 430 : : + 431 : : /** + 432 : : * @notice update the request during a transfer + 433 : : */ + 434 : : function _updateProcessedTransfer(bytes32 key) internal { + 435 : : // Reset to zero + 436 : 20 : transferRequests[key].maxTime = 0; + 437 : 20 : transferRequests[key].askTime = 0; + 438 : : // Change status + 439 : 20 : transferRequests[key].status = STATUS.EXECUTED; + 440 : : // Emit event + 441 : 20 : emit transferProcessed( + 442 : : key, + 443 : : transferRequests[key].from, + 444 : : transferRequests[key].to, + 445 : : transferRequests[key].value, + 446 : : transferRequests[key].id + 447 : : ); + 448 : : } + 449 : : } 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 ceeab30..214958e 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,13 +31,13 @@ lcov.info Lines: - 96 - 96 + 99 + 99 100.0 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 18 @@ -87,7 +87,7 @@
100.0%
100.0 % - 96 / 96 + 99 / 99 94.7 % 18 / 19 98.1 % 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 8096c28..4c2ae50 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,13 +31,13 @@ lcov.info Lines: - 96 - 96 + 99 + 99 100.0 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 18 @@ -87,7 +87,7 @@
100.0%
100.0 % - 96 / 96 + 99 / 99 94.7 % 18 / 19 98.1 % 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 e6d471d..59e6a4a 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,13 +31,13 @@ lcov.info Lines: - 96 - 96 + 99 + 99 100.0 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 18 @@ -87,7 +87,7 @@
100.0%
100.0 % - 96 / 96 + 99 / 99 94.7 % 18 / 19 98.1 % diff --git a/doc/test/coverage/src/rules/operation/abstract/index.html b/doc/test/coverage/src/rules/operation/abstract/index.html index 1e6e812..acb0ad6 100644 --- a/doc/test/coverage/src/rules/operation/abstract/index.html +++ b/doc/test/coverage/src/rules/operation/abstract/index.html @@ -31,13 +31,13 @@ lcov.info Lines: - 96 - 96 + 99 + 99 100.0 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 18 @@ -87,7 +87,7 @@
100.0%
100.0 % - 96 / 96 + 99 / 99 94.7 % 18 / 19 98.1 % 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 d557abc..1e39e73 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: - 84 85 + 86 98.8 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 15 @@ -87,7 +87,7 @@
98.8%98.8%
98.8 % - 84 / 85 + 85 / 86 93.8 % 15 / 16 90.5 % 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 412cd56..2f811c5 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: - 84 85 + 86 98.8 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 15 @@ -87,7 +87,7 @@
98.8%98.8%
98.8 % - 84 / 85 + 85 / 86 93.8 % 15 / 16 90.5 % 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 af166d2..e90b7fc 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: - 84 85 + 86 98.8 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 15 @@ -87,7 +87,7 @@
98.8%98.8%
98.8 % - 84 / 85 + 85 / 86 93.8 % 15 / 16 90.5 % diff --git a/doc/test/coverage/src/rules/operation/index.html b/doc/test/coverage/src/rules/operation/index.html index 2ae074f..37c948b 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: - 84 85 + 86 98.8 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 15 @@ -87,7 +87,7 @@
98.8%98.8%
98.8 % - 84 / 85 + 85 / 86 93.8 % 15 / 16 90.5 % 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 d6b2d99..8ce4954 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 3 @@ -69,15 +69,15 @@ Hit count Sort by hit count - RuleBlacklist.canReturnTransferRestrictionCode + RuleBlacklist.canReturnTransferRestrictionCode 4 - RuleBlacklist.messageForTransferRestriction + RuleBlacklist.messageForTransferRestriction 4 - RuleBlacklist.detectTransferRestriction + RuleBlacklist.detectTransferRestriction 10 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 b63e470..82264b6 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 3 @@ -69,15 +69,15 @@ Hit count Sort by hit count - RuleBlacklist.canReturnTransferRestrictionCode + RuleBlacklist.canReturnTransferRestrictionCode 4 - RuleBlacklist.detectTransferRestriction + RuleBlacklist.detectTransferRestriction 10 - RuleBlacklist.messageForTransferRestriction + RuleBlacklist.messageForTransferRestriction 4 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 8f51703..f28a3c4 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 3 @@ -73,74 +73,78 @@ 2 : : 3 : : pragma solidity ^0.8.20; 4 : : - 5 : : import "./abstract/RuleAddressList/RuleBlacklistInvariantStorage.sol"; + 5 : : import "./abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol"; 6 : : import "./abstract/RuleAddressList/RuleAddressList.sol"; 7 : : import "./abstract/RuleValidateTransfer.sol"; - 8 : : /** - 9 : : * @title a blacklist manager - 10 : : */ - 11 : : - 12 : : contract RuleBlacklist is RuleValidateTransfer, RuleAddressList, RuleBlacklistInvariantStorage { - 13 : : /** - 14 : : * @param admin Address of the contract (Access Control) - 15 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - 16 : : */ - 17 : : constructor( - 18 : : address admin, - 19 : : address forwarderIrrevocable - 20 : : ) RuleAddressList(admin, forwarderIrrevocable) { - 21 : : } - 22 : : - 23 : : /** - 24 : : * @notice Check if an addres is in the whitelist or not - 25 : : * @param _from the origin address - 26 : : * @param _to the destination address - 27 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - 28 : : **/ - 29 : : function detectTransferRestriction( - 30 : : address _from, - 31 : : address _to, - 32 : : uint256 /*_amount */ - 33 : : ) public view override returns (uint8) { - 34 [ + + ]: 20 : if (addressIsListed(_from)) { - 35 : 10 : return CODE_ADDRESS_FROM_IS_BLACKLISTED; - 36 [ + + ]: 10 : } else if (addressIsListed(_to)) { - 37 : 4 : return CODE_ADDRESS_TO_IS_BLACKLISTED; - 38 : : } else { - 39 : 9 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 40 : : } - 41 : : } - 42 : : - 43 : : /** - 44 : : * @notice To know if the restriction code is valid for this rule or not. - 45 : : * @param _restrictionCode The target restriction code - 46 : : * @return true if the restriction code is known, false otherwise - 47 : : **/ - 48 : : function canReturnTransferRestrictionCode( - 49 : : uint8 _restrictionCode - 50 : : ) external pure override returns (bool) { - 51 : 8 : return - 52 : 12 : _restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED || - 53 : 4 : _restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED; - 54 : : } - 55 : : - 56 : : /** - 57 : : * @notice Return the corresponding message - 58 : : * @param _restrictionCode The target restriction code - 59 : : * @return true if the transfer is valid, false otherwise - 60 : : **/ - 61 : : function messageForTransferRestriction( - 62 : : uint8 _restrictionCode - 63 : : ) external pure override returns (string memory) { - 64 [ + + ]: 8 : if (_restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED) { - 65 : 4 : return TEXT_ADDRESS_FROM_IS_BLACKLISTED; - 66 [ + + ]: 4 : } else if (_restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED) { - 67 : 2 : return TEXT_ADDRESS_TO_IS_BLACKLISTED; - 68 : : } else { - 69 : 2 : return TEXT_CODE_NOT_FOUND; - 70 : : } - 71 : : } - 72 : : } + 8 : : + 9 : : /** + 10 : : * @title a blacklist manager + 11 : : */ + 12 : : + 13 : : contract RuleBlacklist is + 14 : : RuleValidateTransfer, + 15 : : RuleAddressList, + 16 : : RuleBlacklistInvariantStorage + 17 : : { + 18 : : /** + 19 : : * @param admin Address of the contract (Access Control) + 20 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + 21 : : */ + 22 : : constructor( + 23 : : address admin, + 24 : : address forwarderIrrevocable + 25 : : ) RuleAddressList(admin, forwarderIrrevocable) {} + 26 : : + 27 : : /** + 28 : : * @notice Check if an addres is in the whitelist or not + 29 : : * @param _from the origin address + 30 : : * @param _to the destination address + 31 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + 32 : : **/ + 33 : : function detectTransferRestriction( + 34 : : address _from, + 35 : : address _to, + 36 : : uint256 /*_amount */ + 37 : : ) public view override returns (uint8) { + 38 [ + + ]: 20 : if (addressIsListed(_from)) { + 39 : 10 : return CODE_ADDRESS_FROM_IS_BLACKLISTED; + 40 [ + + ]: 10 : } else if (addressIsListed(_to)) { + 41 : 4 : return CODE_ADDRESS_TO_IS_BLACKLISTED; + 42 : : } else { + 43 : 9 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 44 : : } + 45 : : } + 46 : : + 47 : : /** + 48 : : * @notice To know if the restriction code is valid for this rule or not. + 49 : : * @param _restrictionCode The target restriction code + 50 : : * @return true if the restriction code is known, false otherwise + 51 : : **/ + 52 : : function canReturnTransferRestrictionCode( + 53 : : uint8 _restrictionCode + 54 : : ) external pure override returns (bool) { + 55 : 8 : return + 56 : 12 : _restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED || + 57 : 4 : _restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED; + 58 : : } + 59 : : + 60 : : /** + 61 : : * @notice Return the corresponding message + 62 : : * @param _restrictionCode The target restriction code + 63 : : * @return true if the transfer is valid, false otherwise + 64 : : **/ + 65 : : function messageForTransferRestriction( + 66 : : uint8 _restrictionCode + 67 : : ) external pure override returns (string memory) { + 68 [ + + ]: 8 : if (_restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED) { + 69 : 4 : return TEXT_ADDRESS_FROM_IS_BLACKLISTED; + 70 [ + + ]: 4 : } else if (_restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED) { + 71 : 2 : return TEXT_ADDRESS_TO_IS_BLACKLISTED; + 72 : : } else { + 73 : 2 : return TEXT_CODE_NOT_FOUND; + 74 : : } + 75 : : } + 76 : : } 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 03e72d5..4b23bb9 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 6 @@ -69,31 +69,31 @@ Hit count Sort by hit count - RuleSanctionList._msgData + RuleSanctionList._msgData 0 - RuleSanctionList.canReturnTransferRestrictionCode + RuleSanctionList.canReturnTransferRestrictionCode 3 - RuleSanctionList.messageForTransferRestriction + RuleSanctionList.messageForTransferRestriction 3 - RuleSanctionList.detectTransferRestriction + RuleSanctionList.detectTransferRestriction 7 - RuleSanctionList._contextSuffixLength + RuleSanctionList._contextSuffixLength 10 - RuleSanctionList._msgSender + RuleSanctionList._msgSender 10 - RuleSanctionList.setSanctionListOracle + RuleSanctionList.setSanctionListOracle 10 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 0dfd668..e04194a 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 6 @@ -69,31 +69,31 @@ Hit count Sort by hit count - RuleSanctionList._contextSuffixLength + RuleSanctionList._contextSuffixLength 10 - RuleSanctionList._msgData + RuleSanctionList._msgData 0 - RuleSanctionList._msgSender + RuleSanctionList._msgSender 10 - RuleSanctionList.canReturnTransferRestrictionCode + RuleSanctionList.canReturnTransferRestrictionCode 3 - RuleSanctionList.detectTransferRestriction + RuleSanctionList.detectTransferRestriction 7 - RuleSanctionList.messageForTransferRestriction + RuleSanctionList.messageForTransferRestriction 3 - RuleSanctionList.setSanctionListOracle + RuleSanctionList.setSanctionListOracle 10 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 a629c51..668801c 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 6 @@ -77,121 +77,132 @@ 6 : : import "../../modules/MetaTxModuleStandalone.sol"; 7 : : import "./abstract/RuleSanctionListInvariantStorage.sol"; 8 : : import "./abstract/RuleValidateTransfer.sol"; - 9 : : interface SanctionsList { - 10 : : function isSanctioned(address addr) external view returns (bool); - 11 : : } - 12 : : - 13 : : contract RuleSanctionList is AccessControl, MetaTxModuleStandalone, RuleValidateTransfer, RuleSanctionlistInvariantStorage { - 14 : : SanctionsList public sanctionsList; - 15 : : - 16 : : /** - 17 : : * @param admin Address of the contract (Access Control) - 18 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - 19 : : */ - 20 : : constructor( - 21 : : address admin, - 22 : : address forwarderIrrevocable - 23 : : ) MetaTxModuleStandalone(forwarderIrrevocable) { - 24 : : if(admin == address(0)){ - 25 : : revert RuleSanctionList_AdminWithAddressZeroNotAllowed(); - 26 : : } - 27 : : _grantRole(DEFAULT_ADMIN_ROLE, admin); - 28 : : _grantRole(SANCTIONLIST_ROLE, admin); - 29 : : } - 30 : : - 31 : : /** - 32 : : * @notice Set the oracle contract - 33 : : * @param sanctionContractOracle_ address of your oracle contract - 34 : : * @dev zero address is authorized to authorize all transfers - 35 : : */ - 36 : : function setSanctionListOracle( - 37 : : address sanctionContractOracle_ - 38 : : ) public onlyRole(SANCTIONLIST_ROLE) { - 39 : 18 : sanctionsList = SanctionsList(sanctionContractOracle_); - 40 : : } - 41 : : - 42 : : /** - 43 : : * @notice Check if an addres is in the whitelist or not - 44 : : * @param _from the origin address - 45 : : * @param _to the destination address - 46 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - 47 : : **/ - 48 : : function detectTransferRestriction( - 49 : : address _from, - 50 : : address _to, - 51 : : uint256 /*_amount */ - 52 : : ) public view override returns (uint8) { - 53 [ + + ]: 28 : if(address(sanctionsList) != address(0)){ - 54 [ + + ]: 14 : if (sanctionsList.isSanctioned(_from)) { - 55 : 4 : return CODE_ADDRESS_FROM_IS_SANCTIONED; - 56 [ + + ]: 10 : } else if (sanctionsList.isSanctioned(_to)) { - 57 : 4 : return CODE_ADDRESS_TO_IS_SANCTIONED; - 58 : : } - 59 : : } - 60 : 9 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 61 : : } - 62 : : - 63 : : /** - 64 : : * @notice To know if the restriction code is valid for this rule or not. - 65 : : * @param _restrictionCode The target restriction code - 66 : : * @return true if the restriction code is known, false otherwise - 67 : : **/ - 68 : : function canReturnTransferRestrictionCode( - 69 : : uint8 _restrictionCode - 70 : : ) external pure override returns (bool) { - 71 : 6 : return - 72 : 9 : _restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED || - 73 : 4 : _restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED; - 74 : : } - 75 : : - 76 : : /** - 77 : : * @notice Return the corresponding message - 78 : : * @param _restrictionCode The target restriction code - 79 : : * @return true if the transfer is valid, false otherwise - 80 : : **/ - 81 : : function messageForTransferRestriction( - 82 : : uint8 _restrictionCode - 83 : : ) external pure override returns (string memory) { - 84 [ + + ]: 6 : if (_restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED) { - 85 : 2 : return TEXT_ADDRESS_FROM_IS_SANCTIONED; - 86 [ + + ]: 4 : } else if (_restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED) { - 87 : 2 : return TEXT_ADDRESS_TO_IS_SANCTIONED; - 88 : : } else { - 89 : 2 : return TEXT_CODE_NOT_FOUND; - 90 : : } - 91 : : } - 92 : : - 93 : : /** - 94 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 95 : : */ - 96 : : function _msgSender() - 97 : : internal - 98 : : view - 99 : : override(ERC2771Context, Context) - 100 : : returns (address sender) - 101 : : { - 102 : 30 : return ERC2771Context._msgSender(); - 103 : : } - 104 : : - 105 : : /** - 106 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 107 : : */ - 108 : : function _msgData() - 109 : : internal - 110 : : view - 111 : : override(ERC2771Context, Context) - 112 : : returns (bytes calldata) - 113 : : { - 114 : 0 : return ERC2771Context._msgData(); - 115 : : } - 116 : : - 117 : : /** - 118 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 119 : : */ - 120 : : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { - 121 : 30 : return ERC2771Context._contextSuffixLength(); - 122 : : } - 123 : : } + 9 : : + 10 : : interface SanctionsList { + 11 : : function isSanctioned(address addr) external view returns (bool); + 12 : : } + 13 : : + 14 : : contract RuleSanctionList is + 15 : : AccessControl, + 16 : : MetaTxModuleStandalone, + 17 : : RuleValidateTransfer, + 18 : : RuleSanctionlistInvariantStorage + 19 : : { + 20 : : SanctionsList public sanctionsList; + 21 : : + 22 : : /** + 23 : : * @param admin Address of the contract (Access Control) + 24 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + 25 : : */ + 26 : : constructor( + 27 : : address admin, + 28 : : address forwarderIrrevocable + 29 : : ) MetaTxModuleStandalone(forwarderIrrevocable) { + 30 : : if (admin == address(0)) { + 31 : : revert RuleSanctionList_AdminWithAddressZeroNotAllowed(); + 32 : : } + 33 : : _grantRole(DEFAULT_ADMIN_ROLE, admin); + 34 : : _grantRole(SANCTIONLIST_ROLE, admin); + 35 : : } + 36 : : + 37 : : /** + 38 : : * @notice Set the oracle contract + 39 : : * @param sanctionContractOracle_ address of your oracle contract + 40 : : * @dev zero address is authorized to authorize all transfers + 41 : : */ + 42 : : function setSanctionListOracle( + 43 : : address sanctionContractOracle_ + 44 : : ) public onlyRole(SANCTIONLIST_ROLE) { + 45 : 18 : sanctionsList = SanctionsList(sanctionContractOracle_); + 46 : : } + 47 : : + 48 : : /** + 49 : : * @notice Check if an addres is in the whitelist or not + 50 : : * @param _from the origin address + 51 : : * @param _to the destination address + 52 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + 53 : : **/ + 54 : : function detectTransferRestriction( + 55 : : address _from, + 56 : : address _to, + 57 : : uint256 /*_amount */ + 58 : : ) public view override returns (uint8) { + 59 [ + + ]: 28 : if (address(sanctionsList) != address(0)) { + 60 [ + + ]: 14 : if (sanctionsList.isSanctioned(_from)) { + 61 : 4 : return CODE_ADDRESS_FROM_IS_SANCTIONED; + 62 [ + + ]: 10 : } else if (sanctionsList.isSanctioned(_to)) { + 63 : 4 : return CODE_ADDRESS_TO_IS_SANCTIONED; + 64 : : } + 65 : : } + 66 : 9 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 67 : : } + 68 : : + 69 : : /** + 70 : : * @notice To know if the restriction code is valid for this rule or not. + 71 : : * @param _restrictionCode The target restriction code + 72 : : * @return true if the restriction code is known, false otherwise + 73 : : **/ + 74 : : function canReturnTransferRestrictionCode( + 75 : : uint8 _restrictionCode + 76 : : ) external pure override returns (bool) { + 77 : 6 : return + 78 : 9 : _restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED || + 79 : 4 : _restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED; + 80 : : } + 81 : : + 82 : : /** + 83 : : * @notice Return the corresponding message + 84 : : * @param _restrictionCode The target restriction code + 85 : : * @return true if the transfer is valid, false otherwise + 86 : : **/ + 87 : : function messageForTransferRestriction( + 88 : : uint8 _restrictionCode + 89 : : ) external pure override returns (string memory) { + 90 [ + + ]: 6 : if (_restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED) { + 91 : 2 : return TEXT_ADDRESS_FROM_IS_SANCTIONED; + 92 [ + + ]: 4 : } else if (_restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED) { + 93 : 2 : return TEXT_ADDRESS_TO_IS_SANCTIONED; + 94 : : } else { + 95 : 2 : return TEXT_CODE_NOT_FOUND; + 96 : : } + 97 : : } + 98 : : + 99 : : /** + 100 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 101 : : */ + 102 : : function _msgSender() + 103 : : internal + 104 : : view + 105 : : override(ERC2771Context, Context) + 106 : : returns (address sender) + 107 : : { + 108 : 30 : return ERC2771Context._msgSender(); + 109 : : } + 110 : : + 111 : : /** + 112 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 113 : : */ + 114 : : function _msgData() + 115 : : internal + 116 : : view + 117 : : override(ERC2771Context, Context) + 118 : : returns (bytes calldata) + 119 : : { + 120 : 0 : return ERC2771Context._msgData(); + 121 : : } + 122 : : + 123 : : /** + 124 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 125 : : */ + 126 : : function _contextSuffixLength() + 127 : : internal + 128 : : view + 129 : : override(ERC2771Context, Context) + 130 : : returns (uint256) + 131 : : { + 132 : 30 : return ERC2771Context._contextSuffixLength(); + 133 : : } + 134 : : } 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 625c644..1860092 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 3 @@ -69,15 +69,15 @@ Hit count Sort by hit count - RuleWhitelist.messageForTransferRestriction + RuleWhitelist.messageForTransferRestriction 7 - RuleWhitelist.canReturnTransferRestrictionCode + RuleWhitelist.canReturnTransferRestrictionCode 8 - RuleWhitelist.detectTransferRestriction + RuleWhitelist.detectTransferRestriction 28 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 0b98954..4cd41b0 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 3 @@ -69,15 +69,15 @@ Hit count Sort by hit count - RuleWhitelist.canReturnTransferRestrictionCode + RuleWhitelist.canReturnTransferRestrictionCode 8 - RuleWhitelist.detectTransferRestriction + RuleWhitelist.detectTransferRestriction 28 - RuleWhitelist.messageForTransferRestriction + RuleWhitelist.messageForTransferRestriction 7 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 158f5d7..b99bd74 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 3 @@ -73,74 +73,78 @@ 2 : : 3 : : pragma solidity ^0.8.20; 4 : : - 5 : : import "./abstract/RuleAddressList/RuleWhitelistInvariantStorage.sol"; + 5 : : import "./abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol"; 6 : : import "./abstract/RuleAddressList/RuleAddressList.sol"; 7 : : import "./abstract/RuleValidateTransfer.sol"; - 8 : : /** - 9 : : * @title a whitelist manager - 10 : : */ - 11 : : - 12 : : contract RuleWhitelist is RuleValidateTransfer, RuleAddressList, RuleWhitelistInvariantStorage { - 13 : : /** - 14 : : * @param admin Address of the contract (Access Control) - 15 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - 16 : : */ - 17 : : constructor( - 18 : : address admin, - 19 : : address forwarderIrrevocable - 20 : : ) RuleAddressList(admin, forwarderIrrevocable) { - 21 : : } - 22 : : - 23 : : /** - 24 : : * @notice Check if an addres is in the whitelist or not - 25 : : * @param _from the origin address - 26 : : * @param _to the destination address - 27 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - 28 : : **/ - 29 : : function detectTransferRestriction( - 30 : : address _from, - 31 : : address _to, - 32 : : uint256 /*_amount */ - 33 : : ) public view override returns (uint8) { - 34 [ + + ]: 56 : if (!addressIsListed(_from)) { - 35 : 26 : return CODE_ADDRESS_FROM_NOT_WHITELISTED; - 36 [ + + ]: 30 : } else if (! addressIsListed(_to)) { - 37 : 10 : return CODE_ADDRESS_TO_NOT_WHITELISTED; - 38 : : } else { - 39 : 30 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 40 : : } - 41 : : } - 42 : : - 43 : : /** - 44 : : * @notice To know if the restriction code is valid for this rule or not - 45 : : * @param _restrictionCode The target restriction code - 46 : : * @return true if the restriction code is known, false otherwise - 47 : : **/ - 48 : : function canReturnTransferRestrictionCode( - 49 : : uint8 _restrictionCode - 50 : : ) external pure override returns (bool) { - 51 : 16 : return - 52 : 24 : _restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED || - 53 : 8 : _restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED; - 54 : : } - 55 : : - 56 : : /** - 57 : : * @notice Return the corresponding message - 58 : : * @param _restrictionCode The target restriction code - 59 : : * @return true if the transfer is valid, false otherwise - 60 : : **/ - 61 : : function messageForTransferRestriction( - 62 : : uint8 _restrictionCode - 63 : : ) external pure override returns (string memory) { - 64 [ + + ]: 14 : if (_restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) { - 65 : 8 : return TEXT_ADDRESS_FROM_NOT_WHITELISTED; - 66 [ + + ]: 6 : } else if (_restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) { - 67 : 4 : return TEXT_ADDRESS_TO_NOT_WHITELISTED; - 68 : : } else { - 69 : 2 : return TEXT_CODE_NOT_FOUND; - 70 : : } - 71 : : } - 72 : : } + 8 : : + 9 : : /** + 10 : : * @title a whitelist manager + 11 : : */ + 12 : : + 13 : : contract RuleWhitelist is + 14 : : RuleValidateTransfer, + 15 : : RuleAddressList, + 16 : : RuleWhitelistInvariantStorage + 17 : : { + 18 : : /** + 19 : : * @param admin Address of the contract (Access Control) + 20 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + 21 : : */ + 22 : : constructor( + 23 : : address admin, + 24 : : address forwarderIrrevocable + 25 : : ) RuleAddressList(admin, forwarderIrrevocable) {} + 26 : : + 27 : : /** + 28 : : * @notice Check if an addres is in the whitelist or not + 29 : : * @param _from the origin address + 30 : : * @param _to the destination address + 31 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + 32 : : **/ + 33 : : function detectTransferRestriction( + 34 : : address _from, + 35 : : address _to, + 36 : : uint256 /*_amount */ + 37 : : ) public view override returns (uint8) { + 38 [ + + ]: 56 : if (!addressIsListed(_from)) { + 39 : 26 : return CODE_ADDRESS_FROM_NOT_WHITELISTED; + 40 [ + + ]: 30 : } else if (!addressIsListed(_to)) { + 41 : 10 : return CODE_ADDRESS_TO_NOT_WHITELISTED; + 42 : : } else { + 43 : 30 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 44 : : } + 45 : : } + 46 : : + 47 : : /** + 48 : : * @notice To know if the restriction code is valid for this rule or not + 49 : : * @param _restrictionCode The target restriction code + 50 : : * @return true if the restriction code is known, false otherwise + 51 : : **/ + 52 : : function canReturnTransferRestrictionCode( + 53 : : uint8 _restrictionCode + 54 : : ) external pure override returns (bool) { + 55 : 16 : return + 56 : 24 : _restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED || + 57 : 8 : _restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED; + 58 : : } + 59 : : + 60 : : /** + 61 : : * @notice Return the corresponding message + 62 : : * @param _restrictionCode The target restriction code + 63 : : * @return true if the transfer is valid, false otherwise + 64 : : **/ + 65 : : function messageForTransferRestriction( + 66 : : uint8 _restrictionCode + 67 : : ) external pure override returns (string memory) { + 68 [ + + ]: 14 : if (_restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) { + 69 : 8 : return TEXT_ADDRESS_FROM_NOT_WHITELISTED; + 70 [ + + ]: 6 : } else if (_restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) { + 71 : 4 : return TEXT_ADDRESS_TO_NOT_WHITELISTED; + 72 : : } else { + 73 : 2 : return TEXT_CODE_NOT_FOUND; + 74 : : } + 75 : : } + 76 : : } diff --git a/doc/test/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func-sort-c.html b/doc/test/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func-sort-c.html new file mode 100644 index 0000000..b52bb36 --- /dev/null +++ b/doc/test/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func-sort-c.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - src/rules/validation/RuleWhitelistWrapper.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/rules/validation - RuleWhitelistWrapper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:262892.9 %
Date:2024-06-11 10:19:24Functions:5683.3 %
Branches:91275.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistWrapper._msgData0
RuleWhitelistWrapper.messageForTransferRestriction3
RuleWhitelistWrapper.canReturnTransferRestrictionCode4
RuleWhitelistWrapper.detectTransferRestriction11
RuleWhitelistWrapper._contextSuffixLength36
RuleWhitelistWrapper._msgSender36
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func.html b/doc/test/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func.html new file mode 100644 index 0000000..72bf006 --- /dev/null +++ b/doc/test/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - src/rules/validation/RuleWhitelistWrapper.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/rules/validation - RuleWhitelistWrapper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:262892.9 %
Date:2024-06-11 10:19:24Functions:5683.3 %
Branches:91275.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistWrapper._contextSuffixLength36
RuleWhitelistWrapper._msgData0
RuleWhitelistWrapper._msgSender36
RuleWhitelistWrapper.canReturnTransferRestrictionCode4
RuleWhitelistWrapper.detectTransferRestriction11
RuleWhitelistWrapper.messageForTransferRestriction3
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/rules/validation/RuleWhitelistWrapper.sol.gcov.html b/doc/test/coverage/src/rules/validation/RuleWhitelistWrapper.sol.gcov.html new file mode 100644 index 0000000..e33534c --- /dev/null +++ b/doc/test/coverage/src/rules/validation/RuleWhitelistWrapper.sol.gcov.html @@ -0,0 +1,226 @@ + + + + + + + LCOV - lcov.info - src/rules/validation/RuleWhitelistWrapper.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/rules/validation - RuleWhitelistWrapper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:262892.9 %
Date:2024-06-11 10:19:24Functions:5683.3 %
Branches:91275.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : 
+       3                 :            : pragma solidity ^0.8.20;
+       4                 :            : 
+       5                 :            : import "OZ/access/AccessControl.sol";
+       6                 :            : import "../../modules/RuleEngineValidationCommon.sol";
+       7                 :            : import "../../modules/MetaTxModuleStandalone.sol";
+       8                 :            : import "./abstract/RuleValidateTransfer.sol";
+       9                 :            : import "./abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol";
+      10                 :            : import "./abstract/RuleAddressList/RuleAddressList.sol";
+      11                 :            : 
+      12                 :            : /**
+      13                 :            :  * @title Wrapper to call several different whitelist rules
+      14                 :            :  */
+      15                 :            : contract RuleWhitelistWrapper is
+      16                 :            :     RuleEngineValidationCommon,
+      17                 :            :     MetaTxModuleStandalone,
+      18                 :            :     RuleValidateTransfer,
+      19                 :            :     RuleWhitelistInvariantStorage
+      20                 :            : {
+      21                 :            :     /**
+      22                 :            :      * @param admin Address of the contract (Access Control)
+      23                 :            :      * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
+      24                 :            :      */
+      25                 :            :     constructor(
+      26                 :            :         address admin,
+      27                 :            :         address forwarderIrrevocable
+      28                 :            :     ) MetaTxModuleStandalone(forwarderIrrevocable) {
+      29                 :            :         if (admin == address(0)) {
+      30                 :            :             revert RuleEngine_AdminWithAddressZeroNotAllowed();
+      31                 :            :         }
+      32                 :            :         _grantRole(DEFAULT_ADMIN_ROLE, admin);
+      33                 :            :         _grantRole(RULE_ENGINE_OPERATOR_ROLE, admin);
+      34                 :            :     }
+      35                 :            : 
+      36                 :            :     /**
+      37                 :            :      * @notice Go through all the whitelist rules to know if a restriction exists on the transfer
+      38                 :            :      * @param _from the origin address
+      39                 :            :      * @param _to the destination address
+      40                 :            :      * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
+      41                 :            :      **/
+      42                 :            :     function detectTransferRestriction(
+      43                 :            :         address _from,
+      44                 :            :         address _to,
+      45                 :            :         uint256 /*_amount*/
+      46                 :            :     ) public view override returns (uint8) {
+      47                 :         33 :         address[] memory targetAddress = new address[](2);
+      48                 :         33 :         bool[] memory isListed = new bool[](2);
+      49                 :         33 :         bool[] memory result = new bool[](2);
+      50                 :         22 :         targetAddress[0] = _from;
+      51                 :         22 :         targetAddress[1] = _to;
+      52                 :         22 :         uint256 rulesLength = _rulesValidation.length;
+      53                 :            :         // For each whitelist rule, we ask if from or to are in the whitelist
+      54                 :         99 :         for (uint256 i = 0; i < rulesLength; ++i) {
+      55                 :            :             // External call
+      56                 :         66 :             isListed = RuleAddressList(_rulesValidation[i])
+      57                 :            :                 .addressIsListedBatch(targetAddress);
+      58         [ #  + ]:         74 :             if (isListed[0] && !result[0]) {
+      59                 :            :                 // Update if from is in the list
+      60                 :         14 :                 result[0] = true;
+      61                 :            :             }
+      62         [ #  + ]:         74 :             if (isListed[1] && !result[1]) {
+      63                 :            :                 // Update if to is in the list
+      64                 :         14 :                 result[1] = true;
+      65                 :            :             }
+      66                 :            :         }
+      67         [ +  + ]:         22 :         if (!result[0]) {
+      68                 :          8 :             return CODE_ADDRESS_FROM_NOT_WHITELISTED;
+      69         [ +  + ]:         14 :         } else if (!result[1]) {
+      70                 :          4 :             return CODE_ADDRESS_TO_NOT_WHITELISTED;
+      71                 :            :         } else {
+      72                 :         15 :             return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+      73                 :            :         }
+      74                 :            :     }
+      75                 :            : 
+      76                 :            :     /**
+      77                 :            :      * @notice To know if the restriction code is valid for this rule or not
+      78                 :            :      * @param _restrictionCode The target restriction code
+      79                 :            :      * @return true if the restriction code is known, false otherwise
+      80                 :            :      **/
+      81                 :            :     function canReturnTransferRestrictionCode(
+      82                 :            :         uint8 _restrictionCode
+      83                 :            :     ) external pure override returns (bool) {
+      84                 :          8 :         return
+      85                 :         12 :             _restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED ||
+      86                 :          4 :             _restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED;
+      87                 :            :     }
+      88                 :            : 
+      89                 :            :     /**
+      90                 :            :      * @notice Return the corresponding message
+      91                 :            :      * @param _restrictionCode The target restriction code
+      92                 :            :      * @return true if the transfer is valid, false otherwise
+      93                 :            :      **/
+      94                 :            :     function messageForTransferRestriction(
+      95                 :            :         uint8 _restrictionCode
+      96                 :            :     ) external pure override returns (string memory) {
+      97         [ +  + ]:          6 :         if (_restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) {
+      98                 :          4 :             return TEXT_ADDRESS_FROM_NOT_WHITELISTED;
+      99         [ +  # ]:          2 :         } else if (_restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) {
+     100                 :          2 :             return TEXT_ADDRESS_TO_NOT_WHITELISTED;
+     101                 :            :         } else {
+     102                 :          0 :             return TEXT_CODE_NOT_FOUND;
+     103                 :            :         }
+     104                 :            :     }
+     105                 :            : 
+     106                 :            :     /**
+     107                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
+     108                 :            :      */
+     109                 :            :     function _msgSender()
+     110                 :            :         internal
+     111                 :            :         view
+     112                 :            :         override(ERC2771Context, Context)
+     113                 :            :         returns (address sender)
+     114                 :            :     {
+     115                 :        108 :         return ERC2771Context._msgSender();
+     116                 :            :     }
+     117                 :            : 
+     118                 :            :     /**
+     119                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
+     120                 :            :      */
+     121                 :            :     function _msgData()
+     122                 :            :         internal
+     123                 :            :         view
+     124                 :            :         override(ERC2771Context, Context)
+     125                 :            :         returns (bytes calldata)
+     126                 :            :     {
+     127                 :          0 :         return ERC2771Context._msgData();
+     128                 :            :     }
+     129                 :            : 
+     130                 :            :     /**
+     131                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
+     132                 :            :      */
+     133                 :            :     function _contextSuffixLength()
+     134                 :            :         internal
+     135                 :            :         view
+     136                 :            :         override(ERC2771Context, Context)
+     137                 :            :         returns (uint256)
+     138                 :            :     {
+     139                 :        108 :         return ERC2771Context._contextSuffixLength();
+     140                 :            :     }
+     141                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + 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 7380e8e..4d71919 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 @@ -31,18 +31,18 @@ lcov.info Lines: - 8 - 9 - 88.9 % + 12 + 13 + 92.3 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 8 9 - 88.9 % + 10 + 90.0 % @@ -69,40 +69,44 @@ Hit count Sort by hit count - RuleAddressList._msgData + RuleAddressList._msgData 0 - RuleAddressList.removeAddressFromTheList + RuleAddressList.removeAddressFromTheList 3 - RuleAddressList.removeAddressesFromTheList + RuleAddressList.removeAddressesFromTheList 4 - RuleAddressList.addAddressesToTheList - 15 + RuleAddressList.addAddressesToTheList + 17 - RuleAddressList.numberListedAddress + RuleAddressList.numberListedAddress 24 - RuleAddressList.addAddressToTheList - 40 + RuleAddressList.addressIsListedBatch + 36 + + + RuleAddressList.addAddressToTheList + 52 - RuleAddressList._contextSuffixLength - 72 + RuleAddressList._contextSuffixLength + 86 - RuleAddressList._msgSender - 72 + RuleAddressList._msgSender + 86 - RuleAddressList.addressIsListed - 83 + RuleAddressList.addressIsListed + 86
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 0905f5b..dda2ef2 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 @@ -31,18 +31,18 @@ lcov.info Lines: - 8 - 9 - 88.9 % + 12 + 13 + 92.3 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 8 9 - 88.9 % + 10 + 90.0 % @@ -69,39 +69,43 @@ Hit count Sort by hit count - RuleAddressList._contextSuffixLength - 72 + RuleAddressList._contextSuffixLength + 86 - RuleAddressList._msgData + RuleAddressList._msgData 0 - RuleAddressList._msgSender - 72 + RuleAddressList._msgSender + 86 + + + RuleAddressList.addAddressToTheList + 52 - RuleAddressList.addAddressToTheList - 40 + RuleAddressList.addAddressesToTheList + 17 - RuleAddressList.addAddressesToTheList - 15 + RuleAddressList.addressIsListed + 86 - RuleAddressList.addressIsListed - 83 + RuleAddressList.addressIsListedBatch + 36 - RuleAddressList.numberListedAddress + RuleAddressList.numberListedAddress 24 - RuleAddressList.removeAddressFromTheList + RuleAddressList.removeAddressFromTheList 3 - RuleAddressList.removeAddressesFromTheList + RuleAddressList.removeAddressesFromTheList 4 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 ae31a25..3e44820 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 @@ -31,18 +31,18 @@ lcov.info Lines: - 8 - 9 - 88.9 % + 12 + 13 + 92.3 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 8 9 - 88.9 % + 10 + 90.0 % @@ -76,132 +76,153 @@ 5 : : import "OZ/access/AccessControl.sol"; 6 : : import "./../../../../modules/MetaTxModuleStandalone.sol"; 7 : : import "./RuleAddressListInternal.sol"; - 8 : : import "./RuleAddressListInvariantStorage.sol"; - 9 : : /** - 10 : : @title an addresses list manager - 11 : : */ - 12 : : - 13 : : abstract contract RuleAddressList is AccessControl, MetaTxModuleStandalone, RuleAddressListInternal, RuleAddressListInvariantStorage { - 14 : : - 15 : : - 16 : : // Number of addresses in the whitelist at the moment - 17 : : uint256 private numAddressesWhitelisted; - 18 : : - 19 : : /** - 20 : : * @param admin Address of the contract (Access Control) - 21 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - 22 : : */ - 23 : : constructor( - 24 : : address admin, - 25 : : address forwarderIrrevocable - 26 : : ) MetaTxModuleStandalone(forwarderIrrevocable) { - 27 : : if(admin == address(0)){ - 28 : : revert RuleAddressList_AdminWithAddressZeroNotAllowed(); - 29 : : } - 30 : : _grantRole(DEFAULT_ADMIN_ROLE, admin); - 31 : : _grantRole(ADDRESS_LIST_ROLE, admin); - 32 : : } - 33 : : - 34 : : /** - 35 : : * @notice Add addresses to the whitelist - 36 : : * If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert). - 37 : : * @param listWhitelistedAddress an array with the addresses to whitelist - 38 : : */ - 39 : : function addAddressesToTheList( - 40 : : address[] calldata listWhitelistedAddress - 41 : : ) public onlyRole(ADDRESS_LIST_ROLE) { - 42 : 28 : _addAddressesToThelist(listWhitelistedAddress); - 43 : : } - 44 : : - 45 : : /** - 46 : : * @notice Remove addresses from the whitelist - 47 : : * If the address does not exist in the whitelist, there is no change for this address. - 48 : : * The transaction remains valid (no revert). - 49 : : * @param listWhitelistedAddress an array with the addresses to remove - 50 : : */ - 51 : : function removeAddressesFromTheList( - 52 : : address[] calldata listWhitelistedAddress - 53 : : ) public onlyRole(ADDRESS_LIST_ROLE) { - 54 : 6 : _removeAddressesFromThelist(listWhitelistedAddress); - 55 : : } - 56 : : - 57 : : /** - 58 : : * @notice Add one address to the whitelist - 59 : : * If the address already exists, the transaction is reverted to save gas. - 60 : : * @param _newWhitelistAddress The address to whitelist - 61 : : */ - 62 : : function addAddressToTheList( - 63 : : address _newWhitelistAddress - 64 : : ) public onlyRole(ADDRESS_LIST_ROLE) { - 65 : 78 : _addAddressToThelist(_newWhitelistAddress); - 66 : : } - 67 : : - 68 : : /** - 69 : : * @notice Remove one address from the whitelist - 70 : : * If the address does not exist in the whitelist, the transaction is reverted to save gas. - 71 : : * @param _removeWhitelistAddress The address to remove - 72 : : * - 73 : : */ - 74 : : function removeAddressFromTheList( - 75 : : address _removeWhitelistAddress - 76 : : ) public onlyRole(ADDRESS_LIST_ROLE) { - 77 : 4 : _removeAddressFromThelist( _removeWhitelistAddress); - 78 : : } - 79 : : - 80 : : /** - 81 : : * @notice Get the number of listed addresses - 82 : : * @return Number of listed addresses - 83 : : * - 84 : : */ - 85 : : function numberListedAddress() public view returns (uint256) { - 86 : 72 : return _numberListedAddress(); - 87 : : } - 88 : : - 89 : : - 90 : : /** - 91 : : * @notice Know if an address is listed or not - 92 : : * @param _targetAddress The concerned address - 93 : : * @return True if the address is listed, false otherwise - 94 : : * - 95 : : */ - 96 : : function addressIsListed( - 97 : : address _targetAddress - 98 : : ) public view returns (bool) { - 99 : 423 : return _addressIsListed(_targetAddress); - 100 : : } - 101 : : - 102 : : - 103 : : /** - 104 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 105 : : */ - 106 : : function _msgSender() - 107 : : internal - 108 : : view - 109 : : override(ERC2771Context, Context) - 110 : : returns (address sender) - 111 : : { - 112 : 216 : return ERC2771Context._msgSender(); - 113 : : } - 114 : : - 115 : : /** - 116 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 117 : : */ - 118 : : function _msgData() - 119 : : internal - 120 : : view - 121 : : override(ERC2771Context, Context) - 122 : : returns (bytes calldata) - 123 : : { - 124 : 0 : return ERC2771Context._msgData(); - 125 : : } - 126 : : - 127 : : /** - 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 : 216 : return ERC2771Context._contextSuffixLength(); - 132 : : } - 133 : : } + 8 : : import "./invariantStorage/RuleAddressListInvariantStorage.sol"; + 9 : : + 10 : : /** + 11 : : @title an addresses list manager + 12 : : */ + 13 : : + 14 : : abstract contract RuleAddressList is + 15 : : AccessControl, + 16 : : MetaTxModuleStandalone, + 17 : : RuleAddressListInternal, + 18 : : RuleAddressListInvariantStorage + 19 : : { + 20 : : // Number of addresses in the whitelist at the moment + 21 : : uint256 private numAddressesWhitelisted; + 22 : : + 23 : : /** + 24 : : * @param admin Address of the contract (Access Control) + 25 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + 26 : : */ + 27 : : constructor( + 28 : : address admin, + 29 : : address forwarderIrrevocable + 30 : : ) MetaTxModuleStandalone(forwarderIrrevocable) { + 31 : : if (admin == address(0)) { + 32 : : revert RuleAddressList_AdminWithAddressZeroNotAllowed(); + 33 : : } + 34 : : _grantRole(DEFAULT_ADMIN_ROLE, admin); + 35 : : _grantRole(ADDRESS_LIST_ROLE, admin); + 36 : : } + 37 : : + 38 : : /** + 39 : : * @notice Add addresses to the whitelist + 40 : : * If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert). + 41 : : * @param listWhitelistedAddress an array with the addresses to whitelist + 42 : : */ + 43 : : function addAddressesToTheList( + 44 : : address[] calldata listWhitelistedAddress + 45 : : ) public onlyRole(ADDRESS_LIST_ROLE) { + 46 : 32 : _addAddressesToThelist(listWhitelistedAddress); + 47 : : } + 48 : : + 49 : : /** + 50 : : * @notice Remove addresses from the whitelist + 51 : : * If the address does not exist in the whitelist, there is no change for this address. + 52 : : * The transaction remains valid (no revert). + 53 : : * @param listWhitelistedAddress an array with the addresses to remove + 54 : : */ + 55 : : function removeAddressesFromTheList( + 56 : : address[] calldata listWhitelistedAddress + 57 : : ) public onlyRole(ADDRESS_LIST_ROLE) { + 58 : 6 : _removeAddressesFromThelist(listWhitelistedAddress); + 59 : : } + 60 : : + 61 : : /** + 62 : : * @notice Add one address to the whitelist + 63 : : * If the address already exists, the transaction is reverted to save gas. + 64 : : * @param _newWhitelistAddress The address to whitelist + 65 : : */ + 66 : : function addAddressToTheList( + 67 : : address _newWhitelistAddress + 68 : : ) public onlyRole(ADDRESS_LIST_ROLE) { + 69 : 102 : _addAddressToThelist(_newWhitelistAddress); + 70 : : } + 71 : : + 72 : : /** + 73 : : * @notice Remove one address from the whitelist + 74 : : * If the address does not exist in the whitelist, the transaction is reverted to save gas. + 75 : : * @param _removeWhitelistAddress The address to remove + 76 : : * + 77 : : */ + 78 : : function removeAddressFromTheList( + 79 : : address _removeWhitelistAddress + 80 : : ) public onlyRole(ADDRESS_LIST_ROLE) { + 81 : 4 : _removeAddressFromThelist(_removeWhitelistAddress); + 82 : : } + 83 : : + 84 : : /** + 85 : : * @notice Get the number of listed addresses + 86 : : * @return Number of listed addresses + 87 : : * + 88 : : */ + 89 : : function numberListedAddress() public view returns (uint256) { + 90 : 72 : return _numberListedAddress(); + 91 : : } + 92 : : + 93 : : /** + 94 : : * @notice Know if an address is listed or not + 95 : : * @param _targetAddress The concerned address + 96 : : * @return True if the address is listed, false otherwise + 97 : : * + 98 : : */ + 99 : : function addressIsListed( + 100 : : address _targetAddress + 101 : : ) public view returns (bool) { + 102 : 432 : return _addressIsListed(_targetAddress); + 103 : : } + 104 : : + 105 : : /** + 106 : : * @notice batch version of {addressIsListed} + 107 : : * + 108 : : */ + 109 : : function addressIsListedBatch( + 110 : : address[] memory _targetAddresses + 111 : : ) public view returns (bool[] memory) { + 112 : 108 : bool[] memory isListed = new bool[](_targetAddresses.length); + 113 : 250 : for (uint256 i = 0; i < _targetAddresses.length; ++i) { + 114 : 142 : isListed[i] = _addressIsListed(_targetAddresses[i]); + 115 : : } + 116 : 72 : return isListed; + 117 : : } + 118 : : + 119 : : /** + 120 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 121 : : */ + 122 : : function _msgSender() + 123 : : internal + 124 : : view + 125 : : override(ERC2771Context, Context) + 126 : : returns (address sender) + 127 : : { + 128 : 258 : return ERC2771Context._msgSender(); + 129 : : } + 130 : : + 131 : : /** + 132 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 133 : : */ + 134 : : function _msgData() + 135 : : internal + 136 : : view + 137 : : override(ERC2771Context, Context) + 138 : : returns (bytes calldata) + 139 : : { + 140 : 0 : return ERC2771Context._msgData(); + 141 : : } + 142 : : + 143 : : /** + 144 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 145 : : */ + 146 : : function _contextSuffixLength() + 147 : : internal + 148 : : view + 149 : : override(ERC2771Context, Context) + 150 : : returns (uint256) + 151 : : { + 152 : 258 : return ERC2771Context._contextSuffixLength(); + 153 : : } + 154 : : } 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 511dbce..034d5b0 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 6 @@ -69,28 +69,28 @@ Hit count Sort by hit count - RuleAddressListInternal._removeAddressFromThelist + RuleAddressListInternal._removeAddressFromThelist 2 - RuleAddressListInternal._removeAddressesFromThelist + RuleAddressListInternal._removeAddressesFromThelist 3 - RuleAddressListInternal._addAddressesToThelist - 14 + RuleAddressListInternal._addAddressesToThelist + 16 - RuleAddressListInternal._numberListedAddress + RuleAddressListInternal._numberListedAddress 24 - RuleAddressListInternal._addAddressToThelist - 39 + RuleAddressListInternal._addAddressToThelist + 51 - RuleAddressListInternal._addressIsListed - 141 + RuleAddressListInternal._addressIsListed + 215
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 66d10d6..3a52fd0 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 6 @@ -69,27 +69,27 @@ Hit count Sort by hit count - RuleAddressListInternal._addAddressToThelist - 39 + RuleAddressListInternal._addAddressToThelist + 51 - RuleAddressListInternal._addAddressesToThelist - 14 + RuleAddressListInternal._addAddressesToThelist + 16 - RuleAddressListInternal._addressIsListed - 141 + RuleAddressListInternal._addressIsListed + 215 - RuleAddressListInternal._numberListedAddress + RuleAddressListInternal._numberListedAddress 24 - RuleAddressListInternal._removeAddressFromThelist + RuleAddressListInternal._removeAddressFromThelist 2 - RuleAddressListInternal._removeAddressesFromThelist + RuleAddressListInternal._removeAddressesFromThelist 3 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 5e74800..b102a31 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 6 @@ -74,108 +74,100 @@ 3 : : pragma solidity ^0.8.20; 4 : : 5 : : /** - 6 : : * @title a list manager - 7 : : */ + 6 : : * @title a list manager + 7 : : */ 8 : : 9 : : abstract contract RuleAddressListInternal { 10 : : error Rulelist_AddressAlreadylisted(); 11 : : error Rulelist_AddressNotPresent(); - 12 : : + 12 : : 13 : : mapping(address => bool) private list; 14 : : // Number of addresses in the list at the moment 15 : : uint256 private numAddressesList; 16 : : - 17 : : - 18 : : /** - 19 : : * @notice Add addresses to the list - 20 : : * If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert). - 21 : : * @param listAddresses an array with the addresses to list - 22 : : */ - 23 : : function _addAddressesToThelist( - 24 : : address[] calldata listAddresses - 25 : : ) internal { - 26 : 28 : uint256 numAddressesListLocal = numAddressesList; - 27 : 102 : for (uint256 i = 0; i < listAddresses.length; ++i ) { - 28 [ # + ]: 60 : if (!list[listAddresses[i]]) { - 29 : 56 : list[listAddresses[i]] = true; - 30 : 56 : ++numAddressesListLocal; - 31 : : } - 32 : : } - 33 : 28 : numAddressesList = numAddressesListLocal; - 34 : : } - 35 : : - 36 : : /** - 37 : : * @notice Remove addresses from the list - 38 : : * If the address does not exist in the list, there is no change for this address. - 39 : : * The transaction remains valid (no revert). - 40 : : * @param listAddresses an array with the addresses to remove - 41 : : */ - 42 : : function _removeAddressesFromThelist( - 43 : : address[] calldata listAddresses - 44 : : ) internal { - 45 : 6 : uint256 numAddressesListLocal = numAddressesList; - 46 : 23 : for (uint256 i = 0; i < listAddresses.length; ++i ) { - 47 [ # + ]: 7 : if (list[listAddresses[i]]) { - 48 : 12 : list[listAddresses[i]] = false; - 49 : 12 : --numAddressesListLocal; - 50 : : } - 51 : : } - 52 : 6 : numAddressesList = numAddressesListLocal; - 53 : : } - 54 : : - 55 : : /** - 56 : : * @notice Add one address to the list - 57 : : * If the address already exists, the transaction is reverted to save gas. - 58 : : * @param _newlistAddress The address to list - 59 : : */ - 60 : : function _addAddressToThelist( - 61 : : address _newlistAddress - 62 : : ) internal { - 63 [ + + ]: 39 : if(list[_newlistAddress]) - 64 : : { - 65 : 2 : revert Rulelist_AddressAlreadylisted(); - 66 : : } - 67 : 76 : list[_newlistAddress] = true; - 68 : 76 : ++numAddressesList; - 69 : : } - 70 : : - 71 : : /** - 72 : : * @notice Remove one address from the list - 73 : : * If the address does not exist in the list, the transaction is reverted to save gas. - 74 : : * @param _removelistAddress The address to remove - 75 : : * - 76 : : */ - 77 : : function _removeAddressFromThelist( - 78 : : address _removelistAddress - 79 : : ) internal { - 80 [ + + ]: 4 : if(!list[_removelistAddress]){ - 81 : 2 : revert Rulelist_AddressNotPresent(); - 82 : : } - 83 : 2 : list[_removelistAddress] = false; - 84 : 2 : --numAddressesList; - 85 : : } - 86 : : - 87 : : /** - 88 : : * @notice Get the number of listed addresses - 89 : : * @return Number of listed addresses - 90 : : * - 91 : : */ - 92 : : function _numberListedAddress() internal view returns (uint256) { - 93 : 48 : return numAddressesList; - 94 : : } - 95 : : - 96 : : /** - 97 : : * @notice Know if an address is listed or not - 98 : : * @param _targetAddress The concerned address - 99 : : * @return True if the address is listed, false otherwise - 100 : : * - 101 : : */ - 102 : : function _addressIsListed( - 103 : : address _targetAddress - 104 : : ) internal view returns (bool) { - 105 : 282 : return list[_targetAddress]; - 106 : : } - 107 : : } + 17 : : /** + 18 : : * @notice Add addresses to the list + 19 : : * If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert). + 20 : : * @param listAddresses an array with the addresses to list + 21 : : */ + 22 : : function _addAddressesToThelist(address[] calldata listAddresses) internal { + 23 : 32 : uint256 numAddressesListLocal = numAddressesList; + 24 : 116 : for (uint256 i = 0; i < listAddresses.length; ++i) { + 25 [ # + ]: 68 : if (!list[listAddresses[i]]) { + 26 : 64 : list[listAddresses[i]] = true; + 27 : 64 : ++numAddressesListLocal; + 28 : : } + 29 : : } + 30 : 32 : numAddressesList = numAddressesListLocal; + 31 : : } + 32 : : + 33 : : /** + 34 : : * @notice Remove addresses from the list + 35 : : * If the address does not exist in the list, there is no change for this address. + 36 : : * The transaction remains valid (no revert). + 37 : : * @param listAddresses an array with the addresses to remove + 38 : : */ + 39 : : function _removeAddressesFromThelist( + 40 : : address[] calldata listAddresses + 41 : : ) internal { + 42 : 6 : uint256 numAddressesListLocal = numAddressesList; + 43 : 23 : for (uint256 i = 0; i < listAddresses.length; ++i) { + 44 [ # + ]: 7 : if (list[listAddresses[i]]) { + 45 : 12 : list[listAddresses[i]] = false; + 46 : 12 : --numAddressesListLocal; + 47 : : } + 48 : : } + 49 : 6 : numAddressesList = numAddressesListLocal; + 50 : : } + 51 : : + 52 : : /** + 53 : : * @notice Add one address to the list + 54 : : * If the address already exists, the transaction is reverted to save gas. + 55 : : * @param _newlistAddress The address to list + 56 : : */ + 57 : : function _addAddressToThelist(address _newlistAddress) internal { + 58 [ + + ]: 51 : if (list[_newlistAddress]) { + 59 : 2 : revert Rulelist_AddressAlreadylisted(); + 60 : : } + 61 : 100 : list[_newlistAddress] = true; + 62 : 100 : ++numAddressesList; + 63 : : } + 64 : : + 65 : : /** + 66 : : * @notice Remove one address from the list + 67 : : * If the address does not exist in the list, the transaction is reverted to save gas. + 68 : : * @param _removelistAddress The address to remove + 69 : : * + 70 : : */ + 71 : : function _removeAddressFromThelist(address _removelistAddress) internal { + 72 [ + + ]: 4 : if (!list[_removelistAddress]) { + 73 : 2 : revert Rulelist_AddressNotPresent(); + 74 : : } + 75 : 2 : list[_removelistAddress] = false; + 76 : 2 : --numAddressesList; + 77 : : } + 78 : : + 79 : : /** + 80 : : * @notice Get the number of listed addresses + 81 : : * @return Number of listed addresses + 82 : : * + 83 : : */ + 84 : : function _numberListedAddress() internal view returns (uint256) { + 85 : 48 : return numAddressesList; + 86 : : } + 87 : : + 88 : : /** + 89 : : * @notice Know if an address is listed or not + 90 : : * @param _targetAddress The concerned address + 91 : : * @return True if the address is listed, false otherwise + 92 : : * + 93 : : */ + 94 : : function _addressIsListed( + 95 : : address _targetAddress + 96 : : ) internal view returns (bool) { + 97 : 430 : return list[_targetAddress]; + 98 : : } + 99 : : } 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 2c18e01..71a79b8 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 @@ -31,18 +31,18 @@ lcov.info Lines: - 30 - 31 - 96.8 % + 34 + 35 + 97.1 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 14 15 - 93.3 % + 16 + 93.8 % @@ -96,12 +96,12 @@ RuleAddressList.sol -
88.9%88.9%
+
92.3%92.3%
- 88.9 % - 8 / 9 - 88.9 % - 8 / 9 + 92.3 % + 12 / 13 + 90.0 % + 9 / 10 - 0 / 0 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 3b3a30a..c73796f 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 @@ -31,18 +31,18 @@ lcov.info Lines: - 30 - 31 - 96.8 % + 34 + 35 + 97.1 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 14 15 - 93.3 % + 16 + 93.8 % @@ -84,12 +84,12 @@ RuleAddressList.sol -
88.9%88.9%
+
92.3%92.3%
- 88.9 % - 8 / 9 - 88.9 % - 8 / 9 + 92.3 % + 12 / 13 + 90.0 % + 9 / 10 - 0 / 0 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 ab0cc0e..7344e95 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 @@ -31,18 +31,18 @@ lcov.info Lines: - 30 - 31 - 96.8 % + 34 + 35 + 97.1 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 14 15 - 93.3 % + 16 + 93.8 % @@ -84,12 +84,12 @@ RuleAddressList.sol -
88.9%88.9%
+
92.3%92.3%
- 88.9 % - 8 / 9 - 88.9 % - 8 / 9 + 92.3 % + 12 / 13 + 90.0 % + 9 / 10 - 0 / 0 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 1c40a15..8b576c0 100644 --- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index.html +++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index.html @@ -31,18 +31,18 @@ lcov.info Lines: - 30 - 31 - 96.8 % + 34 + 35 + 97.1 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 14 15 - 93.3 % + 16 + 93.8 % @@ -84,12 +84,12 @@ RuleAddressList.sol -
88.9%88.9%
+
92.3%92.3%
- 88.9 % - 8 / 9 - 88.9 % - 8 / 9 + 92.3 % + 12 / 13 + 90.0 % + 9 / 10 - 0 / 0 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 4495caa..de6e037 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-15 12:20:21 + 2024-06-11 10:19:24 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 97372fa..df568ad 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-15 12:20:21 + 2024-06-11 10:19:24 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 a4ed5c4..89b228f 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 1 @@ -75,14 +75,14 @@ 4 : : 5 : : import "../../../interfaces/IRuleValidation.sol"; 6 : : - 7 : : abstract contract RuleValidateTransfer is IRuleValidation{ - 8 : : /** - 9 : : * @notice Validate a transfer - 10 : : * @param _from the origin address - 11 : : * @param _to the destination address - 12 : : * @param _amount to transfer - 13 : : * @return isValid => true if the transfer is valid, false otherwise - 14 : : **/ + 7 : : abstract contract RuleValidateTransfer is IRuleValidation { + 8 : : /** + 9 : : * @notice Validate a transfer + 10 : : * @param _from the origin address + 11 : : * @param _to the destination address + 12 : : * @param _amount to transfer + 13 : : * @return isValid => true if the transfer is valid, false otherwise + 14 : : **/ 15 : : function validateTransfer( 16 : : address _from, 17 : : address _to, 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 760e987..85c73c5 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-15 12:20:21 + 2024-06-11 10:19:24 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 f0ef7d6..11ccdbb 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-15 12:20:21 + 2024-06-11 10:19:24 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 464156f..a2371ee 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-15 12:20:21 + 2024-06-11 10:19:24 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 093d2c0..f79bdac 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-15 12:20:21 + 2024-06-11 10:19:24 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 4fe50bf..0a4a8dd 100644 --- a/doc/test/coverage/src/rules/validation/index-sort-b.html +++ b/doc/test/coverage/src/rules/validation/index-sort-b.html @@ -31,27 +31,27 @@ lcov.info Lines: - 43 - 44 - 97.7 % + 69 + 72 + 95.8 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 12 - 13 - 92.3 % + 17 + 19 + 89.5 % Branches: - 26 - 26 - 100.0 % + 35 + 38 + 92.1 % @@ -81,6 +81,18 @@ Functions Sort by function coverage Branches Sort by branch coverage + + RuleWhitelistWrapper.sol + +
92.9%92.9%
+ + 92.9 % + 26 / 28 + 83.3 % + 5 / 6 + 75.0 % + 9 / 12 + RuleBlacklist.sol 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 946c249..086d6a1 100644 --- a/doc/test/coverage/src/rules/validation/index-sort-f.html +++ b/doc/test/coverage/src/rules/validation/index-sort-f.html @@ -31,27 +31,27 @@ lcov.info Lines: - 43 - 44 - 97.7 % + 69 + 72 + 95.8 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 12 - 13 - 92.3 % + 17 + 19 + 89.5 % Branches: - 26 - 26 - 100.0 % + 35 + 38 + 92.1 % @@ -81,6 +81,18 @@ Functions Sort by function coverage Branches Sort by branch coverage + + RuleWhitelistWrapper.sol + +
92.9%92.9%
+ + 92.9 % + 26 / 28 + 83.3 % + 5 / 6 + 75.0 % + 9 / 12 + RuleSanctionList.sol 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 ca1eb77..d20fb85 100644 --- a/doc/test/coverage/src/rules/validation/index-sort-l.html +++ b/doc/test/coverage/src/rules/validation/index-sort-l.html @@ -31,27 +31,27 @@ lcov.info Lines: - 43 - 44 - 97.7 % + 69 + 72 + 95.8 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 12 - 13 - 92.3 % + 17 + 19 + 89.5 % Branches: - 26 - 26 - 100.0 % + 35 + 38 + 92.1 % @@ -81,6 +81,18 @@ Functions Sort by function coverage Branches Sort by branch coverage + + RuleWhitelistWrapper.sol + +
92.9%92.9%
+ + 92.9 % + 26 / 28 + 83.3 % + 5 / 6 + 75.0 % + 9 / 12 + RuleSanctionList.sol diff --git a/doc/test/coverage/src/rules/validation/index.html b/doc/test/coverage/src/rules/validation/index.html index 7799d57..e0071b7 100644 --- a/doc/test/coverage/src/rules/validation/index.html +++ b/doc/test/coverage/src/rules/validation/index.html @@ -31,27 +31,27 @@ lcov.info Lines: - 43 - 44 - 97.7 % + 69 + 72 + 95.8 % Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: - 12 - 13 - 92.3 % + 17 + 19 + 89.5 % Branches: - 26 - 26 - 100.0 % + 35 + 38 + 92.1 % @@ -117,6 +117,18 @@ 100.0 % 8 / 8 + + RuleWhitelistWrapper.sol + +
92.9%92.9%
+ + 92.9 % + 26 / 28 + 83.3 % + 5 / 6 + 75.0 % + 9 / 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 70f8339..498ac69 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 2 @@ -69,15 +69,15 @@ Hit count Sort by hit count - SanctionListOracle.removeFromSanctionsList + SanctionListOracle.removeFromSanctionsList 0 - SanctionListOracle.addToSanctionsList + SanctionListOracle.addToSanctionsList 10 - SanctionListOracle.isSanctioned + SanctionListOracle.isSanctioned 12 diff --git a/doc/test/coverage/test/utils/SanctionListOracle.sol.func.html b/doc/test/coverage/test/utils/SanctionListOracle.sol.func.html index 0928957..b8d16d5 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 2 @@ -69,15 +69,15 @@ Hit count Sort by hit count - SanctionListOracle.addToSanctionsList + SanctionListOracle.addToSanctionsList 10 - SanctionListOracle.isSanctioned + SanctionListOracle.isSanctioned 12 - SanctionListOracle.removeFromSanctionsList + SanctionListOracle.removeFromSanctionsList 0 diff --git a/doc/test/coverage/test/utils/SanctionListOracle.sol.gcov.html b/doc/test/coverage/test/utils/SanctionListOracle.sol.gcov.html index fb570e9..2344b67 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 2 @@ -73,28 +73,26 @@ 2 : : pragma solidity ^0.8.20; 3 : : 4 : : /** - 5 : : * @notice Test contract from - 6 : : * https://etherscan.io/address/0x40c57923924b5c5c5455c48d93317139addac8fb#code - 7 : : */ + 5 : : * @notice Test contract from + 6 : : * https://etherscan.io/address/0x40c57923924b5c5c5455c48d93317139addac8fb#code + 7 : : */ 8 : : contract SanctionListOracle { - 9 : : - 10 : : constructor() {} - 11 : : - 12 : : mapping(address => bool) private sanctionedAddresses; - 13 : : - 14 : : - 15 : : function addToSanctionsList(address newSanction) public{ - 16 : 20 : sanctionedAddresses[newSanction] = true; - 17 : : } - 18 : : - 19 : : function removeFromSanctionsList(address removeSanction) public{ - 20 : 0 : sanctionedAddresses[removeSanction] = true; - 21 : : } - 22 : : - 23 : : function isSanctioned(address addr) public view returns (bool) { - 24 : 36 : return sanctionedAddresses[addr] == true ; - 25 : : } - 26 : : } + 9 : : constructor() {} + 10 : : + 11 : : mapping(address => bool) private sanctionedAddresses; + 12 : : + 13 : : function addToSanctionsList(address newSanction) public { + 14 : 20 : sanctionedAddresses[newSanction] = true; + 15 : : } + 16 : : + 17 : : function removeFromSanctionsList(address removeSanction) public { + 18 : 0 : sanctionedAddresses[removeSanction] = true; + 19 : : } + 20 : : + 21 : : function isSanctioned(address addr) public view returns (bool) { + 22 : 36 : return sanctionedAddresses[addr] == true; + 23 : : } + 24 : : } diff --git a/doc/test/coverage/test/utils/index-sort-b.html b/doc/test/coverage/test/utils/index-sort-b.html index 252f067..609b21b 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-15 12:20:21 + 2024-06-11 10:19:24 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 25b4893..6a9e697 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-15 12:20:21 + 2024-06-11 10:19:24 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 2c71311..788f148 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-15 12:20:21 + 2024-06-11 10:19:24 Functions: 2 diff --git a/doc/test/coverage/test/utils/index.html b/doc/test/coverage/test/utils/index.html index 487e98c..bccc378 100644 --- a/doc/test/coverage/test/utils/index.html +++ b/doc/test/coverage/test/utils/index.html @@ -37,7 +37,7 @@ Date: - 2024-05-15 12:20:21 + 2024-06-11 10:19:24 Functions: 2 diff --git a/doc/test/lcov.info b/doc/test/lcov.info index 0ce6817..ea61b44 100644 --- a/doc/test/lcov.info +++ b/doc/test/lcov.info @@ -1,10 +1,7 @@ TN: SF:script/CMTATWithRuleEngineScript.s.sol -FN:14,CMTATWithRuleEngineScript.run +FN:15,CMTATWithRuleEngineScript.run FNDA:0,CMTATWithRuleEngineScript.run -DA:16,0 -DA:16,0 -DA:16,0 DA:17,0 DA:17,0 DA:17,0 @@ -13,31 +10,34 @@ DA:18,0 DA:18,0 DA:19,0 DA:19,0 +DA:19,0 DA:20,0 DA:20,0 DA:21,0 DA:21,0 -DA:23,0 -DA:23,0 -DA:23,0 -DA:36,0 -DA:36,0 -DA:38,0 -DA:38,0 -DA:38,0 -DA:42,0 -DA:42,0 -DA:44,0 -DA:44,0 -DA:44,0 +DA:22,0 +DA:22,0 +DA:24,0 +DA:24,0 +DA:24,0 +DA:37,0 +DA:37,0 +DA:39,0 +DA:39,0 +DA:39,0 +DA:43,0 +DA:43,0 DA:45,0 DA:45,0 -DA:46,0 -DA:46,0 -DA:47,0 -DA:47,0 -DA:49,0 -DA:49,0 +DA:45,0 +DA:50,0 +DA:50,0 +DA:51,0 +DA:51,0 +DA:52,0 +DA:52,0 +DA:54,0 +DA:54,0 FNF:1 FNH:0 LF:15 @@ -90,192 +90,194 @@ BRH:0 end_of_record TN: SF:src/RuleEngine.sol -FN:44,RuleEngine.detectTransferRestriction -FNDA:13,RuleEngine.detectTransferRestriction -DA:50,22 -DA:50,22 -DA:50,22 -DA:51,22 -DA:51,22 -DA:51,22 -BRDA:51,0,0,12 -BRDA:51,0,1,10 -DA:52,12 -DA:52,12 -DA:56,10 -DA:56,10 -DA:57,10 -DA:57,10 -DA:57,11 -DA:57,1 -DA:58,6 -DA:58,6 -DA:58,6 -DA:63,6 -DA:63,6 -BRDA:63,1,0,5 -BRDA:63,1,1,1 -DA:64,5 -DA:64,5 -DA:68,5 +FN:47,RuleEngine.detectTransferRestriction +FNDA:17,RuleEngine.detectTransferRestriction +DA:53,26 +DA:53,26 +DA:53,26 +DA:58,26 +DA:58,26 +DA:58,26 +BRDA:58,0,0,15 +BRDA:58,0,1,11 +DA:59,15 +DA:59,15 +DA:63,11 +DA:63,11 +DA:64,11 +DA:64,11 +DA:64,12 +DA:64,1 +DA:65,6 +DA:65,6 +DA:65,6 +DA:67,6 +DA:67,6 +BRDA:67,1,0,5 +BRDA:67,1,1,1 DA:68,5 DA:68,5 -FN:78,RuleEngine.validateTransfer +DA:72,6 +DA:72,6 +DA:72,6 +FN:82,RuleEngine.validateTransfer FNDA:9,RuleEngine.validateTransfer -DA:83,9 -DA:83,9 -DA:83,9 -DA:83,9 -DA:83,9 -FN:91,RuleEngine.messageForTransferRestriction -FNDA:14,RuleEngine.messageForTransferRestriction -DA:95,14 -DA:95,14 -DA:96,14 -DA:96,14 -DA:96,16 -DA:96,2 -DA:97,9 -DA:97,9 -BRDA:97,2,0,- -BRDA:97,2,1,7 -DA:98,7 -DA:98,7 -DA:99,7 -DA:99,7 -DA:103,7 -DA:103,7 -DA:104,7 -DA:104,7 -DA:104,8 -DA:104,1 -DA:105,2 -DA:105,2 -BRDA:105,3,0,- -BRDA:105,3,1,1 -DA:106,1 -DA:106,1 -DA:107,1 -DA:107,1 -DA:110,6 -DA:110,6 -FN:116,RuleEngine.operateOnTransfer -FNDA:45,RuleEngine.operateOnTransfer -DA:118,44 -DA:118,44 -BRDA:118,4,0,7 -BRDA:118,4,1,37 -DA:119,7 -DA:119,7 -DA:122,37 -DA:122,37 -DA:122,37 -FN:128,RuleEngine._msgSender -FNDA:244,RuleEngine._msgSender -DA:134,244 -DA:134,244 -DA:134,244 -FN:140,RuleEngine._msgData +DA:87,9 +DA:87,9 +DA:88,9 +DA:88,9 +DA:88,9 +DA:89,9 +DA:89,9 +FN:97,RuleEngine.messageForTransferRestriction +FNDA:18,RuleEngine.messageForTransferRestriction +DA:101,18 +DA:101,18 +DA:102,18 +DA:102,18 +DA:102,21 +DA:102,3 +DA:104,13 +DA:104,13 +BRDA:103,2,0,- +BRDA:103,2,1,10 +DA:107,10 +DA:107,10 +DA:108,10 +DA:108,10 +DA:113,8 +DA:113,8 +DA:114,8 +DA:114,8 +DA:114,9 +DA:114,1 +DA:116,2 +DA:116,2 +BRDA:115,3,0,- +BRDA:115,3,1,1 +DA:119,1 +DA:119,1 +DA:120,1 +DA:120,1 +DA:124,7 +DA:124,7 +FN:130,RuleEngine.operateOnTransfer +FNDA:52,RuleEngine.operateOnTransfer +DA:137,51 +DA:137,51 +BRDA:136,4,0,10 +BRDA:136,4,1,41 +DA:139,10 +DA:139,10 +DA:142,41 +DA:142,41 +DA:142,41 +FN:148,RuleEngine._msgSender +FNDA:263,RuleEngine._msgSender +DA:154,263 +DA:154,263 +DA:154,263 +FN:160,RuleEngine._msgData FNDA:0,RuleEngine._msgData -DA:146,0 -DA:146,0 -DA:146,0 -FN:152,RuleEngine._contextSuffixLength -FNDA:244,RuleEngine._contextSuffixLength -DA:153,244 -DA:153,244 -DA:153,244 +DA:166,0 +DA:166,0 +DA:166,0 +FN:172,RuleEngine._contextSuffixLength +FNDA:263,RuleEngine._contextSuffixLength +DA:178,263 +DA:178,263 +DA:178,263 FNF:7 FNH:6 -LF:27 -LH:26 +LF:29 +LH:28 BRF:10 BRH:8 end_of_record TN: SF:src/modules/RuleEngineOperation.sol -FN:21,RuleEngineOperation.setRulesOperation +FN:26,RuleEngineOperation.setRulesOperation FNDA:11,RuleEngineOperation.setRulesOperation -DA:24,11 -DA:24,11 -BRDA:24,0,0,10 -BRDA:24,0,1,11 -DA:25,10 -DA:25,10 -DA:27,11 -DA:27,11 -DA:28,8 -DA:28,8 -FN:35,RuleEngineOperation.clearRulesOperation +DA:29,11 +DA:29,11 +BRDA:29,0,0,10 +BRDA:29,0,1,11 +DA:30,10 +DA:30,10 +DA:32,11 +DA:32,11 +DA:33,8 +DA:33,8 +FN:40,RuleEngineOperation.clearRulesOperation FNDA:4,RuleEngineOperation.clearRulesOperation -DA:36,4 -DA:36,4 -FN:43,RuleEngineOperation._clearRulesOperation +DA:41,4 +DA:41,4 +FN:48,RuleEngineOperation._clearRulesOperation FNDA:14,RuleEngineOperation._clearRulesOperation -DA:44,14 -DA:44,14 -DA:46,14 -DA:46,14 -DA:46,31 -DA:46,17 -DA:49,17 -DA:49,17 +DA:49,14 +DA:49,14 +DA:51,14 +DA:51,14 +DA:51,31 DA:51,17 -DA:51,17 -DA:53,14 -DA:53,14 -FN:61,RuleEngineOperation.addRuleOperation +DA:54,17 +DA:54,17 +DA:56,17 +DA:56,17 +DA:58,14 +DA:58,14 +FN:66,RuleEngineOperation.addRuleOperation FNDA:68,RuleEngineOperation.addRuleOperation -DA:62,68 -DA:62,68 -DA:63,66 -DA:63,66 -FN:76,RuleEngineOperation.removeRuleOperation +DA:69,68 +DA:69,68 +DA:70,66 +DA:70,66 +FN:83,RuleEngineOperation.removeRuleOperation FNDA:5,RuleEngineOperation.removeRuleOperation -DA:80,5 -DA:80,5 -FN:93,RuleEngineOperation._removeRuleOperation +DA:87,5 +DA:87,5 +FN:100,RuleEngineOperation._removeRuleOperation FNDA:22,RuleEngineOperation._removeRuleOperation -DA:97,22 -DA:97,22 -DA:98,21 -DA:98,21 -FN:104,RuleEngineOperation.rulesCountOperation +DA:101,22 +DA:101,22 +DA:102,21 +DA:102,21 +FN:108,RuleEngineOperation.rulesCountOperation FNDA:41,RuleEngineOperation.rulesCountOperation -DA:105,41 -DA:105,41 -FN:112,RuleEngineOperation.getRuleIndexOperation +DA:109,41 +DA:109,41 +FN:116,RuleEngineOperation.getRuleIndexOperation FNDA:3,RuleEngineOperation.getRuleIndexOperation -DA:113,3 -DA:113,3 -DA:113,3 -FN:121,RuleEngineOperation.ruleOperation +DA:119,3 +DA:119,3 +DA:119,3 +FN:127,RuleEngineOperation.ruleOperation FNDA:1,RuleEngineOperation.ruleOperation -DA:122,1 -DA:122,1 -FN:129,RuleEngineOperation.rulesOperation +DA:130,1 +DA:130,1 +FN:137,RuleEngineOperation.rulesOperation FNDA:5,RuleEngineOperation.rulesOperation -DA:130,5 -DA:130,5 -FN:140,RuleEngineOperation._operateOnTransfer -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 +DA:143,5 +DA:143,5 +FN:152,RuleEngineOperation._operateOnTransfer +FNDA:41,RuleEngineOperation._operateOnTransfer +DA:157,41 +DA:157,41 +DA:158,41 +DA:158,41 +DA:158,57 +DA:158,16 +DA:159,33 +DA:159,33 +DA:159,33 +DA:164,33 +DA:164,33 +BRDA:164,1,0,17 +BRDA:164,1,1,16 +DA:165,17 +DA:165,17 +DA:168,24 +DA:168,24 FNF:11 FNH:11 LF:25 @@ -285,192 +287,203 @@ BRH:4 end_of_record TN: SF:src/modules/RuleEngineValidation.sol -FN:24,RuleEngineValidation.setRulesValidation -FNDA:22,RuleEngineValidation.setRulesValidation -DA:27,21 -DA:27,21 -BRDA:27,0,0,20 -BRDA:27,0,1,21 -DA:28,20 -DA:28,20 +FN:29,RuleEngineValidation.detectTransferRestrictionValidation +FNDA:3,RuleEngineValidation.detectTransferRestrictionValidation +DA:34,82 +DA:34,82 +DA:35,82 +DA:35,82 +DA:35,97 +DA:35,15 +DA:36,43 +DA:36,43 +DA:36,43 +DA:38,43 +DA:38,43 +BRDA:38,0,0,28 +BRDA:38,0,1,15 +DA:39,28 +DA:39,28 +DA:43,54 +DA:43,54 +DA:43,54 +FN:53,RuleEngineValidation.validateTransferValidation +FNDA:2,RuleEngineValidation.validateTransferValidation +DA:58,53 +DA:58,53 +DA:59,53 +DA:59,53 +DA:59,53 +DA:60,53 +DA:60,53 +FNF:2 +FNH:2 +LF:9 +LH:9 +BRF:2 +BRH:2 +end_of_record +TN: +SF:src/modules/RuleEngineValidationCommon.sol +FN:27,RuleEngineValidationCommon.setRulesValidation +FNDA:22,RuleEngineValidationCommon.setRulesValidation DA:30,21 DA:30,21 -DA:31,18 -DA:31,18 -FN:38,RuleEngineValidation.clearRulesValidation -FNDA:6,RuleEngineValidation.clearRulesValidation -DA:39,5 -DA:39,5 -FN:46,RuleEngineValidation._clearRulesValidation -FNDA:25,RuleEngineValidation._clearRulesValidation -DA:47,25 -DA:47,25 -DA:49,25 -DA:49,25 -DA:49,53 -DA:49,28 +BRDA:30,0,0,20 +BRDA:30,0,1,21 +DA:31,20 +DA:31,20 +DA:33,21 +DA:33,21 +DA:34,18 +DA:34,18 +FN:41,RuleEngineValidationCommon.clearRulesValidation +FNDA:6,RuleEngineValidationCommon.clearRulesValidation +DA:42,5 +DA:42,5 +FN:49,RuleEngineValidationCommon._clearRulesValidation +FNDA:25,RuleEngineValidationCommon._clearRulesValidation +DA:50,25 +DA:50,25 +DA:52,25 +DA:52,25 +DA:52,53 DA:52,28 -DA:52,28 -DA:54,28 -DA:54,28 -DA:56,25 -DA:56,25 -FN:64,RuleEngineValidation.addRuleValidation -FNDA:67,RuleEngineValidation.addRuleValidation -DA:65,66 -DA:65,66 -DA:66,64 -DA:66,64 -FN:79,RuleEngineValidation.removeRuleValidation -FNDA:6,RuleEngineValidation.removeRuleValidation -DA:83,5 -DA:83,5 -FN:96,RuleEngineValidation._removeRuleValidation -FNDA:33,RuleEngineValidation._removeRuleValidation -DA:100,33 -DA:100,33 -DA:101,32 -DA:101,32 -FN:107,RuleEngineValidation.rulesCountValidation -FNDA:69,RuleEngineValidation.rulesCountValidation -DA:108,69 -DA:108,69 -FN:115,RuleEngineValidation.getRuleIndexValidation -FNDA:3,RuleEngineValidation.getRuleIndexValidation -DA:116,3 -DA:116,3 -DA:116,3 -FN:124,RuleEngineValidation.ruleValidation -FNDA:1,RuleEngineValidation.ruleValidation -DA:125,1 -DA:125,1 -FN:132,RuleEngineValidation.rulesValidation -FNDA:5,RuleEngineValidation.rulesValidation -DA:133,5 -DA:133,5 -FN:143,RuleEngineValidation.detectTransferRestrictionValidation -FNDA:3,RuleEngineValidation.detectTransferRestrictionValidation -DA:148,71 -DA:148,71 -DA:149,71 -DA:149,71 -DA:149,81 -DA:149,10 -DA:150,32 -DA:150,32 -DA:150,32 -DA:155,32 -DA:155,32 -BRDA:155,1,0,22 -BRDA:155,1,1,10 -DA:156,22 -DA:156,22 -DA:160,49 -DA:160,49 -DA:160,49 -FN:170,RuleEngineValidation.validateTransferValidation -FNDA:2,RuleEngineValidation.validateTransferValidation -DA:175,46 -DA:175,46 -DA:175,46 -DA:175,46 -DA:175,46 -FNF:12 -FNH:12 -LF:26 -LH:26 -BRF:4 -BRH:4 +DA:55,28 +DA:55,28 +DA:57,28 +DA:57,28 +DA:59,25 +DA:59,25 +FN:67,RuleEngineValidationCommon.addRuleValidation +FNDA:115,RuleEngineValidationCommon.addRuleValidation +DA:70,114 +DA:70,114 +DA:71,112 +DA:71,112 +FN:84,RuleEngineValidationCommon.removeRuleValidation +FNDA:6,RuleEngineValidationCommon.removeRuleValidation +DA:88,5 +DA:88,5 +FN:101,RuleEngineValidationCommon._removeRuleValidation +FNDA:33,RuleEngineValidationCommon._removeRuleValidation +DA:102,33 +DA:102,33 +DA:103,32 +DA:103,32 +FN:109,RuleEngineValidationCommon.rulesCountValidation +FNDA:69,RuleEngineValidationCommon.rulesCountValidation +DA:110,69 +DA:110,69 +FN:117,RuleEngineValidationCommon.getRuleIndexValidation +FNDA:3,RuleEngineValidationCommon.getRuleIndexValidation +DA:120,3 +DA:120,3 +DA:120,3 +FN:128,RuleEngineValidationCommon.ruleValidation +FNDA:1,RuleEngineValidationCommon.ruleValidation +DA:131,1 +DA:131,1 +FN:138,RuleEngineValidationCommon.rulesValidation +FNDA:5,RuleEngineValidationCommon.rulesValidation +DA:144,5 +DA:144,5 +FNF:10 +FNH:10 +LF:19 +LH:19 +BRF:2 +BRH:2 end_of_record TN: SF:src/modules/RuleInternal.sol -FN:20,RuleInternal._setRules +FN:19,RuleInternal._setRules FNDA:32,RuleInternal._setRules -DA:23,32 -DA:23,32 -BRDA:23,0,0,2 -BRDA:23,0,1,30 -DA:24,2 -DA:24,2 -DA:26,30 -DA:26,30 -DA:26,74 -DA:27,48 -DA:27,48 -DA:27,48 -DA:27,48 -BRDA:27,1,0,2 -BRDA:27,1,1,46 +DA:20,32 +DA:20,32 +BRDA:20,0,0,2 +BRDA:20,0,1,30 +DA:21,2 +DA:21,2 +DA:23,30 +DA:23,30 +DA:23,74 +DA:24,48 +DA:24,48 +DA:24,48 +DA:24,48 +BRDA:24,1,0,2 +BRDA:24,1,1,46 +DA:25,2 +DA:25,2 +DA:27,46 +BRDA:27,2,0,2 +BRDA:27,2,1,44 DA:28,2 DA:28,2 -DA:30,46 -BRDA:30,2,0,2 -BRDA:30,2,1,44 -DA:31,2 -DA:31,2 +DA:30,44 +DA:30,44 +DA:31,44 +DA:31,44 DA:33,44 DA:33,44 -DA:34,44 -DA:34,44 -DA:36,44 -DA:36,44 -FN:46,RuleInternal._addRule -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,132 -DA:49,2 -DA:49,2 -DA:51,132 -BRDA:51,4,0,2 -BRDA:51,4,1,130 -DA:53,2 -DA:53,2 -DA:55,130 -DA:55,130 -DA:56,130 -DA:56,130 -FN:69,RuleInternal._removeRule +FN:43,RuleInternal._addRule +FNDA:182,RuleInternal._addRule +DA:44,182 +DA:44,182 +DA:44,182 +DA:44,182 +BRDA:44,3,0,2 +BRDA:44,3,1,180 +DA:45,2 +DA:45,2 +DA:47,180 +BRDA:47,4,0,2 +BRDA:47,4,1,178 +DA:48,2 +DA:48,2 +DA:50,178 +DA:50,178 +DA:51,178 +DA:51,178 +FN:64,RuleInternal._removeRule FNDA:55,RuleInternal._removeRule -DA:74,55 -DA:74,55 -BRDA:74,5,0,2 -BRDA:74,5,1,53 -DA:76,2 -DA:76,2 -DA:78,53 -DA:78,53 -DA:78,53 -BRDA:78,6,0,- -BRDA:78,6,1,4 -DA:79,4 -DA:79,4 -DA:81,53 -DA:81,53 -DA:82,53 -DA:82,53 -DA:83,53 -DA:83,53 -FN:90,RuleInternal.getRuleIndex +DA:69,55 +DA:69,55 +BRDA:69,5,0,2 +BRDA:69,5,1,53 +DA:70,2 +DA:70,2 +DA:72,53 +DA:72,53 +DA:72,53 +BRDA:72,6,0,- +BRDA:72,6,1,4 +DA:73,4 +DA:73,4 +DA:75,53 +DA:75,53 +DA:76,53 +DA:76,53 +DA:77,53 +DA:77,53 +FN:84,RuleInternal.getRuleIndex FNDA:6,RuleInternal.getRuleIndex -DA:91,6 -DA:91,6 -DA:92,6 -DA:92,6 -DA:92,12 -DA:93,10 -DA:93,10 -BRDA:93,7,0,4 -BRDA:93,7,1,6 -DA:94,4 -DA:94,4 -DA:97,6 -DA:97,6 -DA:100,2 -DA:100,2 +DA:88,6 +DA:88,6 +DA:89,6 +DA:89,6 +DA:89,12 +DA:90,10 +DA:90,10 +BRDA:90,7,0,4 +BRDA:90,7,1,6 +DA:91,4 +DA:91,4 +DA:94,6 +DA:94,6 +DA:97,2 +DA:97,2 FNF:4 FNH:4 LF:29 @@ -480,147 +493,134 @@ BRH:15 end_of_record TN: SF:src/rules/operation/RuleConditionalTransfer.sol -FN:50,RuleConditionalTransfer.createTransferRequest +FN:55,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:59,105 +DA:59,105 +DA:59,105 +DA:60,105 +DA:60,105 +DA:60,105 +DA:61,105 +DA:61,105 +BRDA:61,0,0,1 +BRDA:61,0,1,104 +DA:62,1 +DA:62,1 +DA:64,104 +DA:64,104 +BRDA:64,1,0,- +BRDA:64,1,1,101 +DA:65,101 +DA:65,101 +DA:66,101 +DA:66,101 +DA:66,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:78,101 +DA:78,101 +DA:79,101 +DA:79,101 DA:82,3 DA:82,3 -FN:89,RuleConditionalTransfer.createTransferRequestBatch +DA:83,3 +DA:83,3 +DA:84,3 +DA:84,3 +FN:97,RuleConditionalTransfer.createTransferRequestBatch FNDA:3,RuleConditionalTransfer.createTransferRequestBatch -DA:90,3 -DA:90,3 -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 +DA:101,3 +DA:101,3 +BRDA:101,2,0,1 +BRDA:101,2,1,2 +DA:102,1 +DA:102,1 +DA:104,2 +DA:104,2 +BRDA:104,3,0,1 +BRDA:104,3,1,1 +DA:105,1 +DA:105,1 +DA:107,1 +DA:107,1 +DA:107,4 +DA:107,3 +DA:108,3 +DA:108,3 +FN:115,RuleConditionalTransfer.cancelTransferRequest FNDA:6,RuleConditionalTransfer.cancelTransferRequest -DA:107,6 -DA:107,6 -FN:113,RuleConditionalTransfer.cancelTransferRequestBatch +DA:116,6 +DA:116,6 +FN:122,RuleConditionalTransfer.cancelTransferRequestBatch FNDA:3,RuleConditionalTransfer.cancelTransferRequestBatch -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 +DA:123,3 +DA:123,3 +BRDA:123,4,0,1 +BRDA:123,4,1,2 +DA:124,1 +DA:124,1 +DA:127,2 +DA:127,2 +DA:127,6 +DA:127,4 +DA:128,5 +DA:128,5 +DA:128,5 +BRDA:128,5,0,1 +BRDA:128,5,1,4 +DA:129,1 +DA:129,1 +DA:132,1 +DA:132,1 +DA:132,4 +DA:132,3 +DA:133,3 +DA:133,3 +FN:137,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 +DA:138,9 +DA:138,9 +DA:138,9 +BRDA:138,6,0,1 +BRDA:138,6,1,8 +DA:139,1 +DA:139,1 +DA:141,8 +DA:141,8 +DA:143,8 +DA:143,8 +DA:143,8 +BRDA:143,7,0,1 +BRDA:143,7,1,7 +DA:144,1 +DA:144,1 +DA:148,7 +DA:148,7 +DA:148,7 +DA:149,2 +DA:149,2 +BRDA:147,8,0,1 +BRDA:147,8,1,6 +DA:151,1 +DA:151,1 +DA:153,6 +DA:153,6 +FN:156,RuleConditionalTransfer.getRequestTrade FNDA:57,RuleConditionalTransfer.getRequestTrade -DA:153,57 -DA:153,57 -DA:153,57 -DA:154,57 -DA:154,57 -FN:162,RuleConditionalTransfer.getRequestByStatus +DA:161,57 +DA:161,57 +DA:161,57 +DA:162,57 +DA:162,57 +FN:170,RuleConditionalTransfer.getRequestByStatus FNDA:35,RuleConditionalTransfer.getRequestByStatus -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: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:173,35 +DA:173,35 +DA:174,35 +DA:174,35 DA:175,35 DA:175,35 DA:178,35 @@ -629,508 +629,525 @@ 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 +BRDA:179,9,0,36 +BRDA:179,9,1,38 +DA:180,36 +DA:180,36 +DA:185,35 +DA:185,35 +DA:185,35 +DA:188,35 +DA:188,35 +DA:188,73 +DA:188,38 +DA:189,38 +DA:189,38 +BRDA:189,10,0,- +BRDA:189,10,1,36 +DA:191,36 +DA:191,36 +DA:194,36 +DA:194,36 +DA:195,36 +DA:195,36 +DA:198,35 +DA:198,35 +FN:205,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 +DA:216,33 +DA:216,33 +DA:216,33 +DA:216,33 +BRDA:216,11,0,2 +BRDA:216,11,1,16 +DA:218,18 +DA:218,18 +DA:218,18 +DA:219,3 +DA:219,3 +BRDA:217,12,0,2 +BRDA:217,12,1,16 +DA:221,2 +DA:221,2 +DA:226,31 +DA:226,31 +BRDA:226,13,0,4 +BRDA:226,13,1,27 +DA:227,4 +DA:227,4 +DA:229,27 +DA:229,27 +DA:229,27 +DA:230,27 +DA:230,27 +BRDA:230,14,0,10 +BRDA:230,14,1,17 +DA:231,10 +DA:231,10 +DA:232,10 +DA:232,10 +DA:234,17 +DA:234,17 +FN:244,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:252,2 -DA:252,2 +DA:250,11 +DA:250,11 +DA:250,11 +DA:250,11 +BRDA:250,15,0,- +BRDA:250,15,1,1 +DA:252,3 +DA:252,3 +DA:252,3 DA:253,2 DA:253,2 -FN:261,RuleConditionalTransfer.messageForTransferRestriction +BRDA:251,16,0,- +BRDA:251,16,1,1 +DA:255,1 +DA:255,1 +DA:255,1 +DA:258,10 +DA:258,10 +DA:258,10 +DA:259,10 +DA:259,10 +DA:259,10 +DA:259,10 +BRDA:259,17,0,8 +BRDA:259,17,1,2 +DA:260,8 +DA:260,8 +DA:262,2 +DA:262,2 +DA:262,2 +FN:271,RuleConditionalTransfer.canReturnTransferRestrictionCode +FNDA:2,RuleConditionalTransfer.canReturnTransferRestrictionCode +DA:274,2 +DA:274,2 +DA:274,2 +FN:282,RuleConditionalTransfer.messageForTransferRestriction FNDA:3,RuleConditionalTransfer.messageForTransferRestriction -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 +DA:285,3 +DA:285,3 +BRDA:285,18,0,2 +BRDA:285,18,1,1 +DA:286,2 +DA:286,2 +DA:288,1 +DA:288,1 +FN:299,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 +DA:305,41 +DA:305,41 +BRDA:304,19,0,4 +BRDA:304,19,1,37 +DA:310,4 +DA:310,4 +DA:312,37 +DA:312,37 +FN:321,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 +DA:324,37 +DA:324,37 +DA:324,37 +DA:330,37 +DA:330,37 +DA:330,37 +DA:333,37 +DA:333,37 +BRDA:333,20,0,12 +BRDA:333,20,1,25 +DA:334,12 +DA:334,12 +DA:336,25 +DA:336,25 +FN:343,RuleConditionalTransfer._msgSender FNDA:452,RuleConditionalTransfer._msgSender -DA:321,452 -DA:321,452 -DA:321,452 -FN:327,RuleConditionalTransfer._msgData +DA:349,452 +DA:349,452 +DA:349,452 +FN:355,RuleConditionalTransfer._msgData FNDA:0,RuleConditionalTransfer._msgData -DA:333,0 -DA:333,0 -DA:333,0 -FN:339,RuleConditionalTransfer._contextSuffixLength +DA:361,0 +DA:361,0 +DA:361,0 +FN:367,RuleConditionalTransfer._contextSuffixLength FNDA:452,RuleConditionalTransfer._contextSuffixLength -DA:340,452 -DA:340,452 -DA:340,452 +DA:373,452 +DA:373,452 +DA:373,452 FNF:16 FNH:15 -LF:85 -LH:84 +LF:86 +LH:85 BRF:42 BRH:38 end_of_record TN: SF:src/rules/operation/abstract/RuleConditionalTransferOperator.sol -FN:25,RuleConditionalTransferOperator.setConditionalWhitelist +FN:29,RuleConditionalTransferOperator.setConditionalWhitelist FNDA:25,RuleConditionalTransferOperator.setConditionalWhitelist -DA:26,25 -DA:26,25 -DA:27,25 -DA:27,25 -FN:33,RuleConditionalTransferOperator.setIssuanceOptions +DA:32,25 +DA:32,25 +DA:33,25 +DA:33,25 +FN:39,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:43,4 +DA:43,4 +BRDA:42,0,0,2 +BRDA:42,0,1,4 +DA:46,2 +DA:46,2 +DA:50,4 +DA:50,4 +BRDA:49,1,0,2 +BRDA:49,1,1,4 DA:53,2 DA:53,2 -FN:62,RuleConditionalTransferOperator.setTimeLimit +FN:63,RuleConditionalTransferOperator.setAutomaticTransfer +FNDA:3,RuleConditionalTransferOperator.setAutomaticTransfer +DA:67,2 +DA:67,2 +BRDA:66,2,0,2 +BRDA:66,2,1,2 +DA:70,2 +DA:70,2 +DA:75,2 +DA:75,2 +DA:75,2 +DA:76,2 +DA:76,2 +BRDA:74,3,0,2 +BRDA:74,3,1,2 +DA:78,2 +DA:78,2 +FN:87,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 +DA:91,3 +DA:91,3 +BRDA:90,4,0,3 +BRDA:90,4,1,3 +DA:94,3 +DA:94,3 +DA:98,3 +DA:98,3 +BRDA:97,5,0,3 +BRDA:97,5,1,3 +DA:101,3 +DA:101,3 +FN:111,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 +DA:115,4 +DA:115,4 +BRDA:114,6,0,4 +BRDA:114,6,1,4 +DA:118,4 +DA:118,4 +DA:122,4 +DA:122,4 +BRDA:121,7,0,4 +BRDA:121,7,1,4 +DA:125,4 +DA:125,4 +FN:135,RuleConditionalTransferOperator.createTransferRequestWithApproval FNDA:6,RuleConditionalTransferOperator.createTransferRequestWithApproval -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: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: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,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 +FN:147,RuleConditionalTransferOperator.approveTransferRequest +FNDA:33,RuleConditionalTransferOperator.approveTransferRequest +DA:152,32 +DA:152,32 +FN:158,RuleConditionalTransferOperator.approveTransferRequestWithId +FNDA:5,RuleConditionalTransferOperator.approveTransferRequestWithId +DA:162,4 +DA:162,4 +DA:162,4 +BRDA:162,8,0,2 +BRDA:162,8,1,2 +DA:163,2 +DA:163,2 +DA:165,2 +DA:165,2 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 +FN:174,RuleConditionalTransferOperator.resetRequestStatus +FNDA:3,RuleConditionalTransferOperator.resetRequestStatus +DA:177,2 +DA:177,2 +DA:177,2 +BRDA:177,9,0,1 +BRDA:177,9,1,1 +DA:178,1 +DA:178,1 DA:180,1 DA:180,1 -DA:182,1 -DA:182,1 -DA:182,5 -DA:182,4 -DA:183,4 -DA:183,4 -FN:190,RuleConditionalTransferOperator.resetRequestStatusBatch +DA:181,1 +DA:181,1 +FN:188,RuleConditionalTransferOperator.approveTransferRequestBatchWithId +FNDA:7,RuleConditionalTransferOperator.approveTransferRequestBatchWithId +DA:192,5 +DA:192,5 +BRDA:192,10,0,1 +BRDA:192,10,1,4 +DA:193,1 +DA:193,1 +DA:195,4 +DA:195,4 +BRDA:195,11,0,1 +BRDA:195,11,1,3 +DA:196,1 +DA:196,1 +DA:199,3 +DA:199,3 +DA:199,13 +DA:199,10 +DA:200,11 +DA:200,11 +DA:200,11 +BRDA:200,12,0,1 +BRDA:200,12,1,10 +DA:201,1 +DA:201,1 +DA:204,2 +DA:204,2 +DA:204,6 +DA:204,4 +DA:205,5 +DA:205,5 +DA:208,5 +DA:208,5 +FN:215,RuleConditionalTransferOperator.approveTransferRequestBatch +FNDA:7,RuleConditionalTransferOperator.approveTransferRequestBatch +DA:220,6 +DA:220,6 +BRDA:220,13,0,1 +BRDA:220,13,1,5 +DA:221,1 +DA:221,1 +DA:224,5 +DA:224,5 +BRDA:223,14,0,3 +BRDA:223,14,1,2 +DA:227,3 +DA:227,3 +DA:229,2 +DA:229,2 +DA:229,11 +DA:229,9 +DA:230,9 +DA:230,9 +FN:241,RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch +FNDA:3,RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch +DA:244,2 +DA:244,2 +BRDA:244,15,0,1 +BRDA:244,15,1,1 +DA:245,1 +DA:245,1 +DA:247,1 +DA:247,1 +DA:247,5 +DA:247,4 +DA:248,4 +DA:248,4 +FN:255,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 +DA:258,3 +DA:258,3 +BRDA:258,16,0,1 +BRDA:258,16,1,2 +DA:259,1 +DA:259,1 +DA:262,2 +DA:262,2 +DA:262,5 +DA:262,3 +DA:263,4 +DA:263,4 +DA:263,4 +BRDA:263,17,0,1 +BRDA:263,17,1,3 +DA:264,1 +DA:264,1 +DA:267,1 +DA:267,1 +DA:267,4 +DA:267,3 +DA:268,3 +DA:268,3 +DA:269,3 +DA:269,3 +FN:274,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 +DA:279,41 +DA:279,41 +BRDA:279,18,0,1 +BRDA:279,18,1,40 +DA:280,1 +DA:280,1 +DA:282,40 +DA:282,40 +DA:282,40 +DA:285,40 +DA:285,40 +DA:286,40 +DA:286,40 +BRDA:286,19,0,1 +BRDA:286,19,1,6 +DA:287,7 +DA:287,7 +BRDA:287,20,0,1 +BRDA:287,20,1,6 +DA:288,1 +DA:288,1 +DA:291,6 +DA:291,6 +DA:293,6 +DA:293,6 +DA:301,33 +DA:301,33 +FN:305,RuleConditionalTransferOperator._createTransferRequestWithApproval FNDA:0,RuleConditionalTransferOperator._createTransferRequestWithApproval -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 -DA:257,1 -DA:257,1 -FN:261,RuleConditionalTransferOperator._resetRequestStatus +DA:311,15 +DA:311,15 +DA:311,15 +DA:314,15 +DA:314,15 +BRDA:314,21,0,- +BRDA:314,21,1,14 +DA:315,14 +DA:315,14 +DA:315,14 +DA:326,14 +DA:326,14 +DA:327,14 +DA:327,14 +DA:328,14 +DA:328,14 +DA:335,14 +DA:335,14 +DA:338,1 +DA:338,1 +DA:341,1 +DA:341,1 +DA:342,1 +DA:342,1 +FN:352,RuleConditionalTransferOperator._resetRequestStatus FNDA:10,RuleConditionalTransferOperator._resetRequestStatus -DA:264,10 -DA:264,10 -DA:265,10 -DA:265,10 -FN:268,RuleConditionalTransferOperator._checkRequestStatus +DA:353,10 +DA:353,10 +DA:354,10 +DA:354,10 +FN:363,RuleConditionalTransferOperator._checkRequestStatus FNDA:119,RuleConditionalTransferOperator._checkRequestStatus -DA:270,119 -DA:270,119 -DA:270,119 -FN:273,RuleConditionalTransferOperator._approveRequest +DA:365,119 +DA:365,119 +DA:366,119 +DA:366,119 +FN:370,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 +DA:375,46 +DA:375,46 +BRDA:375,22,0,1 +BRDA:375,22,1,45 +DA:376,1 +DA:376,1 +DA:378,45 +BRDA:378,23,0,2 +BRDA:378,23,1,2 +DA:381,27 +DA:381,27 +BRDA:380,24,0,3 +BRDA:380,24,1,24 +DA:384,3 +DA:384,3 +DA:387,24 +DA:387,24 +DA:389,24 +DA:389,24 +DA:392,24 +DA:392,24 +DA:400,24 +DA:400,24 +DA:401,2 +DA:401,2 +DA:401,2 +DA:401,2 +BRDA:399,25,0,2 +BRDA:399,25,1,2 +DA:406,2 +DA:406,2 +DA:406,2 +BRDA:405,26,0,2 +BRDA:405,26,1,2 +DA:412,2 +DA:412,2 +DA:420,18 +DA:420,18 +DA:421,18 +DA:421,18 +FN:434,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 +DA:436,10 +DA:436,10 +DA:437,10 +DA:437,10 +DA:439,10 +DA:439,10 +DA:441,10 +DA:441,10 FNF:19 FNH:18 -LF:96 -LH:96 +LF:99 +LH:99 BRF:54 BRH:53 end_of_record TN: SF:src/rules/validation/RuleBlacklist.sol -FN:29,RuleBlacklist.detectTransferRestriction +FN:33,RuleBlacklist.detectTransferRestriction FNDA:10,RuleBlacklist.detectTransferRestriction -DA:34,10 -DA:34,10 -BRDA:34,0,0,5 -BRDA:34,0,1,5 -DA:35,5 -DA:35,5 -DA:36,5 -DA:36,5 -BRDA:36,1,0,2 -BRDA:36,1,1,3 -DA:37,2 -DA:37,2 -DA:39,3 -DA:39,3 -DA:39,3 -FN:48,RuleBlacklist.canReturnTransferRestrictionCode +DA:38,10 +DA:38,10 +BRDA:38,0,0,5 +BRDA:38,0,1,5 +DA:39,5 +DA:39,5 +DA:40,5 +DA:40,5 +BRDA:40,1,0,2 +BRDA:40,1,1,3 +DA:41,2 +DA:41,2 +DA:43,3 +DA:43,3 +DA:43,3 +FN:52,RuleBlacklist.canReturnTransferRestrictionCode FNDA:4,RuleBlacklist.canReturnTransferRestrictionCode -DA:51,4 -DA:51,4 -DA:52,4 -DA:52,4 -DA:52,4 -DA:53,2 -DA:53,2 -FN:61,RuleBlacklist.messageForTransferRestriction +DA:55,4 +DA:55,4 +DA:56,4 +DA:56,4 +DA:56,4 +DA:57,2 +DA:57,2 +FN:65,RuleBlacklist.messageForTransferRestriction FNDA:4,RuleBlacklist.messageForTransferRestriction -DA:64,4 -DA:64,4 -BRDA:64,2,0,2 -BRDA:64,2,1,2 -DA:65,2 -DA:65,2 -DA:66,2 -DA:66,2 -BRDA:66,3,0,1 -BRDA:66,3,1,1 -DA:67,1 -DA:67,1 -DA:69,1 -DA:69,1 +DA:68,4 +DA:68,4 +BRDA:68,2,0,2 +BRDA:68,2,1,2 +DA:69,2 +DA:69,2 +DA:70,2 +DA:70,2 +BRDA:70,3,0,1 +BRDA:70,3,1,1 +DA:71,1 +DA:71,1 +DA:73,1 +DA:73,1 FNF:3 FNH:3 LF:13 @@ -1140,73 +1157,73 @@ BRH:8 end_of_record TN: SF:src/rules/validation/RuleSanctionList.sol -FN:36,RuleSanctionList.setSanctionListOracle +FN:42,RuleSanctionList.setSanctionListOracle FNDA:10,RuleSanctionList.setSanctionListOracle -DA:39,9 -DA:39,9 -FN:48,RuleSanctionList.detectTransferRestriction +DA:45,9 +DA:45,9 +FN:54,RuleSanctionList.detectTransferRestriction FNDA:7,RuleSanctionList.detectTransferRestriction -DA:53,7 -DA:53,7 -DA:53,7 -DA:53,7 -BRDA:53,0,0,2 -BRDA:53,0,1,3 -DA:54,7 -DA:54,7 -BRDA:54,1,0,2 -BRDA:54,1,1,5 -DA:55,2 -DA:55,2 -DA:56,5 -DA:56,5 -BRDA:56,2,0,2 -BRDA:56,2,1,3 -DA:57,2 -DA:57,2 -DA:60,3 -DA:60,3 -DA:60,3 -FN:68,RuleSanctionList.canReturnTransferRestrictionCode +DA:59,7 +DA:59,7 +DA:59,7 +DA:59,7 +BRDA:59,0,0,2 +BRDA:59,0,1,3 +DA:60,7 +DA:60,7 +BRDA:60,1,0,2 +BRDA:60,1,1,5 +DA:61,2 +DA:61,2 +DA:62,5 +DA:62,5 +BRDA:62,2,0,2 +BRDA:62,2,1,3 +DA:63,2 +DA:63,2 +DA:66,3 +DA:66,3 +DA:66,3 +FN:74,RuleSanctionList.canReturnTransferRestrictionCode FNDA:3,RuleSanctionList.canReturnTransferRestrictionCode -DA:71,3 -DA:71,3 -DA:72,3 -DA:72,3 -DA:72,3 -DA:73,2 -DA:73,2 -FN:81,RuleSanctionList.messageForTransferRestriction +DA:77,3 +DA:77,3 +DA:78,3 +DA:78,3 +DA:78,3 +DA:79,2 +DA:79,2 +FN:87,RuleSanctionList.messageForTransferRestriction FNDA:3,RuleSanctionList.messageForTransferRestriction -DA:84,3 -DA:84,3 -BRDA:84,3,0,1 -BRDA:84,3,1,2 -DA:85,1 -DA:85,1 -DA:86,2 -DA:86,2 -BRDA:86,4,0,1 -BRDA:86,4,1,1 -DA:87,1 -DA:87,1 -DA:89,1 -DA:89,1 -FN:96,RuleSanctionList._msgSender +DA:90,3 +DA:90,3 +BRDA:90,3,0,1 +BRDA:90,3,1,2 +DA:91,1 +DA:91,1 +DA:92,2 +DA:92,2 +BRDA:92,4,0,1 +BRDA:92,4,1,1 +DA:93,1 +DA:93,1 +DA:95,1 +DA:95,1 +FN:102,RuleSanctionList._msgSender FNDA:10,RuleSanctionList._msgSender -DA:102,10 -DA:102,10 -DA:102,10 -FN:108,RuleSanctionList._msgData +DA:108,10 +DA:108,10 +DA:108,10 +FN:114,RuleSanctionList._msgData FNDA:0,RuleSanctionList._msgData -DA:114,0 -DA:114,0 -DA:114,0 -FN:120,RuleSanctionList._contextSuffixLength +DA:120,0 +DA:120,0 +DA:120,0 +FN:126,RuleSanctionList._contextSuffixLength FNDA:10,RuleSanctionList._contextSuffixLength -DA:121,10 -DA:121,10 -DA:121,10 +DA:132,10 +DA:132,10 +DA:132,10 FNF:7 FNH:6 LF:18 @@ -1216,48 +1233,48 @@ BRH:10 end_of_record TN: SF:src/rules/validation/RuleWhitelist.sol -FN:29,RuleWhitelist.detectTransferRestriction +FN:33,RuleWhitelist.detectTransferRestriction FNDA:28,RuleWhitelist.detectTransferRestriction -DA:34,28 -DA:34,28 -BRDA:34,0,0,13 -BRDA:34,0,1,15 -DA:35,13 -DA:35,13 -DA:36,15 -DA:36,15 -BRDA:36,1,0,5 -BRDA:36,1,1,10 -DA:37,5 -DA:37,5 -DA:39,10 -DA:39,10 -DA:39,10 -FN:48,RuleWhitelist.canReturnTransferRestrictionCode +DA:38,28 +DA:38,28 +BRDA:38,0,0,13 +BRDA:38,0,1,15 +DA:39,13 +DA:39,13 +DA:40,15 +DA:40,15 +BRDA:40,1,0,5 +BRDA:40,1,1,10 +DA:41,5 +DA:41,5 +DA:43,10 +DA:43,10 +DA:43,10 +FN:52,RuleWhitelist.canReturnTransferRestrictionCode FNDA:8,RuleWhitelist.canReturnTransferRestrictionCode -DA:51,8 -DA:51,8 -DA:52,8 -DA:52,8 -DA:52,8 -DA:53,4 -DA:53,4 -FN:61,RuleWhitelist.messageForTransferRestriction +DA:55,8 +DA:55,8 +DA:56,8 +DA:56,8 +DA:56,8 +DA:57,4 +DA:57,4 +FN:65,RuleWhitelist.messageForTransferRestriction FNDA:7,RuleWhitelist.messageForTransferRestriction -DA:64,7 -DA:64,7 -BRDA:64,2,0,4 -BRDA:64,2,1,3 -DA:65,4 -DA:65,4 -DA:66,3 -DA:66,3 -BRDA:66,3,0,2 -BRDA:66,3,1,1 -DA:67,2 -DA:67,2 -DA:69,1 -DA:69,1 +DA:68,7 +DA:68,7 +BRDA:68,2,0,4 +BRDA:68,2,1,3 +DA:69,4 +DA:69,4 +DA:70,3 +DA:70,3 +BRDA:70,3,0,2 +BRDA:70,3,1,1 +DA:71,2 +DA:71,2 +DA:73,1 +DA:73,1 FNF:3 FNH:3 LF:13 @@ -1266,123 +1283,237 @@ BRF:8 BRH:8 end_of_record TN: +SF:src/rules/validation/RuleWhitelistWrapper.sol +FN:42,RuleWhitelistWrapper.detectTransferRestriction +FNDA:11,RuleWhitelistWrapper.detectTransferRestriction +DA:47,11 +DA:47,11 +DA:47,11 +DA:48,11 +DA:48,11 +DA:48,11 +DA:49,11 +DA:49,11 +DA:49,11 +DA:50,11 +DA:50,11 +DA:51,11 +DA:51,11 +DA:52,11 +DA:52,11 +DA:54,11 +DA:54,11 +DA:54,44 +DA:54,33 +DA:56,33 +DA:56,33 +DA:58,33 +DA:58,33 +DA:58,8 +BRDA:58,0,0,- +BRDA:58,0,1,7 +DA:60,7 +DA:60,7 +DA:62,33 +DA:62,33 +DA:62,8 +BRDA:62,1,0,- +BRDA:62,1,1,7 +DA:64,7 +DA:64,7 +DA:67,11 +DA:67,11 +BRDA:67,2,0,4 +BRDA:67,2,1,7 +DA:68,4 +DA:68,4 +DA:69,7 +DA:69,7 +BRDA:69,3,0,2 +BRDA:69,3,1,5 +DA:70,2 +DA:70,2 +DA:72,5 +DA:72,5 +DA:72,5 +FN:81,RuleWhitelistWrapper.canReturnTransferRestrictionCode +FNDA:4,RuleWhitelistWrapper.canReturnTransferRestrictionCode +DA:84,4 +DA:84,4 +DA:85,4 +DA:85,4 +DA:85,4 +DA:86,2 +DA:86,2 +FN:94,RuleWhitelistWrapper.messageForTransferRestriction +FNDA:3,RuleWhitelistWrapper.messageForTransferRestriction +DA:97,3 +DA:97,3 +BRDA:97,4,0,2 +BRDA:97,4,1,1 +DA:98,2 +DA:98,2 +DA:99,1 +DA:99,1 +BRDA:99,5,0,1 +BRDA:99,5,1,- +DA:100,1 +DA:100,1 +DA:102,0 +DA:102,0 +FN:109,RuleWhitelistWrapper._msgSender +FNDA:36,RuleWhitelistWrapper._msgSender +DA:115,36 +DA:115,36 +DA:115,36 +FN:121,RuleWhitelistWrapper._msgData +FNDA:0,RuleWhitelistWrapper._msgData +DA:127,0 +DA:127,0 +DA:127,0 +FN:133,RuleWhitelistWrapper._contextSuffixLength +FNDA:36,RuleWhitelistWrapper._contextSuffixLength +DA:139,36 +DA:139,36 +DA:139,36 +FNF:6 +FNH:5 +LF:28 +LH:26 +BRF:12 +BRH:9 +end_of_record +TN: SF:src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol -FN:39,RuleAddressList.addAddressesToTheList -FNDA:15,RuleAddressList.addAddressesToTheList -DA:42,14 -DA:42,14 -FN:51,RuleAddressList.removeAddressesFromTheList +FN:43,RuleAddressList.addAddressesToTheList +FNDA:17,RuleAddressList.addAddressesToTheList +DA:46,16 +DA:46,16 +FN:55,RuleAddressList.removeAddressesFromTheList FNDA:4,RuleAddressList.removeAddressesFromTheList -DA:54,3 -DA:54,3 -FN:62,RuleAddressList.addAddressToTheList -FNDA:40,RuleAddressList.addAddressToTheList -DA:65,39 -DA:65,39 -FN:74,RuleAddressList.removeAddressFromTheList +DA:58,3 +DA:58,3 +FN:66,RuleAddressList.addAddressToTheList +FNDA:52,RuleAddressList.addAddressToTheList +DA:69,51 +DA:69,51 +FN:78,RuleAddressList.removeAddressFromTheList FNDA:3,RuleAddressList.removeAddressFromTheList -DA:77,2 -DA:77,2 -FN:85,RuleAddressList.numberListedAddress +DA:81,2 +DA:81,2 +FN:89,RuleAddressList.numberListedAddress FNDA:24,RuleAddressList.numberListedAddress -DA:86,24 -DA:86,24 -DA:86,24 -FN:96,RuleAddressList.addressIsListed -FNDA:83,RuleAddressList.addressIsListed -DA:99,141 -DA:99,141 -DA:99,141 -FN:106,RuleAddressList._msgSender -FNDA:72,RuleAddressList._msgSender -DA:112,72 -DA:112,72 -DA:112,72 -FN:118,RuleAddressList._msgData +DA:90,24 +DA:90,24 +DA:90,24 +FN:99,RuleAddressList.addressIsListed +FNDA:86,RuleAddressList.addressIsListed +DA:102,144 +DA:102,144 +DA:102,144 +FN:109,RuleAddressList.addressIsListedBatch +FNDA:36,RuleAddressList.addressIsListedBatch +DA:112,36 +DA:112,36 +DA:112,36 +DA:113,36 +DA:113,36 +DA:113,107 +DA:113,71 +DA:114,71 +DA:114,71 +DA:116,36 +DA:116,36 +FN:122,RuleAddressList._msgSender +FNDA:86,RuleAddressList._msgSender +DA:128,86 +DA:128,86 +DA:128,86 +FN:134,RuleAddressList._msgData FNDA:0,RuleAddressList._msgData -DA:124,0 -DA:124,0 -DA:124,0 -FN:130,RuleAddressList._contextSuffixLength -FNDA:72,RuleAddressList._contextSuffixLength -DA:131,72 -DA:131,72 -DA:131,72 -FNF:9 -FNH:8 -LF:9 -LH:8 +DA:140,0 +DA:140,0 +DA:140,0 +FN:146,RuleAddressList._contextSuffixLength +FNDA:86,RuleAddressList._contextSuffixLength +DA:152,86 +DA:152,86 +DA:152,86 +FNF:10 +FNH:9 +LF:13 +LH:12 BRF:0 BRH:0 end_of_record TN: SF:src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol -FN:23,RuleAddressListInternal._addAddressesToThelist -FNDA:14,RuleAddressListInternal._addAddressesToThelist -DA:26,14 -DA:26,14 -DA:27,14 -DA:27,14 -DA:27,44 -DA:27,30 -DA:28,30 -DA:28,30 -BRDA:28,0,0,- -BRDA:28,0,1,28 -DA:29,28 -DA:29,28 -DA:30,28 -DA:30,28 -DA:33,14 -DA:33,14 -FN:42,RuleAddressListInternal._removeAddressesFromThelist +FN:22,RuleAddressListInternal._addAddressesToThelist +FNDA:16,RuleAddressListInternal._addAddressesToThelist +DA:23,16 +DA:23,16 +DA:24,16 +DA:24,16 +DA:24,50 +DA:24,34 +DA:25,34 +DA:25,34 +BRDA:25,0,0,- +BRDA:25,0,1,32 +DA:26,32 +DA:26,32 +DA:27,32 +DA:27,32 +DA:30,16 +DA:30,16 +FN:39,RuleAddressListInternal._removeAddressesFromThelist FNDA:3,RuleAddressListInternal._removeAddressesFromThelist -DA:45,3 -DA:45,3 -DA:46,3 -DA:46,3 -DA:46,10 -DA:46,7 -DA:47,7 -BRDA:47,1,0,- -BRDA:47,1,1,6 -DA:48,6 -DA:48,6 -DA:49,6 -DA:49,6 -DA:52,3 -DA:52,3 -FN:60,RuleAddressListInternal._addAddressToThelist -FNDA:39,RuleAddressListInternal._addAddressToThelist -DA:63,39 -BRDA:63,2,0,1 -BRDA:63,2,1,38 -DA:65,1 -DA:65,1 -DA:67,38 -DA:67,38 -DA:68,38 -DA:68,38 -FN:77,RuleAddressListInternal._removeAddressFromThelist +DA:42,3 +DA:42,3 +DA:43,3 +DA:43,3 +DA:43,10 +DA:43,7 +DA:44,7 +BRDA:44,1,0,- +BRDA:44,1,1,6 +DA:45,6 +DA:45,6 +DA:46,6 +DA:46,6 +DA:49,3 +DA:49,3 +FN:57,RuleAddressListInternal._addAddressToThelist +FNDA:51,RuleAddressListInternal._addAddressToThelist +DA:58,51 +BRDA:58,2,0,1 +BRDA:58,2,1,50 +DA:59,1 +DA:59,1 +DA:61,50 +DA:61,50 +DA:62,50 +DA:62,50 +FN:71,RuleAddressListInternal._removeAddressFromThelist FNDA:2,RuleAddressListInternal._removeAddressFromThelist -DA:80,2 -DA:80,2 -BRDA:80,3,0,1 -BRDA:80,3,1,1 -DA:81,1 -DA:81,1 -DA:83,1 -DA:83,1 -DA:84,1 -DA:84,1 -FN:92,RuleAddressListInternal._numberListedAddress +DA:72,2 +DA:72,2 +BRDA:72,3,0,1 +BRDA:72,3,1,1 +DA:73,1 +DA:73,1 +DA:75,1 +DA:75,1 +DA:76,1 +DA:76,1 +FN:84,RuleAddressListInternal._numberListedAddress FNDA:24,RuleAddressListInternal._numberListedAddress -DA:93,24 -DA:93,24 -FN:102,RuleAddressListInternal._addressIsListed -FNDA:141,RuleAddressListInternal._addressIsListed -DA:105,141 -DA:105,141 +DA:85,24 +DA:85,24 +FN:94,RuleAddressListInternal._addressIsListed +FNDA:215,RuleAddressListInternal._addressIsListed +DA:97,215 +DA:97,215 FNF:6 FNH:6 LF:22 @@ -1410,19 +1541,19 @@ BRH:0 end_of_record TN: SF:test/utils/SanctionListOracle.sol -FN:15,SanctionListOracle.addToSanctionsList +FN:13,SanctionListOracle.addToSanctionsList FNDA:10,SanctionListOracle.addToSanctionsList -DA:16,10 -DA:16,10 -FN:19,SanctionListOracle.removeFromSanctionsList +DA:14,10 +DA:14,10 +FN:17,SanctionListOracle.removeFromSanctionsList FNDA:0,SanctionListOracle.removeFromSanctionsList -DA:20,0 -DA:20,0 -FN:23,SanctionListOracle.isSanctioned +DA:18,0 +DA:18,0 +FN:21,SanctionListOracle.isSanctioned FNDA:12,SanctionListOracle.isSanctioned -DA:24,12 -DA:24,12 -DA:24,12 +DA:22,12 +DA:22,12 +DA:22,12 FNF:3 FNH:2 LF:3 diff --git a/script/CMTATWithRuleEngineScript.s.sol b/script/CMTATWithRuleEngineScript.s.sol index 1bf6313..8303f01 100644 --- a/script/CMTATWithRuleEngineScript.s.sol +++ b/script/CMTATWithRuleEngineScript.s.sol @@ -7,6 +7,7 @@ import "forge-std/Script.sol"; import "CMTAT/CMTAT_STANDALONE.sol"; import "src/RuleEngine.sol"; import "src/rules/validation/RuleWhitelist.sol"; + /** @title Deploy a CMTAT, a RuleWhitelist and a RuleEngine */ @@ -41,7 +42,11 @@ contract CMTATWithRuleEngineScript is Script { ); console.log("whitelist: ", address(ruleWhitelist)); // ruleEngine - RuleEngine RULE_ENGINE = new RuleEngine(ADMIN, trustedForwarder, address(CMTAT_CONTRACT)); + RuleEngine RULE_ENGINE = new RuleEngine( + ADMIN, + trustedForwarder, + address(CMTAT_CONTRACT) + ); console.log("RuleEngine : ", address(RULE_ENGINE)); RULE_ENGINE.addRuleValidation(ruleWhitelist); CMTAT_CONTRACT.setRuleEngine(RULE_ENGINE); diff --git a/src/RuleEngine.sol b/src/RuleEngine.sol index 7b56c4b..9e8009c 100644 --- a/src/RuleEngine.sol +++ b/src/RuleEngine.sol @@ -7,124 +7,144 @@ import "./modules/MetaTxModuleStandalone.sol"; import "./modules/RuleEngineOperation.sol"; import "./modules/RuleEngineValidation.sol"; - /** -* @title Implementation of a ruleEngine as defined by the CMTAT -*/ -contract RuleEngine is IRuleEngine, RuleEngineOperation, RuleEngineValidation, MetaTxModuleStandalone { + * @title Implementation of a ruleEngine as defined by the CMTAT + */ +contract RuleEngine is + IRuleEngine, + RuleEngineOperation, + RuleEngineValidation, + MetaTxModuleStandalone +{ error RuleEngine_TransferInvalid(); + /** - * @param admin Address of the contract (Access Control) - * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - */ + * @param admin Address of the contract (Access Control) + * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + */ constructor( address admin, address forwarderIrrevocable, address tokenContract ) MetaTxModuleStandalone(forwarderIrrevocable) { - if(admin == address(0)) - { + if (admin == address(0)) { revert RuleEngine_AdminWithAddressZeroNotAllowed(); } - if(tokenContract != address(0)){ + if (tokenContract != address(0)) { _grantRole(TOKEN_CONTRACT_ROLE, tokenContract); } _grantRole(DEFAULT_ADMIN_ROLE, admin); - _grantRole(RULE_ENGINE_ROLE, admin); + _grantRole(RULE_ENGINE_OPERATOR_ROLE, admin); } - - /** - * @notice Go through all the rule to know if a restriction exists on the transfer - * @param _from the origin address - * @param _to the destination address - * @param _amount to transfer - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - **/ + /** + * @notice Go through all the rule to know if a restriction exists on the transfer + * @param _from the origin address + * @param _to the destination address + * @param _amount to transfer + * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + **/ function detectTransferRestriction( address _from, address _to, uint256 _amount ) public view override returns (uint8) { // Validation - uint8 code = RuleEngineValidation.detectTransferRestrictionValidation(_from, _to, _amount); - if(code != uint8(REJECTED_CODE_BASE.TRANSFER_OK) ){ + uint8 code = RuleEngineValidation.detectTransferRestrictionValidation( + _from, + _to, + _amount + ); + if (code != uint8(REJECTED_CODE_BASE.TRANSFER_OK)) { return code; } // Operation uint256 rulesLength = _rulesOperation.length; - for (uint256 i = 0; i < rulesLength; ++i ) { - uint8 restriction = IRuleValidation(_rulesOperation[i]).detectTransferRestriction( - _from, - _to, - _amount - ); + for (uint256 i = 0; i < rulesLength; ++i) { + uint8 restriction = IRuleValidation(_rulesOperation[i]) + .detectTransferRestriction(_from, _to, _amount); if (restriction > 0) { return restriction; } } - + return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } - /** - * @notice Validate a transfer - * @param _from the origin address - * @param _to the destination address - * @param _amount to transfer - * @return True if the transfer is valid, false otherwise - **/ + /** + * @notice Validate a transfer + * @param _from the origin address + * @param _to the destination address + * @param _amount to transfer + * @return True if the transfer is valid, false otherwise + **/ function validateTransfer( address _from, address _to, uint256 _amount ) public view override returns (bool) { - return detectTransferRestriction(_from, _to, _amount) == uint8(REJECTED_CODE_BASE.TRANSFER_OK); + return + detectTransferRestriction(_from, _to, _amount) == + uint8(REJECTED_CODE_BASE.TRANSFER_OK); } - /** - * @notice Return the message corresponding to the code - * @param _restrictionCode The target restriction code - * @return True if the transfer is valid, false otherwise - **/ + /** + * @notice Return the message corresponding to the code + * @param _restrictionCode The target restriction code + * @return True if the transfer is valid, false otherwise + **/ function messageForTransferRestriction( uint8 _restrictionCode ) external view override returns (string memory) { // Validation uint256 rulesLength = _rulesValidation.length; for (uint256 i = 0; i < rulesLength; ++i) { - if (IRuleValidation(_rulesValidation[i]).canReturnTransferRestrictionCode(_restrictionCode)) { + if ( + IRuleValidation(_rulesValidation[i]) + .canReturnTransferRestrictionCode(_restrictionCode) + ) { return - IRuleValidation(_rulesValidation[i]).messageForTransferRestriction(_restrictionCode); + IRuleValidation(_rulesValidation[i]) + .messageForTransferRestriction(_restrictionCode); } } // operation rulesLength = _rulesOperation.length; for (uint256 i = 0; i < rulesLength; ++i) { - if (IRuleValidation(_rulesOperation[i]).canReturnTransferRestrictionCode(_restrictionCode)) { + if ( + IRuleValidation(_rulesOperation[i]) + .canReturnTransferRestrictionCode(_restrictionCode) + ) { return - IRuleValidation(_rulesOperation[i]).messageForTransferRestriction(_restrictionCode); + IRuleValidation(_rulesOperation[i]) + .messageForTransferRestriction(_restrictionCode); } } return "Unknown restriction code"; } /* - * @notice function protected by access control - */ - function operateOnTransfer(address from, address to, uint256 amount) external override onlyRole(TOKEN_CONTRACT_ROLE) returns (bool isValid) { + * @notice function protected by access control + */ + function operateOnTransfer( + address from, + address to, + uint256 amount + ) external override onlyRole(TOKEN_CONTRACT_ROLE) returns (bool isValid) { // Validate the transfer - if(!RuleEngineValidation.validateTransferValidation(from, to, amount)){ - return false; + if ( + !RuleEngineValidation.validateTransferValidation(from, to, amount) + ) { + return false; } // Apply operation on RuleEngine return RuleEngineOperation._operateOnTransfer(from, to, amount); } - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - */ + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ function _msgSender() internal view @@ -134,9 +154,9 @@ contract RuleEngine is IRuleEngine, RuleEngineOperation, RuleEngineValidation, M return ERC2771Context._msgSender(); } - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - */ + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ function _msgData() internal view @@ -146,10 +166,15 @@ contract RuleEngine is IRuleEngine, RuleEngineOperation, RuleEngineValidation, M return ERC2771Context._msgData(); } - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - */ - function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ + function _contextSuffixLength() + internal + view + override(ERC2771Context, Context) + returns (uint256) + { return ERC2771Context._contextSuffixLength(); } } diff --git a/src/interfaces/IRuleEngineOperation.sol b/src/interfaces/IRuleEngineOperation.sol index d351510..7b17e2d 100644 --- a/src/interfaces/IRuleEngineOperation.sol +++ b/src/interfaces/IRuleEngineOperation.sol @@ -2,8 +2,7 @@ pragma solidity ^0.8.20; - -interface IRuleEngineOperation{ +interface IRuleEngineOperation { /** * @dev define the rules, the precedent rules will be overwritten */ @@ -23,5 +22,4 @@ interface IRuleEngineOperation{ * @dev return all the rules */ function rulesOperation() external view returns (address[] memory); - } diff --git a/src/interfaces/IRuleEngineValidation.sol b/src/interfaces/IRuleEngineValidation.sol index d88be2c..13db097 100644 --- a/src/interfaces/IRuleEngineValidation.sol +++ b/src/interfaces/IRuleEngineValidation.sol @@ -3,6 +3,27 @@ pragma solidity ^0.8.20; interface IRuleEngineValidation { + /** + * @dev See ERC-1404 + * + */ + function detectTransferRestrictionValidation( + address _from, + address _to, + uint256 _amount + ) external view returns (uint8); + + /** + * @dev Returns true if the transfer is valid, and false otherwise. + */ + function validateTransferValidation( + address _from, + address _to, + uint256 _amount + ) external view returns (bool isValid); +} + +interface IRuleEngineValidationCommon { /** * @dev define the rules, the precedent rules will be overwritten */ @@ -22,23 +43,4 @@ interface IRuleEngineValidation { * @dev return all the rules */ function rulesValidation() external view returns (address[] memory); - - /** - * @dev See ERC-1404 - * - */ - function detectTransferRestrictionValidation( - address _from, - address _to, - uint256 _amount - ) external view returns (uint8); - - /** - * @dev Returns true if the transfer is valid, and false otherwise. - */ - function validateTransferValidation( - address _from, - address _to, - uint256 _amount - ) external view returns (bool isValid); } diff --git a/src/interfaces/IRuleOperation.sol b/src/interfaces/IRuleOperation.sol index f4f3622..5874646 100644 --- a/src/interfaces/IRuleOperation.sol +++ b/src/interfaces/IRuleOperation.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.20; interface IRuleOperation { - /** * @dev Returns true if the transfer is valid, and false otherwise. */ diff --git a/src/modules/RuleEngineInvariantStorage.sol b/src/modules/RuleEngineInvariantStorage.sol index 774567e..2421e64 100644 --- a/src/modules/RuleEngineInvariantStorage.sol +++ b/src/modules/RuleEngineInvariantStorage.sol @@ -16,10 +16,11 @@ abstract contract RuleEngineInvariantStorage { /// @notice Generate when all the rules are cleared event ClearRules(address[] rulesRemoved); - /// @notice Role to manage the ruleEngine - bytes32 public constant RULE_ENGINE_ROLE = keccak256("RULE_ENGINE_ROLE"); + bytes32 public constant RULE_ENGINE_OPERATOR_ROLE = + keccak256("RULE_ENGINE_OPERATOR_ROLE"); /// @notice token contract - bytes32 public constant TOKEN_CONTRACT_ROLE = keccak256("TOKEN_CONTRACT_ROLE"); -} \ No newline at end of file + bytes32 public constant TOKEN_CONTRACT_ROLE = + keccak256("TOKEN_CONTRACT_ROLE"); +} diff --git a/src/modules/RuleEngineOperation.sol b/src/modules/RuleEngineOperation.sol index 6118b2d..b238ff4 100644 --- a/src/modules/RuleEngineOperation.sol +++ b/src/modules/RuleEngineOperation.sol @@ -6,10 +6,15 @@ import "./RuleInternal.sol"; import "../interfaces/IRuleEngineOperation.sol"; import "../interfaces/IRuleOperation.sol"; import "OZ/access/AccessControl.sol"; + /** -* @title Implementation of a ruleEngine defined by the CMTAT -*/ -abstract contract RuleEngineOperation is AccessControl, RuleInternal, IRuleEngineOperation { + * @title Implementation of a ruleEngine defined by the CMTAT + */ +abstract contract RuleEngineOperation is + AccessControl, + RuleInternal, + IRuleEngineOperation +{ /// @dev Array of rules address[] internal _rulesOperation; @@ -20,9 +25,9 @@ abstract contract RuleEngineOperation is AccessControl, RuleInternal, IRuleEngin */ function setRulesOperation( address[] calldata rules_ - ) public onlyRole(RULE_ENGINE_ROLE) { - if(_rulesOperation.length > 0){ - _clearRulesOperation(); + ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { + if (_rulesOperation.length > 0) { + _clearRulesOperation(); } _setRules(rules_); _rulesOperation = rules_; @@ -32,8 +37,8 @@ abstract contract RuleEngineOperation is AccessControl, RuleInternal, IRuleEngin * @notice Clear all the rules of the array of rules * */ - function clearRulesOperation() public onlyRole(RULE_ENGINE_ROLE) { - _clearRulesOperation(); + function clearRulesOperation() public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { + _clearRulesOperation(); } /** @@ -43,11 +48,11 @@ abstract contract RuleEngineOperation is AccessControl, RuleInternal, IRuleEngin function _clearRulesOperation() internal { uint256 index; // we remove the last element first since it is more optimized. - for(uint256 i = _rulesOperation.length; i > 0; --i){ - unchecked { + for (uint256 i = _rulesOperation.length; i > 0; --i) { + unchecked { // don't underflow since i > 0 index = i - 1; - } + } _removeRuleOperation(_rulesOperation[index], index); } emit ClearRules(_rulesOperation); @@ -58,9 +63,11 @@ abstract contract RuleEngineOperation is AccessControl, RuleInternal, IRuleEngin * Revert if one rule is a zero address or if the rule is already present * */ - function addRuleOperation(IRuleOperation rule_) public onlyRole(RULE_ENGINE_ROLE) { - RuleInternal._addRule( _rulesOperation, address(rule_)); - emit AddRule(address(rule_)); + function addRuleOperation( + IRuleOperation rule_ + ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { + RuleInternal._addRule(_rulesOperation, address(rule_)); + emit AddRule(address(rule_)); } /** @@ -76,7 +83,7 @@ abstract contract RuleEngineOperation is AccessControl, RuleInternal, IRuleEngin function removeRuleOperation( IRuleOperation rule_, uint256 index - ) public onlyRole(RULE_ENGINE_ROLE) { + ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { _removeRuleOperation(address(rule_), index); } @@ -90,69 +97,74 @@ abstract contract RuleEngineOperation is AccessControl, RuleInternal, IRuleEngin * * */ - function _removeRuleOperation( - address rule_, - uint256 index - ) internal { - RuleInternal._removeRule(_rulesOperation, rule_, index); + function _removeRuleOperation(address rule_, uint256 index) internal { + RuleInternal._removeRule(_rulesOperation, rule_, index); emit RemoveRule(address(rule_)); } /** - * @return The number of rules inside the array - */ + * @return The number of rules inside the array + */ function rulesCountOperation() external view override returns (uint256) { return _rulesOperation.length; } /** - * @notice Get the index of a rule inside the list - * @return index if the rule is found, _rulesOperation.length otherwise - */ - function getRuleIndexOperation(IRuleOperation rule_) external view returns (uint256 index) { + * @notice Get the index of a rule inside the list + * @return index if the rule is found, _rulesOperation.length otherwise + */ + function getRuleIndexOperation( + IRuleOperation rule_ + ) external view returns (uint256 index) { return RuleInternal.getRuleIndex(_rulesOperation, address(rule_)); } /** - * @notice Get the rule at the position specified by ruleId - * @param ruleId index of the rule - * @return a rule address - */ - function ruleOperation(uint256 ruleId) external view override returns (address) { + * @notice Get the rule at the position specified by ruleId + * @param ruleId index of the rule + * @return a rule address + */ + function ruleOperation( + uint256 ruleId + ) external view override returns (address) { return _rulesOperation[ruleId]; } /** - * @notice Get all the rules - * @return An array of rules - */ - function rulesOperation() external view override returns (address[] memory) { + * @notice Get all the rules + * @return An array of rules + */ + function rulesOperation() + external + view + override + returns (address[] memory) + { return _rulesOperation; } - - /** - * @notice Go through all the rule to know if a restriction exists on the transfer - * @param _from the origin address - * @param _to the destination address - * @param _amount to transfer - **/ + /** + * @notice Go through all the rule to know if a restriction exists on the transfer + * @param _from the origin address + * @param _to the destination address + * @param _amount to transfer + **/ function _operateOnTransfer( address _from, address _to, uint256 _amount - ) internal returns (bool isValid){ + ) internal returns (bool isValid) { uint256 rulesLength = _rulesOperation.length; - for (uint256 i = 0; i < rulesLength; ++i ) { + for (uint256 i = 0; i < rulesLength; ++i) { bool result = IRuleOperation(_rulesOperation[i]).operateOnTransfer( _from, _to, _amount ); - if(!result){ + if (!result) { return false; } } return true; } -} \ No newline at end of file +} diff --git a/src/modules/RuleEngineValidation.sol b/src/modules/RuleEngineValidation.sol index 6a8fe02..d049dd4 100644 --- a/src/modules/RuleEngineValidation.sol +++ b/src/modules/RuleEngineValidation.sol @@ -4,174 +4,59 @@ pragma solidity ^0.8.20; import "OZ/access/AccessControl.sol"; import "./RuleInternal.sol"; +import "./RuleEngineValidationCommon.sol"; import "../interfaces/IRuleEngineValidation.sol"; import "../interfaces/IRuleValidation.sol"; import "CMTAT/interfaces/draft-IERC1404/draft-IERC1404EnumCode.sol"; -/** -* @title Implementation of a ruleEngine defined by the CMTAT -*/ -abstract contract RuleEngineValidation is AccessControl, RuleInternal, IRuleEngineValidation, IERC1404EnumCode { - /// @dev Array of rules - address[] internal _rulesValidation; - - - /** - * @notice Set all the rules, will overwrite all the previous rules. \n - * Revert if one rule is a zero address or if the rule is already present - * @dev take address[] instead of IRuleEngineValidation[] since it is not possible to cast IRuleEngineValidation[] -> address[] - * - */ - function setRulesValidation( - address[] calldata rules_ - ) public override onlyRole(RULE_ENGINE_ROLE) { - if(_rulesValidation.length > 0){ - _clearRulesValidation(); - } - _setRules(rules_); - _rulesValidation = rules_; - } - - /** - * @notice Clear all the rules of the array of rules - * - */ - function clearRulesValidation() public onlyRole(RULE_ENGINE_ROLE) { - _clearRulesValidation(); - } - - /** - * @notice Clear all the rules of the array of rules - * - */ - function _clearRulesValidation() internal { - uint256 index; - // we remove the last element first since it is more optimized. - for(uint256 i = _rulesValidation.length; i > 0; --i){ - unchecked { - // don't underflow since i > 0 - index = i - 1; - } - _removeRuleValidation(_rulesValidation[index], index); - } - emit ClearRules(_rulesValidation); - } - - /** - * @notice Add a rule to the array of rules - * Revert if one rule is a zero address or if the rule is already present - * - */ - function addRuleValidation(IRuleValidation rule_) public onlyRole(RULE_ENGINE_ROLE) { - RuleInternal._addRule( _rulesValidation, address(rule_)); - emit AddRule(address(rule_)); - } - - /** - * @notice Remove a rule from the array of rules - * Revert if the rule found at the specified index does not match the rule in argument - * @param rule_ address of the target rule - * @param index the position inside the array of rule - * @dev To reduce the array size, the last rule is moved to the location occupied - * by the rule to remove - * - * - */ - function removeRuleValidation( - IRuleValidation rule_, - uint256 index - ) public onlyRole(RULE_ENGINE_ROLE) { - _removeRuleValidation(address(rule_), index); - } - /** - * @notice Remove a rule from the array of rules - * Revert if the rule found at the specified index does not match the rule in argument - * @param rule_ address of the target rule - * @param index the position inside the array of rule - * @dev To reduce the array size, the last rule is moved to the location occupied - * by the rule to remove - * - * - */ - function _removeRuleValidation( - address rule_, - uint256 index - ) internal { - RuleInternal._removeRule(_rulesValidation, rule_, index); - emit RemoveRule(address(rule_)); - } - - /** - * @return The number of rules inside the array - */ - function rulesCountValidation() external view override returns (uint256) { - return _rulesValidation.length; - } - - /** - * @notice Get the index of a rule inside the list - * @return index if the rule is found, _rulesValidation.length otherwise - */ - function getRuleIndexValidation(IRuleValidation rule_) external view returns (uint256 index) { - return RuleInternal.getRuleIndex(_rulesValidation, address(rule_)); - } - - /** - * @notice Get the rule at the position specified by ruleId - * @param ruleId index of the rule - * @return a rule address - */ - function ruleValidation(uint256 ruleId) external view override returns (address) { - return _rulesValidation[ruleId]; - } - - /** - * @notice Get all the rules - * @return An array of rules - */ - function rulesValidation() external view override returns (address[] memory) { - return _rulesValidation; - } - - /** - * @notice Go through all the rule to know if a restriction exists on the transfer - * @param _from the origin address - * @param _to the destination address - * @param _amount to transfer - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - **/ +/** + * @title Implementation of a ruleEngine defined by the CMTAT + */ +abstract contract RuleEngineValidation is + AccessControl, + RuleInternal, + RuleEngineValidationCommon, + IRuleEngineValidation, + IERC1404EnumCode +{ + /** + * @notice Go through all the rule to know if a restriction exists on the transfer + * @param _from the origin address + * @param _to the destination address + * @param _amount to transfer + * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + **/ function detectTransferRestrictionValidation( address _from, address _to, uint256 _amount ) public view override returns (uint8) { uint256 rulesLength = _rulesValidation.length; - for (uint256 i = 0; i < rulesLength; ++i ) { - uint8 restriction = IRuleValidation(_rulesValidation[i]).detectTransferRestriction( - _from, - _to, - _amount - ); + for (uint256 i = 0; i < rulesLength; ++i) { + uint8 restriction = IRuleValidation(_rulesValidation[i]) + .detectTransferRestriction(_from, _to, _amount); if (restriction > 0) { return restriction; } } - + return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } - /** - * @notice Validate a transfer - * @param _from the origin address - * @param _to the destination address - * @param _amount to transfer - * @return True if the transfer is valid, false otherwise - **/ + /** + * @notice Validate a transfer + * @param _from the origin address + * @param _to the destination address + * @param _amount to transfer + * @return True if the transfer is valid, false otherwise + **/ function validateTransferValidation( address _from, address _to, uint256 _amount ) public view override returns (bool) { - return detectTransferRestrictionValidation(_from, _to, _amount) == uint8(REJECTED_CODE_BASE.TRANSFER_OK); + return + detectTransferRestrictionValidation(_from, _to, _amount) == + uint8(REJECTED_CODE_BASE.TRANSFER_OK); } -} \ No newline at end of file +} diff --git a/src/modules/RuleEngineValidationCommon.sol b/src/modules/RuleEngineValidationCommon.sol new file mode 100644 index 0000000..e821a64 --- /dev/null +++ b/src/modules/RuleEngineValidationCommon.sol @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +import "OZ/access/AccessControl.sol"; +import "./RuleInternal.sol"; +import "../interfaces/IRuleEngineValidation.sol"; +import "../interfaces/IRuleValidation.sol"; + +/** + * @title Implementation of a ruleEngine defined by the CMTAT + */ +abstract contract RuleEngineValidationCommon is + AccessControl, + RuleInternal, + IRuleEngineValidationCommon +{ + /// @dev Array of rules + address[] internal _rulesValidation; + + /** + * @notice Set all the rules, will overwrite all the previous rules. \n + * Revert if one rule is a zero address or if the rule is already present + * @dev take address[] instead of IRuleEngineValidation[] since it is not possible to cast IRuleEngineValidation[] -> address[] + * + */ + function setRulesValidation( + address[] calldata rules_ + ) public override onlyRole(RULE_ENGINE_OPERATOR_ROLE) { + if (_rulesValidation.length > 0) { + _clearRulesValidation(); + } + _setRules(rules_); + _rulesValidation = rules_; + } + + /** + * @notice Clear all the rules of the array of rules + * + */ + function clearRulesValidation() public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { + _clearRulesValidation(); + } + + /** + * @notice Clear all the rules of the array of rules + * + */ + function _clearRulesValidation() internal { + uint256 index; + // we remove the last element first since it is more optimized. + for (uint256 i = _rulesValidation.length; i > 0; --i) { + unchecked { + // don't underflow since i > 0 + index = i - 1; + } + _removeRuleValidation(_rulesValidation[index], index); + } + emit ClearRules(_rulesValidation); + } + + /** + * @notice Add a rule to the array of rules + * Revert if one rule is a zero address or if the rule is already present + * + */ + function addRuleValidation( + IRuleValidation rule_ + ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { + RuleInternal._addRule(_rulesValidation, address(rule_)); + emit AddRule(address(rule_)); + } + + /** + * @notice Remove a rule from the array of rules + * Revert if the rule found at the specified index does not match the rule in argument + * @param rule_ address of the target rule + * @param index the position inside the array of rule + * @dev To reduce the array size, the last rule is moved to the location occupied + * by the rule to remove + * + * + */ + function removeRuleValidation( + IRuleValidation rule_, + uint256 index + ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) { + _removeRuleValidation(address(rule_), index); + } + + /** + * @notice Remove a rule from the array of rules + * Revert if the rule found at the specified index does not match the rule in argument + * @param rule_ address of the target rule + * @param index the position inside the array of rule + * @dev To reduce the array size, the last rule is moved to the location occupied + * by the rule to remove + * + * + */ + function _removeRuleValidation(address rule_, uint256 index) internal { + RuleInternal._removeRule(_rulesValidation, rule_, index); + emit RemoveRule(address(rule_)); + } + + /** + * @return The number of rules inside the array + */ + function rulesCountValidation() external view override returns (uint256) { + return _rulesValidation.length; + } + + /** + * @notice Get the index of a rule inside the list + * @return index if the rule is found, _rulesValidation.length otherwise + */ + function getRuleIndexValidation( + IRuleValidation rule_ + ) external view returns (uint256 index) { + return RuleInternal.getRuleIndex(_rulesValidation, address(rule_)); + } + + /** + * @notice Get the rule at the position specified by ruleId + * @param ruleId index of the rule + * @return a rule address + */ + function ruleValidation( + uint256 ruleId + ) external view override returns (address) { + return _rulesValidation[ruleId]; + } + + /** + * @notice Get all the rules + * @return An array of rules + */ + function rulesValidation() + external + view + override + returns (address[] memory) + { + return _rulesValidation; + } +} diff --git a/src/modules/RuleInternal.sol b/src/modules/RuleInternal.sol index 5ce3782..b6ce3cd 100644 --- a/src/modules/RuleInternal.sol +++ b/src/modules/RuleInternal.sol @@ -4,10 +4,9 @@ pragma solidity ^0.8.20; import "./RuleEngineInvariantStorage.sol"; /** -* @title Implementation of a ruleEngine defined by the CMTAT -*/ + * @title Implementation of a ruleEngine defined by the CMTAT + */ abstract contract RuleInternal is RuleEngineInvariantStorage { - /// @dev Indicate if a rule already exists // Can be shared betwen RuleOperation and RuleValidation since it is a mapping mapping(address => bool) _ruleIsPresent; @@ -17,17 +16,15 @@ abstract contract RuleInternal is RuleEngineInvariantStorage { * Revert if one rule is a zero address or if the rule is already present * */ - function _setRules( - address[] calldata rules_ - ) internal { - if(rules_.length == 0){ + function _setRules(address[] calldata rules_) internal { + if (rules_.length == 0) { revert RuleEngine_ArrayIsEmpty(); } for (uint256 i = 0; i < rules_.length; ) { - if( address(rules_[i]) == address(0x0)){ - revert RuleEngine_RuleAddressZeroNotAllowed(); + if (address(rules_[i]) == address(0x0)) { + revert RuleEngine_RuleAddressZeroNotAllowed(); } - if(_ruleIsPresent[rules_[i]]){ + if (_ruleIsPresent[rules_[i]]) { revert RuleEngine_RuleAlreadyExists(); } _ruleIsPresent[rules_[i]] = true; @@ -43,13 +40,11 @@ abstract contract RuleInternal is RuleEngineInvariantStorage { * Revert if one rule is a zero address or if the rule is already present * */ - function _addRule(address[] storage _rules, address rule_) internal { - if( address(rule_) == address(0x0)) - { + function _addRule(address[] storage _rules, address rule_) internal { + if (address(rule_) == address(0x0)) { revert RuleEngine_RuleAddressZeroNotAllowed(); } - if( _ruleIsPresent[rule_]) - { + if (_ruleIsPresent[rule_]) { revert RuleEngine_RuleAlreadyExists(); } _rules.push(rule_); @@ -71,8 +66,7 @@ abstract contract RuleInternal is RuleEngineInvariantStorage { address rule_, uint256 index ) internal { - if(_rules[index] != rule_) - { + if (_rules[index] != rule_) { revert RuleEngine_RuleDoNotMatch(); } if (index != _rules.length - 1) { @@ -84,12 +78,15 @@ abstract contract RuleInternal is RuleEngineInvariantStorage { } /** - * @notice Get the index of a rule inside the list - * @return index if the rule is found, _rules.length otherwise - */ - function getRuleIndex(address[] storage _rules, address rule_) internal view returns (uint256 index) { + * @notice Get the index of a rule inside the list + * @return index if the rule is found, _rules.length otherwise + */ + function getRuleIndex( + address[] storage _rules, + address rule_ + ) internal view returns (uint256 index) { uint256 rulesLength = _rules.length; - for (index = 0; index < rulesLength;) { + for (index = 0; index < rulesLength; ) { if (_rules[index] == rule_) { return index; } @@ -99,4 +96,4 @@ abstract contract RuleInternal is RuleEngineInvariantStorage { } return _rules.length; } -} \ No newline at end of file +} diff --git a/src/rules/operation/RuleConditionalTransfer.sol b/src/rules/operation/RuleConditionalTransfer.sol index 5b6b03b..431bc38 100644 --- a/src/rules/operation/RuleConditionalTransfer.sol +++ b/src/rules/operation/RuleConditionalTransfer.sol @@ -4,73 +4,75 @@ pragma solidity ^0.8.20; import "OZ/access/AccessControl.sol"; import "../../interfaces/IRuleOperation.sol"; -import "./../../modules/MetaTxModuleStandalone.sol"; +import "./../../modules/MetaTxModuleStandalone.sol"; import "./abstract/RuleConditionalTransferInvariantStorage.sol"; import "./abstract/RuleConditionalTransferOperator.sol"; import "../validation/abstract/RuleValidateTransfer.sol"; import "CMTAT/interfaces/engine/IRuleEngine.sol"; /** -* @title a whitelist manager -*/ + * @title a whitelist manager + */ -contract RuleConditionalTransfer is RuleValidateTransfer, IRuleOperation, RuleConditionalTransferOperator, MetaTxModuleStandalone { +contract RuleConditionalTransfer is + RuleValidateTransfer, + IRuleOperation, + RuleConditionalTransferOperator, + MetaTxModuleStandalone +{ /** - * @param admin Address of the contract (Access Control) - * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - */ + * @param admin Address of the contract (Access Control) + * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + */ constructor( address admin, address forwarderIrrevocable, IRuleEngine ruleEngineContract, OPTION memory options_ ) MetaTxModuleStandalone(forwarderIrrevocable) { - if(admin == address(0)){ + if (admin == address(0)) { revert RuleConditionalTransfer_AdminWithAddressZeroNotAllowed(); } _grantRole(DEFAULT_ADMIN_ROLE, admin); _grantRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, admin); - if(address(ruleEngineContract) != address(0x0)){ + if (address(ruleEngineContract) != address(0x0)) { _grantRole(RULE_ENGINE_CONTRACT_ROLE, address(ruleEngineContract)); } - if(options_.timeLimit.timeLimitToApprove == 0){ + if (options_.timeLimit.timeLimitToApprove == 0) { options_.timeLimit.timeLimitToApprove = type(uint64).max; } - if(options_.timeLimit.timeLimitToTransfer == 0){ + if (options_.timeLimit.timeLimitToTransfer == 0) { options_.timeLimit.timeLimitToTransfer = type(uint64).max; } 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 { + * @notice Create a request of transfer for yourselves + * @param to recipient of tokens + * @param value amount of tokens to transfer + */ + function createTransferRequest(address to, uint256 value) public { // WAIT => Will set a new delay to approve // APPROVED => will overwrite previous status // DENIED => reject address from = _msgSender(); bytes32 key = keccak256(abi.encode(from, to, value)); - if(transferRequests[key].status == STATUS.DENIED){ - revert RuleConditionalTransfer_TransferDenied(); + if (transferRequests[key].status == STATUS.DENIED) { + revert RuleConditionalTransfer_TransferDenied(); } - if(_checkRequestStatus(key)){ - uint256 requestIdLocal = requestId; - TransferRequest memory newTransferApproval = TransferRequest({ - key:key, + if (_checkRequestStatus(key)) { + uint256 requestIdLocal = requestId; + TransferRequest memory newTransferApproval = TransferRequest({ + key: key, id: requestIdLocal, from: from, - to:to, - value:value, + to: to, + value: value, askTime: block.timestamp, - maxTime:0, + maxTime: 0, status: STATUS.WAIT - } - ); + }); transferRequests[key] = newTransferApproval; IdToKey[requestIdLocal] = key; emit transferWaiting(key, from, to, value, requestId); @@ -79,77 +81,83 @@ contract RuleConditionalTransfer is RuleValidateTransfer, IRuleOperation, RuleC // Overwrite previous approval transferRequests[key].askTime = block.timestamp; transferRequests[key].status = STATUS.WAIT; - emit transferWaiting(key, from, to, value, transferRequests[key].id); + emit transferWaiting( + key, + from, + to, + value, + transferRequests[key].id + ); } } /** - * @notice Batch version of {createTransferRequest} - */ - function createTransferRequestBatch(address[] memory tos, uint256[] memory values) public{ - if(tos.length == 0){ + * @notice Batch version of {createTransferRequest} + */ + function createTransferRequestBatch( + address[] memory tos, + uint256[] memory values + ) public { + if (tos.length == 0) { revert RuleConditionalTransfer_EmptyArray(); } - if(tos.length != values.length){ + if (tos.length != values.length) { revert RuleConditionalTransfer_InvalidLengthArray(); } - for(uint256 i = 0; i < tos.length; ++i){ + for (uint256 i = 0; i < tos.length; ++i) { createTransferRequest(tos[i], values[i]); } } /** - * @notice allow a token holder to cancel/reset his own request - */ - function cancelTransferRequest( - uint256 requestId_ - ) public { + * @notice allow a token holder to cancel/reset his own request + */ + function cancelTransferRequest(uint256 requestId_) public { _cancelTransferRequest(requestId_); } /** - * @notice allow a token holder to cancel/reset his own request - */ - function cancelTransferRequestBatch( - uint256[] memory requestIds - ) public { - if(requestIds.length == 0){ + * @notice allow a token holder to cancel/reset his own request + */ + function cancelTransferRequestBatch(uint256[] memory requestIds) public { + if (requestIds.length == 0) { revert RuleConditionalTransfer_EmptyArray(); } // Check id validity before performing actions - for(uint256 i = 0; i < requestIds.length; ++i){ - if(requestIds[i] + 1 > requestId) { + for (uint256 i = 0; i < requestIds.length; ++i) { + if (requestIds[i] + 1 > requestId) { revert RuleConditionalTransfer_InvalidId(); } } - for(uint256 i = 0; i < requestIds.length; ++i){ + for (uint256 i = 0; i < requestIds.length; ++i) { _cancelTransferRequest(requestIds[i]); } - } - function _cancelTransferRequest( - uint256 requestId_ - ) internal { - if(requestId_ + 1 > requestId) { + function _cancelTransferRequest(uint256 requestId_) internal { + if (requestId_ + 1 > requestId) { revert RuleConditionalTransfer_InvalidId(); } bytes32 key = IdToKey[requestId_]; // Check Sender - if(transferRequests[key].from != _msgSender()){ + if (transferRequests[key].from != _msgSender()) { revert RuleConditionalTransfer_InvalidSender(); } // Check status - if(transferRequests[key].status != STATUS.WAIT - && transferRequests[key].status != STATUS.APPROVED - ){ + if ( + transferRequests[key].status != STATUS.WAIT && + transferRequests[key].status != STATUS.APPROVED + ) { revert RuleConditionalTransfer_Wrong_Status(); } _resetRequestStatus(key); } - - function getRequestTrade(address from, address to, uint256 value) public view returns (TransferRequest memory) { + function getRequestTrade( + address from, + address to, + uint256 value + ) public view returns (TransferRequest memory) { bytes32 key = keccak256(abi.encode(from, to, value)); return transferRequests[key]; } @@ -159,7 +167,9 @@ contract RuleConditionalTransfer is RuleValidateTransfer, IRuleOperation, RuleC * @param _targetStatus The status of the transactions you want to retrieve * @return array with corresponding transactions */ - function getRequestByStatus(STATUS _targetStatus) public view returns (TransferRequest[] memory) { + function getRequestByStatus( + STATUS _targetStatus + ) public view returns (TransferRequest[] memory) { uint totalRequestCount = requestId; uint requestCount = 0; uint currentIndex = 0; @@ -178,7 +188,9 @@ contract RuleConditionalTransfer is RuleValidateTransfer, IRuleOperation, RuleC for (uint i = 0; i < totalRequestCount; ++i) { if (transferRequests[IdToKey[i]].status == _targetStatus) { //uint currentId = i + 1; - TransferRequest memory currentRequest = transferRequests[IdToKey[i]]; + TransferRequest memory currentRequest = transferRequests[ + IdToKey[i] + ]; requests[currentIndex] = currentRequest; currentIndex += 1; } @@ -194,70 +206,79 @@ contract RuleConditionalTransfer is RuleValidateTransfer, IRuleOperation, RuleC address _from, address _to, uint256 _amount - ) public override onlyRole(RULE_ENGINE_CONTRACT_ROLE) returns(bool isValid){ + ) + public + override + onlyRole(RULE_ENGINE_CONTRACT_ROLE) + returns (bool isValid) + { // No need of approval if from and to are in the whitelist - if(address(whitelistConditionalTransfer) != address(0)){ - if(whitelistConditionalTransfer.addressIsListed(_from) && whitelistConditionalTransfer.addressIsListed(_to)){ + if (address(whitelistConditionalTransfer) != address(0)) { + if ( + whitelistConditionalTransfer.addressIsListed(_from) && + whitelistConditionalTransfer.addressIsListed(_to) + ) { return true; - } + } } // Mint & Burn - if(_validateBurnMint(_from, _to)) { + if (_validateBurnMint(_from, _to)) { return true; } bytes32 key = keccak256(abi.encode(_from, _to, _amount)); - if(_validateApproval(key)) { - _updateProcessedTransfer(key); - return true; + if (_validateApproval(key)) { + _updateProcessedTransfer(key); + return true; } else { - return false; + return false; } } - /** - * @notice Check if the transfer is valid - * @param _from the origin address - * @param _to the destination address - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - **/ + /** + * @notice Check if the transfer is valid + * @param _from the origin address + * @param _to the destination address + * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + **/ function detectTransferRestriction( address _from, address _to, uint256 _amount ) public view override returns (uint8) { // No need of approval if from and to are in the whitelist - if(address(whitelistConditionalTransfer) != address(0)){ - if(whitelistConditionalTransfer.addressIsListed(_from) && whitelistConditionalTransfer.addressIsListed(_to)){ + if (address(whitelistConditionalTransfer) != address(0)) { + if ( + whitelistConditionalTransfer.addressIsListed(_from) && + whitelistConditionalTransfer.addressIsListed(_to) + ) { return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - } + } } bytes32 key = keccak256(abi.encode(_from, _to, _amount)); - if (!_validateBurnMint(_from,_to) && !_validateApproval(key)) { + if (!_validateBurnMint(_from, _to) && !_validateApproval(key)) { return CODE_TRANSFER_REQUEST_NOT_APPROVED; - } - else { + } else { return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } } - /** - * @notice To know if the restriction code is valid for this rule or not. - * @param _restrictionCode The target restriction code - * @return true if the restriction code is known, false otherwise - **/ + /** + * @notice To know if the restriction code is valid for this rule or not. + * @param _restrictionCode The target restriction code + * @return true if the restriction code is known, false otherwise + **/ function canReturnTransferRestrictionCode( uint8 _restrictionCode ) external pure override returns (bool) { - return - _restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED; + return _restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED; } - /** - * @notice Return the corresponding message - * @param _restrictionCode The target restriction code - * @return true if the transfer is valid, false otherwise - **/ + /** + * @notice Return the corresponding message + * @param _restrictionCode The target restriction code + * @return true if the transfer is valid, false otherwise + **/ function messageForTransferRestriction( uint8 _restrictionCode ) external pure override returns (string memory) { @@ -269,8 +290,8 @@ contract RuleConditionalTransfer is RuleValidateTransfer, IRuleOperation, RuleC } /** - * - * @dev + * + * @dev * Test burn and mint condition * Returns true if the transfer is valid, and false otherwise. * @@ -278,40 +299,47 @@ contract RuleConditionalTransfer is RuleValidateTransfer, IRuleOperation, RuleC function _validateBurnMint( address _from, address _to - ) internal view returns(bool isValid){ + ) internal view returns (bool isValid) { // Mint & Burn - if( - (_from == address(0) && options.issuance.authorizedMintWithoutApproval) - || (_to == address(0) && options.issuance.authorizedBurnWithoutApproval) - ){ + if ( + (_from == address(0) && + options.issuance.authorizedMintWithoutApproval) || + (_to == address(0) && + options.issuance.authorizedBurnWithoutApproval) + ) { return true; } return false; } /** - * - * @dev + * + * @dev * Test transfer approval condition * Returns true if the transfer is valid, and false otherwise. */ function _validateApproval( bytes32 key - ) internal view returns(bool isValid){ - bool automaticApprovalCondition = options.automaticApproval.isActivate && ((transferRequests[key].askTime + options.automaticApproval.timeLimitBeforeAutomaticApproval ) >= block.timestamp); - bool isTransferApproved = (transferRequests[key].status == STATUS.APPROVED) - && (transferRequests[key].maxTime >= block.timestamp); - if(automaticApprovalCondition || isTransferApproved) - { + ) internal view returns (bool isValid) { + bool automaticApprovalCondition = options + .automaticApproval + .isActivate && + ((transferRequests[key].askTime + + options.automaticApproval.timeLimitBeforeAutomaticApproval) >= + block.timestamp); + bool isTransferApproved = (transferRequests[key].status == + STATUS.APPROVED) && + (transferRequests[key].maxTime >= block.timestamp); + if (automaticApprovalCondition || isTransferApproved) { return true; } else { return false; } } - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - */ + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ function _msgSender() internal view @@ -321,9 +349,9 @@ contract RuleConditionalTransfer is RuleValidateTransfer, IRuleOperation, RuleC return ERC2771Context._msgSender(); } - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - */ + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ function _msgData() internal view @@ -333,10 +361,15 @@ contract RuleConditionalTransfer is RuleValidateTransfer, IRuleOperation, RuleC return ERC2771Context._msgData(); } - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - */ - function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ + function _contextSuffixLength() + internal + view + override(ERC2771Context, Context) + returns (uint256) + { return ERC2771Context._contextSuffixLength(); } } diff --git a/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol b/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol index 04c40e2..1abcff9 100644 --- a/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol +++ b/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol @@ -5,12 +5,15 @@ import "OZ/token/ERC20/IERC20.sol"; import "../../validation/abstract/RuleCommonInvariantStorage.sol"; import "src/rules/validation/RuleWhitelist.sol"; -abstract contract RuleConditionalTransferInvariantStorage is RuleCommonInvariantStorage { + +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. - */ + * 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; @@ -33,9 +36,9 @@ abstract contract RuleConditionalTransferInvariantStorage is RuleCommonInvariant struct AUTOMATIC_APPROVAL { bool isActivate; /** - * If the transfer is not approved or denied within {timeLimitBeforeAutomaticApproval}, - * the request is considered as approved during a transfer. - */ + * If the transfer is not approved or denied within {timeLimitBeforeAutomaticApproval}, + * the request is considered as approved during a transfer. + */ uint256 timeLimitBeforeAutomaticApproval; } @@ -45,8 +48,15 @@ abstract contract RuleConditionalTransferInvariantStorage is RuleCommonInvariant AUTOMATIC_APPROVAL automaticApproval; AUTOMATIC_TRANSFER automaticTransfer; } - - enum STATUS { NONE, WAIT, APPROVED, DENIED, EXECUTED, CANCELLED } + + enum STATUS { + NONE, + WAIT, + APPROVED, + DENIED, + EXECUTED, + CANCELLED + } struct TransferRequestKeyElement { address from; @@ -65,8 +75,10 @@ abstract contract RuleConditionalTransferInvariantStorage is RuleCommonInvariant } // Role - bytes32 public constant RULE_ENGINE_CONTRACT_ROLE = keccak256("RULE_ENGINE_CONTRACT_ROLE"); - bytes32 public constant RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE = keccak256("RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE"); + bytes32 public constant RULE_ENGINE_CONTRACT_ROLE = + keccak256("RULE_ENGINE_CONTRACT_ROLE"); + bytes32 public constant RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE = + keccak256("RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE"); // String string constant TEXT_TRANSFER_REQUEST_NOT_APPROVED = @@ -75,7 +87,6 @@ abstract contract RuleConditionalTransferInvariantStorage is RuleCommonInvariant // It is very important that each rule uses an unique code uint8 public constant CODE_TRANSFER_REQUEST_NOT_APPROVED = 51; - // error error RuleConditionalTransfer_AdminWithAddressZeroNotAllowed(); error RuleConditionalTransfer_TransferAlreadyApproved(); @@ -90,11 +101,43 @@ abstract contract RuleConditionalTransferInvariantStorage is RuleCommonInvariant error RuleConditionalTransfer_EmptyArray(); // Event - event transferProcessed(bytes32 indexed key, address indexed from, address indexed to, uint256 value, uint256 id); - event transferWaiting(bytes32 indexed key, address indexed from, address indexed to, uint256 value, uint256 id); - event transferApproved(bytes32 indexed key, address indexed from, address indexed to, uint256 value, uint256 id ); - event transferDenied(bytes32 indexed key, address indexed from, address indexed to, uint256 value, uint256 id); - event transferReset(bytes32 indexed key, address indexed from, address indexed to, uint256 value, uint256 id); + event transferProcessed( + bytes32 indexed key, + address indexed from, + address indexed to, + uint256 value, + uint256 id + ); + event transferWaiting( + bytes32 indexed key, + address indexed from, + address indexed to, + uint256 value, + uint256 id + ); + event transferApproved( + bytes32 indexed key, + address indexed from, + address indexed to, + uint256 value, + uint256 id + ); + event transferDenied( + bytes32 indexed key, + address indexed from, + address indexed to, + uint256 value, + uint256 id + ); + event transferReset( + bytes32 indexed key, + address indexed from, + address indexed to, + uint256 value, + uint256 id + ); - event WhitelistConditionalTransfer(RuleWhitelist indexed whitelistConditionalTransfer); -} \ No newline at end of file + event WhitelistConditionalTransfer( + RuleWhitelist indexed whitelistConditionalTransfer + ); +} diff --git a/src/rules/operation/abstract/RuleConditionalTransferOperator.sol b/src/rules/operation/abstract/RuleConditionalTransferOperator.sol index 5a8497f..80bf67d 100644 --- a/src/rules/operation/abstract/RuleConditionalTransferOperator.sol +++ b/src/rules/operation/abstract/RuleConditionalTransferOperator.sol @@ -4,90 +4,138 @@ pragma solidity ^0.8.20; import "OZ/access/AccessControl.sol"; import "./RuleConditionalTransferInvariantStorage.sol"; -import "OZ/token/ERC20/utils/SafeERC20.sol"; +import "OZ/token/ERC20/utils/SafeERC20.sol"; + /** -* @title Restricted functions -*/ -abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditionalTransferInvariantStorage { + * @title Restricted functions + */ +abstract contract RuleConditionalTransferOperator is + AccessControl, + RuleConditionalTransferInvariantStorage +{ // Security using SafeERC20 for IERC20; - + // public variable with automatic Getter OPTION public options; uint256 public requestId; mapping(uint256 => bytes32) public IdToKey; mapping(bytes32 => TransferRequest) public transferRequests; - RuleWhitelist public whitelistConditionalTransfer; + 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){ + * @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; + function setIssuanceOptions( + ISSUANCE calldata issuance_ + ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + if ( + options.issuance.authorizedMintWithoutApproval != + issuance_.authorizedMintWithoutApproval + ) { + options.issuance.authorizedMintWithoutApproval = issuance_ + .authorizedMintWithoutApproval; } - if(options.issuance.authorizedBurnWithoutApproval != issuance_.authorizedBurnWithoutApproval ){ - options.issuance.authorizedBurnWithoutApproval = issuance_.authorizedBurnWithoutApproval; + if ( + options.issuance.authorizedBurnWithoutApproval != + issuance_.authorizedBurnWithoutApproval + ) { + options.issuance.authorizedBurnWithoutApproval = issuance_ + .authorizedBurnWithoutApproval; } } /** - * @notice set/unset the option to perform the transfer if the request is approved by the rule operator. - * To perform the transfer, the token holder has to approve the rule to spend tokens on his behalf (standard ERC-20 approval). - * If the allowance is not sufficient, the request will be approved, but without performing the transfer. - */ - function setAutomaticTransfer(AUTOMATIC_TRANSFER calldata automaticTransfer_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - if(automaticTransfer_.isActivate != options.automaticTransfer.isActivate){ - options.automaticTransfer.isActivate = automaticTransfer_.isActivate; - } - // No need to put the cmtat to zero to deactivate automaticTransfer - if(address(automaticTransfer_.cmtat) != address(options.automaticTransfer.cmtat)){ + * @notice set/unset the option to perform the transfer if the request is approved by the rule operator. + * To perform the transfer, the token holder has to approve the rule to spend tokens on his behalf (standard ERC-20 approval). + * If the allowance is not sufficient, the request will be approved, but without performing the transfer. + */ + function setAutomaticTransfer( + AUTOMATIC_TRANSFER calldata automaticTransfer_ + ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + if ( + automaticTransfer_.isActivate != + options.automaticTransfer.isActivate + ) { + options.automaticTransfer.isActivate = automaticTransfer_ + .isActivate; + } + // No need to put the cmtat to zero to deactivate automaticTransfer + if ( + address(automaticTransfer_.cmtat) != + address(options.automaticTransfer.cmtat) + ) { options.automaticTransfer.cmtat = automaticTransfer_.cmtat; - } + } } /** - * @notice set time limit for new requests (Approval and transfer) - * timeLimitToApprove: time limit for an operator to approve a request - * timeLimitToTransfer: once a request is approved, time limit for the token holder to perform the transfer - */ - function setTimeLimit(TIME_LIMIT memory timeLimit_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - if(options.timeLimit.timeLimitToApprove != timeLimit_.timeLimitToApprove){ - options.timeLimit.timeLimitToApprove = timeLimit_.timeLimitToApprove; + * @notice set time limit for new requests (Approval and transfer) + * timeLimitToApprove: time limit for an operator to approve a request + * timeLimitToTransfer: once a request is approved, time limit for the token holder to perform the transfer + */ + function setTimeLimit( + TIME_LIMIT memory timeLimit_ + ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + if ( + options.timeLimit.timeLimitToApprove != + timeLimit_.timeLimitToApprove + ) { + options.timeLimit.timeLimitToApprove = timeLimit_ + .timeLimitToApprove; } - if(options.timeLimit.timeLimitToTransfer != timeLimit_.timeLimitToTransfer){ - options.timeLimit.timeLimitToTransfer = timeLimit_.timeLimitToTransfer; + if ( + options.timeLimit.timeLimitToTransfer != + timeLimit_.timeLimitToTransfer + ) { + options.timeLimit.timeLimitToTransfer = timeLimit_ + .timeLimitToTransfer; } } + /** - * @notice If the transfer is not approved or denied within {timeLimitBeforeAutomaticApproval}, - * the request is considered as approved during a transfer. - * - */ - function setAutomaticApproval(AUTOMATIC_APPROVAL memory automaticApproval_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - if(options.automaticApproval.isActivate != automaticApproval_.isActivate ){ - options.automaticApproval.isActivate = automaticApproval_.isActivate; + * @notice If the transfer is not approved or denied within {timeLimitBeforeAutomaticApproval}, + * the request is considered as approved during a transfer. + * + */ + function setAutomaticApproval( + AUTOMATIC_APPROVAL memory automaticApproval_ + ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + if ( + options.automaticApproval.isActivate != + automaticApproval_.isActivate + ) { + options.automaticApproval.isActivate = automaticApproval_ + .isActivate; } - if(options.automaticApproval.timeLimitBeforeAutomaticApproval != automaticApproval_.timeLimitBeforeAutomaticApproval){ - options.automaticApproval.timeLimitBeforeAutomaticApproval = automaticApproval_.timeLimitBeforeAutomaticApproval; + if ( + options.automaticApproval.timeLimitBeforeAutomaticApproval != + automaticApproval_.timeLimitBeforeAutomaticApproval + ) { + options + .automaticApproval + .timeLimitBeforeAutomaticApproval = automaticApproval_ + .timeLimitBeforeAutomaticApproval; } } /** - * @notice create a transfer request directly approved - */ + * @notice create a transfer request directly approved + */ function createTransferRequestWithApproval( TransferRequestKeyElement calldata keyElement - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - _createTransferRequestWithApproval(keyElement); + ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + _createTransferRequestWithApproval(keyElement); } /** @@ -97,31 +145,36 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio @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); } /** - * @notice approve a transferRequestby using its id - */ + * @notice approve a transferRequestby using its id + */ function approveTransferRequestWithId( - uint256 requestId_, bool isApproved - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - if(requestId_ + 1 > requestId) { + uint256 requestId_, + bool isApproved + ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + if (requestId_ + 1 > requestId) { revert RuleConditionalTransfer_InvalidId(); } - TransferRequest memory transferRequest = transferRequests[IdToKey[requestId_]]; + TransferRequest memory transferRequest = transferRequests[ + IdToKey[requestId_] + ]; _approveRequest(transferRequest, isApproved); - } + } /** - * @notice reset to None the status of a request - */ + * @notice reset to None the status of a request + */ function resetRequestStatus( uint256 requestId_ - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - if(requestId_ + 1 > requestId) { + ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + if (requestId_ + 1 > requestId) { revert RuleConditionalTransfer_InvalidId(); } bytes32 key = IdToKey[requestId_]; @@ -130,185 +183,267 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio /***** Batch function */ /** - * @notice Batch version of {approveTransferRequestWithId} - */ + * @notice Batch version of {approveTransferRequestWithId} + */ function approveTransferRequestBatchWithId( - uint256[] calldata requestId_, bool[] calldata isApproved - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - if(requestId_.length == 0){ + 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 - for(uint256 i = 0; i < requestId_.length; ++i){ - if(requestId_[i] + 1 > requestId) { + for (uint256 i = 0; i < requestId_.length; ++i) { + if (requestId_[i] + 1 > requestId) { revert RuleConditionalTransfer_InvalidId(); } } - for(uint256 i = 0; i < requestId_.length; ++i){ - TransferRequest memory transferRequest = transferRequests[IdToKey[requestId_[i]]]; + for (uint256 i = 0; i < requestId_.length; ++i) { + TransferRequest memory transferRequest = transferRequests[ + IdToKey[requestId_[i]] + ]; _approveRequest(transferRequest, isApproved[i]); } } /** - * @notice Batch version of {approveTransferRequest} - */ + * @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){ + 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]); + for (uint256 i = 0; i < keyElements.length; ++i) { + _approveTransferRequestKeyElement( + keyElements[i], + partialValues[i], + isApproved[i] + ); } } /** - * @notice Batch version of {createTransferRequestWithApproval} - */ + * @notice Batch version of {createTransferRequestWithApproval} + */ function createTransferRequestWithApprovalBatch( - TransferRequestKeyElement[] calldata keyElements - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - if(keyElements.length == 0){ + TransferRequestKeyElement[] calldata keyElements + ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + if (keyElements.length == 0) { revert RuleConditionalTransfer_EmptyArray(); } - for(uint256 i = 0; i < keyElements.length; ++i){ + for (uint256 i = 0; i < keyElements.length; ++i) { _createTransferRequestWithApproval(keyElements[i]); } } /** - * @notice Batch version of {resetRequestStatus} - */ + * @notice Batch version of {resetRequestStatus} + */ function resetRequestStatusBatch( uint256[] memory requestIds - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ - if(requestIds.length == 0){ + ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { + if (requestIds.length == 0) { revert RuleConditionalTransfer_EmptyArray(); } // Check id validity before performing actions - for(uint256 i = 0; i < requestIds.length; ++i){ - if(requestIds[i] + 1 > requestId) { + for (uint256 i = 0; i < requestIds.length; ++i) { + if (requestIds[i] + 1 > requestId) { revert RuleConditionalTransfer_InvalidId(); } } - for(uint256 i = 0; i < requestIds.length; ++i){ + for (uint256 i = 0; i < requestIds.length; ++i) { bytes32 key = IdToKey[requestIds[i]]; _resetRequestStatus(key); } } - /*** Internal functions ****/ function _approveTransferRequestKeyElement( - TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved + TransferRequestKeyElement calldata keyElement, + uint256 partialValue, + bool isApproved ) internal { - if(partialValue > keyElement.value){ + if (partialValue > keyElement.value) { revert RuleConditionalTransfer_InvalidValueApproved(); } - bytes32 key = keccak256(abi.encode(keyElement.from, keyElement.to, keyElement.value)); + bytes32 key = keccak256( + abi.encode(keyElement.from, keyElement.to, keyElement.value) + ); TransferRequest memory transferRequest = transferRequests[key]; - if(partialValue > 0 ){ - if(! isApproved){ + if (partialValue > 0) { + if (!isApproved) { revert RuleConditionalTransfer_CannotDeniedPartially(); } // Denied the first request _approveRequest(transferRequest, false); // Create new request - _createTransferRequestWithApproval(TransferRequestKeyElement({from: keyElement.from, to: keyElement.to, value: partialValue})); - }else{ + _createTransferRequestWithApproval( + TransferRequestKeyElement({ + from: keyElement.from, + to: keyElement.to, + value: partialValue + }) + ); + } else { _approveRequest(transferRequest, isApproved); } } function _createTransferRequestWithApproval( TransferRequestKeyElement memory keyElement - ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){ + ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) { // WAIT => Will overwrite // APPROVED => will overwrite previous status with a new delay // DENIED => will overwrite - bytes32 key = keccak256(abi.encode(keyElement.from, keyElement.to, keyElement.value)); - if(_checkRequestStatus(key)){ - TransferRequest memory newTransferApproval = TransferRequest({ + bytes32 key = keccak256( + abi.encode(keyElement.from, keyElement.to, keyElement.value) + ); + if (_checkRequestStatus(key)) { + TransferRequest memory newTransferApproval = TransferRequest({ key: key, id: requestId, from: keyElement.from, to: keyElement.to, value: keyElement.value, - askTime:0, - maxTime : block.timestamp + options.timeLimit.timeLimitToTransfer, - status:STATUS.APPROVED - }); + askTime: 0, + maxTime: block.timestamp + + options.timeLimit.timeLimitToTransfer, + status: STATUS.APPROVED + }); transferRequests[key] = newTransferApproval; IdToKey[requestId] = key; - emit transferApproved(key, keyElement.from, keyElement.to, keyElement.value, requestId); + emit transferApproved( + key, + keyElement.from, + keyElement.to, + keyElement.value, + requestId + ); ++requestId; } else { // Overwrite previous approval - transferRequests[key].maxTime = block.timestamp + options.timeLimit.timeLimitToTransfer; + transferRequests[key].maxTime = + block.timestamp + + options.timeLimit.timeLimitToTransfer; transferRequests[key].status = STATUS.APPROVED; - emit transferApproved(key, keyElement.from, keyElement.to, keyElement.value, transferRequests[key].id); + emit transferApproved( + key, + keyElement.from, + keyElement.to, + keyElement.value, + transferRequests[key].id + ); } } - function _resetRequestStatus( - bytes32 key - ) internal { + function _resetRequestStatus(bytes32 key) internal { transferRequests[key].status = STATUS.NONE; - emit transferReset(key, transferRequests[key].from, transferRequests[key].to, transferRequests[key].value, transferRequests[key].id ); + emit transferReset( + key, + transferRequests[key].from, + transferRequests[key].to, + transferRequests[key].value, + transferRequests[key].id + ); } - function _checkRequestStatus(bytes32 key) internal view returns(bool) { + 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); + 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){ + if (transferRequest.status != STATUS.WAIT) { revert RuleConditionalTransfer_Wrong_Status(); } - if(isApproved){ + if (isApproved) { // Time - if(block.timestamp > (transferRequest.askTime + options.timeLimit.timeLimitToApprove)){ + if ( + block.timestamp > + (transferRequest.askTime + options.timeLimit.timeLimitToApprove) + ) { revert RuleConditionalTransfer_timeExceeded(); } // Set status transferRequests[transferRequest.key].status = STATUS.APPROVED; // Set max time - transferRequests[transferRequest.key].maxTime = block.timestamp + options.timeLimit.timeLimitToTransfer; - emit transferApproved(transferRequest.key, transferRequest.from, transferRequest.to, transferRequest.value, transferRequests[transferRequest.key].id ); - if(options.automaticTransfer.isActivate && address(options.automaticTransfer.cmtat) != address(0)){ + transferRequests[transferRequest.key].maxTime = + block.timestamp + + options.timeLimit.timeLimitToTransfer; + emit transferApproved( + transferRequest.key, + transferRequest.from, + transferRequest.to, + transferRequest.value, + transferRequests[transferRequest.key].id + ); + if ( + options.automaticTransfer.isActivate && + address(options.automaticTransfer.cmtat) != address(0) + ) { // Transfer with approval // External call - if(options.automaticTransfer.cmtat.allowance(transferRequest.from, address(this)) >= transferRequest.value){ - // Will call the ruleEngine and the rule again... - options.automaticTransfer.cmtat.safeTransferFrom(transferRequest.from, transferRequest.to, transferRequest.value); - } + if ( + options.automaticTransfer.cmtat.allowance( + transferRequest.from, + address(this) + ) >= transferRequest.value + ) { + // Will call the ruleEngine and the rule again... + options.automaticTransfer.cmtat.safeTransferFrom( + transferRequest.from, + transferRequest.to, + transferRequest.value + ); + } } } else { transferRequests[transferRequest.key].status = STATUS.DENIED; - emit transferDenied(transferRequest.key, transferRequest.from, transferRequest.to, transferRequest.value, transferRequests[transferRequest.key].id ); + emit transferDenied( + transferRequest.key, + transferRequest.from, + transferRequest.to, + transferRequest.value, + transferRequests[transferRequest.key].id + ); } } /** - * @notice update the request during a transfer - */ + * @notice update the request during a transfer + */ function _updateProcessedTransfer(bytes32 key) internal { - // Reset to zero - transferRequests[key].maxTime = 0; - transferRequests[key].askTime = 0; - // Change status - transferRequests[key].status = STATUS.EXECUTED; - // Emit event - emit transferProcessed(key, transferRequests[key].from, transferRequests[key].to, transferRequests[key].value, transferRequests[key].id); + // Reset to zero + transferRequests[key].maxTime = 0; + transferRequests[key].askTime = 0; + // Change status + transferRequests[key].status = STATUS.EXECUTED; + // Emit event + emit transferProcessed( + key, + transferRequests[key].from, + transferRequests[key].to, + transferRequests[key].value, + transferRequests[key].id + ); } } diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol index 78b5c53..2ac9028 100644 --- a/src/rules/validation/RuleBlacklist.sol +++ b/src/rules/validation/RuleBlacklist.sol @@ -2,30 +2,34 @@ pragma solidity ^0.8.20; -import "./abstract/RuleAddressList/RuleBlacklistInvariantStorage.sol"; +import "./abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol"; import "./abstract/RuleAddressList/RuleAddressList.sol"; import "./abstract/RuleValidateTransfer.sol"; + /** -* @title a blacklist manager -*/ + * @title a blacklist manager + */ -contract RuleBlacklist is RuleValidateTransfer, RuleAddressList, RuleBlacklistInvariantStorage { +contract RuleBlacklist is + RuleValidateTransfer, + RuleAddressList, + RuleBlacklistInvariantStorage +{ /** - * @param admin Address of the contract (Access Control) - * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - */ + * @param admin Address of the contract (Access Control) + * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + */ constructor( address admin, address forwarderIrrevocable - ) RuleAddressList(admin, forwarderIrrevocable) { - } + ) RuleAddressList(admin, forwarderIrrevocable) {} - /** - * @notice Check if an addres is in the whitelist or not - * @param _from the origin address - * @param _to the destination address - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - **/ + /** + * @notice Check if an addres is in the whitelist or not + * @param _from the origin address + * @param _to the destination address + * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + **/ function detectTransferRestriction( address _from, address _to, @@ -40,11 +44,11 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressList, RuleBlacklistIn } } - /** - * @notice To know if the restriction code is valid for this rule or not. - * @param _restrictionCode The target restriction code - * @return true if the restriction code is known, false otherwise - **/ + /** + * @notice To know if the restriction code is valid for this rule or not. + * @param _restrictionCode The target restriction code + * @return true if the restriction code is known, false otherwise + **/ function canReturnTransferRestrictionCode( uint8 _restrictionCode ) external pure override returns (bool) { @@ -53,11 +57,11 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressList, RuleBlacklistIn _restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED; } - /** - * @notice Return the corresponding message - * @param _restrictionCode The target restriction code - * @return true if the transfer is valid, false otherwise - **/ + /** + * @notice Return the corresponding message + * @param _restrictionCode The target restriction code + * @return true if the transfer is valid, false otherwise + **/ function messageForTransferRestriction( uint8 _restrictionCode ) external pure override returns (string memory) { diff --git a/src/rules/validation/RuleSanctionList.sol b/src/rules/validation/RuleSanctionList.sol index b66434a..7c45113 100644 --- a/src/rules/validation/RuleSanctionList.sol +++ b/src/rules/validation/RuleSanctionList.sol @@ -6,22 +6,28 @@ import "OZ/access/AccessControl.sol"; import "../../modules/MetaTxModuleStandalone.sol"; import "./abstract/RuleSanctionListInvariantStorage.sol"; import "./abstract/RuleValidateTransfer.sol"; + interface SanctionsList { function isSanctioned(address addr) external view returns (bool); } -contract RuleSanctionList is AccessControl, MetaTxModuleStandalone, RuleValidateTransfer, RuleSanctionlistInvariantStorage { - SanctionsList public sanctionsList; +contract RuleSanctionList is + AccessControl, + MetaTxModuleStandalone, + RuleValidateTransfer, + RuleSanctionlistInvariantStorage +{ + SanctionsList public sanctionsList; /** - * @param admin Address of the contract (Access Control) - * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - */ + * @param admin Address of the contract (Access Control) + * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + */ constructor( address admin, address forwarderIrrevocable ) MetaTxModuleStandalone(forwarderIrrevocable) { - if(admin == address(0)){ + if (admin == address(0)) { revert RuleSanctionList_AdminWithAddressZeroNotAllowed(); } _grantRole(DEFAULT_ADMIN_ROLE, admin); @@ -34,50 +40,50 @@ contract RuleSanctionList is AccessControl, MetaTxModuleStandalone, RuleValidat * @dev zero address is authorized to authorize all transfers */ function setSanctionListOracle( - address sanctionContractOracle_ + address sanctionContractOracle_ ) public onlyRole(SANCTIONLIST_ROLE) { sanctionsList = SanctionsList(sanctionContractOracle_); } - /** - * @notice Check if an addres is in the whitelist or not - * @param _from the origin address - * @param _to the destination address - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - **/ + /** + * @notice Check if an addres is in the whitelist or not + * @param _from the origin address + * @param _to the destination address + * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + **/ function detectTransferRestriction( address _from, address _to, uint256 /*_amount */ ) public view override returns (uint8) { - if(address(sanctionsList) != address(0)){ + if (address(sanctionsList) != address(0)) { if (sanctionsList.isSanctioned(_from)) { return CODE_ADDRESS_FROM_IS_SANCTIONED; } else if (sanctionsList.isSanctioned(_to)) { - return CODE_ADDRESS_TO_IS_SANCTIONED; + return CODE_ADDRESS_TO_IS_SANCTIONED; } } return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } - /** - * @notice To know if the restriction code is valid for this rule or not. - * @param _restrictionCode The target restriction code - * @return true if the restriction code is known, false otherwise - **/ + /** + * @notice To know if the restriction code is valid for this rule or not. + * @param _restrictionCode The target restriction code + * @return true if the restriction code is known, false otherwise + **/ function canReturnTransferRestrictionCode( uint8 _restrictionCode ) external pure override returns (bool) { return - _restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED || + _restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED || _restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED; } - /** - * @notice Return the corresponding message - * @param _restrictionCode The target restriction code - * @return true if the transfer is valid, false otherwise - **/ + /** + * @notice Return the corresponding message + * @param _restrictionCode The target restriction code + * @return true if the transfer is valid, false otherwise + **/ function messageForTransferRestriction( uint8 _restrictionCode ) external pure override returns (string memory) { @@ -90,9 +96,9 @@ contract RuleSanctionList is AccessControl, MetaTxModuleStandalone, RuleValidat } } - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - */ + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ function _msgSender() internal view @@ -102,9 +108,9 @@ contract RuleSanctionList is AccessControl, MetaTxModuleStandalone, RuleValidat return ERC2771Context._msgSender(); } - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - */ + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ function _msgData() internal view @@ -114,10 +120,15 @@ contract RuleSanctionList is AccessControl, MetaTxModuleStandalone, RuleValidat return ERC2771Context._msgData(); } - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - */ - function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ + function _contextSuffixLength() + internal + view + override(ERC2771Context, Context) + returns (uint256) + { return ERC2771Context._contextSuffixLength(); } -} \ No newline at end of file +} diff --git a/src/rules/validation/RuleWhitelist.sol b/src/rules/validation/RuleWhitelist.sol index db73956..eac668b 100644 --- a/src/rules/validation/RuleWhitelist.sol +++ b/src/rules/validation/RuleWhitelist.sol @@ -2,30 +2,34 @@ pragma solidity ^0.8.20; -import "./abstract/RuleAddressList/RuleWhitelistInvariantStorage.sol"; +import "./abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol"; import "./abstract/RuleAddressList/RuleAddressList.sol"; import "./abstract/RuleValidateTransfer.sol"; + /** -* @title a whitelist manager -*/ + * @title a whitelist manager + */ -contract RuleWhitelist is RuleValidateTransfer, RuleAddressList, RuleWhitelistInvariantStorage { +contract RuleWhitelist is + RuleValidateTransfer, + RuleAddressList, + RuleWhitelistInvariantStorage +{ /** - * @param admin Address of the contract (Access Control) - * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - */ + * @param admin Address of the contract (Access Control) + * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + */ constructor( address admin, address forwarderIrrevocable - ) RuleAddressList(admin, forwarderIrrevocable) { - } + ) RuleAddressList(admin, forwarderIrrevocable) {} - /** - * @notice Check if an addres is in the whitelist or not - * @param _from the origin address - * @param _to the destination address - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - **/ + /** + * @notice Check if an addres is in the whitelist or not + * @param _from the origin address + * @param _to the destination address + * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + **/ function detectTransferRestriction( address _from, address _to, @@ -33,18 +37,18 @@ contract RuleWhitelist is RuleValidateTransfer, RuleAddressList, RuleWhitelistIn ) public view override returns (uint8) { if (!addressIsListed(_from)) { return CODE_ADDRESS_FROM_NOT_WHITELISTED; - } else if (! addressIsListed(_to)) { + } else if (!addressIsListed(_to)) { return CODE_ADDRESS_TO_NOT_WHITELISTED; } else { return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } } - /** - * @notice To know if the restriction code is valid for this rule or not - * @param _restrictionCode The target restriction code - * @return true if the restriction code is known, false otherwise - **/ + /** + * @notice To know if the restriction code is valid for this rule or not + * @param _restrictionCode The target restriction code + * @return true if the restriction code is known, false otherwise + **/ function canReturnTransferRestrictionCode( uint8 _restrictionCode ) external pure override returns (bool) { @@ -53,11 +57,11 @@ contract RuleWhitelist is RuleValidateTransfer, RuleAddressList, RuleWhitelistIn _restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED; } - /** - * @notice Return the corresponding message - * @param _restrictionCode The target restriction code - * @return true if the transfer is valid, false otherwise - **/ + /** + * @notice Return the corresponding message + * @param _restrictionCode The target restriction code + * @return true if the transfer is valid, false otherwise + **/ function messageForTransferRestriction( uint8 _restrictionCode ) external pure override returns (string memory) { diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol new file mode 100644 index 0000000..7038bac --- /dev/null +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +import "OZ/access/AccessControl.sol"; +import "../../modules/RuleEngineValidationCommon.sol"; +import "../../modules/MetaTxModuleStandalone.sol"; +import "./abstract/RuleValidateTransfer.sol"; +import "./abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol"; +import "./abstract/RuleAddressList/RuleAddressList.sol"; + +/** + * @title Wrapper to call several different whitelist rules + */ +contract RuleWhitelistWrapper is + RuleEngineValidationCommon, + MetaTxModuleStandalone, + RuleValidateTransfer, + RuleWhitelistInvariantStorage +{ + /** + * @param admin Address of the contract (Access Control) + * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + */ + constructor( + address admin, + address forwarderIrrevocable + ) MetaTxModuleStandalone(forwarderIrrevocable) { + if (admin == address(0)) { + revert RuleEngine_AdminWithAddressZeroNotAllowed(); + } + _grantRole(DEFAULT_ADMIN_ROLE, admin); + _grantRole(RULE_ENGINE_OPERATOR_ROLE, admin); + } + + /** + * @notice Go through all the whitelist rules to know if a restriction exists on the transfer + * @param _from the origin address + * @param _to the destination address + * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + **/ + function detectTransferRestriction( + address _from, + address _to, + uint256 /*_amount*/ + ) public view override returns (uint8) { + address[] memory targetAddress = new address[](2); + bool[] memory isListed = new bool[](2); + bool[] memory result = new bool[](2); + targetAddress[0] = _from; + targetAddress[1] = _to; + uint256 rulesLength = _rulesValidation.length; + // For each whitelist rule, we ask if from or to are in the whitelist + for (uint256 i = 0; i < rulesLength; ++i) { + // External call + isListed = RuleAddressList(_rulesValidation[i]) + .addressIsListedBatch(targetAddress); + if (isListed[0] && !result[0]) { + // Update if from is in the list + result[0] = true; + } + if (isListed[1] && !result[1]) { + // Update if to is in the list + result[1] = true; + } + } + if (!result[0]) { + return CODE_ADDRESS_FROM_NOT_WHITELISTED; + } else if (!result[1]) { + return CODE_ADDRESS_TO_NOT_WHITELISTED; + } else { + return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + } + + /** + * @notice To know if the restriction code is valid for this rule or not + * @param _restrictionCode The target restriction code + * @return true if the restriction code is known, false otherwise + **/ + function canReturnTransferRestrictionCode( + uint8 _restrictionCode + ) external pure override returns (bool) { + return + _restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED || + _restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED; + } + + /** + * @notice Return the corresponding message + * @param _restrictionCode The target restriction code + * @return true if the transfer is valid, false otherwise + **/ + function messageForTransferRestriction( + uint8 _restrictionCode + ) external pure override returns (string memory) { + if (_restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) { + return TEXT_ADDRESS_FROM_NOT_WHITELISTED; + } else if (_restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) { + return TEXT_ADDRESS_TO_NOT_WHITELISTED; + } else { + return TEXT_CODE_NOT_FOUND; + } + } + + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ + function _msgSender() + internal + view + override(ERC2771Context, Context) + returns (address sender) + { + return ERC2771Context._msgSender(); + } + + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ + function _msgData() + internal + view + override(ERC2771Context, Context) + returns (bytes calldata) + { + return ERC2771Context._msgData(); + } + + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ + function _contextSuffixLength() + internal + view + override(ERC2771Context, Context) + returns (uint256) + { + return ERC2771Context._contextSuffixLength(); + } +} diff --git a/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol b/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol index 7827916..0caddc0 100644 --- a/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol +++ b/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol @@ -5,26 +5,30 @@ pragma solidity ^0.8.20; import "OZ/access/AccessControl.sol"; import "./../../../../modules/MetaTxModuleStandalone.sol"; import "./RuleAddressListInternal.sol"; -import "./RuleAddressListInvariantStorage.sol"; +import "./invariantStorage/RuleAddressListInvariantStorage.sol"; + /** @title an addresses list manager */ -abstract contract RuleAddressList is AccessControl, MetaTxModuleStandalone, RuleAddressListInternal, RuleAddressListInvariantStorage { - - +abstract contract RuleAddressList is + AccessControl, + MetaTxModuleStandalone, + RuleAddressListInternal, + RuleAddressListInvariantStorage +{ // Number of addresses in the whitelist at the moment uint256 private numAddressesWhitelisted; - + /** - * @param admin Address of the contract (Access Control) - * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - */ + * @param admin Address of the contract (Access Control) + * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + */ constructor( address admin, address forwarderIrrevocable ) MetaTxModuleStandalone(forwarderIrrevocable) { - if(admin == address(0)){ + if (admin == address(0)) { revert RuleAddressList_AdminWithAddressZeroNotAllowed(); } _grantRole(DEFAULT_ADMIN_ROLE, admin); @@ -39,12 +43,12 @@ abstract contract RuleAddressList is AccessControl, MetaTxModuleStandalone, Rule function addAddressesToTheList( address[] calldata listWhitelistedAddress ) public onlyRole(ADDRESS_LIST_ROLE) { - _addAddressesToThelist(listWhitelistedAddress); + _addAddressesToThelist(listWhitelistedAddress); } /** * @notice Remove addresses from the whitelist - * If the address does not exist in the whitelist, there is no change for this address. + * If the address does not exist in the whitelist, there is no change for this address. * The transaction remains valid (no revert). * @param listWhitelistedAddress an array with the addresses to remove */ @@ -74,7 +78,7 @@ abstract contract RuleAddressList is AccessControl, MetaTxModuleStandalone, Rule function removeAddressFromTheList( address _removeWhitelistAddress ) public onlyRole(ADDRESS_LIST_ROLE) { - _removeAddressFromThelist( _removeWhitelistAddress); + _removeAddressFromThelist(_removeWhitelistAddress); } /** @@ -86,7 +90,6 @@ abstract contract RuleAddressList is AccessControl, MetaTxModuleStandalone, Rule return _numberListedAddress(); } - /** * @notice Know if an address is listed or not * @param _targetAddress The concerned address @@ -99,10 +102,23 @@ abstract contract RuleAddressList is AccessControl, MetaTxModuleStandalone, Rule return _addressIsListed(_targetAddress); } + /** + * @notice batch version of {addressIsListed} + * + */ + function addressIsListedBatch( + address[] memory _targetAddresses + ) public view returns (bool[] memory) { + bool[] memory isListed = new bool[](_targetAddresses.length); + for (uint256 i = 0; i < _targetAddresses.length; ++i) { + isListed[i] = _addressIsListed(_targetAddresses[i]); + } + return isListed; + } - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - */ + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ function _msgSender() internal view @@ -112,9 +128,9 @@ abstract contract RuleAddressList is AccessControl, MetaTxModuleStandalone, Rule return ERC2771Context._msgSender(); } - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - */ + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ function _msgData() internal view @@ -124,10 +140,15 @@ abstract contract RuleAddressList is AccessControl, MetaTxModuleStandalone, Rule return ERC2771Context._msgData(); } - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - */ - function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ + function _contextSuffixLength() + internal + view + override(ERC2771Context, Context) + returns (uint256) + { return ERC2771Context._contextSuffixLength(); } } diff --git a/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol b/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol index bbeac04..862618c 100644 --- a/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol +++ b/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol @@ -3,28 +3,25 @@ pragma solidity ^0.8.20; /** -* @title a list manager -*/ + * @title a list manager + */ abstract contract RuleAddressListInternal { error Rulelist_AddressAlreadylisted(); error Rulelist_AddressNotPresent(); - + mapping(address => bool) private list; // Number of addresses in the list at the moment uint256 private numAddressesList; - /** * @notice Add addresses to the list * If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert). * @param listAddresses an array with the addresses to list */ - function _addAddressesToThelist( - address[] calldata listAddresses - ) internal { + function _addAddressesToThelist(address[] calldata listAddresses) internal { uint256 numAddressesListLocal = numAddressesList; - for (uint256 i = 0; i < listAddresses.length; ++i ) { + for (uint256 i = 0; i < listAddresses.length; ++i) { if (!list[listAddresses[i]]) { list[listAddresses[i]] = true; ++numAddressesListLocal; @@ -35,7 +32,7 @@ abstract contract RuleAddressListInternal { /** * @notice Remove addresses from the list - * If the address does not exist in the list, there is no change for this address. + * If the address does not exist in the list, there is no change for this address. * The transaction remains valid (no revert). * @param listAddresses an array with the addresses to remove */ @@ -43,7 +40,7 @@ abstract contract RuleAddressListInternal { address[] calldata listAddresses ) internal { uint256 numAddressesListLocal = numAddressesList; - for (uint256 i = 0; i < listAddresses.length; ++i ) { + for (uint256 i = 0; i < listAddresses.length; ++i) { if (list[listAddresses[i]]) { list[listAddresses[i]] = false; --numAddressesListLocal; @@ -57,11 +54,8 @@ abstract contract RuleAddressListInternal { * If the address already exists, the transaction is reverted to save gas. * @param _newlistAddress The address to list */ - function _addAddressToThelist( - address _newlistAddress - ) internal { - if(list[_newlistAddress]) - { + function _addAddressToThelist(address _newlistAddress) internal { + if (list[_newlistAddress]) { revert Rulelist_AddressAlreadylisted(); } list[_newlistAddress] = true; @@ -74,10 +68,8 @@ abstract contract RuleAddressListInternal { * @param _removelistAddress The address to remove * */ - function _removeAddressFromThelist( - address _removelistAddress - ) internal { - if(!list[_removelistAddress]){ + function _removeAddressFromThelist(address _removelistAddress) internal { + if (!list[_removelistAddress]) { revert Rulelist_AddressNotPresent(); } list[_removelistAddress] = false; diff --git a/src/rules/validation/abstract/RuleAddressList/RuleAddressListInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol similarity index 80% rename from src/rules/validation/abstract/RuleAddressList/RuleAddressListInvariantStorage.sol rename to src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol index 7c39001..6f7ba17 100644 --- a/src/rules/validation/abstract/RuleAddressList/RuleAddressListInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol @@ -2,10 +2,10 @@ pragma solidity ^0.8.20; -abstract contract RuleAddressListInvariantStorage{ +abstract contract RuleAddressListInvariantStorage { // custom errors error RuleAddressList_AdminWithAddressZeroNotAllowed(); - + // Role bytes32 public constant ADDRESS_LIST_ROLE = keccak256("ADDRESS_LIST_ROLE"); -} \ No newline at end of file +} diff --git a/src/rules/validation/abstract/RuleAddressList/RuleBlacklistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol similarity index 92% rename from src/rules/validation/abstract/RuleAddressList/RuleBlacklistInvariantStorage.sol rename to src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol index c363cf8..4543254 100644 --- a/src/rules/validation/abstract/RuleAddressList/RuleBlacklistInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol @@ -2,9 +2,9 @@ pragma solidity ^0.8.20; -import "../RuleCommonInvariantStorage.sol"; -abstract contract RuleBlacklistInvariantStorage is RuleCommonInvariantStorage { +import "../../RuleCommonInvariantStorage.sol"; +abstract contract RuleBlacklistInvariantStorage is RuleCommonInvariantStorage { // String string constant TEXT_ADDRESS_FROM_IS_BLACKLISTED = "The sender is not in the whitelist"; @@ -15,4 +15,4 @@ abstract contract RuleBlacklistInvariantStorage is RuleCommonInvariantStorage { // It is very important that each rule uses an unique code uint8 public constant CODE_ADDRESS_FROM_IS_BLACKLISTED = 41; uint8 public constant CODE_ADDRESS_TO_IS_BLACKLISTED = 42; -} \ No newline at end of file +} diff --git a/src/rules/validation/abstract/RuleAddressList/RuleWhitelistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol similarity index 92% rename from src/rules/validation/abstract/RuleAddressList/RuleWhitelistInvariantStorage.sol rename to src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol index 85b90bf..fd5848b 100644 --- a/src/rules/validation/abstract/RuleAddressList/RuleWhitelistInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol @@ -2,9 +2,9 @@ pragma solidity ^0.8.20; -import "../RuleCommonInvariantStorage.sol"; -abstract contract RuleWhitelistInvariantStorage is RuleCommonInvariantStorage { +import "../../RuleCommonInvariantStorage.sol"; +abstract contract RuleWhitelistInvariantStorage is RuleCommonInvariantStorage { // String string constant TEXT_ADDRESS_FROM_NOT_WHITELISTED = "The sender is not in the whitelist"; @@ -15,4 +15,4 @@ abstract contract RuleWhitelistInvariantStorage is RuleCommonInvariantStorage { // It is very important that each rule uses an unique code uint8 public constant CODE_ADDRESS_FROM_NOT_WHITELISTED = 21; uint8 public constant CODE_ADDRESS_TO_NOT_WHITELISTED = 22; -} \ No newline at end of file +} diff --git a/src/rules/validation/abstract/RuleCommonInvariantStorage.sol b/src/rules/validation/abstract/RuleCommonInvariantStorage.sol index f34ae39..855e72f 100644 --- a/src/rules/validation/abstract/RuleCommonInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleCommonInvariantStorage.sol @@ -4,4 +4,4 @@ pragma solidity ^0.8.20; abstract contract RuleCommonInvariantStorage { // Text string constant TEXT_CODE_NOT_FOUND = "Unknown restriction code"; -} \ No newline at end of file +} diff --git a/src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol b/src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol index 36a1fc9..f496498 100644 --- a/src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol @@ -3,23 +3,25 @@ pragma solidity ^0.8.20; import "./RuleCommonInvariantStorage.sol"; -abstract contract RuleSanctionlistInvariantStorage is RuleCommonInvariantStorage { + +abstract contract RuleSanctionlistInvariantStorage is + RuleCommonInvariantStorage +{ // custom errors error RuleSanctionList_AdminWithAddressZeroNotAllowed(); error RuleSanctionList_AddressAlreadyWhitelisted(); - + // Role bytes32 public constant SANCTIONLIST_ROLE = keccak256("SANCTIONLIST_ROLE"); - + // Text string constant TEXT_ADDRESS_FROM_IS_SANCTIONED = "The sender is sanctioned"; string constant TEXT_ADDRESS_TO_IS_SANCTIONED = "The recipient is sanctioned"; - // Code // It is very important that each rule uses an unique code uint8 public constant CODE_ADDRESS_FROM_IS_SANCTIONED = 31; uint8 public constant CODE_ADDRESS_TO_IS_SANCTIONED = 32; -} \ No newline at end of file +} diff --git a/src/rules/validation/abstract/RuleValidateTransfer.sol b/src/rules/validation/abstract/RuleValidateTransfer.sol index b1cf14f..b6844b2 100644 --- a/src/rules/validation/abstract/RuleValidateTransfer.sol +++ b/src/rules/validation/abstract/RuleValidateTransfer.sol @@ -4,14 +4,14 @@ pragma solidity ^0.8.20; import "../../../interfaces/IRuleValidation.sol"; -abstract contract RuleValidateTransfer is IRuleValidation{ - /** - * @notice Validate a transfer - * @param _from the origin address - * @param _to the destination address - * @param _amount to transfer - * @return isValid => true if the transfer is valid, false otherwise - **/ +abstract contract RuleValidateTransfer is IRuleValidation { + /** + * @notice Validate a transfer + * @param _from the origin address + * @param _to the destination address + * @param _amount to transfer + * @return isValid => true if the transfer is valid, false otherwise + **/ function validateTransfer( address _from, address _to, diff --git a/test/HelperContract.sol b/test/HelperContract.sol index f8a351c..6027ad7 100644 --- a/test/HelperContract.sol +++ b/test/HelperContract.sol @@ -14,18 +14,27 @@ import "src/rules/validation/RuleSanctionList.sol"; import "src/rules/validation/RuleBlacklist.sol"; // RuleWhitelist import "src/rules/validation/RuleWhitelist.sol"; -import "src/rules/validation/abstract/RuleAddressList/RuleWhitelistInvariantStorage.sol"; -import "src/rules/validation/abstract/RuleAddressList/RuleAddressListInvariantStorage.sol"; +import "src/rules/validation/RuleWhitelistWrapper.sol"; +import "src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol"; +import "src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol"; import "src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol"; import "src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol"; // Rule interface import "src/interfaces/IRuleValidation.sol"; import "src/interfaces/IRuleOperation.sol"; + /** -* @title Constants used by the tests -*/ -abstract contract HelperContract is RuleWhitelistInvariantStorage, RuleBlacklistInvariantStorage, RuleAddressListInvariantStorage, RuleSanctionlistInvariantStorage, RuleEngineInvariantStorage, RuleConditionalTransferInvariantStorage { + * @title Constants used by the tests + */ +abstract contract HelperContract is + RuleWhitelistInvariantStorage, + RuleBlacklistInvariantStorage, + RuleAddressListInvariantStorage, + RuleSanctionlistInvariantStorage, + RuleEngineInvariantStorage, + RuleConditionalTransferInvariantStorage +{ // EOA to perform tests address constant ZERO_ADDRESS = address(0); address constant DEFAULT_ADMIN_ADDRESS = address(1); @@ -44,8 +53,8 @@ abstract contract HelperContract is RuleWhitelistInvariantStorage, RuleBlacklist "0xdc72ed553f2544c34465af23b847953efeb813428162d767f9ba5f4013be6760"; string constant DEFAULT_ADMIN_ROLE_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000"; - - uint256 DEFAULT_TIME_LIMIT_TO_APPROVE = 7 days; + + uint256 DEFAULT_TIME_LIMIT_TO_APPROVE = 7 days; uint256 DEFAULT_TIME_LIMIT_TO_TRANSFER = 7 days; // contract RuleBlacklist ruleBlacklist; @@ -58,9 +67,10 @@ abstract contract HelperContract is RuleWhitelistInvariantStorage, RuleBlacklist uint8 constant NO_ERROR = 0; // Forwarder - string ERC2771ForwarderDomain = 'ERC2771ForwarderDomain'; + string ERC2771ForwarderDomain = "ERC2771ForwarderDomain"; error Rulelist_AddressAlreadylisted(); error Rulelist_AddressNotPresent(); + constructor() {} } diff --git a/test/RuleBlacklist/CMTATIntegration.t.sol b/test/RuleBlacklist/CMTATIntegration.t.sol index de366f5..f8c387d 100644 --- a/test/RuleBlacklist/CMTATIntegration.t.sol +++ b/test/RuleBlacklist/CMTATIntegration.t.sol @@ -7,8 +7,8 @@ import "../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title Integration test with the CMTAT -*/ + * @title Integration test with the CMTAT + */ contract CMTATIntegration is Test, HelperContract { // Defined in CMTAT.sol uint8 constant TRANSFER_OK = 0; @@ -47,7 +47,11 @@ contract CMTATIntegration is Test, HelperContract { // specific arrange vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock = new RuleEngine(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, address(CMTAT_CONTRACT)); + ruleEngineMock = new RuleEngine( + DEFAULT_ADMIN_ADDRESS, + ZERO_ADDRESS, + address(CMTAT_CONTRACT) + ); vm.prank(DEFAULT_ADMIN_ADDRESS); ruleEngineMock.addRuleValidation(ruleBlacklist); vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -80,7 +84,13 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( - abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount)); + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + amount + ) + ); // Act CMTAT_CONTRACT.transfer(ADDRESS2, amount); } @@ -93,7 +103,13 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( - abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount)); + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + amount + ) + ); // Act CMTAT_CONTRACT.transfer(ADDRESS2, amount); } @@ -112,12 +128,17 @@ contract CMTATIntegration is Test, HelperContract { ) ); require(success); - // Act vm.prank(ADDRESS1); vm.expectRevert( - abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount)); + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + amount + ) + ); CMTAT_CONTRACT.transfer(ADDRESS2, amount); } @@ -238,7 +259,13 @@ contract CMTATIntegration is Test, HelperContract { // Act vm.expectRevert( - abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ZERO_ADDRESS, ADDRESS1, amount)); + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ZERO_ADDRESS, + ADDRESS1, + amount + ) + ); vm.prank(DEFAULT_ADMIN_ADDRESS); CMTAT_CONTRACT.mint(ADDRESS1, amount); } diff --git a/test/RuleBlacklist/RuleBlacklist.t.sol b/test/RuleBlacklist/RuleBlacklist.t.sol index f4dbbed..2e73349 100644 --- a/test/RuleBlacklist/RuleBlacklist.t.sol +++ b/test/RuleBlacklist/RuleBlacklist.t.sol @@ -7,8 +7,8 @@ import "../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title Integration test with the CMTAT -*/ + * @title Integration test with the CMTAT + */ contract RuleBlacklistTest is Test, HelperContract { // Defined in CMTAT.sol uint8 constant TRANSFER_OK = 0; @@ -23,7 +23,10 @@ contract RuleBlacklistTest is Test, HelperContract { ruleBlacklist = new RuleBlacklist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); } - function testCanRuleBlacklistReturnMessageNotFoundWithUnknownCodeId() public view { + function testCanRuleBlacklistReturnMessageNotFoundWithUnknownCodeId() + public + view + { // Act string memory message1 = ruleBlacklist.messageForTransferRestriction( 255 diff --git a/test/RuleConditionalTransfer/CMTATIntegration.t.sol b/test/RuleConditionalTransfer/CMTATIntegration.t.sol index 5b6f002..67221e0 100644 --- a/test/RuleConditionalTransfer/CMTATIntegration.t.sol +++ b/test/RuleConditionalTransfer/CMTATIntegration.t.sol @@ -7,8 +7,8 @@ import "../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title Integration test with the CMTAT -*/ + * @title Integration test with the CMTAT + */ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { // Defined in CMTAT.sol uint8 constant TRANSFER_OK = 0; @@ -25,15 +25,15 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { uint256 FLAG = 5; uint256 defaultValue = 10; - bytes32 defaultKey = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); + bytes32 defaultKey = + keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); - TransferRequestKeyElement transferRequestInput = TransferRequestKeyElement({ + TransferRequestKeyElement transferRequestInput = + TransferRequestKeyElement({ from: ADDRESS1, to: ADDRESS2, - value:defaultValue - }); - - + value: defaultValue + }); // Arrange function setUp() public { @@ -42,8 +42,8 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { timeLimitToTransfer: 30 days }); ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval:true, - authorizedBurnWithoutApproval:true + authorizedMintWithoutApproval: true, + authorizedBurnWithoutApproval: true }); AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ @@ -52,16 +52,16 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { }); AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate:false, + isActivate: false, cmtat: IERC20(address(0)) }); OPTION memory options = OPTION({ - issuance:issuanceOption_, + issuance: issuanceOption_, timeLimit: timeLimit_, automaticApproval: automaticApproval_, - automaticTransfer:automaticTransfer_ + automaticTransfer: automaticTransfer_ }); - + // global arrange uint8 decimals = 0; vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -79,22 +79,28 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { FLAG ); - // RuleEngine vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock = new RuleEngine(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, address(CMTAT_CONTRACT)); + ruleEngineMock = new RuleEngine( + DEFAULT_ADMIN_ADDRESS, + ZERO_ADDRESS, + address(CMTAT_CONTRACT) + ); // RuleConditionalTransfer vm.prank(DEFAULT_ADMIN_ADDRESS); ruleConditionalTransfer = new RuleConditionalTransfer( DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, - ruleEngineMock, + ruleEngineMock, options ); - // specific arrange + // specific arrange vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer.grantRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + ruleConditionalTransfer.grantRole( + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS + ); // RuleEngine vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -108,12 +114,12 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { 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{ + function _createTransferRequest() internal { vm.prank(ADDRESS1); // Act vm.expectEmit(true, true, true, true); @@ -126,7 +132,13 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { // Arrange vm.prank(ADDRESS1); vm.expectRevert( - abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21)); + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + 21 + ) + ); // Act CMTAT_CONTRACT.transfer(ADDRESS2, 21); } @@ -135,49 +147,56 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { // Arrange vm.prank(ADDRESS1); // Act - bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2,defaultValue)); - ruleConditionalTransfer.createTransferRequest(ADDRESS2,defaultValue); - + 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); + 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); + CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); // Assert resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); - assertEq(resUint256, ADDRESS1_BALANCE_INIT -defaultValue); + assertEq(resUint256, ADDRESS1_BALANCE_INIT - defaultValue); resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS2); - assertEq(resUint256, ADDRESS2_BALANCE_INIT +defaultValue); + 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)); + 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); + 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); + CMTAT_CONTRACT.transfer(ADDRESS2, partialValue); // Assert resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); @@ -192,58 +211,81 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { // Arrange _createTransferRequest(); uint256 partialValue = 5; - bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2,partialValue)); + 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); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + partialValue, + true + ); // Act vm.expectRevert( - abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, defaultValue)); + 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); - + 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); + 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.expectRevert( + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + defaultValue + ) + ); vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2,defaultValue); + 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); + 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); + CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); } function testCanSetTimeLimitWithTransferExceeded() public { @@ -257,8 +299,11 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { // Arrange _createTransferRequest(); vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0,true); - + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + true + ); // Assert // Timeout @@ -266,10 +311,15 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { vm.warp(block.timestamp + 1 days + 1 seconds); vm.expectRevert( - abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2,defaultValue)); + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + defaultValue + ) + ); vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2,defaultValue); - + CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); } function testCanMintWithoutApproval() public { @@ -285,7 +335,7 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { function testCanBurnWithoutApproval() public { // Act vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.burn(ADDRESS1,defaultValue, "test"); + CMTAT_CONTRACT.burn(ADDRESS1, defaultValue, "test"); // Assert resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); @@ -294,54 +344,70 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { function testCannotMintWithoutApproval() public { ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval:false, - authorizedBurnWithoutApproval:true + 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)); + 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 + 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"); + 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, + 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); + 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); + emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + true + ); } function testCanTransferIfAutomaticApprovalSetAndTimeExceeds() public { @@ -351,35 +417,42 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { }); 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); + emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); + CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); } - function testCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds() public { + 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); + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + defaultValue + ) + ); + CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); } } diff --git a/test/RuleConditionalTransfer/CMTATIntegrationWhitelist.t .sol b/test/RuleConditionalTransfer/CMTATIntegrationWhitelist.t .sol index 64f5664..e0ff4e8 100644 --- a/test/RuleConditionalTransfer/CMTATIntegrationWhitelist.t .sol +++ b/test/RuleConditionalTransfer/CMTATIntegrationWhitelist.t .sol @@ -7,8 +7,8 @@ import "../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title Integration test with the CMTAT -*/ + * @title Integration test with the CMTAT + */ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { // Defined in CMTAT.sol uint8 constant TRANSFER_OK = 0; @@ -25,15 +25,15 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { uint256 FLAG = 5; uint256 defaultValue = 10; - bytes32 defaultKey = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); + bytes32 defaultKey = + keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); - TransferRequestKeyElement transferRequestInput = TransferRequestKeyElement({ + TransferRequestKeyElement transferRequestInput = + TransferRequestKeyElement({ from: ADDRESS1, to: ADDRESS2, - value:defaultValue - }); - - + value: defaultValue + }); // Arrange function setUp() public { @@ -42,8 +42,8 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { timeLimitToTransfer: 30 days }); ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval:true, - authorizedBurnWithoutApproval:true + authorizedMintWithoutApproval: true, + authorizedBurnWithoutApproval: true }); AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ @@ -52,16 +52,16 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { }); AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate:false, + isActivate: false, cmtat: IERC20(address(0)) }); OPTION memory options = OPTION({ - issuance:issuanceOption_, + issuance: issuanceOption_, timeLimit: timeLimit_, automaticApproval: automaticApproval_, - automaticTransfer:automaticTransfer_ + automaticTransfer: automaticTransfer_ }); - + // global arrange uint8 decimals = 0; vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -79,28 +79,34 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { 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)); + 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, + ruleEngineMock, options ); // Add whitelist vm.prank(DEFAULT_ADMIN_ADDRESS); ruleConditionalTransfer.setConditionalWhitelist(ruleWhitelist); - // specific arrange + // specific arrange vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer.grantRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + ruleConditionalTransfer.grantRole( + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS + ); // RuleEngine vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -114,12 +120,12 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { 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{ + function _createTransferRequest() internal { vm.prank(ADDRESS1); // Act vm.expectEmit(true, true, true, true); @@ -128,7 +134,9 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { } /******* Transfer *******/ - function testCanMakeATransferWithoutApprovalIfFromAndToAreInTheWhitelist() public { + function testCanMakeATransferWithoutApprovalIfFromAndToAreInTheWhitelist() + public + { vm.prank(DEFAULT_ADMIN_ADDRESS); ruleWhitelist.addAddressToTheList(ADDRESS1); vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -139,30 +147,49 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { CMTAT_CONTRACT.transfer(ADDRESS2, 21); } - function testCannotMakeATransferWithoutApprovalIfOnlyFromIsInTheWhitelist() public { + function testCannotMakeATransferWithoutApprovalIfOnlyFromIsInTheWhitelist() + public + { vm.prank(DEFAULT_ADMIN_ADDRESS); ruleWhitelist.addAddressToTheList(ADDRESS1); // Arrange // Act vm.expectRevert( - abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21)); + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + 21 + ) + ); vm.prank(ADDRESS1); CMTAT_CONTRACT.transfer(ADDRESS2, 21); } - function testCannotMakeATransferWithoutApprovalIfOnlyToIsInTheWhitelist() public { + function testCannotMakeATransferWithoutApprovalIfOnlyToIsInTheWhitelist() + public + { vm.prank(DEFAULT_ADMIN_ADDRESS); ruleWhitelist.addAddressToTheList(ADDRESS2); // Arrange // Act vm.expectRevert( - abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21)); + 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); + RuleWhitelist ruleWhitelist2 = new RuleWhitelist( + DEFAULT_ADMIN_ADDRESS, + ZERO_ADDRESS + ); vm.prank(DEFAULT_ADMIN_ADDRESS); vm.expectEmit(true, false, false, false); emit WhitelistConditionalTransfer(ruleWhitelist2); @@ -180,7 +207,10 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { function testCanUnSetWhitelist() public { // Arrange - RuleWhitelist ruleWhitelist2 = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); + RuleWhitelist ruleWhitelist2 = new RuleWhitelist( + DEFAULT_ADMIN_ADDRESS, + ZERO_ADDRESS + ); vm.prank(DEFAULT_ADMIN_ADDRESS); vm.expectEmit(true, false, false, false); emit WhitelistConditionalTransfer(ruleWhitelist2); @@ -192,12 +222,20 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { // Act vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer.setConditionalWhitelist(RuleWhitelist(ZERO_ADDRESS)); + ruleConditionalTransfer.setConditionalWhitelist( + RuleWhitelist(ZERO_ADDRESS) + ); // Assert vm.prank(ADDRESS1); vm.expectRevert( - abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21)); + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + 21 + ) + ); CMTAT_CONTRACT.transfer(ADDRESS2, 21); } @@ -207,7 +245,7 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { ruleWhitelist.addAddressToTheList(ADDRESS1); vm.prank(DEFAULT_ADMIN_ADDRESS); ruleWhitelist.addAddressToTheList(ADDRESS2); - + // Act uint8 resUint8 = ruleConditionalTransfer.detectTransferRestriction( ADDRESS1, @@ -219,11 +257,13 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { assertEq(resUint8, 0); } - function testCanDetectTransferRestrictionWithOnlyFromInTheWhitelist() public { + function testCanDetectTransferRestrictionWithOnlyFromInTheWhitelist() + public + { // Arrange vm.prank(DEFAULT_ADMIN_ADDRESS); ruleWhitelist.addAddressToTheList(ADDRESS1); - + // Act uint8 resUint8 = ruleConditionalTransfer.detectTransferRestriction( ADDRESS1, @@ -239,7 +279,7 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { // Arrange vm.prank(DEFAULT_ADMIN_ADDRESS); ruleWhitelist.addAddressToTheList(ADDRESS2); - + // Act uint8 resUint8 = ruleConditionalTransfer.detectTransferRestriction( ADDRESS1, @@ -251,15 +291,19 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { 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)); + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + 21 + ) + ); // Act CMTAT_CONTRACT.transfer(ADDRESS2, 21); } @@ -268,49 +312,56 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { // Arrange vm.prank(ADDRESS1); // Act - bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2,defaultValue)); - ruleConditionalTransfer.createTransferRequest(ADDRESS2,defaultValue); - + 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); + 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); + CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); // Assert resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); - assertEq(resUint256, ADDRESS1_BALANCE_INIT -defaultValue); + assertEq(resUint256, ADDRESS1_BALANCE_INIT - defaultValue); resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS2); - assertEq(resUint256, ADDRESS2_BALANCE_INIT +defaultValue); + 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)); + 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); + 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); + CMTAT_CONTRACT.transfer(ADDRESS2, partialValue); // Assert resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); @@ -325,58 +376,81 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { // Arrange _createTransferRequest(); uint256 partialValue = 5; - bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2,partialValue)); + 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); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + partialValue, + true + ); // Act vm.expectRevert( - abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, defaultValue)); + 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); - + 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); + 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.expectRevert( + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + defaultValue + ) + ); vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2,defaultValue); + 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); + 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); + CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); } function testCanSetTimeLimitWithTransferExceeded() public { @@ -390,8 +464,11 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { // Arrange _createTransferRequest(); vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0,true); - + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + true + ); // Assert // Timeout @@ -399,10 +476,15 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { vm.warp(block.timestamp + 1 days + 1 seconds); vm.expectRevert( - abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2,defaultValue)); + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + defaultValue + ) + ); vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2,defaultValue); - + CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); } function testCanMintWithoutApproval() public { @@ -418,7 +500,7 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { function testCanBurnWithoutApproval() public { // Act vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.burn(ADDRESS1,defaultValue, "test"); + CMTAT_CONTRACT.burn(ADDRESS1, defaultValue, "test"); // Assert resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); @@ -427,54 +509,70 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { function testCannotMintWithoutApproval() public { ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval:false, - authorizedBurnWithoutApproval:true + 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)); + 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 + 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"); + 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, + 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); + 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); + emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + true + ); } function testCanTransferIfAutomaticApprovalSetAndTimeExceeds() public { @@ -484,35 +582,42 @@ contract CMTATIntegrationConditionalTransfer is Test, HelperContract { }); 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); + emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); + CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); } - function testCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds() public { + 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); + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + defaultValue + ) + ); + CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); } } diff --git a/test/RuleConditionalTransfer/RuleConditionalTransfer.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransfer.t.sol index 789a04f..3dcac3e 100644 --- a/test/RuleConditionalTransfer/RuleConditionalTransfer.t.sol +++ b/test/RuleConditionalTransfer/RuleConditionalTransfer.t.sol @@ -6,8 +6,8 @@ import "../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title General functions of the RuleWhitelist -*/ + * @title General functions of the RuleWhitelist + */ contract RuleConditionalTransferTest is Test, HelperContract { RuleEngine ruleEngineMock; uint256 resUint256; @@ -17,8 +17,8 @@ contract RuleConditionalTransferTest is Test, HelperContract { string resString; uint8 CODE_NONEXISTENT = 255; uint256 defaultValue = 10; - bytes32 defaultKey = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); - + bytes32 defaultKey = + keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); // Batch test uint256 value2 = 1; @@ -30,33 +30,38 @@ contract RuleConditionalTransferTest is Test, HelperContract { bytes32 key4 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value4)); bytes32 key5 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value5)); - TransferRequestKeyElement transferRequestInput2 = TransferRequestKeyElement({ + TransferRequestKeyElement transferRequestInput2 = + TransferRequestKeyElement({ from: ADDRESS1, to: ADDRESS2, - value:value2 - }); + value: value2 + }); - TransferRequestKeyElement transferRequestInput3 = TransferRequestKeyElement({ + TransferRequestKeyElement transferRequestInput3 = + TransferRequestKeyElement({ from: ADDRESS2, to: ADDRESS1, - value:value3 - }); + value: value3 + }); - TransferRequestKeyElement transferRequestInput4 = TransferRequestKeyElement({ + TransferRequestKeyElement transferRequestInput4 = + TransferRequestKeyElement({ from: ADDRESS1, to: ADDRESS2, - value:value4 - }); - TransferRequestKeyElement transferRequestInput5 = TransferRequestKeyElement({ + value: value4 + }); + TransferRequestKeyElement transferRequestInput5 = + TransferRequestKeyElement({ from: ADDRESS1, to: ADDRESS2, - value:value5 - }); - TransferRequestKeyElement transferRequestInput = TransferRequestKeyElement({ + value: value5 + }); + TransferRequestKeyElement transferRequestInput = + TransferRequestKeyElement({ from: ADDRESS1, to: ADDRESS2, - value:defaultValue - }); + value: defaultValue + }); // Arrange function setUp() public { @@ -64,26 +69,26 @@ contract RuleConditionalTransferTest is Test, HelperContract { timeLimitToApprove: 7 days, timeLimitToTransfer: 30 days }); - - AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ + + AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ isActivate: false, timeLimitBeforeAutomaticApproval: 0 }); ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval:false, - authorizedBurnWithoutApproval:false + authorizedMintWithoutApproval: false, + authorizedBurnWithoutApproval: false }); AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate:false, + isActivate: false, cmtat: IERC20(address(0)) }); OPTION memory options = OPTION({ - issuance:issuanceOption_, + issuance: issuanceOption_, timeLimit: timeLimit_, automaticApproval: automaticApproval_, - automaticTransfer:automaticTransfer_ + automaticTransfer: automaticTransfer_ }); ruleEngineMock = new RuleEngine( RULE_ENGINE_OPERATOR_ADDRESS, @@ -94,14 +99,17 @@ contract RuleConditionalTransferTest is Test, HelperContract { ruleConditionalTransfer = new RuleConditionalTransfer( DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, - ruleEngineMock, + ruleEngineMock, options ); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer.grantRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + ruleConditionalTransfer.grantRole( + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS + ); } - function _createTransferRequest() internal{ + function _createTransferRequest() internal { vm.prank(ADDRESS1); // Act vm.expectEmit(true, true, true, true); @@ -109,7 +117,8 @@ contract RuleConditionalTransferTest is Test, HelperContract { ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); + TransferRequest memory transferRequest = ruleConditionalTransfer + .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); assertEq(transferRequest.key, defaultKey); assertEq(transferRequest.id, 0); assertEq(transferRequest.from, ADDRESS1); @@ -117,13 +126,14 @@ contract RuleConditionalTransferTest is Test, HelperContract { assertEq(transferRequest.value, defaultValue); assertEq(uint256(transferRequest.status), uint256(STATUS.WAIT)); - TransferRequest[] memory transferRequests = ruleConditionalTransfer.getRequestByStatus(STATUS.WAIT); - assertEq(transferRequests[0].key , defaultKey); - assertEq(transferRequests.length , 1); + TransferRequest[] memory transferRequests = ruleConditionalTransfer + .getRequestByStatus(STATUS.WAIT); + assertEq(transferRequests[0].key, defaultKey); + assertEq(transferRequests.length, 1); } - function _createTransferRequestBatch() public{ - // Arrange + function _createTransferRequestBatch() public { + // Arrange _createTransferRequest(); // Second and third request @@ -139,8 +149,9 @@ contract RuleConditionalTransferTest is Test, HelperContract { ruleConditionalTransfer.createTransferRequest(ADDRESS2, value5); } - function _checkRequestPartial() internal view{ - TransferRequest memory transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); + function _checkRequestPartial() internal view { + TransferRequest memory transferRequest = ruleConditionalTransfer + .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); assertEq(transferRequest.key, defaultKey); assertEq(transferRequest.id, 0); assertEq(transferRequest.from, ADDRESS1); @@ -149,7 +160,11 @@ contract RuleConditionalTransferTest is Test, HelperContract { assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED)); // 2 - transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, value2); + transferRequest = ruleConditionalTransfer.getRequestTrade( + ADDRESS1, + ADDRESS2, + value2 + ); assertEq(transferRequest.key, key2); assertEq(transferRequest.id, 1); assertEq(transferRequest.from, ADDRESS1); @@ -158,7 +173,11 @@ contract RuleConditionalTransferTest is Test, HelperContract { assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED)); // 3 - transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS2, ADDRESS1, value3); + transferRequest = ruleConditionalTransfer.getRequestTrade( + ADDRESS2, + ADDRESS1, + value3 + ); assertEq(transferRequest.key, key3); assertEq(transferRequest.id, 2); assertEq(transferRequest.from, ADDRESS2); @@ -167,7 +186,11 @@ contract RuleConditionalTransferTest is Test, HelperContract { assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED)); // 4 - transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, value4); + transferRequest = ruleConditionalTransfer.getRequestTrade( + ADDRESS1, + ADDRESS2, + value4 + ); assertEq(transferRequest.key, key4); assertEq(transferRequest.id, 3); assertEq(transferRequest.from, ADDRESS1); @@ -176,12 +199,12 @@ contract RuleConditionalTransferTest is Test, HelperContract { assertEq(uint256(transferRequest.status), uint256(STATUS.DENIED)); } - function _checkRequestBatch() internal view { _checkRequestPartial(); - + // 5 - TransferRequest memory transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, value5); + TransferRequest memory transferRequest = ruleConditionalTransfer + .getRequestTrade(ADDRESS1, ADDRESS2, value5); assertEq(transferRequest.key, key5); assertEq(transferRequest.id, 4); assertEq(transferRequest.from, ADDRESS1); @@ -195,24 +218,29 @@ contract RuleConditionalTransferTest is Test, HelperContract { } /** - * @dev test first - */ + * @dev test first + */ function testCanCreateTransferRequestWithApproval() public { vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); // Act vm.expectEmit(true, true, true, true); emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequestWithApproval(transferRequestInput); + ruleConditionalTransfer.createTransferRequestWithApproval( + transferRequestInput + ); } function testCanCreateTransferRequestWithApprovalBatch() public { // Arrange - TransferRequestKeyElement[] memory transferRequestKeyElements = new TransferRequestKeyElement[](4); + TransferRequestKeyElement[] + memory transferRequestKeyElements = new TransferRequestKeyElement[]( + 4 + ); transferRequestKeyElements[0] = transferRequestInput; transferRequestKeyElements[1] = transferRequestInput2; transferRequestKeyElements[2] = transferRequestInput3; transferRequestKeyElements[3] = transferRequestInput4; - + // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectEmit(true, true, true, true); @@ -223,22 +251,30 @@ contract RuleConditionalTransferTest is Test, HelperContract { emit transferApproved(key3, ADDRESS2, ADDRESS1, value3, 2); vm.expectEmit(true, true, true, true); emit transferApproved(key4, ADDRESS1, ADDRESS2, value4, 3); - ruleConditionalTransfer.createTransferRequestWithApprovalBatch(transferRequestKeyElements); + ruleConditionalTransfer.createTransferRequestWithApprovalBatch( + transferRequestKeyElements + ); } - function testCanCreateTransferRequestWithApprovalBatchWithEmptyArray() public { + function testCanCreateTransferRequestWithApprovalBatchWithEmptyArray() + public + { // Arrange - TransferRequestKeyElement[] memory transferRequestKeyElements = new TransferRequestKeyElement[](0); - + TransferRequestKeyElement[] + memory transferRequestKeyElements = new TransferRequestKeyElement[]( + 0 + ); + // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector); - ruleConditionalTransfer.createTransferRequestWithApprovalBatch(transferRequestKeyElements); + ruleConditionalTransfer.createTransferRequestWithApprovalBatch( + transferRequestKeyElements + ); } - /** - * @dev test overwrite branch, previous approval + * @dev test overwrite branch, previous approval */ function testCanCreateTransferRequestWithApprovalAgain() public { vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); @@ -246,16 +282,18 @@ contract RuleConditionalTransferTest is Test, HelperContract { bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); vm.expectEmit(true, true, true, true); emit transferApproved(key, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequestWithApproval(transferRequestInput); + ruleConditionalTransfer.createTransferRequestWithApproval( + transferRequestInput + ); // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectEmit(true, true, true, true); emit transferApproved(key, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequestWithApproval(transferRequestInput); + ruleConditionalTransfer.createTransferRequestWithApproval( + transferRequestInput + ); } - - /**** Request approval ****** */ function testCanHolderCreateRequestBatch() public { @@ -264,11 +302,11 @@ contract RuleConditionalTransferTest is Test, HelperContract { values[0] = defaultValue; values[1] = value2; values[2] = value4; - address[] memory addresses = new address[](3); + address[] memory addresses = new address[](3); addresses[0] = ADDRESS2; addresses[1] = ADDRESS2; addresses[2] = ADDRESS2; - + // Act vm.prank(ADDRESS1); vm.expectEmit(true, true, true, true); @@ -277,14 +315,14 @@ contract RuleConditionalTransferTest is Test, HelperContract { emit transferWaiting(key2, ADDRESS1, ADDRESS2, value2, 1); vm.expectEmit(true, true, true, true); emit transferWaiting(key4, ADDRESS1, ADDRESS2, value4, 2); - ruleConditionalTransfer.createTransferRequestBatch(addresses,values ); + ruleConditionalTransfer.createTransferRequestBatch(addresses, values); } function testCannotHolderCreateRequestBatchEmptyArray() public { // Arrange uint256[] memory values = new uint256[](0); - address[] memory addresses = new address[](0); - + address[] memory addresses = new address[](0); + // Act vm.prank(ADDRESS1); vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector); @@ -294,8 +332,8 @@ contract RuleConditionalTransferTest is Test, HelperContract { function testCannotHolderCreateRequestBatchIfLEngthMismatch() public { // Arrange uint256[] memory values = new uint256[](3); - address[] memory addresses = new address[](1); - + address[] memory addresses = new address[](1); + // Act vm.prank(ADDRESS1); vm.expectRevert(RuleConditionalTransfer_InvalidLengthArray.selector); @@ -305,15 +343,18 @@ contract RuleConditionalTransferTest is Test, HelperContract { function testCanApproveRequestCreatedByHolder() public { // Arrange _createTransferRequest(); - + // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectEmit(true, true, true, true); emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0,true); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + true + ); } - function testCanPartiallyApproveRequestCreatedByHolder() public { // Arrange _createTransferRequest(); @@ -324,7 +365,11 @@ contract RuleConditionalTransferTest is Test, HelperContract { vm.expectEmit(true, true, true, true); emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); emit transferWaiting(key, ADDRESS1, ADDRESS2, partialValue, 1); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, partialValue,true); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + partialValue, + true + ); } function testCannotPartiallyDeniedRequestCreatedByHolder() public { @@ -334,29 +379,43 @@ contract RuleConditionalTransferTest is Test, HelperContract { // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectRevert(RuleConditionalTransfer_CannotDeniedPartially.selector); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, partialValue, false); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + partialValue, + false + ); } - function testCannotPartiallyApprovedRequestCreatedByHolderIfPartialValueIsBiggerThanValue() public { + function testCannotPartiallyApprovedRequestCreatedByHolderIfPartialValueIsBiggerThanValue() + public + { // Arrange _createTransferRequest(); uint256 partialValue = 5000; // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectRevert(RuleConditionalTransfer_InvalidValueApproved.selector); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, partialValue, false); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + partialValue, + false + ); } function testCanCreateAndApproveRequestCreatedByHolderAgain() public { // Arrange // First request _createTransferRequest(); - + // First approval vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectEmit(true, true, true, true); emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0, true); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + true + ); // Second request vm.prank(ADDRESS1); @@ -366,10 +425,15 @@ contract RuleConditionalTransferTest is Test, HelperContract { vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectEmit(true, true, true, true); emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0, true); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + true + ); // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); + TransferRequest memory transferRequest = ruleConditionalTransfer + .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); assertEq(transferRequest.key, defaultKey); assertEq(transferRequest.id, 0); assertEq(transferRequest.from, ADDRESS1); @@ -378,7 +442,6 @@ contract RuleConditionalTransferTest is Test, HelperContract { assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED)); } - /*** Batch */ function testCanCreateAndApproveRequestCreatedByHolderInBatch() public { // Arrange @@ -388,13 +451,16 @@ contract RuleConditionalTransferTest is Test, HelperContract { partialValues[1] = 0; partialValues[2] = 0; partialValues[3] = 0; - bool[] memory isApproveds = new bool[](4); + bool[] memory isApproveds = new bool[](4); isApproveds[0] = true; isApproveds[1] = true; isApproveds[2] = true; isApproveds[3] = false; - TransferRequestKeyElement[] memory transferRequestKeyElements = new TransferRequestKeyElement[](4); + TransferRequestKeyElement[] + memory transferRequestKeyElements = new TransferRequestKeyElement[]( + 4 + ); transferRequestKeyElements[0] = transferRequestInput; transferRequestKeyElements[1] = transferRequestInput2; transferRequestKeyElements[2] = transferRequestInput3; @@ -410,60 +476,92 @@ contract RuleConditionalTransferTest is Test, HelperContract { emit transferApproved(key3, ADDRESS2, ADDRESS1, value3, 2); vm.expectEmit(true, true, true, true); emit transferDenied(key4, ADDRESS1, ADDRESS2, value4, 3); - ruleConditionalTransfer.approveTransferRequestBatch(transferRequestKeyElements, partialValues, isApproveds); + ruleConditionalTransfer.approveTransferRequestBatch( + transferRequestKeyElements, + partialValues, + isApproveds + ); // Assert _checkRequestBatch(); } - - function testCannotCreateAndApproveRequestCreatedByHolderInBatchWithLenghtMismatch() public { + function testCannotCreateAndApproveRequestCreatedByHolderInBatchWithLenghtMismatch() + public + { // Arrange uint256[] memory partialValues = new uint256[](4); // Lenght mismatch - bool[] memory isApproveds = new bool[](3); + bool[] memory isApproveds = new bool[](3); - TransferRequestKeyElement[] memory transferRequestKeyElements = new TransferRequestKeyElement[](4); + TransferRequestKeyElement[] + memory transferRequestKeyElements = new TransferRequestKeyElement[]( + 4 + ); // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectRevert(RuleConditionalTransfer_InvalidLengthArray.selector); - ruleConditionalTransfer.approveTransferRequestBatch(transferRequestKeyElements, partialValues, isApproveds); + ruleConditionalTransfer.approveTransferRequestBatch( + transferRequestKeyElements, + partialValues, + isApproveds + ); // Act uint256[] memory partialValuesV2 = new uint256[](1); partialValuesV2[0] = 0; vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectRevert(RuleConditionalTransfer_InvalidLengthArray.selector); - ruleConditionalTransfer.approveTransferRequestBatch(transferRequestKeyElements, partialValuesV2, isApproveds); - + ruleConditionalTransfer.approveTransferRequestBatch( + transferRequestKeyElements, + partialValuesV2, + isApproveds + ); // Act uint256[] memory partialValuesV3 = new uint256[](4); // Lenght mismatch - bool[] memory isApprovedsV3 = new bool[](4); - TransferRequestKeyElement[] memory transferRequestKeyElementsV3 = new TransferRequestKeyElement[](2); + bool[] memory isApprovedsV3 = new bool[](4); + TransferRequestKeyElement[] + memory transferRequestKeyElementsV3 = new TransferRequestKeyElement[]( + 2 + ); transferRequestKeyElementsV3[0] = transferRequestInput; transferRequestKeyElementsV3[1] = transferRequestInput2; vm.expectRevert(RuleConditionalTransfer_InvalidLengthArray.selector); vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.approveTransferRequestBatch(transferRequestKeyElementsV3, partialValuesV3, isApprovedsV3); + ruleConditionalTransfer.approveTransferRequestBatch( + transferRequestKeyElementsV3, + partialValuesV3, + isApprovedsV3 + ); } - function testCannotCreateAndApproveRequestCreatedByHolderInBatchWithEmptyArry() public { + function testCannotCreateAndApproveRequestCreatedByHolderInBatchWithEmptyArry() + public + { // Arrange uint256[] memory partialValues = new uint256[](0); // Lenght mismatch - bool[] memory isApproveds = new bool[](0); + bool[] memory isApproveds = new bool[](0); - TransferRequestKeyElement[] memory transferRequestKeyElements = new TransferRequestKeyElement[](0); + TransferRequestKeyElement[] + memory transferRequestKeyElements = new TransferRequestKeyElement[]( + 0 + ); // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector); - ruleConditionalTransfer.approveTransferRequestBatch(transferRequestKeyElements, partialValues, isApproveds); - + ruleConditionalTransfer.approveTransferRequestBatch( + transferRequestKeyElements, + partialValues, + isApproveds + ); } - function testCanCreateAndApproveRequestCreatedByHolderInBatchWithPartialValues() public { + function testCanCreateAndApproveRequestCreatedByHolderInBatchWithPartialValues() + public + { // Arrange _createTransferRequestBatch(); uint256[] memory partialValues = new uint256[](5); @@ -473,15 +571,20 @@ contract RuleConditionalTransferTest is Test, HelperContract { partialValues[3] = 0; // partial value partialValues[4] = 500; - bytes32 key5PartialValue = keccak256(abi.encode(ADDRESS1, ADDRESS2, partialValues[4])); - bool[] memory isApproveds = new bool[](5); + bytes32 key5PartialValue = keccak256( + abi.encode(ADDRESS1, ADDRESS2, partialValues[4]) + ); + bool[] memory isApproveds = new bool[](5); isApproveds[0] = true; isApproveds[1] = true; isApproveds[2] = true; isApproveds[3] = false; isApproveds[4] = true; - TransferRequestKeyElement[] memory transferRequestKeyElements = new TransferRequestKeyElement[](5); + TransferRequestKeyElement[] + memory transferRequestKeyElements = new TransferRequestKeyElement[]( + 5 + ); transferRequestKeyElements[0] = transferRequestInput; transferRequestKeyElements[1] = transferRequestInput2; transferRequestKeyElements[2] = transferRequestInput3; @@ -501,14 +604,25 @@ contract RuleConditionalTransferTest is Test, HelperContract { vm.expectEmit(true, true, true, true); emit transferDenied(key5, ADDRESS1, ADDRESS2, value5, 4); vm.expectEmit(true, true, true, true); - emit transferApproved(key5PartialValue, ADDRESS1, ADDRESS2, partialValues[4], 5); - ruleConditionalTransfer.approveTransferRequestBatch(transferRequestKeyElements, partialValues, isApproveds); + emit transferApproved( + key5PartialValue, + ADDRESS1, + ADDRESS2, + partialValues[4], + 5 + ); + ruleConditionalTransfer.approveTransferRequestBatch( + transferRequestKeyElements, + partialValues, + isApproveds + ); // Assert _checkRequestPartial(); // 5 - TransferRequest memory transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, value5); + TransferRequest memory transferRequest = ruleConditionalTransfer + .getRequestTrade(ADDRESS1, ADDRESS2, value5); assertEq(transferRequest.key, key5); assertEq(transferRequest.id, 4); assertEq(transferRequest.from, ADDRESS1); @@ -516,12 +630,16 @@ contract RuleConditionalTransferTest is Test, HelperContract { assertEq(transferRequest.value, value5); assertEq(uint256(transferRequest.status), uint256(STATUS.DENIED)); // new request - transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, partialValues[4]); + transferRequest = ruleConditionalTransfer.getRequestTrade( + ADDRESS1, + ADDRESS2, + partialValues[4] + ); assertEq(transferRequest.key, key5PartialValue); assertEq(transferRequest.id, 5); assertEq(transferRequest.from, ADDRESS1); assertEq(transferRequest.to, ADDRESS2); - assertEq(transferRequest.value,partialValues[4]); + assertEq(transferRequest.value, partialValues[4]); assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED)); } @@ -529,16 +647,16 @@ contract RuleConditionalTransferTest is Test, HelperContract { function testCanApproveRequestCreatedByHolderWithId() public { // Arrange _createTransferRequest(); - + // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectEmit(true, true, true, true); emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequestWithId( 0, true); - + ruleConditionalTransfer.approveTransferRequestWithId(0, true); // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); + TransferRequest memory transferRequest = ruleConditionalTransfer + .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); assertEq(transferRequest.key, defaultKey); assertEq(transferRequest.id, 0); assertEq(transferRequest.from, ADDRESS1); @@ -547,18 +665,16 @@ contract RuleConditionalTransferTest is Test, HelperContract { assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED)); } - - /***** Batch */ function testCanApproveRequestInBatchCreatedByHolderWithId() public { - _createTransferRequestBatch(); + _createTransferRequestBatch(); uint256[] memory ids = new uint256[](4); ids[0] = 0; ids[1] = 1; ids[2] = 2; ids[3] = 3; - bool[] memory isApproveds = new bool[](4); + bool[] memory isApproveds = new bool[](4); isApproveds[0] = true; isApproveds[1] = true; isApproveds[2] = true; @@ -573,38 +689,50 @@ contract RuleConditionalTransferTest is Test, HelperContract { emit transferApproved(key3, ADDRESS2, ADDRESS1, value3, 2); vm.expectEmit(true, true, true, true); emit transferDenied(key4, ADDRESS1, ADDRESS2, value4, 3); - ruleConditionalTransfer.approveTransferRequestBatchWithId( ids, isApproveds); - + ruleConditionalTransfer.approveTransferRequestBatchWithId( + ids, + isApproveds + ); // Assert _checkRequestBatch(); } - - function testCannotApproveRequestInBatchCreatedByHolderWithIdWithinvalidLength() public { - _createTransferRequestBatch(); + function testCannotApproveRequestInBatchCreatedByHolderWithIdWithinvalidLength() + public + { + _createTransferRequestBatch(); uint256[] memory ids = new uint256[](4); // Wrong length here - bool[] memory isApproveds = new bool[](3); + bool[] memory isApproveds = new bool[](3); // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectRevert(RuleConditionalTransfer_InvalidLengthArray.selector); - ruleConditionalTransfer.approveTransferRequestBatchWithId( ids, isApproveds); + ruleConditionalTransfer.approveTransferRequestBatchWithId( + ids, + isApproveds + ); } - function testCannotApproveRequestInBatchCreatedByHolderWithIdWithEmptyArray() public { - _createTransferRequestBatch(); + function testCannotApproveRequestInBatchCreatedByHolderWithIdWithEmptyArray() + public + { + _createTransferRequestBatch(); uint256[] memory ids = new uint256[](0); // Wrong length here - bool[] memory isApproveds = new bool[](0); + bool[] memory isApproveds = new bool[](0); // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector); - ruleConditionalTransfer.approveTransferRequestBatchWithId( ids, isApproveds); + ruleConditionalTransfer.approveTransferRequestBatchWithId( + ids, + isApproveds + ); } - - function testCannotApproveRequestInBatchCreatedByHolderWithWrongId() public { + function testCannotApproveRequestInBatchCreatedByHolderWithWrongId() + public + { _createTransferRequestBatch(); uint256[] memory ids = new uint256[](4); ids[0] = 0; @@ -612,7 +740,7 @@ contract RuleConditionalTransferTest is Test, HelperContract { ////// Wrong id here !!! ids[2] = 6; ids[3] = 3; - bool[] memory isApproveds = new bool[](4); + bool[] memory isApproveds = new bool[](4); isApproveds[0] = true; isApproveds[1] = true; isApproveds[2] = true; @@ -620,12 +748,16 @@ contract RuleConditionalTransferTest is Test, HelperContract { // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectRevert(RuleConditionalTransfer_InvalidId.selector); - ruleConditionalTransfer.approveTransferRequestBatchWithId( ids, isApproveds); + ruleConditionalTransfer.approveTransferRequestBatchWithId( + ids, + isApproveds + ); } - - function testCannotApproveRequestInBatchCreatedByHolderIfTimeExceed() public { - _createTransferRequestBatch(); + function testCannotApproveRequestInBatchCreatedByHolderIfTimeExceed() + public + { + _createTransferRequestBatch(); // Jump vm.warp(block.timestamp + 604801); uint256[] memory ids = new uint256[](4); @@ -633,7 +765,7 @@ contract RuleConditionalTransferTest is Test, HelperContract { ids[1] = 1; ids[2] = 2; ids[3] = 3; - bool[] memory isApproveds = new bool[](4); + bool[] memory isApproveds = new bool[](4); isApproveds[0] = true; isApproveds[1] = true; isApproveds[2] = true; @@ -641,37 +773,42 @@ contract RuleConditionalTransferTest is Test, HelperContract { // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectRevert(RuleConditionalTransfer_timeExceeded.selector); - ruleConditionalTransfer.approveTransferRequestBatchWithId( ids, isApproveds); + ruleConditionalTransfer.approveTransferRequestBatchWithId( + ids, + isApproveds + ); } - function testCannotApproveOrDeniedRequestCreatedByHolderWithWrongId() public { + function testCannotApproveOrDeniedRequestCreatedByHolderWithWrongId() + public + { // Arrange _createTransferRequest(); - + // Act // Approve vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectRevert(RuleConditionalTransfer_InvalidId.selector); - ruleConditionalTransfer.approveTransferRequestWithId( 1, true); + ruleConditionalTransfer.approveTransferRequestWithId(1, true); // Denied vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectRevert(RuleConditionalTransfer_InvalidId.selector); - ruleConditionalTransfer.approveTransferRequestWithId( 1, false); + ruleConditionalTransfer.approveTransferRequestWithId(1, false); } - function testCanDeniedRequestCreatedByHolderWithId() public { // Arrange _createTransferRequest(); - + // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectEmit(true, true, true, true); emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequestWithId( 0, false); + ruleConditionalTransfer.approveTransferRequestWithId(0, false); // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); + TransferRequest memory transferRequest = ruleConditionalTransfer + .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); assertEq(transferRequest.key, defaultKey); assertEq(transferRequest.id, 0); assertEq(transferRequest.from, ADDRESS1); @@ -684,15 +821,20 @@ contract RuleConditionalTransferTest is Test, HelperContract { function testCanDeniedRequestCreatedByHolder() public { // Arrange _createTransferRequest(); - + // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectEmit(true, true, true, true); - emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0,false); + emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + false + ); // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); + TransferRequest memory transferRequest = ruleConditionalTransfer + .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); assertEq(transferRequest.key, defaultKey); assertEq(transferRequest.id, 0); assertEq(transferRequest.from, ADDRESS1); @@ -700,9 +842,10 @@ contract RuleConditionalTransferTest is Test, HelperContract { assertEq(transferRequest.value, defaultValue); assertEq(uint256(transferRequest.status), uint256(STATUS.DENIED)); - TransferRequest[] memory transferRequests = ruleConditionalTransfer.getRequestByStatus(STATUS.DENIED); - assertEq(transferRequests[0].key , defaultKey); - assertEq(transferRequests.length , 1); + TransferRequest[] memory transferRequests = ruleConditionalTransfer + .getRequestByStatus(STATUS.DENIED); + assertEq(transferRequests[0].key, defaultKey); + assertEq(transferRequests.length, 1); } function testCannotHolderCreateRequestIfDenied() public { @@ -710,9 +853,12 @@ contract RuleConditionalTransferTest is Test, HelperContract { _createTransferRequest(); vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectEmit(true, true, true, true); - emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0,false); - + emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + false + ); // Act vm.prank(ADDRESS1); @@ -722,15 +868,19 @@ contract RuleConditionalTransferTest is Test, HelperContract { /****** Getter *****/ function testCanReturnTradeByStatus() public { - // Arrange - // First request + // Arrange + // First request _createTransferRequest(); // Change the status request to APPROVE vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectEmit(true, true, true, true); emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0, false); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + false + ); // Second request uint256 value = 100; @@ -738,7 +888,8 @@ contract RuleConditionalTransferTest is Test, HelperContract { ruleConditionalTransfer.createTransferRequest(ADDRESS2, value); // Act - TransferRequest[] memory transferRequest = ruleConditionalTransfer.getRequestByStatus(STATUS.WAIT); + TransferRequest[] memory transferRequest = ruleConditionalTransfer + .getRequestByStatus(STATUS.WAIT); // Assert assertEq(transferRequest.length, 1); bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, value)); @@ -755,10 +906,14 @@ contract RuleConditionalTransferTest is Test, HelperContract { ruleConditionalTransfer.createTransferRequest(ADDRESS2, valueThird); // Act - transferRequest = ruleConditionalTransfer.getRequestByStatus(STATUS.WAIT); + transferRequest = ruleConditionalTransfer.getRequestByStatus( + STATUS.WAIT + ); // Assert assertEq(transferRequest.length, 2); - bytes32 keyThird = keccak256(abi.encode(ADDRESS1, ADDRESS2, valueThird)); + bytes32 keyThird = keccak256( + abi.encode(ADDRESS1, ADDRESS2, valueThird) + ); assertEq(transferRequest[1].key, keyThird); assertEq(transferRequest[1].id, 2); assertEq(transferRequest[1].from, ADDRESS1); @@ -767,18 +922,21 @@ contract RuleConditionalTransferTest is Test, HelperContract { assertEq(uint256(transferRequest[1].status), uint256(STATUS.WAIT)); } - function testCannotApproveRequestIfTimeExceeded() public { // Arrange _createTransferRequest(); - + // Timeout // 7 days *24*60*60 = 604800 seconds vm.warp(block.timestamp + 604801); // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectRevert(RuleConditionalTransfer_timeExceeded.selector); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0, true); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + true + ); } /*** Edge case ******/ @@ -786,14 +944,18 @@ contract RuleConditionalTransferTest is Test, HelperContract { function testCannotApproveRequestIfWrongStatus() public { // Arrange // No create request - + // Timeout // 7 days *24*60*60 = 604800 seconds vm.warp(block.timestamp + 604801); // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectRevert(RuleConditionalTransfer_Wrong_Status.selector); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0, true); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + true + ); } function testCanSetTimeLimitWithTransferApprovalExceeded() public { @@ -803,7 +965,7 @@ contract RuleConditionalTransferTest is Test, HelperContract { }); // Arrange _createTransferRequest(); - + // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); ruleConditionalTransfer.setTimeLimit(timeLimit_); @@ -813,9 +975,12 @@ contract RuleConditionalTransferTest is Test, HelperContract { // >1 days vm.warp(block.timestamp + 1 days + 1 seconds); - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectRevert(RuleConditionalTransfer_timeExceeded.selector); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0, true); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + true + ); } } diff --git a/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol index f9a18c7..fc59416 100644 --- a/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol +++ b/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol @@ -6,8 +6,8 @@ import "../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title Tests on the Access Control -*/ + * @title Tests on the Access Control + */ contract RuleConditionalTransferAccessControl is Test, HelperContract { RuleEngine ruleEngineMock; // Custom error openZeppelin @@ -22,40 +22,42 @@ contract RuleConditionalTransferAccessControl is Test, HelperContract { string resString; uint8 CODE_NONEXISTENT = 255; uint256 defaultValue = 10; - bytes32 defaultKey = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); + bytes32 defaultKey = + keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); - TransferRequestKeyElement transferRequestInput = TransferRequestKeyElement({ + TransferRequestKeyElement transferRequestInput = + TransferRequestKeyElement({ from: ADDRESS1, to: ADDRESS2, - value:defaultValue - }); + value: defaultValue + }); // Arrange function setUp() public { - TIME_LIMIT memory timeLimit_ =TIME_LIMIT({ + TIME_LIMIT memory timeLimit_ = TIME_LIMIT({ timeLimitToApprove: 7 days, timeLimitToTransfer: 30 days }); - - AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ + + AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ isActivate: false, timeLimitBeforeAutomaticApproval: 0 }); ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval:false, - authorizedBurnWithoutApproval:false + authorizedMintWithoutApproval: false, + authorizedBurnWithoutApproval: false }); AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate:false, + isActivate: false, cmtat: IERC20(address(0)) }); - + OPTION memory options = OPTION({ - issuance:issuanceOption_, + issuance: issuanceOption_, timeLimit: timeLimit_, automaticApproval: automaticApproval_, - automaticTransfer:automaticTransfer_ + automaticTransfer: automaticTransfer_ }); ruleEngineMock = new RuleEngine( RULE_ENGINE_OPERATOR_ADDRESS, @@ -66,14 +68,17 @@ contract RuleConditionalTransferAccessControl is Test, HelperContract { ruleConditionalTransfer = new RuleConditionalTransfer( DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, - ruleEngineMock, + ruleEngineMock, options ); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer.grantRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + ruleConditionalTransfer.grantRole( + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS + ); } - function _createTransferRequest() internal{ + function _createTransferRequest() internal { vm.prank(ADDRESS1); // Act vm.expectEmit(true, true, true, true); @@ -81,80 +86,145 @@ contract RuleConditionalTransferAccessControl is Test, HelperContract { ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); } - function testCannotAttackerApproveARequestCreatedByTokenHolder() public { _createTransferRequest(); - + vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE + ) + ); vm.prank(ATTACKER); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0, true); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + true + ); } - function testCannotAttackerApproveWithIdARequestCreatedByTokenHolder() public { + function testCannotAttackerApproveWithIdARequestCreatedByTokenHolder() + public + { _createTransferRequest(); - + vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE + ) + ); vm.prank(ATTACKER); ruleConditionalTransfer.approveTransferRequestWithId(0, true); } function testCannotAttackerResetARequest() public { - _createTransferRequest(); - + _createTransferRequest(); + vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE)); + 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)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE + ) + ); vm.prank(ATTACKER); - ruleConditionalTransfer.createTransferRequestWithApproval(transferRequestInput); + ruleConditionalTransfer.createTransferRequestWithApproval( + transferRequestInput + ); } /*** Batch */ - function testCannotAttackerApproveBatchWithIdARequestCreatedByTokenHolder() public { + function testCannotAttackerApproveBatchWithIdARequestCreatedByTokenHolder() + public + { _createTransferRequest(); uint256[] memory ids = new uint256[](1); ids[0] = 0; bool[] memory isApproveds = new bool[](1); isApproveds[0] = true; vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE + ) + ); vm.prank(ATTACKER); - ruleConditionalTransfer.approveTransferRequestBatchWithId(ids, isApproveds); + ruleConditionalTransfer.approveTransferRequestBatchWithId( + ids, + isApproveds + ); } - function testCannotAttackerApproveBatchRequestCreatedByTokenHolder() public { - TransferRequestKeyElement[] memory keyElements = new TransferRequestKeyElement[](0); + 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)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE + ) + ); vm.prank(ATTACKER); - ruleConditionalTransfer.approveTransferRequestBatch(keyElements, partialValues, boolIsApproved); + ruleConditionalTransfer.approveTransferRequestBatch( + keyElements, + partialValues, + boolIsApproved + ); } function testCannotAttackerResetBatch() public { uint256[] memory ids = new uint256[](0); bool[] memory boolIsApproved = new bool[](0); vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE + ) + ); vm.prank(ATTACKER); - ruleConditionalTransfer.approveTransferRequestBatchWithId(ids, boolIsApproved); + ruleConditionalTransfer.approveTransferRequestBatchWithId( + ids, + boolIsApproved + ); } function testCannotAttackerCreateTransferRequestWithApprovalBatch() public { - TransferRequestKeyElement[] memory keyElements = new TransferRequestKeyElement[](0); + TransferRequestKeyElement[] + memory keyElements = new TransferRequestKeyElement[](0); vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE + ) + ); vm.prank(ATTACKER); - ruleConditionalTransfer.createTransferRequestWithApprovalBatch(keyElements); + ruleConditionalTransfer.createTransferRequestWithApprovalBatch( + keyElements + ); } /******** OPTIONS CONFIGURATION *********/ @@ -164,40 +234,60 @@ contract RuleConditionalTransferAccessControl is Test, HelperContract { timeLimitToTransfer: 200 days }); vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE + ) + ); vm.prank(ATTACKER); ruleConditionalTransfer.setTimeLimit(timeLimit_); } function testCannotAttackerSetAutomaticTransfer() public { AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate:false, + isActivate: false, cmtat: IERC20(address(0)) }); vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE + ) + ); vm.prank(ATTACKER); ruleConditionalTransfer.setAutomaticTransfer(automaticTransfer_); } function testCannotAttackerSetIssuanceOptions() public { ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval:false, - authorizedBurnWithoutApproval:false + authorizedMintWithoutApproval: false, + authorizedBurnWithoutApproval: false }); vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE + ) + ); vm.prank(ATTACKER); ruleConditionalTransfer.setIssuanceOptions(issuanceOption_); } function testCannotAttackerSetAuomaticApproval() public { - AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ + AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ isActivate: false, timeLimitBeforeAutomaticApproval: 0 }); vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE + ) + ); vm.prank(ATTACKER); ruleConditionalTransfer.setAutomaticApproval(automaticApproval_); } diff --git a/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol index 5083279..e3c7f8d 100644 --- a/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol +++ b/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol @@ -6,8 +6,8 @@ import "../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title General functions of the RuleWhitelist -*/ + * @title General functions of the RuleWhitelist + */ contract RuleConditionalTransferResetTest is Test, HelperContract { RuleEngine ruleEngineMock; uint256 resUint256; @@ -17,13 +17,15 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { string resString; uint8 CODE_NONEXISTENT = 255; uint256 defaultValue = 10; - bytes32 defaultKey = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); + bytes32 defaultKey = + keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); - TransferRequestKeyElement transferRequestInput = TransferRequestKeyElement({ + TransferRequestKeyElement transferRequestInput = + TransferRequestKeyElement({ from: ADDRESS1, to: ADDRESS2, - value:defaultValue - }); + value: defaultValue + }); uint256 value2 = 1; uint256 value3 = 2; @@ -35,17 +37,19 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { bytes32 key4 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value4)); bytes32 key5 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value5)); - TransferRequestKeyElement transferRequestInput2 = TransferRequestKeyElement({ + TransferRequestKeyElement transferRequestInput2 = + TransferRequestKeyElement({ from: ADDRESS1, to: ADDRESS2, - value:value2 - }); + value: value2 + }); - TransferRequestKeyElement transferRequestInput3 = TransferRequestKeyElement({ + TransferRequestKeyElement transferRequestInput3 = + TransferRequestKeyElement({ from: ADDRESS2, to: ADDRESS1, - value:value3 - }); + value: value3 + }); // Arrange function setUp() public { @@ -53,26 +57,26 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { timeLimitToApprove: 7 days, timeLimitToTransfer: 30 days }); - - AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ + + AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ isActivate: false, timeLimitBeforeAutomaticApproval: 0 }); ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval:false, - authorizedBurnWithoutApproval:false + authorizedMintWithoutApproval: false, + authorizedBurnWithoutApproval: false }); AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate:false, + isActivate: false, cmtat: IERC20(address(0)) }); OPTION memory options = OPTION({ - issuance:issuanceOption_, + issuance: issuanceOption_, timeLimit: timeLimit_, automaticApproval: automaticApproval_, - automaticTransfer:automaticTransfer_ + automaticTransfer: automaticTransfer_ }); ruleEngineMock = new RuleEngine( RULE_ENGINE_OPERATOR_ADDRESS, @@ -83,15 +87,18 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { ruleConditionalTransfer = new RuleConditionalTransfer( DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, - ruleEngineMock, + ruleEngineMock, options ); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer.grantRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + ruleConditionalTransfer.grantRole( + RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS + ); } - function _createTransferRequestBatch() public{ - // Arrange + function _createTransferRequestBatch() public { + // Arrange _createTransferRequest(); // Second and third request @@ -101,8 +108,8 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { ruleConditionalTransfer.createTransferRequest(ADDRESS1, value3); } - function _createTransferRequestBatchByHodler() public{ - // Arrange + function _createTransferRequestBatchByHodler() public { + // Arrange _createTransferRequest(); // Second and third request @@ -112,7 +119,7 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { ruleConditionalTransfer.createTransferRequest(ADDRESS2, value3); } - function _createTransferRequest() internal{ + function _createTransferRequest() internal { vm.prank(ADDRESS1); // Act vm.expectEmit(true, true, true, true); @@ -120,7 +127,8 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); + TransferRequest memory transferRequest = ruleConditionalTransfer + .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); assertEq(transferRequest.key, defaultKey); assertEq(transferRequest.id, 0); assertEq(transferRequest.from, ADDRESS1); @@ -128,9 +136,10 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { assertEq(transferRequest.value, defaultValue); assertEq(uint256(transferRequest.status), uint256(STATUS.WAIT)); - TransferRequest[] memory transferRequests = ruleConditionalTransfer.getRequestByStatus(STATUS.WAIT); - assertEq(transferRequests[0].key , defaultKey); - assertEq(transferRequests.length , 1); + TransferRequest[] memory transferRequests = ruleConditionalTransfer + .getRequestByStatus(STATUS.WAIT); + assertEq(transferRequests[0].key, defaultKey); + assertEq(transferRequests.length, 1); } /***** Reset ********/ @@ -139,7 +148,7 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { // Arrange _createTransferRequest(); - // Act + // Act // Reset vm.prank(ADDRESS1); vm.expectEmit(true, true, true, true); @@ -151,7 +160,11 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { vm.prank(ADDRESS1); ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0,true); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + true + ); // Reset vm.prank(ADDRESS1); @@ -181,7 +194,7 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { ids[0] = 0; ids[1] = 1; ids[2] = 2; - // Act + // Act // Reset vm.prank(ADDRESS1); vm.expectEmit(true, true, true, true); @@ -200,7 +213,7 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { ids[0] = 0; ids[1] = 4; ids[2] = 2; - // Act + // Act // Reset vm.prank(ADDRESS1); vm.expectRevert(RuleConditionalTransfer_InvalidId.selector); @@ -211,7 +224,7 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { // Arrange _createTransferRequestBatchByHodler(); uint256[] memory ids = new uint256[](0); - // Act + // Act // Reset vm.prank(ADDRESS1); vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector); @@ -222,7 +235,7 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { // Arrange _createTransferRequest(); - // Act + // Act // Reset vm.prank(ADDRESS2); vm.expectRevert(RuleConditionalTransfer_InvalidSender.selector); @@ -233,7 +246,7 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { // Arrange _createTransferRequest(); - // Act + // Act // Reset vm.prank(ADDRESS1); vm.expectRevert(RuleConditionalTransfer_InvalidId.selector); @@ -246,9 +259,13 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { // Denied vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0, false); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + false + ); - // Act + // Act // Reset vm.prank(ADDRESS1); vm.expectRevert(RuleConditionalTransfer_Wrong_Status.selector); @@ -264,7 +281,11 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectEmit(true, true, true, true); emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0,false); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + false + ); // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); @@ -273,7 +294,8 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { ruleConditionalTransfer.resetRequestStatus(0); // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); + TransferRequest memory transferRequest = ruleConditionalTransfer + .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); assertEq(transferRequest.key, defaultKey); assertEq(transferRequest.id, 0); assertEq(transferRequest.from, ADDRESS1); @@ -289,7 +311,11 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); // Assert - transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); + transferRequest = ruleConditionalTransfer.getRequestTrade( + ADDRESS1, + ADDRESS2, + defaultValue + ); assertEq(transferRequest.key, defaultKey); assertEq(transferRequest.id, 0); assertEq(transferRequest.from, ADDRESS1); @@ -297,7 +323,6 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { assertEq(transferRequest.value, defaultValue); assertEq(uint256(transferRequest.status), uint256(STATUS.WAIT)); - // Id different from 0 vm.prank(ADDRESS1); // Act @@ -317,7 +342,11 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectEmit(true, true, true, true); emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0,false); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + false + ); // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); @@ -330,7 +359,8 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { ruleConditionalTransfer.resetRequestStatusBatch(ids); // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); + TransferRequest memory transferRequest = ruleConditionalTransfer + .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); assertEq(transferRequest.key, defaultKey); assertEq(transferRequest.id, 0); assertEq(transferRequest.from, ADDRESS1); @@ -338,8 +368,11 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { assertEq(transferRequest.value, defaultValue); assertEq(uint256(transferRequest.status), uint256(STATUS.NONE)); - - transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, value2); + transferRequest = ruleConditionalTransfer.getRequestTrade( + ADDRESS1, + ADDRESS2, + value2 + ); assertEq(transferRequest.key, key2); assertEq(transferRequest.id, 1); assertEq(transferRequest.from, ADDRESS1); @@ -347,7 +380,11 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { assertEq(transferRequest.value, value2); assertEq(uint256(transferRequest.status), uint256(STATUS.NONE)); - transferRequest = ruleConditionalTransfer.getRequestTrade(ADDRESS1, ADDRESS2, value3); + transferRequest = ruleConditionalTransfer.getRequestTrade( + ADDRESS1, + ADDRESS2, + value3 + ); assertEq(transferRequest.key, key3Hodler); assertEq(transferRequest.id, 2); assertEq(transferRequest.from, ADDRESS1); @@ -356,8 +393,9 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { assertEq(uint256(transferRequest.status), uint256(STATUS.NONE)); } - - function testCannotBatchResetADeniedRequestCreatedByHolderWithWrongId() public { + function testCannotBatchResetADeniedRequestCreatedByHolderWithWrongId() + public + { // Arrange _createTransferRequestBatchByHodler(); uint256[] memory ids = new uint256[](3); @@ -368,7 +406,11 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectEmit(true, true, true, true); emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0,false); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + false + ); // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); @@ -376,14 +418,20 @@ contract RuleConditionalTransferResetTest is Test, HelperContract { ruleConditionalTransfer.resetRequestStatusBatch(ids); } - function testCannotBatchResetADeniedRequestCreatedByHolderWithEmptyArray() public { + function testCannotBatchResetADeniedRequestCreatedByHolderWithEmptyArray() + public + { // Arrange _createTransferRequestBatchByHodler(); uint256[] memory ids = new uint256[](0); vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); vm.expectEmit(true, true, true, true); emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0,false); + ruleConditionalTransfer.approveTransferRequest( + transferRequestInput, + 0, + false + ); // Act vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); diff --git a/test/RuleConditionalTransfer/RuleConditionalTransferRestriction.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransferRestriction.t.sol index 1b3d9f2..389843d 100644 --- a/test/RuleConditionalTransfer/RuleConditionalTransferRestriction.t.sol +++ b/test/RuleConditionalTransfer/RuleConditionalTransferRestriction.t.sol @@ -4,10 +4,11 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; import "src/RuleEngine.sol"; + //ADmin, forwarder irrect /RuleEngine /** -* @title General functions of the RuleEngine -*/ + * @title General functions of the RuleEngine + */ contract RuleEngineOperationTest is Test, HelperContract { RuleEngine ruleEngineMock; uint8 resUint8; @@ -17,42 +18,45 @@ contract RuleEngineOperationTest is Test, HelperContract { uint8 CODE_NONEXISTENT = 255; uint256 defaultValue = 20; - TIME_LIMIT timeLimit_ = TIME_LIMIT({ - timeLimitToApprove: DEFAULT_TIME_LIMIT_TO_APPROVE, - timeLimitToTransfer: DEFAULT_TIME_LIMIT_TO_TRANSFER + TIME_LIMIT timeLimit_ = + TIME_LIMIT({ + timeLimitToApprove: DEFAULT_TIME_LIMIT_TO_APPROVE, + timeLimitToTransfer: DEFAULT_TIME_LIMIT_TO_TRANSFER }); - ISSUANCE issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval:false, - authorizedBurnWithoutApproval:false + ISSUANCE issuanceOption_ = + ISSUANCE({ + authorizedMintWithoutApproval: false, + authorizedBurnWithoutApproval: false }); - AUTOMATIC_APPROVAL automaticApproval_ = AUTOMATIC_APPROVAL({ + AUTOMATIC_APPROVAL automaticApproval_ = + AUTOMATIC_APPROVAL({ isActivate: false, timeLimitBeforeAutomaticApproval: 0 }); - AUTOMATIC_TRANSFER automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate:false, - cmtat: IERC20(address(0)) - }); - OPTION options = OPTION({ - issuance:issuanceOption_, + AUTOMATIC_TRANSFER automaticTransfer_ = + AUTOMATIC_TRANSFER({isActivate: false, cmtat: IERC20(address(0))}); + OPTION options = + OPTION({ + issuance: issuanceOption_, timeLimit: timeLimit_, automaticApproval: automaticApproval_, - automaticTransfer:automaticTransfer_ + automaticTransfer: automaticTransfer_ }); - TransferRequestKeyElement transferRequestInput = TransferRequestKeyElement({ + TransferRequestKeyElement transferRequestInput = + TransferRequestKeyElement({ from: ADDRESS1, to: ADDRESS2, - value:defaultValue - }); + value: defaultValue + }); // Arrange function setUp() public { ruleConditionalTransfer = new RuleConditionalTransfer( CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, ZERO_ADDRESS, - ruleEngineMock, + ruleEngineMock, options ); } @@ -63,7 +67,9 @@ contract RuleEngineOperationTest is Test, HelperContract { bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); vm.expectEmit(true, true, true, true); emit transferApproved(key, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequestWithApproval(transferRequestInput); + ruleConditionalTransfer.createTransferRequestWithApproval( + transferRequestInput + ); // Act resUint8 = ruleConditionalTransfer.detectTransferRestriction( ADDRESS1, @@ -87,7 +93,6 @@ contract RuleEngineOperationTest is Test, HelperContract { assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED); } - function testMessageForTransferRestrictionWithUnknownRestrictionCode() public { diff --git a/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol b/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol index 89de71f..940e6b5 100644 --- a/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol +++ b/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol @@ -6,8 +6,8 @@ import "../../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title Tests on the Access Control -*/ + * @title Tests on the Access Control + */ contract RuleEngineAccessControlTest is Test, HelperContract { // Custom error openZeppelin error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); @@ -58,7 +58,12 @@ contract RuleEngineAccessControlTest is Test, HelperContract { // Act vm.prank(ATTACKER); vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_ENGINE_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + RULE_ENGINE_OPERATOR_ROLE + ) + ); (bool success, ) = address(ruleEngineMock).call( abi.encodeCall(ruleEngineMock.setRulesValidation, ruleWhitelistTab) ); @@ -73,7 +78,12 @@ contract RuleEngineAccessControlTest is Test, HelperContract { // Act vm.prank(ATTACKER); vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_ENGINE_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + RULE_ENGINE_OPERATOR_ROLE + ) + ); ruleEngineMock.clearRulesValidation(); // Assert @@ -85,7 +95,12 @@ contract RuleEngineAccessControlTest is Test, HelperContract { // Act vm.prank(ATTACKER); vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_ENGINE_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + RULE_ENGINE_OPERATOR_ROLE + ) + ); ruleEngineMock.addRuleValidation(ruleWhitelist); // Assert @@ -97,7 +112,12 @@ contract RuleEngineAccessControlTest is Test, HelperContract { // Act vm.prank(ATTACKER); vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_ENGINE_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + RULE_ENGINE_OPERATOR_ROLE + ) + ); ruleEngineMock.removeRuleValidation(ruleWhitelist, 0); // Assert @@ -109,7 +129,12 @@ contract RuleEngineAccessControlTest is Test, HelperContract { // Act vm.prank(ATTACKER); vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, TOKEN_CONTRACT_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + TOKEN_CONTRACT_ROLE + ) + ); ruleEngineMock.operateOnTransfer(ADDRESS1, ADDRESS2, 10); } } diff --git a/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol b/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol index 4dfbe9e..ef3d354 100644 --- a/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol +++ b/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol @@ -7,8 +7,8 @@ import "../../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title Tests on the provided functions by OpenZeppelin -*/ + * @title Tests on the provided functions by OpenZeppelin + */ contract RuleEngineAccessControlTest is Test, HelperContract, AccessControl { RuleEngine ruleEngineMock; uint8 resUint8; @@ -43,73 +43,83 @@ contract RuleEngineAccessControlTest is Test, HelperContract, AccessControl { vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); vm.expectEmit(true, true, false, true); emit RoleGranted( - RULE_ENGINE_ROLE, + RULE_ENGINE_OPERATOR_ROLE, ADDRESS1, RULE_ENGINE_OPERATOR_ADDRESS ); - ruleEngineMock.grantRole(RULE_ENGINE_ROLE, ADDRESS1); + ruleEngineMock.grantRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); // Assert - bool res1 = ruleEngineMock.hasRole(RULE_ENGINE_ROLE, ADDRESS1); + bool res1 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); assertEq(res1, true); } function testRevokeRoleAsAdmin() public { // Arrange vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.grantRole(RULE_ENGINE_ROLE, ADDRESS1); + ruleEngineMock.grantRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); // Arrange - Assert - bool res1 = ruleEngineMock.hasRole(RULE_ENGINE_ROLE, ADDRESS1); + bool res1 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); assertEq(res1, true); // Act vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); vm.expectEmit(true, true, false, true); emit RoleRevoked( - RULE_ENGINE_ROLE, + RULE_ENGINE_OPERATOR_ROLE, ADDRESS1, RULE_ENGINE_OPERATOR_ADDRESS ); - ruleEngineMock.revokeRole(RULE_ENGINE_ROLE, ADDRESS1); + ruleEngineMock.revokeRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); // Assert - bool res2 = ruleEngineMock.hasRole(RULE_ENGINE_ROLE, ADDRESS1); + bool res2 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); assertFalse(res2); } function testCannotGrantFromNonAdmin() public { // Arrange - Assert - bool res1 = ruleEngineMock.hasRole(RULE_ENGINE_ROLE, ADDRESS1); + bool res1 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); assertFalse(res1); // Act vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ADDRESS2, DEFAULT_ADMIN_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ADDRESS2, + DEFAULT_ADMIN_ROLE + ) + ); vm.prank(ADDRESS2); - ruleEngineMock.grantRole(RULE_ENGINE_ROLE, ADDRESS2); + ruleEngineMock.grantRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS2); // Assert - bool res2 = ruleEngineMock.hasRole(RULE_ENGINE_ROLE, ADDRESS1); + bool res2 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); assertFalse(res2); } function testCannotRevokeFromNonAdmin() public { // Arrange - Assert - bool res1 = ruleEngineMock.hasRole(RULE_ENGINE_ROLE, ADDRESS1); + bool res1 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); assertFalse(res1); // Arrange vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock.grantRole(RULE_ENGINE_ROLE, ADDRESS1); + ruleEngineMock.grantRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); // Arrange - Assert - bool res2 = ruleEngineMock.hasRole(RULE_ENGINE_ROLE, ADDRESS1); + bool res2 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); assertEq(res2, true); // Act vm.prank(ADDRESS2); vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ADDRESS2, DEFAULT_ADMIN_ROLE)); - ruleEngineMock.revokeRole(RULE_ENGINE_ROLE, ADDRESS1); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ADDRESS2, + DEFAULT_ADMIN_ROLE + ) + ); + ruleEngineMock.revokeRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); // Assert - bool res3 = ruleEngineMock.hasRole(RULE_ENGINE_ROLE, ADDRESS1); + bool res3 = ruleEngineMock.hasRole(RULE_ENGINE_OPERATOR_ROLE, ADDRESS1); assertEq(res3, true); } } diff --git a/test/RuleEngine/RuleEngineDeployment.t.sol b/test/RuleEngine/RuleEngineDeployment.t.sol index 923b709..258d75e 100644 --- a/test/RuleEngine/RuleEngineDeployment.t.sol +++ b/test/RuleEngine/RuleEngineDeployment.t.sol @@ -6,9 +6,10 @@ import "../HelperContract.sol"; import "CMTAT/mocks/MinimalForwarderMock.sol"; import "src/RuleEngine.sol"; import "src/RuleEngine.sol"; + /** -* @title General functions of the RuleEngine -*/ + * @title General functions of the RuleEngine + */ contract RuleEngineTest is Test, HelperContract { RuleEngine ruleEngineMock; uint8 resUint8; @@ -18,15 +19,12 @@ contract RuleEngineTest is Test, HelperContract { uint8 CODE_NONEXISTENT = 255; // Arrange - function setUp() public { - - } + function setUp() public {} function testRightDeployment() public { // Arrange vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - MinimalForwarderMock forwarder = new MinimalForwarderMock( - ); + MinimalForwarderMock forwarder = new MinimalForwarderMock(); forwarder.initialize(ERC2771ForwarderDomain); // Act @@ -37,7 +35,10 @@ contract RuleEngineTest is Test, HelperContract { ); // assert - resBool = ruleEngineMock.hasRole(RULE_ENGINE_ROLE, RULE_ENGINE_OPERATOR_ADDRESS); + resBool = ruleEngineMock.hasRole( + RULE_ENGINE_OPERATOR_ROLE, + RULE_ENGINE_OPERATOR_ADDRESS + ); assertEq(resBool, true); resBool = ruleEngineMock.isTrustedForwarder(address(forwarder)); assertEq(resBool, true); @@ -46,8 +47,7 @@ contract RuleEngineTest is Test, HelperContract { function testCannotDeployContractifAdminAddressIsZero() public { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); - MinimalForwarderMock forwarder = new MinimalForwarderMock( - ); + MinimalForwarderMock forwarder = new MinimalForwarderMock(); forwarder.initialize(ERC2771ForwarderDomain); vm.expectRevert(RuleEngine_AdminWithAddressZeroNotAllowed.selector); // Act @@ -57,6 +57,4 @@ contract RuleEngineTest is Test, HelperContract { ZERO_ADDRESS ); } - - } diff --git a/test/RuleEngine/ruleEngineOperation/RuleEngineOperation.t.sol b/test/RuleEngine/ruleEngineOperation/RuleEngineOperation.t.sol index 48e4383..0b535f0 100644 --- a/test/RuleEngine/ruleEngineOperation/RuleEngineOperation.t.sol +++ b/test/RuleEngine/ruleEngineOperation/RuleEngineOperation.t.sol @@ -4,10 +4,11 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../../HelperContract.sol"; import "src/RuleEngine.sol"; + //ADmin, forwarder irrect /RuleEngine /** -* @title General functions of the RuleEngine -*/ + * @title General functions of the RuleEngine + */ contract RuleEngineOperationTest is Test, HelperContract { RuleEngine ruleEngineMock; uint8 resUint8; @@ -16,31 +17,32 @@ contract RuleEngineOperationTest is Test, HelperContract { string resString; uint8 CODE_NONEXISTENT = 255; - TIME_LIMIT timeLimit_ = TIME_LIMIT({ - timeLimitToApprove: DEFAULT_TIME_LIMIT_TO_APPROVE, - timeLimitToTransfer: DEFAULT_TIME_LIMIT_TO_TRANSFER + TIME_LIMIT timeLimit_ = + TIME_LIMIT({ + timeLimitToApprove: DEFAULT_TIME_LIMIT_TO_APPROVE, + timeLimitToTransfer: DEFAULT_TIME_LIMIT_TO_TRANSFER }); - ISSUANCE issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval:false, - authorizedBurnWithoutApproval:false + ISSUANCE issuanceOption_ = + ISSUANCE({ + authorizedMintWithoutApproval: false, + authorizedBurnWithoutApproval: false }); - AUTOMATIC_APPROVAL automaticApproval_ = AUTOMATIC_APPROVAL({ + AUTOMATIC_APPROVAL automaticApproval_ = + AUTOMATIC_APPROVAL({ isActivate: false, timeLimitBeforeAutomaticApproval: 0 }); - AUTOMATIC_TRANSFER automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate:false, - cmtat: IERC20(address(0)) - }); - OPTION options = OPTION({ - issuance:issuanceOption_, + AUTOMATIC_TRANSFER automaticTransfer_ = + AUTOMATIC_TRANSFER({isActivate: false, cmtat: IERC20(address(0))}); + OPTION options = + OPTION({ + issuance: issuanceOption_, timeLimit: timeLimit_, automaticApproval: automaticApproval_, - automaticTransfer:automaticTransfer_ + automaticTransfer: automaticTransfer_ }); - // Arrange function setUp() public { vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); @@ -52,11 +54,10 @@ contract RuleEngineOperationTest is Test, HelperContract { ruleConditionalTransfer = new RuleConditionalTransfer( CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, ZERO_ADDRESS, - ruleEngineMock, + ruleEngineMock, options ); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); ruleEngineMock.addRuleOperation(ruleConditionalTransfer); // Arrange - Assert @@ -68,21 +69,25 @@ contract RuleEngineOperationTest is Test, HelperContract { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); address[] memory RuleConditionalTransferTab = new address[](2); - RuleConditionalTransferTab[0] = address(IRuleOperation(RuleConditionalTransfer1)); - RuleConditionalTransferTab[1] = address(IRuleOperation(RuleConditionalTransfer2)); + RuleConditionalTransferTab[0] = address( + IRuleOperation(RuleConditionalTransfer1) + ); + RuleConditionalTransferTab[1] = address( + IRuleOperation(RuleConditionalTransfer2) + ); // Act vm.expectEmit(true, false, false, false); emit AddRule(address(RuleConditionalTransfer1)); @@ -90,7 +95,10 @@ contract RuleEngineOperationTest is Test, HelperContract { emit AddRule(address(RuleConditionalTransfer2)); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesOperation, RuleConditionalTransferTab) + abi.encodeCall( + ruleEngineMock.setRulesOperation, + RuleConditionalTransferTab + ) ); // Assert @@ -103,11 +111,11 @@ contract RuleEngineOperationTest is Test, HelperContract { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); address[] memory RuleConditionalTransferTab = new address[](2); RuleConditionalTransferTab[0] = address(RuleConditionalTransfer1); RuleConditionalTransferTab[1] = address(RuleConditionalTransfer1); @@ -116,7 +124,10 @@ contract RuleEngineOperationTest is Test, HelperContract { vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); vm.expectRevert(RuleEngine_RuleAlreadyExists.selector); (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesOperation, RuleConditionalTransferTab) + abi.encodeCall( + ruleEngineMock.setRulesOperation, + RuleConditionalTransferTab + ) ); // Assert @@ -137,7 +148,10 @@ contract RuleEngineOperationTest is Test, HelperContract { // Act vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesOperation, RuleConditionalTransferTab) + abi.encodeCall( + ruleEngineMock.setRulesOperation, + RuleConditionalTransferTab + ) ); // Assert @@ -160,7 +174,10 @@ contract RuleEngineOperationTest is Test, HelperContract { vm.expectRevert("The array is empty2"); (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesOperation, RuleConditionalTransferTab) + abi.encodeCall( + ruleEngineMock.setRulesOperation, + RuleConditionalTransferTab + ) ); resBool = ruleEngineMock.validateTransfer(ADDRESS1, ADDRESS2, 20); @@ -180,25 +197,32 @@ contract RuleEngineOperationTest is Test, HelperContract { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); address[] memory RuleConditionalTransferTab = new address[](2); - RuleConditionalTransferTab[0] = address(IRuleOperation(RuleConditionalTransfer1)); - RuleConditionalTransferTab[1] = address(IRuleOperation(RuleConditionalTransfer2)); + RuleConditionalTransferTab[0] = address( + IRuleOperation(RuleConditionalTransfer1) + ); + RuleConditionalTransferTab[1] = address( + IRuleOperation(RuleConditionalTransfer2) + ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesOperation, RuleConditionalTransferTab) + abi.encodeCall( + ruleEngineMock.setRulesOperation, + RuleConditionalTransferTab + ) ); ruleEngineMock.rulesOperation(); // Assert - Arrange @@ -219,25 +243,32 @@ contract RuleEngineOperationTest is Test, HelperContract { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); address[] memory RuleConditionalTransferTab = new address[](2); - RuleConditionalTransferTab[0] = address(IRuleOperation(RuleConditionalTransfer1)); - RuleConditionalTransferTab[1] = address(IRuleOperation(RuleConditionalTransfer2)); + RuleConditionalTransferTab[0] = address( + IRuleOperation(RuleConditionalTransfer1) + ); + RuleConditionalTransferTab[1] = address( + IRuleOperation(RuleConditionalTransfer2) + ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesOperation, RuleConditionalTransferTab) + abi.encodeCall( + ruleEngineMock.setRulesOperation, + RuleConditionalTransferTab + ) ); // Act @@ -251,7 +282,10 @@ contract RuleEngineOperationTest is Test, HelperContract { // Can set again the previous rules vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); (resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesOperation, RuleConditionalTransferTab) + abi.encodeCall( + ruleEngineMock.setRulesOperation, + RuleConditionalTransferTab + ) ); assertEq(resCallBool, true); // Arrange before assert @@ -273,11 +307,11 @@ contract RuleEngineOperationTest is Test, HelperContract { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); // Act vm.expectEmit(true, false, false, false); @@ -337,11 +371,11 @@ contract RuleEngineOperationTest is Test, HelperContract { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); // Act vm.expectRevert(RuleEngine_RuleDoNotMatch.selector); @@ -357,11 +391,11 @@ contract RuleEngineOperationTest is Test, HelperContract { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); ruleEngineMock.addRuleOperation(RuleConditionalTransfer1); @@ -380,11 +414,11 @@ contract RuleEngineOperationTest is Test, HelperContract { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); ruleEngineMock.addRuleOperation(RuleConditionalTransfer1); @@ -404,21 +438,21 @@ contract RuleEngineOperationTest is Test, HelperContract { // First rule vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); ruleEngineMock.addRuleOperation(RuleConditionalTransfer1); // Second rule vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); ruleEngineMock.addRuleOperation(RuleConditionalTransfer2); @@ -447,23 +481,30 @@ contract RuleEngineOperationTest is Test, HelperContract { // Arrange RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); address[] memory RuleConditionalTransferTab = new address[](2); - RuleConditionalTransferTab[0] = address(IRuleOperation(RuleConditionalTransfer1)); - RuleConditionalTransferTab[1] = address(IRuleOperation(RuleConditionalTransfer2)); + RuleConditionalTransferTab[0] = address( + IRuleOperation(RuleConditionalTransfer1) + ); + RuleConditionalTransferTab[1] = address( + IRuleOperation(RuleConditionalTransfer2) + ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesOperation, RuleConditionalTransferTab) + abi.encodeCall( + ruleEngineMock.setRulesOperation, + RuleConditionalTransferTab + ) ); // Arrange - Assert @@ -479,23 +520,30 @@ contract RuleEngineOperationTest is Test, HelperContract { function testGetRule() public { // Arrange RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); address[] memory RuleConditionalTransferTab = new address[](2); - RuleConditionalTransferTab[0] = address(IRuleOperation(RuleConditionalTransfer1)); - RuleConditionalTransferTab[1] = address(IRuleOperation(RuleConditionalTransfer2)); + RuleConditionalTransferTab[0] = address( + IRuleOperation(RuleConditionalTransfer1) + ); + RuleConditionalTransferTab[1] = address( + IRuleOperation(RuleConditionalTransfer2) + ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesOperation, RuleConditionalTransferTab) + abi.encodeCall( + ruleEngineMock.setRulesOperation, + RuleConditionalTransferTab + ) ); // Arrange - Assert assertEq(resCallBool, true); @@ -510,23 +558,30 @@ contract RuleEngineOperationTest is Test, HelperContract { function testGetRules() public { // Arrange RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); address[] memory RuleConditionalTransferTab = new address[](2); - RuleConditionalTransferTab[0] = address(IRuleOperation(RuleConditionalTransfer1)); - RuleConditionalTransferTab[1] = address(IRuleOperation(RuleConditionalTransfer2)); + RuleConditionalTransferTab[0] = address( + IRuleOperation(RuleConditionalTransfer1) + ); + RuleConditionalTransferTab[1] = address( + IRuleOperation(RuleConditionalTransfer2) + ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesOperation, RuleConditionalTransferTab) + abi.encodeCall( + ruleEngineMock.setRulesOperation, + RuleConditionalTransferTab + ) ); // Arrange - Assert assertEq(resCallBool, true); @@ -544,33 +599,45 @@ contract RuleEngineOperationTest is Test, HelperContract { function testCanGetRuleIndex() public { // Arrange RuleConditionalTransfer RuleConditionalTransfer1 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); RuleConditionalTransfer RuleConditionalTransfer2 = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - - ); + CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, + ZERO_ADDRESS, + ruleEngineMock, + options + ); address[] memory RuleConditionalTransferTab = new address[](2); - RuleConditionalTransferTab[0] = address(IRuleOperation(RuleConditionalTransfer1)); - RuleConditionalTransferTab[1] = address(IRuleOperation(RuleConditionalTransfer2)); + RuleConditionalTransferTab[0] = address( + IRuleOperation(RuleConditionalTransfer1) + ); + RuleConditionalTransferTab[1] = address( + IRuleOperation(RuleConditionalTransfer2) + ); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); (bool resCallBool, ) = address(ruleEngineMock).call( - abi.encodeCall(ruleEngineMock.setRulesOperation, RuleConditionalTransferTab) + abi.encodeCall( + ruleEngineMock.setRulesOperation, + RuleConditionalTransferTab + ) ); // Arrange - Assert assertEq(resCallBool, true); // Act - uint256 index1 = ruleEngineMock.getRuleIndexOperation(RuleConditionalTransfer1); - uint256 index2 = ruleEngineMock.getRuleIndexOperation(RuleConditionalTransfer2); + uint256 index1 = ruleEngineMock.getRuleIndexOperation( + RuleConditionalTransfer1 + ); + uint256 index2 = ruleEngineMock.getRuleIndexOperation( + RuleConditionalTransfer2 + ); // Length of the list because RuleConditionalTransfer is not in the list - uint256 index3 = ruleEngineMock.getRuleIndexOperation(ruleConditionalTransfer); + uint256 index3 = ruleEngineMock.getRuleIndexOperation( + ruleConditionalTransfer + ); // Assert assertEq(index1, 0); diff --git a/test/RuleEngine/ruleEngineOperation/RuleEngineRestriction.t.sol b/test/RuleEngine/ruleEngineOperation/RuleEngineRestriction.t.sol index 36261be..1f052a3 100644 --- a/test/RuleEngine/ruleEngineOperation/RuleEngineRestriction.t.sol +++ b/test/RuleEngine/ruleEngineOperation/RuleEngineRestriction.t.sol @@ -4,10 +4,11 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../../HelperContract.sol"; import "src/RuleEngine.sol"; + //ADmin, forwarder irrect /RuleEngine /** -* @title General functions of the RuleEngine -*/ + * @title General functions of the RuleEngine + */ contract RuleEngineOperationTest is Test, HelperContract { RuleEngine ruleEngineMock; uint8 resUint8; @@ -17,35 +18,39 @@ contract RuleEngineOperationTest is Test, HelperContract { uint8 CODE_NONEXISTENT = 255; uint256 defaultValue = 20; - TIME_LIMIT timeLimit_ = TIME_LIMIT({ - timeLimitToApprove: DEFAULT_TIME_LIMIT_TO_APPROVE, - timeLimitToTransfer: DEFAULT_TIME_LIMIT_TO_TRANSFER + TIME_LIMIT timeLimit_ = + TIME_LIMIT({ + timeLimitToApprove: DEFAULT_TIME_LIMIT_TO_APPROVE, + timeLimitToTransfer: DEFAULT_TIME_LIMIT_TO_TRANSFER }); - ISSUANCE issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval:false, - authorizedBurnWithoutApproval:false + ISSUANCE issuanceOption_ = + ISSUANCE({ + authorizedMintWithoutApproval: false, + authorizedBurnWithoutApproval: false }); - AUTOMATIC_APPROVAL automaticApproval_ = AUTOMATIC_APPROVAL({ + AUTOMATIC_APPROVAL automaticApproval_ = + AUTOMATIC_APPROVAL({ isActivate: false, timeLimitBeforeAutomaticApproval: 0 }); - AUTOMATIC_TRANSFER automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate:false, - cmtat: IERC20(address(0)) - }); - OPTION options = OPTION({ - issuance:issuanceOption_, + AUTOMATIC_TRANSFER automaticTransfer_ = + AUTOMATIC_TRANSFER({isActivate: false, cmtat: IERC20(address(0))}); + OPTION options = + OPTION({ + issuance: issuanceOption_, timeLimit: timeLimit_, automaticApproval: automaticApproval_, - automaticTransfer:automaticTransfer_ + automaticTransfer: automaticTransfer_ }); - TransferRequestKeyElement transferRequestInput = TransferRequestKeyElement({ + TransferRequestKeyElement transferRequestInput = + TransferRequestKeyElement({ from: ADDRESS1, to: ADDRESS2, - value:defaultValue - }); + value: defaultValue + }); + // Arrange function setUp() public { vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); @@ -57,11 +62,10 @@ contract RuleEngineOperationTest is Test, HelperContract { ruleConditionalTransfer = new RuleConditionalTransfer( CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, ZERO_ADDRESS, - ruleEngineMock, + ruleEngineMock, options ); - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); ruleEngineMock.addRuleOperation(ruleConditionalTransfer); // Arrange - Assert @@ -75,7 +79,9 @@ contract RuleEngineOperationTest is Test, HelperContract { bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); vm.expectEmit(true, true, true, true); emit transferApproved(key, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequestWithApproval(transferRequestInput); + ruleConditionalTransfer.createTransferRequestWithApproval( + transferRequestInput + ); // Act resUint8 = ruleEngineMock.detectTransferRestriction( ADDRESS1, @@ -111,7 +117,6 @@ contract RuleEngineOperationTest is Test, HelperContract { assertEq(resString, "Unknown restriction code"); } - function testMessageForTransferRestrictionWithUnknownRestrictionCode() public { diff --git a/test/RuleEngine/ruleEngineValidation/RuleEngineRestriction.t.sol b/test/RuleEngine/ruleEngineValidation/RuleEngineRestriction.t.sol index feabefc..f6d10a7 100644 --- a/test/RuleEngine/ruleEngineValidation/RuleEngineRestriction.t.sol +++ b/test/RuleEngine/ruleEngineValidation/RuleEngineRestriction.t.sol @@ -6,8 +6,8 @@ import "../../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title tests concerning the restrictions and validation for the transfers -*/ + * @title tests concerning the restrictions and validation for the transfers + */ contract RuleEngineRestrictionTest is Test, HelperContract { RuleEngine ruleEngineMock; uint8 resUint8; @@ -123,7 +123,7 @@ contract RuleEngineRestrictionTest is Test, HelperContract { // ruleEngineValidation // Act - resUint8 = ruleEngineMock.detectTransferRestrictionValidation( + resUint8 = ruleEngineMock.detectTransferRestrictionValidation( ADDRESS1, ADDRESS2, 20 @@ -181,11 +181,14 @@ contract RuleEngineRestrictionTest is Test, HelperContract { // ruleEngineValidation // Act - resBool = ruleEngineMock.validateTransferValidation(ADDRESS1, ADDRESS2, 20); + resBool = ruleEngineMock.validateTransferValidation( + ADDRESS1, + ADDRESS2, + 20 + ); // Assert assertEq(resBool, true); - } function testValidateTransferRestricted() public { @@ -198,7 +201,11 @@ contract RuleEngineRestrictionTest is Test, HelperContract { // ruleEngineValidation // Act - resBool = ruleEngineMock.validateTransferValidation(ADDRESS1, ADDRESS2, 20); + resBool = ruleEngineMock.validateTransferValidation( + ADDRESS1, + ADDRESS2, + 20 + ); // Assert assertFalse(resBool); diff --git a/test/RuleEngine/ruleEngineValidation/RuleEngineValidation.t.sol b/test/RuleEngine/ruleEngineValidation/RuleEngineValidation.t.sol index 923b411..896a054 100644 --- a/test/RuleEngine/ruleEngineValidation/RuleEngineValidation.t.sol +++ b/test/RuleEngine/ruleEngineValidation/RuleEngineValidation.t.sol @@ -6,8 +6,8 @@ import "../../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title General functions of the RuleEngine -*/ + * @title General functions of the RuleEngine + */ contract RuleEngineValidationTest is Test, HelperContract { RuleEngine ruleEngineMock; uint8 resUint8; @@ -122,7 +122,6 @@ contract RuleEngineValidationTest is Test, HelperContract { assertEq(resUint256, 1); } - function testCannotSetEmptyRulesT1() public { // Arrange address[] memory ruleWhitelistTab = new address[](0); diff --git a/test/RuleSanctionList/RuleSanctionListAdd.t.sol b/test/RuleSanctionList/RuleSanctionListAdd.t.sol index ae5b6d5..a8d9fcf 100644 --- a/test/RuleSanctionList/RuleSanctionListAdd.t.sol +++ b/test/RuleSanctionList/RuleSanctionListAdd.t.sol @@ -6,13 +6,14 @@ import "../HelperContract.sol"; import "src/RuleEngine.sol"; import "../utils/SanctionListOracle.sol"; + /** -* @title General functions of the ruleSanctionList -*/ + * @title General functions of the ruleSanctionList + */ contract RuleSanctionlistTest is Test, HelperContract { // Custom error openZeppelin error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); - + uint256 resUint256; uint8 resUint8; bool resBool; @@ -21,6 +22,7 @@ contract RuleSanctionlistTest is Test, HelperContract { uint8 CODE_NONEXISTENT = 255; SanctionListOracle sanctionlistOracle; RuleSanctionList ruleSanctionList; + // Arrange function setUp() public { vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); @@ -30,7 +32,6 @@ contract RuleSanctionlistTest is Test, HelperContract { SANCTIONLIST_OPERATOR_ADDRESS, ZERO_ADDRESS ); - } function testCanSetOracle() public { @@ -41,7 +42,12 @@ contract RuleSanctionlistTest is Test, HelperContract { function testCannotAttackerSetOracle() public { vm.prank(ATTACKER); vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, SANCTIONLIST_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + SANCTIONLIST_ROLE + ) + ); ruleSanctionList.setSanctionListOracle(address(sanctionlistOracle)); } } diff --git a/test/RuleSanctionList/RuleSanctionListDeployment.t.sol b/test/RuleSanctionList/RuleSanctionListDeployment.t.sol index 4b1b3cf..2745d2d 100644 --- a/test/RuleSanctionList/RuleSanctionListDeployment.t.sol +++ b/test/RuleSanctionList/RuleSanctionListDeployment.t.sol @@ -4,9 +4,10 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; import "CMTAT/mocks/MinimalForwarderMock.sol"; + /** -* @title General functions of the ruleSanctionList -*/ + * @title General functions of the ruleSanctionList + */ contract RuleSanctionListDeploymentTest is Test, HelperContract { uint256 resUint256; uint8 resUint8; @@ -15,16 +16,14 @@ contract RuleSanctionListDeploymentTest is Test, HelperContract { string resString; uint8 CODE_NONEXISTENT = 255; RuleSanctionList ruleSanctionList; - // Arrange - function setUp() public { - } + // Arrange + function setUp() public {} function testRightDeployment() public { // Arrange vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - MinimalForwarderMock forwarder = new MinimalForwarderMock( - ); + MinimalForwarderMock forwarder = new MinimalForwarderMock(); forwarder.initialize(ERC2771ForwarderDomain); vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); ruleSanctionList = new RuleSanctionList( @@ -33,7 +32,10 @@ contract RuleSanctionListDeploymentTest is Test, HelperContract { ); // assert - resBool = ruleSanctionList.hasRole(SANCTIONLIST_ROLE, SANCTIONLIST_OPERATOR_ADDRESS); + resBool = ruleSanctionList.hasRole( + SANCTIONLIST_ROLE, + SANCTIONLIST_OPERATOR_ADDRESS + ); assertEq(resBool, true); resBool = ruleSanctionList.isTrustedForwarder(address(forwarder)); assertEq(resBool, true); @@ -42,14 +44,12 @@ contract RuleSanctionListDeploymentTest is Test, HelperContract { function testCannotDeployContractIfAdminAddressIsZero() public { // Arrange vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - MinimalForwarderMock forwarder = new MinimalForwarderMock( - ); + MinimalForwarderMock forwarder = new MinimalForwarderMock(); forwarder.initialize(ERC2771ForwarderDomain); - vm.expectRevert(RuleSanctionList_AdminWithAddressZeroNotAllowed.selector); - vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - ruleSanctionList = new RuleSanctionList( - address(0), - address(forwarder) + vm.expectRevert( + RuleSanctionList_AdminWithAddressZeroNotAllowed.selector ); + vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); + ruleSanctionList = new RuleSanctionList(address(0), address(forwarder)); } } diff --git a/test/RuleSanctionList/RuleSanctionListTest.t.sol b/test/RuleSanctionList/RuleSanctionListTest.t.sol index 73a1985..8c9815e 100644 --- a/test/RuleSanctionList/RuleSanctionListTest.t.sol +++ b/test/RuleSanctionList/RuleSanctionListTest.t.sol @@ -5,9 +5,10 @@ import "forge-std/Test.sol"; import "../HelperContract.sol"; import "src/RuleEngine.sol"; import "../utils/SanctionListOracle.sol"; + /** -* @title General functions of the ruleSanctionList -*/ + * @title General functions of the ruleSanctionList + */ contract RuleSanctionlistTest is Test, HelperContract { uint256 resUint256; uint8 resUint8; @@ -17,6 +18,7 @@ contract RuleSanctionlistTest is Test, HelperContract { uint8 CODE_NONEXISTENT = 255; SanctionListOracle sanctionlistOracle; RuleSanctionList ruleSanctionList; + // Arrange function setUp() public { vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); @@ -33,7 +35,7 @@ contract RuleSanctionlistTest is Test, HelperContract { function testCanReturnTransferRestrictionCode() public { // Act resBool = ruleSanctionList.canReturnTransferRestrictionCode( - CODE_ADDRESS_FROM_IS_SANCTIONED + CODE_ADDRESS_FROM_IS_SANCTIONED ); // Assert assertEq(resBool, true); @@ -54,13 +56,13 @@ contract RuleSanctionlistTest is Test, HelperContract { function testReturnTheRightMessageForAGivenCode() public { // Assert resString = ruleSanctionList.messageForTransferRestriction( - CODE_ADDRESS_FROM_IS_SANCTIONED + CODE_ADDRESS_FROM_IS_SANCTIONED ); // Assert assertEq(resString, TEXT_ADDRESS_FROM_IS_SANCTIONED); // Act resString = ruleSanctionList.messageForTransferRestriction( - CODE_ADDRESS_TO_IS_SANCTIONED + CODE_ADDRESS_TO_IS_SANCTIONED ); // Assert assertEq(resString, TEXT_ADDRESS_TO_IS_SANCTIONED); diff --git a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol index 65bde0c..e16cb74 100644 --- a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol +++ b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol @@ -6,8 +6,8 @@ import "../../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title Tests on the Access Control -*/ + * @title Tests on the Access Control + */ contract RuleWhitelistAccessControl is Test, HelperContract { // Custom error openZeppelin error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); @@ -32,7 +32,12 @@ contract RuleWhitelistAccessControl is Test, HelperContract { function testCannotAttackerAddAddressToTheList() public { vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, ADDRESS_LIST_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + ADDRESS_LIST_ROLE + ) + ); vm.prank(ATTACKER); ruleWhitelist.addAddressToTheList(ADDRESS1); @@ -53,7 +58,12 @@ contract RuleWhitelistAccessControl is Test, HelperContract { // Act vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, ADDRESS_LIST_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + ADDRESS_LIST_ROLE + ) + ); vm.prank(ATTACKER); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( @@ -85,7 +95,12 @@ contract RuleWhitelistAccessControl is Test, HelperContract { // Act vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, ADDRESS_LIST_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + ADDRESS_LIST_ROLE + ) + ); vm.prank(ATTACKER); ruleWhitelist.removeAddressFromTheList(ADDRESS1); @@ -117,7 +132,12 @@ contract RuleWhitelistAccessControl is Test, HelperContract { // Act vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, ADDRESS_LIST_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ATTACKER, + ADDRESS_LIST_ROLE + ) + ); vm.prank(ATTACKER); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( diff --git a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol index 96f85dd..9c9404b 100644 --- a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol +++ b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol @@ -7,8 +7,8 @@ import "../../../lib/openzeppelin-contracts/contracts/access/AccessControl.sol"; import "src/RuleEngine.sol"; /** -* @title Tests on the provided functions by OpenZeppelin -*/ + * @title Tests on the provided functions by OpenZeppelin + */ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl { // Defined in CMTAT.sol uint8 constant TRANSFER_OK = 0; @@ -33,7 +33,11 @@ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); vm.expectEmit(true, true, false, true); - emit RoleGranted(ADDRESS_LIST_ROLE, ADDRESS1, WHITELIST_OPERATOR_ADDRESS); + emit RoleGranted( + ADDRESS_LIST_ROLE, + ADDRESS1, + WHITELIST_OPERATOR_ADDRESS + ); ruleWhitelist.grantRole(ADDRESS_LIST_ROLE, ADDRESS1); // Assert bool res1 = ruleWhitelist.hasRole(ADDRESS_LIST_ROLE, ADDRESS1); @@ -51,7 +55,11 @@ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); vm.expectEmit(true, true, false, true); - emit RoleRevoked(ADDRESS_LIST_ROLE, ADDRESS1, WHITELIST_OPERATOR_ADDRESS); + emit RoleRevoked( + ADDRESS_LIST_ROLE, + ADDRESS1, + WHITELIST_OPERATOR_ADDRESS + ); ruleWhitelist.revokeRole(ADDRESS_LIST_ROLE, ADDRESS1); // Assert bool res2 = ruleWhitelist.hasRole(ADDRESS_LIST_ROLE, ADDRESS1); @@ -62,10 +70,15 @@ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl { // Arrange - Assert bool res1 = ruleWhitelist.hasRole(ADDRESS_LIST_ROLE, ADDRESS1); assertFalse(res1); - + // Act vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ADDRESS2, DEFAULT_ADMIN_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ADDRESS2, + DEFAULT_ADMIN_ROLE + ) + ); vm.prank(ADDRESS2); ruleWhitelist.grantRole(ADDRESS_LIST_ROLE, ADDRESS1); // Assert @@ -88,7 +101,12 @@ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl { // Act vm.prank(ADDRESS2); vm.expectRevert( - abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ADDRESS2, DEFAULT_ADMIN_ROLE)); + abi.encodeWithSelector( + AccessControlUnauthorizedAccount.selector, + ADDRESS2, + DEFAULT_ADMIN_ROLE + ) + ); ruleWhitelist.revokeRole(ADDRESS_LIST_ROLE, ADDRESS1); // Assert diff --git a/test/RuleWhitelist/CMTATIntegration.t.sol b/test/RuleWhitelist/CMTATIntegration.t.sol index acd37d8..b91265b 100644 --- a/test/RuleWhitelist/CMTATIntegration.t.sol +++ b/test/RuleWhitelist/CMTATIntegration.t.sol @@ -7,8 +7,8 @@ import "../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title Integration test with the CMTAT -*/ + * @title Integration test with the CMTAT + */ contract CMTATIntegration is Test, HelperContract { // Defined in CMTAT.sol uint8 constant TRANSFER_OK = 0; @@ -47,7 +47,11 @@ contract CMTATIntegration is Test, HelperContract { // specific arrange vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock = new RuleEngine(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, address(CMTAT_CONTRACT)); + ruleEngineMock = new RuleEngine( + DEFAULT_ADMIN_ADDRESS, + ZERO_ADDRESS, + address(CMTAT_CONTRACT) + ); vm.prank(DEFAULT_ADMIN_ADDRESS); ruleEngineMock.addRuleValidation(ruleWhitelist); vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -66,7 +70,13 @@ contract CMTATIntegration is Test, HelperContract { // Arrange vm.prank(ADDRESS1); vm.expectRevert( - abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21)); + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + 21 + ) + ); // Act CMTAT_CONTRACT.transfer(ADDRESS2, 21); } @@ -79,7 +89,13 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( - abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount)); + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + amount + ) + ); // Act CMTAT_CONTRACT.transfer(ADDRESS2, amount); } @@ -92,7 +108,13 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( - abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount)); + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + amount + ) + ); // Act CMTAT_CONTRACT.transfer(ADDRESS2, amount); } diff --git a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol new file mode 100644 index 0000000..e6dc0e9 --- /dev/null +++ b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol @@ -0,0 +1,333 @@ +// 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 CMTATIntegrationWhitelistWrapper 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; + RuleWhitelist ruleWhitelist2; + RuleWhitelist ruleWhitelist3; + RuleWhitelistWrapper ruleWhitelistWrapper; + + // Arrange + function setUp() public { + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelist = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); + ruleWhitelist2 = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); + ruleWhitelist3 = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); + ruleWhitelistWrapper = new RuleWhitelistWrapper( + DEFAULT_ADMIN_ADDRESS, + ZERO_ADDRESS + ); + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelistWrapper.addRuleValidation(ruleWhitelist); + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelistWrapper.addRuleValidation(ruleWhitelist2); + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelistWrapper.addRuleValidation(ruleWhitelist3); + // global arrange + 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 + ); + + // specific arrange + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleEngineMock = new RuleEngine( + DEFAULT_ADMIN_ADDRESS, + ZERO_ADDRESS, + address(CMTAT_CONTRACT) + ); + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleEngineMock.addRuleValidation(ruleWhitelistWrapper); + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT); + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT.mint(ADDRESS2, ADDRESS2_BALANCE_INIT); + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT.mint(ADDRESS3, ADDRESS3_BALANCE_INIT); + vm.prank(DEFAULT_ADMIN_ADDRESS); + // We set the Rule Engine + CMTAT_CONTRACT.setRuleEngine(ruleEngineMock); + } + + /******* Transfer *******/ + function testCannotTransferWithoutAddressWhitelisted() public { + // Arrange + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + 21 + ) + ); + // Act + CMTAT_CONTRACT.transfer(ADDRESS2, 21); + } + + function testCannotTransferWithoutFromAddressWhitelisted() public { + // Arrange + uint256 amount = 21; + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelist.addAddressToTheList(ADDRESS2); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + amount + ) + ); + // Act + CMTAT_CONTRACT.transfer(ADDRESS2, amount); + } + + function testCannotTransferWithoutToAddressWhitelisted() public { + // Arrange + uint256 amount = 21; + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelist.addAddressToTheList(ADDRESS1); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + Errors.CMTAT_InvalidTransfer.selector, + ADDRESS1, + ADDRESS2, + amount + ) + ); + // Act + CMTAT_CONTRACT.transfer(ADDRESS2, amount); + } + + function testCanMakeATransferIfWhitelistedInSeveralDifferentList() public { + // Arrange + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelist.addAddressToTheList(ADDRESS1); + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelist3.addAddressToTheList(ADDRESS1); + + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelist2.addAddressToTheList(ADDRESS2); + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelist3.addAddressToTheList(ADDRESS2); + + // Act + vm.prank(ADDRESS1); + CMTAT_CONTRACT.transfer(ADDRESS2, 11); + + // Assert + resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); + assertEq(resUint256, 20); + resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS2); + assertEq(resUint256, 43); + resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS3); + assertEq(resUint256, 33); + } + + function testCanMakeATransferIfWhitelistedInDifferentList() public { + // Arrange + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelist.addAddressToTheList(ADDRESS1); + + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelist2.addAddressToTheList(ADDRESS2); + + // Act + vm.prank(ADDRESS1); + CMTAT_CONTRACT.transfer(ADDRESS2, 11); + + // Assert + resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); + assertEq(resUint256, 20); + resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS2); + assertEq(resUint256, 43); + resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS3); + assertEq(resUint256, 33); + } + + function testCanMakeATransfer() public { + // Arrange + address[] memory whitelist = new address[](2); + whitelist[0] = ADDRESS1; + whitelist[1] = ADDRESS2; + vm.prank(DEFAULT_ADMIN_ADDRESS); + (bool success, ) = address(ruleWhitelist).call( + abi.encodeWithSignature( + "addAddressesToTheList(address[])", + whitelist + ) + ); + require(success); + + // Act + vm.prank(ADDRESS1); + CMTAT_CONTRACT.transfer(ADDRESS2, 11); + + // Assert + resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); + assertEq(resUint256, 20); + resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS2); + assertEq(resUint256, 43); + resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS3); + assertEq(resUint256, 33); + } + + /******* detectTransferRestriction & messageForTransferRestriction *******/ + function testDetectAndMessageWithFromNotWhitelisted() public { + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelist.addAddressToTheList(ADDRESS2); + resBool = ruleWhitelist.addressIsListed(ADDRESS2); + // Assert + assertEq(resBool, true); + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( + ADDRESS1, + ADDRESS2, + 11 + ); + // Assert + assertEq(res1, CODE_ADDRESS_FROM_NOT_WHITELISTED); + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( + res1 + ); + // Assert + assertEq(message1, TEXT_ADDRESS_FROM_NOT_WHITELISTED); + } + + function testDetectAndMessageWithToNotWhitelisted() public { + // Arrange + // We add the sender to the whitelist + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelist.addAddressToTheList(ADDRESS1); + // Arrange - Assert + resBool = ruleWhitelist.addressIsListed(ADDRESS1); + assertEq(resBool, true); + // Act + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( + ADDRESS1, + ADDRESS2, + 11 + ); + // Assert + assertEq(res1, CODE_ADDRESS_TO_NOT_WHITELISTED); + // Act + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( + res1 + ); + // Assert + assertEq(message1, TEXT_ADDRESS_TO_NOT_WHITELISTED); + } + + function testDetectAndMessageWithFromAndToNotWhitelisted() public view { + // Act + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( + ADDRESS1, + ADDRESS2, + 11 + ); + + // Assert + assertEq(res1, CODE_ADDRESS_FROM_NOT_WHITELISTED); + // Act + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( + res1 + ); + + // Assert + assertEq(message1, TEXT_ADDRESS_FROM_NOT_WHITELISTED); + } + + function testCanReturnUnknownTextMessage() public view { + // Act + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( + 200 + ); + + // Assert + assertEq(message1, TEXT_CODE_NOT_FOUND); + } + + function testDetectAndMessageWithAValidTransfer() public { + // Arrange + // We add the sender and the recipient to the whitelist. + address[] memory whitelist = new address[](2); + whitelist[0] = ADDRESS1; + whitelist[1] = ADDRESS2; + vm.prank(DEFAULT_ADMIN_ADDRESS); + (bool success, ) = address(ruleWhitelist).call( + abi.encodeWithSignature( + "addAddressesToTheList(address[])", + whitelist + ) + ); + require(success); + // Act + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( + ADDRESS1, + ADDRESS2, + 11 + ); + // Assert + assertEq(res1, TRANSFER_OK); + // Act + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( + res1 + ); + // Assert + assertEq(message1, TEXT_TRANSFER_OK); + } + + function testCanMint() public { + // Arrange + // Add address zero to the whitelist + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelist.addAddressToTheList(ZERO_ADDRESS); + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleWhitelist.addAddressToTheList(ADDRESS1); + // Arrange - Assert + resBool = ruleWhitelist.addressIsListed(ZERO_ADDRESS); + assertEq(resBool, true); + + // Act + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT.mint(ADDRESS1, 11); + + // Assert + resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); + assertEq(resUint256, ADDRESS1_BALANCE_INIT + 11); + } +} diff --git a/test/RuleWhitelist/RuleWhitelist.t.sol b/test/RuleWhitelist/RuleWhitelist.t.sol index 47adc6d..d4734ef 100644 --- a/test/RuleWhitelist/RuleWhitelist.t.sol +++ b/test/RuleWhitelist/RuleWhitelist.t.sol @@ -6,8 +6,8 @@ import "../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title General functions of the RuleWhitelist -*/ + * @title General functions of the RuleWhitelist + */ contract RuleWhitelistTest is Test, HelperContract { uint256 resUint256; uint8 resUint8; @@ -25,7 +25,7 @@ contract RuleWhitelistTest is Test, HelperContract { ); } - function _addAddressesToTheList() internal { + function _addAddressesToTheList() internal { address[] memory whitelist = new address[](2); whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; diff --git a/test/RuleWhitelist/RuleWhitelistAdd.t.sol b/test/RuleWhitelist/RuleWhitelistAdd.t.sol index 5bca773..9d425b0 100644 --- a/test/RuleWhitelist/RuleWhitelistAdd.t.sol +++ b/test/RuleWhitelist/RuleWhitelistAdd.t.sol @@ -6,8 +6,8 @@ import "../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title Tests the functions to add addresses to the whitelist -*/ + * @title Tests the functions to add addresses to the whitelist + */ contract RuleWhitelistAddTest is Test, HelperContract { // Defined in CMTAT.sol uint8 constant TRANSFER_OK = 0; @@ -28,7 +28,7 @@ contract RuleWhitelistAddTest is Test, HelperContract { ); } - function _addAddressesToTheList() internal { + function _addAddressesToTheList() internal { address[] memory whitelist = new address[](2); whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; @@ -47,9 +47,18 @@ contract RuleWhitelistAddTest is Test, HelperContract { assertEq(resBool, true); resBool = ruleWhitelist.addressIsListed(ADDRESS2); assertEq(resBool, true); + address[] memory addressesListInput = new address[](2); + addressesListInput[0] = ADDRESS1; + addressesListInput[1] = ADDRESS2; + bool[] memory resBools = ruleWhitelist.addressIsListedBatch( + addressesListInput + ); + assertEq(resBools[0], true); + assertEq(resBools[1], true); + assertEq(resBools.length, 2); } - function testaddAddressToTheList() public { + function testAddAddressToTheList() public { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); ruleWhitelist.addAddressToTheList(ADDRESS1); @@ -57,11 +66,18 @@ contract RuleWhitelistAddTest is Test, HelperContract { // Assert resBool = ruleWhitelist.addressIsListed(ADDRESS1); assertEq(resBool, true); + address[] memory addressesListInput = new address[](1); + addressesListInput[0] = ADDRESS1; + bool[] memory resBools = ruleWhitelist.addressIsListedBatch( + addressesListInput + ); + assertEq(resBools[0], true); + assertEq(resBools.length, 1); resUint256 = ruleWhitelist.numberListedAddress(); assertEq(resUint256, 1); } - function testaddAddressesToTheList() public { + function testAddAddressesToTheList() public { // Arrange resUint256 = ruleWhitelist.numberListedAddress(); assertEq(resUint256, 0); diff --git a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol index 74f6f41..bddb163 100644 --- a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol +++ b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol @@ -5,9 +5,10 @@ import "forge-std/Test.sol"; import "../HelperContract.sol"; import "src/RuleEngine.sol"; import "CMTAT/mocks/MinimalForwarderMock.sol"; + /** -* @title General functions of the RuleWhitelist -*/ + * @title General functions of the RuleWhitelist + */ contract RuleWhitelistTest is Test, HelperContract { uint256 resUint256; uint8 resUint8; @@ -17,14 +18,12 @@ contract RuleWhitelistTest is Test, HelperContract { uint8 CODE_NONEXISTENT = 255; // Arrange - function setUp() public { - } + function setUp() public {} function testRightDeployment() public { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); - MinimalForwarderMock forwarder = new MinimalForwarderMock( - ); + MinimalForwarderMock forwarder = new MinimalForwarderMock(); forwarder.initialize(ERC2771ForwarderDomain); vm.prank(WHITELIST_OPERATOR_ADDRESS); ruleWhitelist = new RuleWhitelist( @@ -33,7 +32,10 @@ contract RuleWhitelistTest is Test, HelperContract { ); // assert - resBool = ruleWhitelist.hasRole(ADDRESS_LIST_ROLE, WHITELIST_OPERATOR_ADDRESS); + resBool = ruleWhitelist.hasRole( + ADDRESS_LIST_ROLE, + WHITELIST_OPERATOR_ADDRESS + ); assertEq(resBool, true); resBool = ruleWhitelist.isTrustedForwarder(address(forwarder)); assertEq(resBool, true); @@ -42,14 +44,12 @@ contract RuleWhitelistTest is Test, HelperContract { function testCannotDeployContractIfAdminAddressIsZero() public { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); - MinimalForwarderMock forwarder = new MinimalForwarderMock( - ); + MinimalForwarderMock forwarder = new MinimalForwarderMock(); forwarder.initialize(ERC2771ForwarderDomain); - vm.expectRevert(RuleAddressList_AdminWithAddressZeroNotAllowed.selector); - vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist = new RuleWhitelist( - address(0), - address(forwarder) + vm.expectRevert( + RuleAddressList_AdminWithAddressZeroNotAllowed.selector ); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist = new RuleWhitelist(address(0), address(forwarder)); } } diff --git a/test/RuleWhitelist/RuleWhitelistRemove.t.sol b/test/RuleWhitelist/RuleWhitelistRemove.t.sol index 89b0550..0edd432 100644 --- a/test/RuleWhitelist/RuleWhitelistRemove.t.sol +++ b/test/RuleWhitelist/RuleWhitelistRemove.t.sol @@ -6,8 +6,8 @@ import "../HelperContract.sol"; import "src/RuleEngine.sol"; /** -* @title Tests the functions to remove addresses from the whitelist -*/ + * @title Tests the functions to remove addresses from the whitelist + */ contract RuleWhitelistRemoveTest is Test, HelperContract { // Defined in CMTAT.sol uint8 constant TRANSFER_OK = 0; @@ -29,7 +29,7 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { ); } - function _addAddressesToTheList() internal { + function _addAddressesToTheList() internal { address[] memory whitelist = new address[](2); whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; diff --git a/test/utils/SanctionListOracle.sol b/test/utils/SanctionListOracle.sol index 308785c..2edaee7 100644 --- a/test/utils/SanctionListOracle.sol +++ b/test/utils/SanctionListOracle.sol @@ -2,25 +2,23 @@ pragma solidity ^0.8.20; /** -* @notice Test contract from -* https://etherscan.io/address/0x40c57923924b5c5c5455c48d93317139addac8fb#code -*/ + * @notice Test contract from + * https://etherscan.io/address/0x40c57923924b5c5c5455c48d93317139addac8fb#code + */ contract SanctionListOracle { + constructor() {} - constructor() {} + mapping(address => bool) private sanctionedAddresses; - mapping(address => bool) private sanctionedAddresses; + function addToSanctionsList(address newSanction) public { + sanctionedAddresses[newSanction] = true; + } + function removeFromSanctionsList(address removeSanction) public { + sanctionedAddresses[removeSanction] = true; + } - function addToSanctionsList(address newSanction) public{ - sanctionedAddresses[newSanction] = true; - } - - function removeFromSanctionsList(address removeSanction) public{ - sanctionedAddresses[removeSanction] = true; - } - - function isSanctioned(address addr) public view returns (bool) { - return sanctionedAddresses[addr] == true ; - } -} \ No newline at end of file + function isSanctioned(address addr) public view returns (bool) { + return sanctionedAddresses[addr] == true; + } +}