diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ecebbd0 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,28 @@ +name: Foundry CI + +on: + push: + branches: [dev, master, main] + pull_request: + branches: [dev, master, main] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Run Forge install + run: forge install + + - name: Run Forge build + run: forge build --sizes + + - name: Run Forge tests + run: forge test -vvv diff --git a/.gitignore b/.gitignore index 8211401..603dabe 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,7 @@ cache/ nethereum-gen.settings #hardhat artifacts/ -cache_hardhat/ \ No newline at end of file +cache_hardhat/ +#drawio +*.bkp +*.dtmp \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fb0250..4173bff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,14 @@ Please follow [https://changelog.md/](https://changelog.md/) conventions. -## v1.0.2 - 10120609 +## v1.0.3 - 20231122 + +- Upgrade the library CMTAT to the version [v2.3.1](https://github.com/CMTA/CMTAT/releases/tag/v2.3.1) +- Use custom errors instead of revert message (gas optimization) +- Add the rule `SanctionList` +- Upgrade OpenZeppelin to the version [v5.0.0](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.0.0) + +## v1.0.2 - 20230609 - Upgrade the library CMTAT to the vesion [v2.3.0](https://github.com/CMTA/CMTAT/releases/tag/v2.3.0) - Set the number of runs for the optimizer to 200 for Hardhat and Foundry, see [https://docs.soliditylang.org/en/v0.8.17/using-the-compiler.html#optimizer-options](https://docs.soliditylang.org/en/v0.8.17/using-the-compiler.html#optimizer-options) diff --git a/README.md b/README.md index 29ac8d1..6896844 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ +> To use the ruleEngine and the different rules, we recommend the latest audited version, from the [Releases](https://github.com/CMTA/CMTAT/releases) page. Currently, it is the version [v1.0.2](https://github.com/CMTA/RuleEngine/releases/tag/v1.0.2) + # RuleEngine This repository includes the RuleEngine contract for the [CMTAT](https://github.com/CMTA/CMTAT) token. -- The CMTAT version used is the version [v2.3.0](https://github.com/CMTA/CMTAT/releases/tag/v2.3.0) -- The OpenZeppelin version used is the version [4.8.1](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v4.8.1) +- The CMTAT version used is the version [v2.3.1](https://github.com/CMTA/CMTAT/releases/tag/v2.3.1) +- The OpenZeppelin version used is the version [v5.0.0](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.0.0) The CMTAT contracts and the OpenZeppelin library are included as a submodule of the present repository. @@ -12,28 +14,37 @@ The contracts have been audited by [ABDKConsulting](https://www.abdk.consulting/ #### First Audit - March 2022 +Fixed version : [v1.0.2](https://github.com/CMTA/RuleEngine/releases/tag/v1.0.2) + The first audit was performed by ABDK on the version [1.0.1](https://github.com/CMTA/RuleEngine/releases/tag/1.0.1). -The release 1.1 contains the different fixes and improvements related to this audit. +The release [v1.0.2](https://github.com/CMTA/RuleEngine/releases/tag/v1.0.2) contains the different fixes and improvements related to this audit. The temporary report is available in [Taurus. Audit 3.3.CollectedIssues.ods](doc/audits/Taurus.Audit3.3.CollectedIssues.ods) +The final report is available in [ABDK_CMTA_CMTATRuleEngine_v_1_0.pdf](https://github.com/CMTA/CMTAT/blob/master/doc/audits/ABDK_CMTA_CMTATRuleEngine_v_1_0/ABDK_CMTA_CMTATRuleEngine_v_1_0.pdf). + ### Tools -You will find the report performed with [Slither](https://github.com/crytic/slither) in [slither-report.md](doc/audits/tools/slither-report.md) +You will find the report performed with [Slither](https://github.com/crytic/slither) in + +| Version | File | +| ------- | ------------------------------------------------------------ | +| v1.0.2 | [v1.0.2-slither-report.md](./doc/audits/tools/v1.0.2-slither-report.md) | +| v1.0.3 | [v1.0.3-slither-report.md](./doc/audits/tools/v1.0.3-slither-report.md) | ## Documentation Here a summary of the main documentation -| Document | Link/Files | -| ----------------------------------- | ---------------------------------------------------- | -| Solidity API Documentation (docgen) | [doc/solidityAPI](./doc/solidityAPI) | -| Technical documentation | [doc/technical.md](./doc/technical.md) | -| Toolchain | [doc/TOOLCHAIN.md](./doc/TOOLCHAIN.md) | -| Functionalities | [doc/functionalities.pdf](./doc/functionalities.pdf) | -| Surya report | [doc/surya](./doc/surya) | -| Test | [doc/test/test.pdf](./doc/test/test.pdf) | +| Document | Link/Files | +| ----------------------------------- | ------------------------------------------------------ | +| Solidity API Documentation (docgen) | [doc/solidityAPI](./doc/solidityAPI) | +| Technical documentation | [doc/technical](./doc/technical) | +| Toolchain | [doc/TOOLCHAIN.md](./doc/TOOLCHAIN.md) | +| Functionalities | [doc/functionalities.pdf](./doc/functionalities.pdf) | +| Surya report | [doc/surya](./doc/surya) | +| Test (v1.0.2) | [doc/test/v1.0.2/test.pdf](./doc/test/v1.0.2/test.pdf) | @@ -66,7 +77,9 @@ forge update See also the command's [documentation](https://book.getfoundry.sh/reference/forge/forge-update). + ## Compilation + The official documentation is available in the Foundry [website](https://book.getfoundry.sh/reference/forge/build-commands) ``` forge build --contracts src/RuleEngine.sol @@ -101,11 +114,20 @@ forge coverage forge coverage --report lcov ``` -See [Solidity Coverage in VS Code with Foundry](https://mirror.xyz/devanon.eth/RrDvKPnlD-pmpuW7hQeR5wWdVjklrpOgPCOA-PJkWFU) +- Generate `index.html` + +```bash +forge coverage --report lcov && genhtml lcov.info --branch-coverage --output-dir coverage +``` + +See [Solidity Coverage in VS Code with Foundry](https://mirror.xyz/devanon.eth/RrDvKPnlD-pmpuW7hQeR5wWdVjklrpOgPCOA-PJkWFU) & [Foundry forge coverage](https://www.rareskills.io/post/foundry-forge-coverage) ## Deployment The official documentation is available in the Foundry [website](https://book.getfoundry.sh/reference/forge/deploy-commands) ### Script + +> This documentation has been written for the version v1.0.2 + To run the script for deployment, you need to create a .env file. The value for CMTAT.ADDRESS is require only to use the script **RuleEngine.s.sol** Warning : put your private key in a .env file is not the best secure way. @@ -130,6 +152,9 @@ forge script script/RuleEngineScript.s.sol:RuleEngineScript --rpc-url=$RPC_URL ``` ### Local + +> This documentation has been written for the version v1.0.2 + With Foundry, you [can create a local testnet](https://book.getfoundry.sh/reference/anvil/) node for deploying and testing smart contracts, based on the [Anvil](https://anvil.works/) framework. On Linux, using the default RPC URL, and Anvil's test private key, run: @@ -143,6 +168,3 @@ forge create CMTAT_BASE --rpc-url=$RPC_URL --private-key=$PRIVATE_KEY --construc ``` See also the command's [documentation](https://book.getfoundry.sh/reference/forge/deploy-command). - - - diff --git a/doc/accessControl/.$access-control.drawio.bkp b/doc/accessControl/.$access-control.drawio.bkp index a0d667c..0a8339b 100644 --- a/doc/accessControl/.$access-control.drawio.bkp +++ b/doc/accessControl/.$access-control.drawio.bkp @@ -1 +1 @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/doc/accessControl/access-control-RuleSanctionList.drawio.png b/doc/accessControl/access-control-RuleSanctionList.drawio.png new file mode 100644 index 0000000..056590f Binary files /dev/null and b/doc/accessControl/access-control-RuleSanctionList.drawio.png differ diff --git a/doc/accessControl/access-control.drawio b/doc/accessControl/access-control.drawio index 42f2a74..e200a74 100644 --- a/doc/accessControl/access-control.drawio +++ b/doc/accessControl/access-control.drawio @@ -1 +1 @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/doc/audits/tools/slither-report.md b/doc/audits/tools/v1.0.2-slither-report.md similarity index 98% rename from doc/audits/tools/slither-report.md rename to doc/audits/tools/v1.0.2-slither-report.md index 8d90d62..74c91fd 100644 --- a/doc/audits/tools/slither-report.md +++ b/doc/audits/tools/v1.0.2-slither-report.md @@ -73,7 +73,7 @@ Confidence: High > Remark: > > Not necessary, the latest solidity version at the time of this release is the version 0.8.20. -> The comment is good but we think three versions backwards is enough. +> The comment is good but we think that three versions backwards is enough. > It is not the best practice to use an outdated version because each version > fixes some bugs. diff --git a/doc/audits/tools/v1.0.3-slither-report.md b/doc/audits/tools/v1.0.3-slither-report.md new file mode 100644 index 0000000..dc5009e --- /dev/null +++ b/doc/audits/tools/v1.0.3-slither-report.md @@ -0,0 +1,18 @@ +**THIS CHECKLIST IS NOT COMPLETE**. Use `--show-ignored-findings` to show all the results. +Summary + - [solc-version](#solc-version) (1 results) (Informational) +## solc-version + +> Remark: +> +> Not necessary, the latest solidity version at the time of this release is the version 0.8.23. +> The comment is good but we think that three versions backwards is enough. +> It is not the best practice to use an outdated version because each version +> fixes some bugs. + +Impact: Informational +Confidence: High + + - [ ] ID-0 +solc-0.8.20 is not recommended for deployment + diff --git a/doc/codelist.md b/doc/codelist.md index b5a2624..26abf32 100644 --- a/doc/codelist.md +++ b/doc/codelist.md @@ -4,11 +4,13 @@ Here the list of codes used by the different rules -| Contract | Constant name | Value | -| ------------- | --------------------------------- | ----- | -| All | NO_ERROR | 0 | -| RuleWhitelist | CODE_ADDRESS_FROM_NOT_WHITELISTED | 20 | -| RuleWhitelist | CODE_ADDRESS_TO_NOT_WHITELISTED | 30 | +| Contract | Constant name | Value | +| ---------------- | --------------------------------- | ----- | +| All | NO_ERROR | 0 | +| RuleWhitelist | CODE_ADDRESS_FROM_NOT_WHITELISTED | 21 | +| RuleWhitelist | CODE_ADDRESS_TO_NOT_WHITELISTED | 22 | +| RuleSanctionList | CODE_ADDRESS_FROM_IS_SANCTIONED | 31 | +| RuleSanctionList | CODE_ADDRESS_TO_IS_SANCTIONED | 32 | diff --git a/doc/functionalities.odt b/doc/functionalities.odt index 13ca866..320a983 100644 Binary files a/doc/functionalities.odt and b/doc/functionalities.odt differ diff --git a/doc/functionalities.pdf b/doc/functionalities.pdf index 4a296df..7c5cf1c 100644 Binary files a/doc/functionalities.pdf and b/doc/functionalities.pdf differ diff --git a/doc/schema/RuleEngine b/doc/schema/RuleEngine new file mode 100644 index 0000000..a10c47c --- /dev/null +++ b/doc/schema/RuleEngine @@ -0,0 +1 @@ +1VpRc+I2EP41zLQPx1iSbfBjgPT60JtmLvRS+qbYAjQxFiOLA+7XV8aysSQTHIKJk5dI67Vk73777a5MD41Xu68cr5ffWETiHnSiXQ9NehACCAL5L5Psc4kHlWDBaaSUjoJH+osooaOkGxqRVFMUjMWCrnVhyJKEhEKTYc7ZVlebs1jfdY0XxBI8hji2pU80EstcChHyjxf+JHSxLLb2PTe/ssKFtnqVdIkjtq2I0H0PjTljIh+tdmMSZ9YrDJPf98eJq+WTcZKIJje4Uz4bcB+Tp/3fs5ftcPrPj/++qFV+4nij3nj8bXo3VU8s9oUdtksqyOMah9l8K33dQ6OlWMVyBuQQp+vc+nO6I3K/kf1wxU6EC7KriNTDfiVsRQTfSxV1FQ6U4RR0gOfl8+3REaDQWVZ9UAixcv6iXPtoHjlQFnqDtaBlLcFxks4J/02wHhwX13637EeS6C6Do5yFMU5TGuoG5GyTRJnlJo6cSaPx/b9y8sXpOwAWkll2ue+iQSGY7Ko3TPbV2QPhVL414Up40iMC8wUR5zFCIi1UbL9V/OLVuKWQcRJjQX/qAVbnKrXDA6PyiUtYAKjDAiLD2ynb8JCou6rxYCwEfQNfgbFQbhhroQNyyte+HEzIAtOUvZAks5pkKek3E0OSQNbZcLOK70LBpGNHWTRRyVZ/4WcSP7CUCsoSqfLMhGCrisJdTBfZBcGMyGUbEdOEjEv+fBUrzaPXM7xUEHoFJKgGJH5boeta1r5WjDp6eHpngvOkbXPcno/Ds/HqdSpefaQjATkXxqsfGJAysdJyvPoWguSQRliQqUoCNqKkCw6haWRLFYyhhADhNVG6olGUrTHiJKW/8PNhvQw86+zlDq/rjXrepBZOr8LfjN+yclKbaLVJXVw7fTQcIN0R78NJocLm85S04jnP8tz3TUzuk4Ukvi5UOt6wc5XOoDW6BDpdDi7my09Wt5hOhkN0IQ+65kK35cGhBQ3B5Qg6siKRHRaOUzuoukOEBbCvQIRu4ALNEwXiusuEgeW7SLYIoSgy2HeSCk7DQxX5MeUR2VFR0oQczyry4y3Z5P0FldeUSJxOMYnvWemi71T+jAWb8srQMXgF3pZXCisbaVpKigOUIxZ1rJ1J2VfI0IFhm8DuZsq+9CbtDLCPIpSxQOeMBZ2acua21rJ77RvzXntFDuwUNw3Mvt+9sNsbmN2ed2M2etuBQcKSrEyJcLo8QAHoGMnkD1jIIic5SKCDpFRijr2U58rQxpLKhSprtpwNQeN02C3IBY6rIQUV3dNbIReYhbVvLNQ25Or7VCmxSemjOR25H87pdS2qH8ttR89ysMgGpL/oS5WnzDwxTTNf84NFcz25b6lqWVgaRuhmzMN1zOLs6LWI+DmNY0PUvKup85vu2Su4DjjgfPHi1riuvc8oH56O+/CSPgS0xLyNibdbJ7sD30rR1+hDAvMDj/tqe9MyKUO7DuBHdI5ZVHPYcZuDsbI6qNYG6rY2ygPYEKXdBinwr9IsBwanAvMr5AlYSmDgfUVNnWOdfHyrKR9oH/nlIF/xupi3U2tLmK/CfFaNgTdgvi1WblwPdwvwFn36V2Fli+wD2G9WHp+G/NW52j6abour+w7wdL4GLmqDsN/2W47zoHY+J6jBpwH1CR6HZhp6F4/L6fGHY7n68fd36P5/ \ No newline at end of file diff --git a/doc/schema/RuleEngine.png b/doc/schema/RuleEngine.png new file mode 100644 index 0000000..3e891c6 Binary files /dev/null and b/doc/schema/RuleEngine.png differ diff --git a/doc/schema/uml.svg b/doc/schema/classDiagram1.0.2.svg similarity index 100% rename from doc/schema/uml.svg rename to doc/schema/classDiagram1.0.2.svg diff --git a/doc/schema/classDiagram1.0.3.svg b/doc/schema/classDiagram1.0.3.svg new file mode 100644 index 0000000..910e7dd --- /dev/null +++ b/doc/schema/classDiagram1.0.3.svg @@ -0,0 +1,212 @@ + + + + + + +UmlClassDiagram + + + +0 + +RuleEngine +src/RuleEngine.sol + +Internal: +   _rules: IRule[] +Public: +   RULE_ENGINE_ROLE: bytes32 +   _ruleIsPresent: mapping(IRule=>bool) + +Internal: +    _msgSender(): (sender: address) +    _msgData(): bytes +External: +    setRules(rules_: IRule[]) <<onlyRole>> +    rulesCount(): uint256 +    getRuleIndex(rule_: IRule): (index: uint256) +    rule(ruleId: uint256): IRule +    rules(): IRule[] +    messageForTransferRestriction(_restrictionCode: uint8): string +Public: +    <<event>> AddRule(rule: IRule) +    <<event>> RemoveRule(rule: IRule) +    <<event>> ClearRules(rulesRemoved: IRule[]) +    constructor(admin: address, forwarderIrrevocable: address) +    clearRules() <<onlyRole>> +    addRule(rule_: IRule) <<onlyRole>> +    removeRule(rule_: IRule, index: uint256) <<onlyRole>> +    detectTransferRestriction(_from: address, _to: address, _amount: uint256): uint8 +    validateTransfer(_from: address, _to: address, _amount: uint256): bool + + + +1 + +<<Abstract>> +MetaTxModuleStandalone +src/modules/MetaTxModuleStandalone.sol + +Internal: +    _msgSender(): (sender: address) +    _msgData(): bytes +Public: +    constructor(trustedForwarder: address) + + + +0->1 + + + + + +2 + +<<Interface>> +SanctionsList +src/rules/RuleSanctionList.sol + +External: +     isSanctioned(addr: address): bool + + + +3 + +RuleSanctionList +src/rules/RuleSanctionList.sol + +Public: +   sanctionsList: SanctionsList + +Internal: +    _msgSender(): (sender: address) +    _msgData(): bytes +External: +    canReturnTransferRestrictionCode(_restrictionCode: uint8): bool +    messageForTransferRestriction(_restrictionCode: uint8): string +Public: +    constructor(admin: address, forwarderIrrevocable: address) +    setSanctionListOracle(sanctionContractOracle_: address) <<onlyRole>> +    validateTransfer(_from: address, _to: address, _amount: uint256): (isValid: bool) +    detectTransferRestriction(_from: address, _to: address, uint256): uint8 + + + +3->1 + + + + + +3->2 + + + + + +6 + +<<Abstract>> +RuleSanctionlistInvariantStorage +src/rules/abstract/RuleSanctionListInvariantStorage.sol + +Public: +   SANCTIONLIST_ROLE: bytes32 +   TEXT_ADDRESS_FROM_IS_SANCTIONED: string +   TEXT_ADDRESS_TO_IS_SANCTIONED: string +   CODE_ADDRESS_FROM_IS_SANCTIONED: uint8 +   CODE_ADDRESS_TO_IS_SANCTIONED: uint8 + + + +3->6 + + + + + +4 + +RuleWhitelist +src/rules/RuleWhitelist.sol + +Private: +   numAddressesWhitelisted: uint256 +Public: +   whitelist: mapping(address=>bool) + +Internal: +    _msgSender(): (sender: address) +    _msgData(): bytes +External: +    numberWhitelistedAddress(): uint256 +    addressIsWhitelisted(_targetAddress: address): bool +    canReturnTransferRestrictionCode(_restrictionCode: uint8): bool +    messageForTransferRestriction(_restrictionCode: uint8): string +Public: +    constructor(admin: address, forwarderIrrevocable: address) +    addAddressesToTheWhitelist(listWhitelistedAddress: address[]) <<onlyRole>> +    removeAddressesFromTheWhitelist(listWhitelistedAddress: address[]) <<onlyRole>> +    addAddressToTheWhitelist(_newWhitelistAddress: address) <<onlyRole>> +    removeAddressFromTheWhitelist(_removeWhitelistAddress: address) <<onlyRole>> +    validateTransfer(_from: address, _to: address, _amount: uint256): (isValid: bool) +    detectTransferRestriction(_from: address, _to: address, uint256): uint8 + + + +4->1 + + + + + +7 + +<<Abstract>> +RuleWhitelistInvariantStorage +src/rules/abstract/RuleWhitelistInvariantStorage.sol + +Public: +   WHITELIST_ROLE: bytes32 +   TEXT_ADDRESS_FROM_NOT_WHITELISTED: string +   TEXT_ADDRESS_TO_NOT_WHITELISTED: string +   CODE_ADDRESS_FROM_NOT_WHITELISTED: uint8 +   CODE_ADDRESS_TO_NOT_WHITELISTED: uint8 + + + +4->7 + + + + + +5 + +<<Abstract>> +RuleCommonInvariantStorage +src/rules/abstract/RuleCommonInvariantStorage.sol + +Public: +   TEXT_CODE_NOT_FOUND: string + + + +6->5 + + + + + +7->5 + + + + + diff --git a/doc/schema/surya/surya_graph_RuleEngine.png b/doc/schema/surya/surya_graph_RuleEngine.png index c705340..52773b7 100644 Binary files a/doc/schema/surya/surya_graph_RuleEngine.png and b/doc/schema/surya/surya_graph_RuleEngine.png differ diff --git a/doc/schema/surya/surya_graph_SanctionList.png b/doc/schema/surya/surya_graph_SanctionList.png new file mode 100644 index 0000000..aa8e88a Binary files /dev/null and b/doc/schema/surya/surya_graph_SanctionList.png differ diff --git a/doc/schema/surya/surya_graph_Whitelist.png b/doc/schema/surya/surya_graph_Whitelist.png index ef933e5..a0c904e 100644 Binary files a/doc/schema/surya/surya_graph_Whitelist.png and b/doc/schema/surya/surya_graph_Whitelist.png differ diff --git a/doc/schema/surya1.0.2/surya_graph_RuleEngine.png b/doc/schema/surya1.0.2/surya_graph_RuleEngine.png new file mode 100644 index 0000000..c705340 Binary files /dev/null and b/doc/schema/surya1.0.2/surya_graph_RuleEngine.png differ diff --git a/doc/schema/surya1.0.2/surya_graph_Whitelist.png b/doc/schema/surya1.0.2/surya_graph_Whitelist.png new file mode 100644 index 0000000..ef933e5 Binary files /dev/null and b/doc/schema/surya1.0.2/surya_graph_Whitelist.png differ diff --git a/doc/solidityAPI/MetaTxStandalone.md b/doc/solidityAPI/MetaTxStandalone.md index 3d2a349..cc5f318 100644 --- a/doc/solidityAPI/MetaTxStandalone.md +++ b/doc/solidityAPI/MetaTxStandalone.md @@ -1,4 +1,4 @@ -# MetaTxModuleStandalone - Solidity API +# MetaTxModuleStandalone [TOC] @@ -10,15 +10,22 @@ _Meta transaction (gasless) module._ constructor(address trustedForwarder) internal ``` -#### _msgSender +### _msgSender ```solidity function _msgSender() internal view virtual returns (address sender) ``` -#### _msgData +_Override for `msg.sender`. Defaults to the original `msg.sender` whenever +a call is not performed by the trusted forwarder or the calldata length is less than +20 bytes (an address length)._ + +### _msgData ```solidity function _msgData() internal view virtual returns (bytes) ``` +_Override for `msg.data`. Defaults to the original `msg.data` whenever +a call is not performed by the trusted forwarder or the calldata length is less than +20 bytes (an address length)._ diff --git a/doc/solidityAPI/RuleEngine.md b/doc/solidityAPI/RuleEngine.md index e4b77c0..6bb6559 100644 --- a/doc/solidityAPI/RuleEngine.md +++ b/doc/solidityAPI/RuleEngine.md @@ -1,10 +1,38 @@ -# RuleEngine - Solidity API +# RuleEngine [TOC] -## Constants/Variables +### RuleEngine_RuleAddressZeroNotAllowed + +```solidity +error RuleEngine_RuleAddressZeroNotAllowed() +``` + +### RuleEngine_RuleAlreadyExists + +```solidity +error RuleEngine_RuleAlreadyExists() +``` + +### RuleEngine_RuleDoNotMatch + +```solidity +error RuleEngine_RuleDoNotMatch() +``` + +### RuleEngine_AdminWithAddressZeroNotAllowed + +```solidity +error RuleEngine_AdminWithAddressZeroNotAllowed() +``` + +### RuleEngine_ArrayIsEmpty + +```solidity +error RuleEngine_ArrayIsEmpty() +``` ### RULE_ENGINE_ROLE @@ -12,9 +40,9 @@ bytes32 RULE_ENGINE_ROLE ``` -*Role to manage the ruleEngine* +_Role to manage the ruleEngine_ -### ruleIsPresent +### _ruleIsPresent ```solidity mapping(contract IRule => bool) _ruleIsPresent @@ -28,9 +56,7 @@ _Indicate if a rule already exists_ contract IRule[] _rules ``` -*Array of rules* - -## Events +_Array of rules_ ### AddRule @@ -56,8 +82,6 @@ event ClearRules(contract IRule[] rulesRemoved) Generate when all the rules are cleared -## Functions - ### constructor ```solidity @@ -71,9 +95,7 @@ constructor(address admin, address forwarderIrrevocable) public | admin | address | Address of the contract (Access Control) | | forwarderIrrevocable | address | Address of the forwarder, required for the gasless support | -### Public/external - -#### setRules +### setRules ```solidity function setRules(contract IRule[] rules_) external @@ -82,7 +104,7 @@ function setRules(contract IRule[] rules_) external 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 -#### clearRules +### clearRules ```solidity function clearRules() public @@ -90,7 +112,7 @@ function clearRules() public Clear all the rules of the array of rules -#### addRule +### addRule ```solidity function addRule(contract IRule rule_) public @@ -99,7 +121,7 @@ function addRule(contract IRule rule_) public Add a rule to the array of rules Revert if one rule is a zero address or if the rule is already present -#### removeRule +### removeRule ```solidity function removeRule(contract IRule rule_, uint256 index) public @@ -111,26 +133,26 @@ Revert if the rule found at the specified index does not match the rule in argum _To reduce the array size, the last rule is moved to the location occupied by the rule to remove_ -##### Parameters +#### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | -| rule_ | contract IRule | address of the target rule | -| index | uint256 | the position inside the array of rule | +| Name | Type | Description | +| ----- | -------------- | ------------------------------------- | +| rule_ | contract IRule | address of the target rule | +| index | uint256 | the position inside the array of rule | -#### rulesCount +### rulesCount ```solidity function rulesCount() external view returns (uint256) ``` -##### Return Values +#### Return Values -| Name | Type | Description | -| ---- | ---- | ----------- | -| [0] | uint256 | The number of rules inside the array | +| Name | Type | Description | +| ---- | ------- | ------------------------------------ | +| [0] | uint256 | The number of rules inside the array | -#### getRuleIndex +### getRuleIndex ```solidity function getRuleIndex(contract IRule rule_) external view returns (uint256 index) @@ -138,13 +160,13 @@ function getRuleIndex(contract IRule rule_) external view returns (uint256 index Get the index of a rule inside the list -##### Return Values +#### Return Values -| Name | Type | Description | -| ---- | ---- | ----------- | +| Name | Type | Description | +| ----- | ------- | --------------------------------------------- | | index | uint256 | if the rule is found, _rules.length otherwise | -#### rule +### rule ```solidity function rule(uint256 ruleId) external view returns (contract IRule) @@ -152,19 +174,19 @@ function rule(uint256 ruleId) external view returns (contract IRule) Get the rule at the position specified by ruleId -##### Parameters +#### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | +| Name | Type | Description | +| ------ | ------- | ----------------- | | ruleId | uint256 | index of the rule | -##### Return Values +#### Return Values -| Name | Type | Description | -| ---- | ---- | ----------- | -| [0] | contract IRule | a rule address | +| Name | Type | Description | +| ---- | -------------- | -------------- | +| [0] | contract IRule | a rule address | -#### rules +### rules ```solidity function rules() external view returns (contract IRule[]) @@ -172,13 +194,13 @@ function rules() external view returns (contract IRule[]) Get all the rules -##### Return Values +#### Return Values -| Name | Type | Description | -| ---- | ---- | ----------- | -| [0] | contract IRule[] | An array of rules | +| Name | Type | Description | +| ---- | ---------------- | ----------------- | +| [0] | contract IRule[] | An array of rules | -#### detectTransferRestriction +### detectTransferRestriction ```solidity function detectTransferRestriction(address _from, address _to, uint256 _amount) public view returns (uint8) @@ -186,21 +208,21 @@ function detectTransferRestriction(address _from, address _to, uint256 _amount) Go through all the rule to know if a restriction exists on the transfer -##### Parameters +#### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | -| _from | address | the origin address | -| _to | address | the destination address | -| _amount | uint256 | to transfer | +| Name | Type | Description | +| ------- | ------- | ----------------------- | +| _from | address | the origin address | +| _to | address | the destination address | +| _amount | uint256 | to transfer | -##### Return Values +#### Return Values -| Name | Type | Description | -| ---- | ---- | ----------- | -| [0] | uint8 | The restricion code or REJECTED_CODE_BASE.TRANSFER_OK | +| Name | Type | Description | +| ---- | ----- | ----------------------------------------------------- | +| [0] | uint8 | The restricion code or REJECTED_CODE_BASE.TRANSFER_OK | -#### validateTransfer +### validateTransfer ```solidity function validateTransfer(address _from, address _to, uint256 _amount) public view returns (bool) @@ -208,21 +230,21 @@ function validateTransfer(address _from, address _to, uint256 _amount) public vi Validate a transfer -##### Parameters +#### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | -| _from | address | the origin address | -| _to | address | the destination address | -| _amount | uint256 | to transfer | +| Name | Type | Description | +| ------- | ------- | ----------------------- | +| _from | address | the origin address | +| _to | address | the destination address | +| _amount | uint256 | to transfer | -##### Return Values +#### Return Values -| Name | Type | Description | -| ---- | ---- | ----------- | -| [0] | bool | True if the transfer is valid, false otherwise | +| Name | Type | Description | +| ---- | ---- | ---------------------------------------------- | +| [0] | bool | True if the transfer is valid, false otherwise | -#### messageForTransferRestriction +### messageForTransferRestriction ```solidity function messageForTransferRestriction(uint8 _restrictionCode) external view returns (string) @@ -230,32 +252,32 @@ function messageForTransferRestriction(uint8 _restrictionCode) external view ret Return the message corresponding to the code -##### Parameters +#### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | +| Name | Type | Description | +| ---------------- | ----- | --------------------------- | | _restrictionCode | uint8 | The target restriction code | -##### Return Values - -| Name | Type | Description | -| ---- | ---- | ----------- | -| [0] | string | True if the transfer is valid, false otherwise | +#### Return Values -### Internal +| Name | Type | Description | +| ---- | ------ | ---------------------------------------------- | +| [0] | string | True if the transfer is valid, false otherwise | -#### _msgSender +### _msgSender ```solidity function _msgSender() internal view returns (address sender) ``` -_This surcharge is not necessary if you do not use the MetaTxModule_. +_This surcharge is not necessary if you do not use the MetaTxModule_ -#### _msgData +### _msgData ```solidity function _msgData() internal view returns (bytes) ``` -_This surcharge is not necessary if you do not use the MetaTxModule. +_This surcharge is not necessary if you do not use the MetaTxModule_ + +## diff --git a/doc/solidityAPI/RuleSanctionList.md b/doc/solidityAPI/RuleSanctionList.md new file mode 100644 index 0000000..65bcadd --- /dev/null +++ b/doc/solidityAPI/RuleSanctionList.md @@ -0,0 +1,152 @@ +# RuleSanctionList + +[TOC] + + + +## SanctionsList + +### isSanctioned + +```solidity +function isSanctioned(address addr) external view returns (bool) +``` + +## RuleSanctionList + +### sanctionsList + +```solidity +contract SanctionsList sanctionsList +``` + +### constructor + +```solidity +constructor(address admin, address forwarderIrrevocable) public +``` + +#### Parameters + +| Name | Type | Description | +| -------------------- | ------- | ---------------------------------------------------------- | +| admin | address | Address of the contract (Access Control) | +| forwarderIrrevocable | address | Address of the forwarder, required for the gasless support | + +### setSanctionListOracle + +```solidity +function setSanctionListOracle(address sanctionContractOracle_) public +``` + +Set the oracle contract + +_zero address is authorized to authorize all transfers_ + +#### Parameters + +| Name | Type | Description | +| ----------------------- | ------- | ------------------------------- | +| sanctionContractOracle_ | address | address of your oracle contract | + +### validateTransfer + +```solidity +function validateTransfer(address _from, address _to, uint256 _amount) public view returns (bool isValid) +``` + +Validate a transfer + +#### Parameters + +| Name | Type | Description | +| ------- | ------- | ----------------------- | +| _from | address | the origin address | +| _to | address | the destination address | +| _amount | uint256 | to transfer | + +#### Return Values + +| Name | Type | Description | +| ------- | ---- | ------------------------------------------------- | +| isValid | bool | => true if the transfer is valid, false otherwise | + +### detectTransferRestriction + +```solidity +function detectTransferRestriction(address _from, address _to, uint256) public view returns (uint8) +``` + +Check if an addres is in the whitelist or not + +#### Parameters + +| Name | Type | Description | +| ----- | ------- | ----------------------- | +| _from | address | the origin address | +| _to | address | the destination address | +| | uint256 | | + +#### Return Values + +| Name | Type | Description | +| ---- | ----- | ----------------------------------------------------- | +| [0] | uint8 | The restricion code or REJECTED_CODE_BASE.TRANSFER_OK | + +### canReturnTransferRestrictionCode + +```solidity +function canReturnTransferRestrictionCode(uint8 _restrictionCode) external pure returns (bool) +``` + +To know if the restriction code is valid for this rule or not. + +#### Parameters + +| Name | Type | Description | +| ---------------- | ----- | --------------------------- | +| _restrictionCode | uint8 | The target restriction code | + +#### Return Values + +| Name | Type | Description | +| ---- | ---- | ------------------------------------------------------ | +| [0] | bool | true if the restriction code is known, false otherwise | + +### messageForTransferRestriction + +```solidity +function messageForTransferRestriction(uint8 _restrictionCode) external pure returns (string) +``` + +Return the corresponding message + +#### Parameters + +| Name | Type | Description | +| ---------------- | ----- | --------------------------- | +| _restrictionCode | uint8 | The target restriction code | + +#### Return Values + +| Name | Type | Description | +| ---- | ------ | ---------------------------------------------- | +| [0] | string | true if the transfer is valid, false otherwise | + +### _msgSender + +```solidity +function _msgSender() internal view returns (address sender) +``` + +_This surcharge is not necessary if you do not use the MetaTxModule_ + +### _msgData + +```solidity +function _msgData() internal view returns (bytes) +``` + +_This surcharge is not necessary if you do not use the MetaTxModule_ + +## diff --git a/doc/solidityAPI/RuleWhitelist.md b/doc/solidityAPI/RuleWhitelist.md index 50cebd9..7367f8a 100644 --- a/doc/solidityAPI/RuleWhitelist.md +++ b/doc/solidityAPI/RuleWhitelist.md @@ -1,55 +1,15 @@ -# RuleWhitelist - Solidity API +# RuleWhitelist [TOC] -## Constants / Variables - -### WHITELIST_ROLE - -```solidity -bytes32 WHITELIST_ROLE -``` - -### TEXT_CODE_NOT_FOUND - -```solidity -string TEXT_CODE_NOT_FOUND -``` - -### TEXT_ADDRESS_FROM_NOT_WHITELISTED - -```solidity -string TEXT_ADDRESS_FROM_NOT_WHITELISTED -``` - -### TEXT_ADDRESS_TO_NOT_WHITELISTED - -```solidity -string TEXT_ADDRESS_TO_NOT_WHITELISTED -``` - -### CODE_ADDRESS_FROM_NOT_WHITELISTED - -```solidity -uint8 CODE_ADDRESS_FROM_NOT_WHITELISTED -``` - -### CODE_ADDRESS_TO_NOT_WHITELISTED - -```solidity -uint8 CODE_ADDRESS_TO_NOT_WHITELISTED -``` - ### whitelist ```solidity mapping(address => bool) whitelist ``` -## Functions - ### constructor ```solidity @@ -58,14 +18,12 @@ constructor(address admin, address forwarderIrrevocable) public #### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | -| admin | address | Address of the contract (Access Control) | +| Name | Type | Description | +| -------------------- | ------- | ---------------------------------------------------------- | +| admin | address | Address of the contract (Access Control) | | forwarderIrrevocable | address | Address of the forwarder, required for the gasless support | -### Public / External - -#### addAddressesToTheWhitelist +### addAddressesToTheWhitelist ```solidity function addAddressesToTheWhitelist(address[] listWhitelistedAddress) public @@ -74,13 +32,13 @@ function addAddressesToTheWhitelist(address[] listWhitelistedAddress) public Add addresses to the whitelist If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert). -##### Parameters +#### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | +| Name | Type | Description | +| ---------------------- | --------- | ---------------------------------------- | | listWhitelistedAddress | address[] | an array with the addresses to whitelist | -#### removeAddressesFromTheWhitelist +### removeAddressesFromTheWhitelist ```solidity function removeAddressesFromTheWhitelist(address[] listWhitelistedAddress) public @@ -90,13 +48,13 @@ Remove addresses from the whitelist If the address does not exist in the whitelist, there is no change for this address. The transaction remains valid (no revert). -##### Parameters +#### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | +| Name | Type | Description | +| ---------------------- | --------- | ------------------------------------- | | listWhitelistedAddress | address[] | an array with the addresses to remove | -#### addAddressToTheWhitelist +### addAddressToTheWhitelist ```solidity function addAddressToTheWhitelist(address _newWhitelistAddress) public @@ -105,13 +63,13 @@ function addAddressToTheWhitelist(address _newWhitelistAddress) public Add one address to the whitelist If the address already exists, the transaction is reverted to save gas. -##### Parameters +#### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | +| Name | Type | Description | +| -------------------- | ------- | ------------------------ | | _newWhitelistAddress | address | The address to whitelist | -#### removeAddressFromTheWhitelist +### removeAddressFromTheWhitelist ```solidity function removeAddressFromTheWhitelist(address _removeWhitelistAddress) public @@ -120,13 +78,13 @@ function removeAddressFromTheWhitelist(address _removeWhitelistAddress) public Remove one address from the whitelist If the address does not exist in the whitelist, the transaction is reverted to save gas. -##### Parameters +#### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | +| Name | Type | Description | +| ----------------------- | ------- | --------------------- | | _removeWhitelistAddress | address | The address to remove | -#### numberWhitelistedAddress +### numberWhitelistedAddress ```solidity function numberWhitelistedAddress() external view returns (uint256) @@ -134,13 +92,13 @@ function numberWhitelistedAddress() external view returns (uint256) Get the number of whitelisted addresses -##### Return Values +#### Return Values -| Name | Type | Description | -| ---- | ---- | ----------- | -| [0] | uint256 | Number of whitelisted addresses | +| Name | Type | Description | +| ---- | ------- | ------------------------------- | +| [0] | uint256 | Number of whitelisted addresses | -#### addressIsWhitelisted +### addressIsWhitelisted ```solidity function addressIsWhitelisted(address _targetAddress) external view returns (bool) @@ -148,19 +106,19 @@ function addressIsWhitelisted(address _targetAddress) external view returns (boo Know if an address is whitelisted or not -##### Parameters +#### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | +| Name | Type | Description | +| -------------- | ------- | --------------------- | | _targetAddress | address | The concerned address | -##### Return Values +#### Return Values -| Name | Type | Description | -| ---- | ---- | ----------- | -| [0] | bool | True if the address is whitelisted, false otherwise | +| Name | Type | Description | +| ---- | ---- | --------------------------------------------------- | +| [0] | bool | True if the address is whitelisted, false otherwise | -#### validateTransfer +### validateTransfer ```solidity function validateTransfer(address _from, address _to, uint256 _amount) public view returns (bool isValid) @@ -168,21 +126,21 @@ function validateTransfer(address _from, address _to, uint256 _amount) public vi Validate a transfer -##### Parameters +#### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | -| _from | address | the origin address | -| _to | address | the destination address | -| _amount | uint256 | to transfer | +| Name | Type | Description | +| ------- | ------- | ----------------------- | +| _from | address | the origin address | +| _to | address | the destination address | +| _amount | uint256 | to transfer | -##### Return Values +#### Return Values -| Name | Type | Description | -| ---- | ---- | ----------- | +| Name | Type | Description | +| ------- | ---- | ------------------------------------------------- | | isValid | bool | => true if the transfer is valid, false otherwise | -#### detectTransferRestriction +### detectTransferRestriction ```solidity function detectTransferRestriction(address _from, address _to, uint256) public view returns (uint8) @@ -190,21 +148,21 @@ function detectTransferRestriction(address _from, address _to, uint256) public v Check if an addres is in the whitelist or not -##### Parameters +#### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | -| _from | address | the origin address | -| _to | address | the destination address | -| | uint256 | | +| Name | Type | Description | +| ----- | ------- | ----------------------- | +| _from | address | the origin address | +| _to | address | the destination address | +| | uint256 | | -##### Return Values +#### Return Values -| Name | Type | Description | -| ---- | ---- | ----------- | -| [0] | uint8 | The restricion code or REJECTED_CODE_BASE.TRANSFER_OK | +| Name | Type | Description | +| ---- | ----- | ----------------------------------------------------- | +| [0] | uint8 | The restricion code or REJECTED_CODE_BASE.TRANSFER_OK | -#### canReturnTransferRestrictionCode +### canReturnTransferRestrictionCode ```solidity function canReturnTransferRestrictionCode(uint8 _restrictionCode) external pure returns (bool) @@ -212,19 +170,19 @@ function canReturnTransferRestrictionCode(uint8 _restrictionCode) external pure To know if the restriction code is valid for this rule or not. -##### Parameters +#### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | +| Name | Type | Description | +| ---------------- | ----- | --------------------------- | | _restrictionCode | uint8 | The target restriction code | -##### Return Values +#### Return Values -| Name | Type | Description | -| ---- | ---- | ----------- | -| [0] | bool | true if the restriction code is known, false otherwise | +| Name | Type | Description | +| ---- | ---- | ------------------------------------------------------ | +| [0] | bool | true if the restriction code is known, false otherwise | -#### messageForTransferRestriction +### messageForTransferRestriction ```solidity function messageForTransferRestriction(uint8 _restrictionCode) external pure returns (string) @@ -232,21 +190,19 @@ function messageForTransferRestriction(uint8 _restrictionCode) external pure ret Return the corresponding message -##### Parameters +#### Parameters -| Name | Type | Description | -| ---- | ---- | ----------- | +| Name | Type | Description | +| ---------------- | ----- | --------------------------- | | _restrictionCode | uint8 | The target restriction code | -##### Return Values - -| Name | Type | Description | -| ---- | ---- | ----------- | -| [0] | string | true if the transfer is valid, false otherwise | +#### Return Values -#### Internal +| Name | Type | Description | +| ---- | ------ | ---------------------------------------------- | +| [0] | string | true if the transfer is valid, false otherwise | -#### _msgSender +### _msgSender ```solidity function _msgSender() internal view returns (address sender) @@ -254,33 +210,10 @@ function _msgSender() internal view returns (address sender) _This surcharge is not necessary if you do not use the MetaTxModule_ -#### _msgData +### _msgData ```solidity function _msgData() internal view returns (bytes) ``` _This surcharge is not necessary if you do not use the MetaTxModule_ - -## MetaTxModuleStandalone - -_Meta transaction (gasless) module._ - -### constructor - -```solidity -constructor(address trustedForwarder) internal -``` - -#### _msgSender - -```solidity -function _msgSender() internal view virtual returns (address sender) -``` - -#### _msgData - -```solidity -function _msgData() internal view virtual returns (bytes) -``` - diff --git a/doc/technical.md b/doc/technical.md deleted file mode 100644 index a99cd04..0000000 --- a/doc/technical.md +++ /dev/null @@ -1,130 +0,0 @@ -# Technical choice - -[TOC] - -## Schema - -### UML - -![uml](./schema/uml.svg) - -## Graph - -### RuleEngine - -![surya_graph_RuleEngine](./schema/surya/surya_graph_RuleEngine.png) - -### Whitelist - -![surya_graph_Whitelist](./schema/surya/surya_graph_Whitelist.png) - -## Access Control - -### Admin - -### Whitelist - -The default admin is the address put in argument(`admin`) inside the constructor. It is set in the constructor when the contract is deployed. - -### RuleEngine - -The default admin is the address put in argument(`admin`) inside the constructor. It is set in the constructor when the contract is deployed. - -### Schema - -Here a schema of the Access Control. - -**RuleEngine** -![alt text](./accessControl/access-control-RuleEngine.png) - -**RuleWhitelist** -![alt text](./accessControl/access-control-RuleWhitelist.png) - - - -## Functionality - -### Upgradeable - -The Rule Engine and the Whitelist contracts are not upgradeable. The reason is the following: -If we need a new on, we just issue a new one, and tell the token to use the new. This would happen if we need more than just whitelisting, for ex. - -### Urgency mechanism -* Pause - There are no functionalities to put in pause the contracts. - -* We have removed the possibility to Kill the contracts, to destroy the bytecode, from - The whitelist and the RuleEngine contracts for the following reasons: - - * The opcode SELFDESTRUCT which the property of destroying the contract (= deletion of any storage keys or code) will be remove with the Cancun Upgrade, an upgrade of the Ethereum network. - - Therefore, when the Ethereum Network will integrate this upgrade, this functionality will no longer be available. - - See https://eips.ethereum.org/EIPS/eip-6780 & https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/cancun.md - - * It was recommended by the audit team - - > Implementing an ability to destroy a contract is a bad practice, as it cause more risks than benefits. - - -### Gasless support - -> The gasless integration was not part of the audit performed by ABDK on the version [1.0.1](https://github.com/CMTA/RuleEngine/releases/tag/1.0.1) - -The RuleEngine and the Whitelist contracts support client-side gasless transactions using the [Gas Station Network](https://docs.opengsn.org/#the-problem) (GSN) pattern, the main open standard for transfering fee payment to another account than that of the transaction issuer. The contract uses the OpenZeppelin contract `ERC2771Context`, which allows a contract to get the original client with `_msgSender()` instead of the fee payer given by `msg.sender` . - -At deployment, the parameter `forwarder` inside the contract constructor has to be set with the defined address of the forwarder. Please note that the forwarder can not be changed after deployment. - -Please see the OpenGSN [documentation](https://docs.opengsn.org/contracts/#receiving-a-relayed-call) for more details on what is done to support GSN in the contract. - -## RuleEngine - -### Duplicate rules - -**setRules** - -If one rule is already present, the function is reverted - -**addRule** - -If one rule is already present, the function is reverted - -### Null address - -**setRules** - -The function is reverted if one rule is the zero address - -**addRule** - -The function is reverted if one rule is the zero address - -## Whitelist - -### Null address -It is possible to add the null address (0x0) to the whitelist. It is a requirement from the CMTAT to be able to mint tokens. - -It is not a security problem because OpenZeppelin doesn't authorize the transfer of tokens to the zero address. - -### Duplicate address - -**addAddress** -If the address already exists, the transaction is reverted to save gas. -**addAddresses** -If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert). - -### NonExistent Address -**removeAddress** -If the address does not exist in the whitelist, the transaction is reverted to save gas. -**removeAddresses** -If the address does not exist in the whitelist, there is no change for this address. The transaction remains valid (no revert). - -## Other - -### Gas Optimization - -Inside a loop, we use `uncheck` to increment to save gas because an array has a length of < 2\**256. -``` - unchecked { ++i; } -``` -See [hackmd.io - gas-optimization-loops](https://hackmd.io/@totomanov/gas-optimization-loops) and [https://github.com/ethereum/solidity/issues/10698](https://github.com/ethereum/solidity/issues/10698) diff --git a/doc/technical/RuleEngine.md b/doc/technical/RuleEngine.md new file mode 100644 index 0000000..7c378f6 --- /dev/null +++ b/doc/technical/RuleEngine.md @@ -0,0 +1,60 @@ +# RuleEngine + +[TOC] + +The RuleEngine is an external contract used to apply transfer restriction to the CMTAT. + +This contract acts as a controller and can call different contract rule to apply rule on each transfer. + +A possible rule is a whitelist rule where only the address inside the whitelist can perform a transfer + +## Schema + +![RuleEngine](../schema/RuleEngine.png) + +### Graph + + + +![surya_graph_RuleEngine](../schema/surya/surya_graph_RuleEngine.png) + + + +## Access Control + +### Admin + +The default admin is the address put in argument(`admin`) inside the constructor. It is set in the constructor when the contract is deployed. + +### Schema + +Here a schema of the Access Control. +![alt text](../accessControl/access-control-RuleEngine.png) + + + + + +## Methods + +### Duplicate rules + +**setRules** + +If one rule is already present, the function is reverted + +**addRule** + +If one rule is already present, the function is reverted + +### Null address + +**setRules** + +The function is reverted if one rule is the zero address + +**addRule** + +The function is reverted if one rule is the zero address + +https://github.com/ethereum/solidity/issues/10698) diff --git a/doc/technical/RuleSanctionList.md b/doc/technical/RuleSanctionList.md new file mode 100644 index 0000000..1191d18 --- /dev/null +++ b/doc/technical/RuleSanctionList.md @@ -0,0 +1,34 @@ +# Rule SanctionList + +[TOC] + +This document defines the rule SanctionList + +## How to use + +The purpose of this contract is to use the oracle contract from Chainalysis to forbid transfer from/to an address included in a sanctions designation (US, EU, or UN). + +The documentation and the contracts addresses are available here: [Chainalysis oracle for sanctions screening](https://go.chainalysis.com/chainalysis-oracle-docs.html) + +## Schema + +### Graph + +### SanctionList + +![surya_graph_Whitelist](../schema/surya/surya_graph_SanctionList.png) + +## Access Control + +### Admin + +The default admin is the address put in argument(`admin`) inside the constructor. It is set in the constructor when the contract is deployed. + +### Schema + +Here a schema of the Access Control. + +**RuleSanctionList** + +![alt text](../accessControl/access-control-RuleSanctionList.drawio.png) + diff --git a/doc/technical/RuleWhitelist.md b/doc/technical/RuleWhitelist.md new file mode 100644 index 0000000..ce64a68 --- /dev/null +++ b/doc/technical/RuleWhitelist.md @@ -0,0 +1,48 @@ +# Rule Whitelist + +[TOC] + +This rule can be used to restrict transfers from/to only addresses inside a whitelist. + +## Schema + +### Graph + +![surya_graph_Whitelist](../schema/surya/surya_graph_Whitelist.png) + + + +## Access Control + +### Admin + +The default admin is the address put in argument(`admin`) inside the constructor. It is set in the constructor when the contract is deployed. + +### Schema + +Here a schema of the Access Control. +![alt text](../accessControl/access-control-RuleWhitelist.png) + + + + + +## Methods + +### Null address +It is possible to add the null address (0x0) to the whitelist. It is a requirement from the CMTAT to be able to mint tokens. + +It is not a security problem because OpenZeppelin doesn't authorize the transfer of tokens to the zero address. + +### Duplicate address + +**addAddress** +If the address already exists, the transaction is reverted to save gas. +**addAddresses** +If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert). + +### NonExistent Address +**removeAddress** +If the address does not exist in the whitelist, the transaction is reverted to save gas. +**removeAddresses** +If the address does not exist in the whitelist, there is no change for this address. The transaction remains valid (no revert). diff --git a/doc/technical/general.md b/doc/technical/general.md new file mode 100644 index 0000000..b0479ec --- /dev/null +++ b/doc/technical/general.md @@ -0,0 +1,56 @@ +# Technical choice + +[TOC] + +## Schema + +### UML + +![uml](../schema/classDiagram1.0.3.svg) + + + +## Functionality + +### Upgradeable + +The Rule Engine, the Rule Whitelist and the Rule SanctionList contracts are not upgradeable. The reason is the following: +If we need a new on, we just issue a new one, and tell the CMTAT token (or the RuleEngine for the rules) to use the new. This would happen if we need more than just whitelisting, for ex. + +### Urgency mechanism +* Pause + There are no functionalities to put in pause the contracts. + +* We have removed the possibility to Kill the contracts, to destroy the bytecode, from + the different contracts (RuleEngine and Rule) for the following reasons: + + * The opcode SELFDESTRUCT which the property of destroying the contract (= deletion of any storage keys or code) will be remove with the Cancun Upgrade, an upgrade of the Ethereum network. + + Therefore, when the Ethereum Network will integrate this upgrade, this functionality will no longer be available. + + See [https://eips.ethereum.org/EIPS/eip-6780](https://eips.ethereum.org/EIPS/eip-6780) & [https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/cancun.md](https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/cancun.md) + + * It was recommended by the audit team + + > Implementing an ability to destroy a contract is a bad practice, as it cause more risks than benefits. + + +### Gasless support + +> The gasless integration was not part of the audit performed by ABDK on the version [1.0.1](https://github.com/CMTA/RuleEngine/releases/tag/1.0.1) + +The RuleEngine, the Whitelist and SanctionList contracts support client-side gasless transactions using the [Gas Station Network](https://docs.opengsn.org/#the-problem) (GSN) pattern, the main open standard for transfering fee payment to another account than that of the transaction issuer. The contract uses the OpenZeppelin contract `ERC2771Context`, which allows a contract to get the original client with `_msgSender()` instead of the fee payer given by `msg.sender` . + +At deployment, the parameter `forwarder` inside the contract constructor has to be set with the defined address of the forwarder. Please note that the forwarder can not be changed after deployment. + +Please see the OpenGSN [documentation](https://docs.opengsn.org/contracts/#receiving-a-relayed-call) for more details on what is done to support GSN in the contract. + +## Other + +### Gas Optimization + +Inside a loop, we use `uncheck` to increment to save gas because an array has a length of < 2\**256. +``` + unchecked { ++i; } +``` +See [hackmd.io - gas-optimization-loops](https://hackmd.io/@totomanov/gas-optimization-loops) and [https://github.com/ethereum/solidity/issues/10698](https://github.com/ethereum/solidity/issues/10698) diff --git a/doc/test/coverage/amber.png b/doc/test/coverage/amber.png new file mode 100644 index 0000000..2cab170 Binary files /dev/null and b/doc/test/coverage/amber.png differ diff --git a/doc/test/coverage/emerald.png b/doc/test/coverage/emerald.png new file mode 100644 index 0000000..38ad4f4 Binary files /dev/null and b/doc/test/coverage/emerald.png differ diff --git a/doc/test/coverage/gcov.css b/doc/test/coverage/gcov.css new file mode 100644 index 0000000..0fcdff1 --- /dev/null +++ b/doc/test/coverage/gcov.css @@ -0,0 +1,519 @@ +/* All views: initial background and text color */ +body +{ + color: #000000; + background-color: #ffffff; +} + +/* All views: standard link format*/ +a:link +{ + color: #284fa8; + text-decoration: underline; +} + +/* All views: standard link - visited format */ +a:visited +{ + color: #00cb40; + text-decoration: underline; +} + +/* All views: standard link - activated format */ +a:active +{ + color: #ff0040; + text-decoration: underline; +} + +/* All views: main title format */ +td.title +{ + text-align: center; + padding-bottom: 10px; + font-family: sans-serif; + font-size: 20pt; + font-style: italic; + font-weight: bold; +} + +/* All views: header item format */ +td.headerItem +{ + text-align: right; + padding-right: 6px; + font-family: sans-serif; + font-weight: bold; + vertical-align: top; + white-space: nowrap; +} + +/* All views: header item value format */ +td.headerValue +{ + text-align: left; + color: #284fa8; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; +} + +/* All views: header item coverage table heading */ +td.headerCovTableHead +{ + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + font-size: 80%; + white-space: nowrap; +} + +/* All views: header item coverage table entry */ +td.headerCovTableEntry +{ + text-align: right; + color: #284fa8; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #dae7fe; +} + +/* All views: header item coverage table entry for high coverage rate */ +td.headerCovTableEntryHi +{ + text-align: right; + color: #000000; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #a7fc9d; +} + +/* All views: header item coverage table entry for medium coverage rate */ +td.headerCovTableEntryMed +{ + text-align: right; + color: #000000; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #ffea20; +} + +/* All views: header item coverage table entry for ow coverage rate */ +td.headerCovTableEntryLo +{ + text-align: right; + color: #000000; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #ff0000; +} + +/* All views: header legend value for legend entry */ +td.headerValueLeg +{ + text-align: left; + color: #000000; + font-family: sans-serif; + font-size: 80%; + white-space: nowrap; + padding-top: 4px; +} + +/* All views: color of horizontal ruler */ +td.ruler +{ + background-color: #6688d4; +} + +/* All views: version string format */ +td.versionInfo +{ + text-align: center; + padding-top: 2px; + font-family: sans-serif; + font-style: italic; +} + +/* Directory view/File view (all)/Test case descriptions: + table headline format */ +td.tableHead +{ + text-align: center; + color: #ffffff; + background-color: #6688d4; + font-family: sans-serif; + font-size: 120%; + font-weight: bold; + white-space: nowrap; + padding-left: 4px; + padding-right: 4px; +} + +span.tableHeadSort +{ + padding-right: 4px; +} + +/* Directory view/File view (all): filename entry format */ +td.coverFile +{ + text-align: left; + padding-left: 10px; + padding-right: 20px; + color: #284fa8; + background-color: #dae7fe; + font-family: monospace; +} + +/* Directory view/File view (all): bar-graph entry format*/ +td.coverBar +{ + padding-left: 10px; + padding-right: 10px; + background-color: #dae7fe; +} + +/* Directory view/File view (all): bar-graph outline color */ +td.coverBarOutline +{ + background-color: #000000; +} + +/* Directory view/File view (all): percentage entry for files with + high coverage rate */ +td.coverPerHi +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #a7fc9d; + font-weight: bold; + font-family: sans-serif; +} + +/* Directory view/File view (all): line count entry for files with + high coverage rate */ +td.coverNumHi +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #a7fc9d; + white-space: nowrap; + font-family: sans-serif; +} + +/* Directory view/File view (all): percentage entry for files with + medium coverage rate */ +td.coverPerMed +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #ffea20; + font-weight: bold; + font-family: sans-serif; +} + +/* Directory view/File view (all): line count entry for files with + medium coverage rate */ +td.coverNumMed +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #ffea20; + white-space: nowrap; + font-family: sans-serif; +} + +/* Directory view/File view (all): percentage entry for files with + low coverage rate */ +td.coverPerLo +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #ff0000; + font-weight: bold; + font-family: sans-serif; +} + +/* Directory view/File view (all): line count entry for files with + low coverage rate */ +td.coverNumLo +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #ff0000; + white-space: nowrap; + font-family: sans-serif; +} + +/* File view (all): "show/hide details" link format */ +a.detail:link +{ + color: #B8D0FF; + font-size:80%; +} + +/* File view (all): "show/hide details" link - visited format */ +a.detail:visited +{ + color: #B8D0FF; + font-size:80%; +} + +/* File view (all): "show/hide details" link - activated format */ +a.detail:active +{ + color: #ffffff; + font-size:80%; +} + +/* File view (detail): test name entry */ +td.testName +{ + text-align: right; + padding-right: 10px; + background-color: #dae7fe; + font-family: sans-serif; +} + +/* File view (detail): test percentage entry */ +td.testPer +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #dae7fe; + font-family: sans-serif; +} + +/* File view (detail): test lines count entry */ +td.testNum +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #dae7fe; + font-family: sans-serif; +} + +/* Test case descriptions: test name format*/ +dt +{ + font-family: sans-serif; + font-weight: bold; +} + +/* Test case descriptions: description table body */ +td.testDescription +{ + padding-top: 10px; + padding-left: 30px; + padding-bottom: 10px; + padding-right: 30px; + background-color: #dae7fe; +} + +/* Source code view: function entry */ +td.coverFn +{ + text-align: left; + padding-left: 10px; + padding-right: 20px; + color: #284fa8; + background-color: #dae7fe; + font-family: monospace; +} + +/* Source code view: function entry zero count*/ +td.coverFnLo +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #ff0000; + font-weight: bold; + font-family: sans-serif; +} + +/* Source code view: function entry nonzero count*/ +td.coverFnHi +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #dae7fe; + font-weight: bold; + font-family: sans-serif; +} + +/* Source code view: source code format */ +pre.source +{ + font-family: monospace; + white-space: pre; + margin-top: 2px; +} + +/* Source code view: line number format */ +span.lineNum +{ + background-color: #efe383; +} + +/* Source code view: format for lines which were executed */ +td.lineCov, +span.lineCov +{ + background-color: #cad7fe; +} + +/* Source code view: format for Cov legend */ +span.coverLegendCov +{ + padding-left: 10px; + padding-right: 10px; + padding-bottom: 2px; + background-color: #cad7fe; +} + +/* Source code view: format for lines which were not executed */ +td.lineNoCov, +span.lineNoCov +{ + background-color: #ff6230; +} + +/* Source code view: format for NoCov legend */ +span.coverLegendNoCov +{ + padding-left: 10px; + padding-right: 10px; + padding-bottom: 2px; + background-color: #ff6230; +} + +/* Source code view (function table): standard link - visited format */ +td.lineNoCov > a:visited, +td.lineCov > a:visited +{ + color: #000000; + text-decoration: underline; +} + +/* Source code view: format for lines which were executed only in a + previous version */ +span.lineDiffCov +{ + background-color: #b5f7af; +} + +/* Source code view: format for branches which were executed + * and taken */ +span.branchCov +{ + background-color: #cad7fe; +} + +/* Source code view: format for branches which were executed + * but not taken */ +span.branchNoCov +{ + background-color: #ff6230; +} + +/* Source code view: format for branches which were not executed */ +span.branchNoExec +{ + background-color: #ff6230; +} + +/* Source code view: format for the source code heading line */ +pre.sourceHeading +{ + white-space: pre; + font-family: monospace; + font-weight: bold; + margin: 0px; +} + +/* All views: header legend value for low rate */ +td.headerValueLegL +{ + font-family: sans-serif; + text-align: center; + white-space: nowrap; + padding-left: 4px; + padding-right: 2px; + background-color: #ff0000; + font-size: 80%; +} + +/* All views: header legend value for med rate */ +td.headerValueLegM +{ + font-family: sans-serif; + text-align: center; + white-space: nowrap; + padding-left: 2px; + padding-right: 2px; + background-color: #ffea20; + font-size: 80%; +} + +/* All views: header legend value for hi rate */ +td.headerValueLegH +{ + font-family: sans-serif; + text-align: center; + white-space: nowrap; + padding-left: 2px; + padding-right: 4px; + background-color: #a7fc9d; + font-size: 80%; +} + +/* All views except source code view: legend format for low coverage */ +span.coverLegendCovLo +{ + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; + background-color: #ff0000; +} + +/* All views except source code view: legend format for med coverage */ +span.coverLegendCovMed +{ + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; + background-color: #ffea20; +} + +/* All views except source code view: legend format for hi coverage */ +span.coverLegendCovHi +{ + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; + background-color: #a7fc9d; +} diff --git a/doc/test/coverage/glass.png b/doc/test/coverage/glass.png new file mode 100644 index 0000000..e1abc00 Binary files /dev/null and b/doc/test/coverage/glass.png differ diff --git a/doc/test/coverage/index-sort-b.html b/doc/test/coverage/index-sort-b.html new file mode 100644 index 0000000..ddbe342 --- /dev/null +++ b/doc/test/coverage/index-sort-b.html @@ -0,0 +1,155 @@ + + + + + + + LCOV - lcov.info + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top levelHitTotalCoverage
Test:lcov.infoLines:10113674.3 %
Date:2023-11-21 13:10:43Functions:313979.5 %
Branches:424887.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Directory Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
script +
0.0%
+
0.0 %0 / 280.0 %0 / 20.0 %0 / 2
src +
95.9%95.9%
+
95.9 %47 / 4992.3 %12 / 1390.0 %18 / 20
src/rules +
96.3%96.3%
+
96.3 %52 / 5489.5 %17 / 1992.3 %24 / 26
test/utils +
33.3%33.3%
+
33.3 %1 / 333.3 %1 / 3-0 / 0
src/modules +
50.0%50.0%
+
50.0 %1 / 250.0 %1 / 2-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/index-sort-f.html b/doc/test/coverage/index-sort-f.html new file mode 100644 index 0000000..db2b75a --- /dev/null +++ b/doc/test/coverage/index-sort-f.html @@ -0,0 +1,155 @@ + + + + + + + LCOV - lcov.info + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top levelHitTotalCoverage
Test:lcov.infoLines:10113674.3 %
Date:2023-11-21 13:10:43Functions:313979.5 %
Branches:424887.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Directory Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
script +
0.0%
+
0.0 %0 / 280.0 %0 / 20.0 %0 / 2
test/utils +
33.3%33.3%
+
33.3 %1 / 333.3 %1 / 3-0 / 0
src/modules +
50.0%50.0%
+
50.0 %1 / 250.0 %1 / 2-0 / 0
src/rules +
96.3%96.3%
+
96.3 %52 / 5489.5 %17 / 1992.3 %24 / 26
src +
95.9%95.9%
+
95.9 %47 / 4992.3 %12 / 1390.0 %18 / 20
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/index-sort-l.html b/doc/test/coverage/index-sort-l.html new file mode 100644 index 0000000..1745e80 --- /dev/null +++ b/doc/test/coverage/index-sort-l.html @@ -0,0 +1,155 @@ + + + + + + + LCOV - lcov.info + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top levelHitTotalCoverage
Test:lcov.infoLines:10113674.3 %
Date:2023-11-21 13:10:43Functions:313979.5 %
Branches:424887.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Directory Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
script +
0.0%
+
0.0 %0 / 280.0 %0 / 20.0 %0 / 2
test/utils +
33.3%33.3%
+
33.3 %1 / 333.3 %1 / 3-0 / 0
src/modules +
50.0%50.0%
+
50.0 %1 / 250.0 %1 / 2-0 / 0
src +
95.9%95.9%
+
95.9 %47 / 4992.3 %12 / 1390.0 %18 / 20
src/rules +
96.3%96.3%
+
96.3 %52 / 5489.5 %17 / 1992.3 %24 / 26
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/index.html b/doc/test/coverage/index.html new file mode 100644 index 0000000..83d96f4 --- /dev/null +++ b/doc/test/coverage/index.html @@ -0,0 +1,155 @@ + + + + + + + LCOV - lcov.info + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top levelHitTotalCoverage
Test:lcov.infoLines:10113674.3 %
Date:2023-11-21 13:10:43Functions:313979.5 %
Branches:424887.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Directory Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
script +
0.0%
+
0.0 %0 / 280.0 %0 / 20.0 %0 / 2
src +
95.9%95.9%
+
95.9 %47 / 4992.3 %12 / 1390.0 %18 / 20
src/modules +
50.0%50.0%
+
50.0 %1 / 250.0 %1 / 2-0 / 0
src/rules +
96.3%96.3%
+
96.3 %52 / 5489.5 %17 / 1992.3 %24 / 26
test/utils +
33.3%33.3%
+
33.3 %1 / 333.3 %1 / 3-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/ruby.png b/doc/test/coverage/ruby.png new file mode 100644 index 0000000..991b6d4 Binary files /dev/null and b/doc/test/coverage/ruby.png differ 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 new file mode 100644 index 0000000..c2ad6e1 --- /dev/null +++ b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - script/CMTATWithRuleEngineScript.s.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - script - CMTATWithRuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0160.0 %
Date:2023-11-21 13:10:43Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
CMTATWithRuleEngineScript.run0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html new file mode 100644 index 0000000..ae44042 --- /dev/null +++ b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - script/CMTATWithRuleEngineScript.s.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - script - CMTATWithRuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0160.0 %
Date:2023-11-21 13:10:43Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
CMTATWithRuleEngineScript.run0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html new file mode 100644 index 0000000..30eef0f --- /dev/null +++ b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html @@ -0,0 +1,137 @@ + + + + + + + LCOV - lcov.info - script/CMTATWithRuleEngineScript.s.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - script - CMTATWithRuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0160.0 %
Date:2023-11-21 13:10:43Functions:010.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: UNLICENSED
+       2                 :            : // Documentation :
+       3                 :            : // https://book.getfoundry.sh/tutorials/solidity-scripting
+       4                 :            : pragma solidity ^0.8.17;
+       5                 :            : 
+       6                 :            : import "forge-std/Script.sol";
+       7                 :            : import "CMTAT/CMTAT_STANDALONE.sol";
+       8                 :            : import "src/RuleEngine.sol";
+       9                 :            : import "src/rules/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 :         uint48 initialDelay = 0;
+      22                 :          0 :         uint8 decimals = 0;
+      23                 :            :         // CMTAT
+      24                 :          0 :         CMTAT_STANDALONE CMTAT_CONTRACT = new CMTAT_STANDALONE(
+      25                 :            :             trustedForwarder,
+      26                 :            :             ADMIN,
+      27                 :            :             initialDelay,
+      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(ADMIN, trustedForwarder);
+      46                 :          0 :         console.log("RuleEngine : ", address(RULE_ENGINE));
+      47                 :          0 :         RULE_ENGINE.addRule(ruleWhitelist);
+      48                 :          0 :         CMTAT_CONTRACT.setRuleEngine(RULE_ENGINE);
+      49                 :            : 
+      50                 :          0 :         vm.stopBroadcast();
+      51                 :            :     }
+      52                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + 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 new file mode 100644 index 0000000..600ff1d --- /dev/null +++ b/doc/test/coverage/script/RuleEngineScript.s.sol.func-sort-c.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - script/RuleEngineScript.s.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - script - RuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2023-11-21 13:10:43Functions:010.0 %
Branches:020.0 %
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleEngineScript.run0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/script/RuleEngineScript.s.sol.func.html b/doc/test/coverage/script/RuleEngineScript.s.sol.func.html new file mode 100644 index 0000000..5a83124 --- /dev/null +++ b/doc/test/coverage/script/RuleEngineScript.s.sol.func.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - script/RuleEngineScript.s.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - script - RuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2023-11-21 13:10:43Functions:010.0 %
Branches:020.0 %
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleEngineScript.run0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/script/RuleEngineScript.s.sol.gcov.html b/doc/test/coverage/script/RuleEngineScript.s.sol.gcov.html new file mode 100644 index 0000000..c6daceb --- /dev/null +++ b/doc/test/coverage/script/RuleEngineScript.s.sol.gcov.html @@ -0,0 +1,121 @@ + + + + + + + LCOV - lcov.info - script/RuleEngineScript.s.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - script - RuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2023-11-21 13:10:43Functions:010.0 %
Branches:020.0 %
+
+ + + + + + + + +

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

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngineScript.s.sol +
0.0%
+
0.0 %0 / 120.0 %0 / 10.0 %0 / 2
CMTATWithRuleEngineScript.s.sol +
0.0%
+
0.0 %0 / 160.0 %0 / 1-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/script/index-sort-f.html b/doc/test/coverage/script/index-sort-f.html new file mode 100644 index 0000000..953bf68 --- /dev/null +++ b/doc/test/coverage/script/index-sort-f.html @@ -0,0 +1,119 @@ + + + + + + + LCOV - lcov.info - script + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - scriptHitTotalCoverage
Test:lcov.infoLines:0280.0 %
Date:2023-11-21 13:10:43Functions:020.0 %
Branches:020.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
CMTATWithRuleEngineScript.s.sol +
0.0%
+
0.0 %0 / 160.0 %0 / 1-0 / 0
RuleEngineScript.s.sol +
0.0%
+
0.0 %0 / 120.0 %0 / 10.0 %0 / 2
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/script/index-sort-l.html b/doc/test/coverage/script/index-sort-l.html new file mode 100644 index 0000000..0cd3179 --- /dev/null +++ b/doc/test/coverage/script/index-sort-l.html @@ -0,0 +1,119 @@ + + + + + + + LCOV - lcov.info - script + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - scriptHitTotalCoverage
Test:lcov.infoLines:0280.0 %
Date:2023-11-21 13:10:43Functions:020.0 %
Branches:020.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngineScript.s.sol +
0.0%
+
0.0 %0 / 120.0 %0 / 10.0 %0 / 2
CMTATWithRuleEngineScript.s.sol +
0.0%
+
0.0 %0 / 160.0 %0 / 1-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/script/index.html b/doc/test/coverage/script/index.html new file mode 100644 index 0000000..483de1c --- /dev/null +++ b/doc/test/coverage/script/index.html @@ -0,0 +1,119 @@ + + + + + + + LCOV - lcov.info - script + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - scriptHitTotalCoverage
Test:lcov.infoLines:0280.0 %
Date:2023-11-21 13:10:43Functions:020.0 %
Branches:020.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
CMTATWithRuleEngineScript.s.sol +
0.0%
+
0.0 %0 / 160.0 %0 / 1-0 / 0
RuleEngineScript.s.sol +
0.0%
+
0.0 %0 / 120.0 %0 / 10.0 %0 / 2
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/snow.png b/doc/test/coverage/snow.png new file mode 100644 index 0000000..2cdae10 Binary files /dev/null and b/doc/test/coverage/snow.png differ diff --git a/doc/test/coverage/src/RuleEngine.sol.func-sort-c.html b/doc/test/coverage/src/RuleEngine.sol.func-sort-c.html new file mode 100644 index 0000000..7ea7c73 --- /dev/null +++ b/doc/test/coverage/src/RuleEngine.sol.func-sort-c.html @@ -0,0 +1,133 @@ + + + + + + + LCOV - lcov.info - src/RuleEngine.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src - RuleEngine.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:474995.9 %
Date:2023-11-21 13:10:43Functions:121392.3 %
Branches:182090.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleEngine._msgData0
RuleEngine.rule1
RuleEngine.clearRules3
RuleEngine.getRuleIndex3
RuleEngine.rules4
RuleEngine.messageForTransferRestriction6
RuleEngine.removeRule6
RuleEngine.detectTransferRestriction7
RuleEngine.addRule9
RuleEngine.setRules10
RuleEngine.validateTransfer10
RuleEngine.rulesCount20
RuleEngine._msgSender38
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/RuleEngine.sol.func.html b/doc/test/coverage/src/RuleEngine.sol.func.html new file mode 100644 index 0000000..3835b16 --- /dev/null +++ b/doc/test/coverage/src/RuleEngine.sol.func.html @@ -0,0 +1,133 @@ + + + + + + + LCOV - lcov.info - src/RuleEngine.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src - RuleEngine.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:474995.9 %
Date:2023-11-21 13:10:43Functions:121392.3 %
Branches:182090.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleEngine._msgData0
RuleEngine._msgSender38
RuleEngine.addRule9
RuleEngine.clearRules3
RuleEngine.detectTransferRestriction7
RuleEngine.getRuleIndex3
RuleEngine.messageForTransferRestriction6
RuleEngine.removeRule6
RuleEngine.rule1
RuleEngine.rules4
RuleEngine.rulesCount20
RuleEngine.setRules10
RuleEngine.validateTransfer10
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/RuleEngine.sol.gcov.html b/doc/test/coverage/src/RuleEngine.sol.gcov.html new file mode 100644 index 0000000..57245ba --- /dev/null +++ b/doc/test/coverage/src/RuleEngine.sol.gcov.html @@ -0,0 +1,340 @@ + + + + + + + LCOV - lcov.info - src/RuleEngine.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src - RuleEngine.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:474995.9 %
Date:2023-11-21 13:10:43Functions:121392.3 %
Branches:182090.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : 
+       3                 :            : pragma solidity ^0.8.20;
+       4                 :            : 
+       5                 :            : import "CMTAT/mocks/RuleEngine/interfaces/IRule.sol";
+       6                 :            : import "CMTAT/mocks/RuleEngine/interfaces/IRuleEngine.sol";
+       7                 :            : import "./modules/MetaTxModuleStandalone.sol";
+       8                 :            : import "../lib/openzeppelin-contracts/contracts/access/AccessControl.sol";
+       9                 :            : 
+      10                 :            : /**
+      11                 :            : @title Implementation of a ruleEngine defined by the CMTAT
+      12                 :            : */
+      13                 :            : contract RuleEngine is IRuleEngine, AccessControl, MetaTxModuleStandalone {
+      14                 :            :     error RuleEngine_RuleAddressZeroNotAllowed();
+      15                 :            :     error RuleEngine_RuleAlreadyExists();
+      16                 :            :     error RuleEngine_RuleDoNotMatch();
+      17                 :            :     error RuleEngine_AdminWithAddressZeroNotAllowed();
+      18                 :            :     error RuleEngine_ArrayIsEmpty();
+      19                 :            :     /// @dev Role to manage the ruleEngine
+      20                 :            :     bytes32 public constant RULE_ENGINE_ROLE = keccak256("RULE_ENGINE_ROLE");
+      21                 :            :     /// @dev Indicate if a rule already exists
+      22                 :            :     mapping(IRule => bool) _ruleIsPresent;
+      23                 :            :     /// @dev Array of rules
+      24                 :            :     IRule[] internal _rules;
+      25                 :            :     /// @notice Generate when a rule is added
+      26                 :            :     event AddRule(IRule indexed rule);
+      27                 :            :     /// @notice Generate when a rule is removed
+      28                 :            :     event RemoveRule(IRule indexed rule);
+      29                 :            :     /// @notice Generate when all the rules are cleared
+      30                 :            :     event ClearRules(IRule[] rulesRemoved);
+      31                 :            : 
+      32                 :            :     /**
+      33                 :            :     * @param admin Address of the contract (Access Control)
+      34                 :            :     * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
+      35                 :            :     */
+      36                 :            :     constructor(
+      37                 :            :         address admin,
+      38                 :            :         address forwarderIrrevocable
+      39                 :            :     ) MetaTxModuleStandalone(forwarderIrrevocable) {
+      40                 :            :         if(admin == address(0))
+      41                 :            :         {
+      42                 :            :             revert RuleEngine_AdminWithAddressZeroNotAllowed();
+      43                 :            :         }
+      44                 :            :         _grantRole(DEFAULT_ADMIN_ROLE, admin);
+      45                 :            :         _grantRole(RULE_ENGINE_ROLE, admin);
+      46                 :            :     }
+      47                 :            : 
+      48                 :            :     /**
+      49                 :            :      * @notice Set all the rules, will overwrite all the previous rules. \n
+      50                 :            :      * Revert if one rule is a zero address or if the rule is already present
+      51                 :            :      *
+      52                 :            :      */
+      53                 :            :     function setRules(
+      54                 :            :         IRule[] calldata rules_
+      55                 :            :     ) external override onlyRole(RULE_ENGINE_ROLE) {
+      56         [ +  + ]:          9 :         if(rules_.length == 0){
+      57                 :          1 :             revert RuleEngine_ArrayIsEmpty();
+      58                 :            :         }
+      59                 :          8 :         for (uint256 i = 0; i < rules_.length; ) {
+      60         [ +  + ]:         15 :             if( address(rules_[i]) == address(0x0)){
+      61                 :          1 :                 revert  RuleEngine_RuleAddressZeroNotAllowed();
+      62                 :            :             }
+      63         [ +  + ]:         14 :             if(_ruleIsPresent[rules_[i]]){
+      64                 :          1 :                 revert RuleEngine_RuleAlreadyExists();
+      65                 :            :             }
+      66                 :         13 :             _ruleIsPresent[rules_[i]] = true;
+      67                 :         13 :             emit AddRule(rules_[i]);
+      68                 :            :             unchecked {
+      69                 :         13 :                 ++i;
+      70                 :            :             }
+      71                 :            :         }
+      72                 :          6 :         _rules = rules_;
+      73                 :            :     }
+      74                 :            : 
+      75                 :            :     /**
+      76                 :            :      * @notice Clear all the rules of the array of rules
+      77                 :            :      *
+      78                 :            :      */
+      79                 :            :     function clearRules() public onlyRole(RULE_ENGINE_ROLE) {
+      80                 :          2 :         emit ClearRules(_rules);
+      81                 :          2 :         _rules = new IRule[](0);
+      82                 :            :     }
+      83                 :            : 
+      84                 :            :     /**
+      85                 :            :      * @notice Add a rule to the array of rules
+      86                 :            :      * Revert if one rule is a zero address or if the rule is already present
+      87                 :            :      *
+      88                 :            :      */
+      89                 :            :     function addRule(IRule rule_) public onlyRole(RULE_ENGINE_ROLE) {
+      90         [ +  + ]:          8 :         if( address(rule_) == address(0x0))
+      91                 :            :         {
+      92                 :          1 :             revert RuleEngine_RuleAddressZeroNotAllowed();
+      93                 :            :         }
+      94         [ +  + ]:          7 :         if( _ruleIsPresent[rule_])
+      95                 :            :         {
+      96                 :          1 :             revert RuleEngine_RuleAlreadyExists();
+      97                 :            :         }
+      98                 :          6 :         _rules.push(rule_);
+      99                 :          6 :         _ruleIsPresent[rule_] = true;
+     100                 :          6 :         emit AddRule(rule_);
+     101                 :            :     }
+     102                 :            : 
+     103                 :            :     /**
+     104                 :            :      * @notice Remove a rule from the array of rules
+     105                 :            :      * Revert if the rule found at the specified index does not match the rule in argument
+     106                 :            :      * @param rule_ address of the target rule
+     107                 :            :      * @param index the position inside the array of rule
+     108                 :            :      * @dev To reduce the array size, the last rule is moved to the location occupied
+     109                 :            :      * by the rule to remove
+     110                 :            :      *
+     111                 :            :      *
+     112                 :            :      */
+     113                 :            :     function removeRule(
+     114                 :            :         IRule rule_,
+     115                 :            :         uint256 index
+     116                 :            :     ) public onlyRole(RULE_ENGINE_ROLE) {
+     117         [ +  + ]:          5 :         if(_rules[index] != rule_)
+     118                 :            :         {
+     119                 :          1 :             revert RuleEngine_RuleDoNotMatch();
+     120                 :            :         }
+     121         [ #  + ]:          4 :         if (index != _rules.length - 1) {
+     122                 :          2 :             _rules[index] = _rules[_rules.length - 1];
+     123                 :            :         }
+     124                 :          4 :         _rules.pop();
+     125                 :          4 :         _ruleIsPresent[rule_] = false;
+     126                 :          4 :         emit RemoveRule(rule_);
+     127                 :            :     }
+     128                 :            : 
+     129                 :            :     /**
+     130                 :            :     * @return The number of rules inside the array
+     131                 :            :     */
+     132                 :            :     function rulesCount() external view override returns (uint256) {
+     133                 :         20 :         return _rules.length;
+     134                 :            :     }
+     135                 :            : 
+     136                 :            :     /**
+     137                 :            :     * @notice Get the index of a rule inside the list
+     138                 :            :     * @return index if the rule is found, _rules.length otherwise
+     139                 :            :     */
+     140                 :            :     function getRuleIndex(IRule rule_) external view returns (uint256 index) {
+     141                 :          0 :         for (index = 0; index < _rules.length; ) {
+     142         [ +  + ]:          5 :             if (_rules[index] == rule_) {
+     143                 :          5 :                 return index;
+     144                 :            :             }
+     145                 :            :             unchecked {
+     146                 :          3 :                 ++index;
+     147                 :            :             }
+     148                 :            :         }
+     149                 :          1 :         return _rules.length;
+     150                 :            :     }
+     151                 :            : 
+     152                 :            :     /**
+     153                 :            :     * @notice Get the rule at the position specified by ruleId
+     154                 :            :     * @param ruleId index of the rule
+     155                 :            :     * @return a rule address
+     156                 :            :     */
+     157                 :            :     function rule(uint256 ruleId) external view override returns (IRule) {
+     158                 :          1 :         return _rules[ruleId];
+     159                 :            :     }
+     160                 :            : 
+     161                 :            :     /**
+     162                 :            :     * @notice Get all the rules
+     163                 :            :     * @return An array of rules
+     164                 :            :     */
+     165                 :            :     function rules() external view override returns (IRule[] memory) {
+     166                 :          4 :         return _rules;
+     167                 :            :     }
+     168                 :            : 
+     169                 :            :     /** 
+     170                 :            :     * @notice Go through all the rule to know if a restriction exists on the transfer
+     171                 :            :     * @param _from the origin address
+     172                 :            :     * @param _to the destination address
+     173                 :            :     * @param _amount to transfer
+     174                 :            :     * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
+     175                 :            :     **/
+     176                 :            :     function detectTransferRestriction(
+     177                 :            :         address _from,
+     178                 :            :         address _to,
+     179                 :            :         uint256 _amount
+     180                 :            :     ) public view override returns (uint8) {
+     181                 :         17 :         for (uint256 i = 0; i < _rules.length; ) {
+     182                 :         17 :             uint8 restriction = _rules[i].detectTransferRestriction(
+     183                 :            :                 _from,
+     184                 :            :                 _to,
+     185                 :            :                 _amount
+     186                 :            :             );
+     187         [ +  + ]:         17 :             if (restriction > 0) {
+     188                 :         12 :                 return restriction;
+     189                 :            :             }
+     190                 :            :             unchecked {
+     191                 :          5 :                 ++i;
+     192                 :            :             }
+     193                 :            :         }
+     194                 :          5 :         return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+     195                 :            :     }
+     196                 :            : 
+     197                 :            :     /** 
+     198                 :            :     * @notice Validate a transfer
+     199                 :            :     * @param _from the origin address
+     200                 :            :     * @param _to the destination address
+     201                 :            :     * @param _amount to transfer
+     202                 :            :     * @return True if the transfer is valid, false otherwise
+     203                 :            :     **/
+     204                 :            :     function validateTransfer(
+     205                 :            :         address _from,
+     206                 :            :         address _to,
+     207                 :            :         uint256 _amount
+     208                 :            :     ) public view override returns (bool) {
+     209                 :         10 :         return detectTransferRestriction(_from, _to, _amount) == uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+     210                 :            :     }
+     211                 :            : 
+     212                 :            :     /** 
+     213                 :            :     * @notice Return the message corresponding to the code
+     214                 :            :     * @param _restrictionCode The target restriction code
+     215                 :            :     * @return True if the transfer is valid, false otherwise
+     216                 :            :     **/
+     217                 :            :     function messageForTransferRestriction(
+     218                 :            :         uint8 _restrictionCode
+     219                 :            :     ) external view override returns (string memory) {
+     220                 :          6 :         for (uint256 i = 0; i < _rules.length; ) {
+     221         [ #  + ]:          5 :             if (_rules[i].canReturnTransferRestrictionCode(_restrictionCode)) {
+     222                 :          4 :                 return
+     223                 :            :                     _rules[i].messageForTransferRestriction(_restrictionCode);
+     224                 :            :             }
+     225                 :            :             unchecked {
+     226                 :          1 :                 ++i;
+     227                 :            :             }
+     228                 :            :         }
+     229                 :          2 :         return "Unknown restriction code";
+     230                 :            :     }
+     231                 :            : 
+     232                 :            :     /** 
+     233                 :            :     * @dev This surcharge is not necessary if you do not use the MetaTxModule
+     234                 :            :     */
+     235                 :            :     function _msgSender()
+     236                 :            :         internal
+     237                 :            :         view
+     238                 :            :         override(MetaTxModuleStandalone, Context)
+     239                 :            :         returns (address sender)
+     240                 :            :     {
+     241                 :         38 :         return MetaTxModuleStandalone._msgSender();
+     242                 :            :     }
+     243                 :            : 
+     244                 :            :     /** 
+     245                 :            :     * @dev This surcharge is not necessary if you do not use the MetaTxModule
+     246                 :            :     */
+     247                 :            :     function _msgData()
+     248                 :            :         internal
+     249                 :            :         view
+     250                 :            :         override(MetaTxModuleStandalone, Context)
+     251                 :            :         returns (bytes calldata)
+     252                 :            :     {
+     253                 :          0 :         return MetaTxModuleStandalone._msgData();
+     254                 :            :     }
+     255                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/index-sort-b.html b/doc/test/coverage/src/index-sort-b.html new file mode 100644 index 0000000..39d6409 --- /dev/null +++ b/doc/test/coverage/src/index-sort-b.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - srcHitTotalCoverage
Test:lcov.infoLines:474995.9 %
Date:2023-11-21 13:10:43Functions:121392.3 %
Branches:182090.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngine.sol +
95.9%95.9%
+
95.9 %47 / 4992.3 %12 / 1390.0 %18 / 20
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/index-sort-f.html b/doc/test/coverage/src/index-sort-f.html new file mode 100644 index 0000000..544b632 --- /dev/null +++ b/doc/test/coverage/src/index-sort-f.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - srcHitTotalCoverage
Test:lcov.infoLines:474995.9 %
Date:2023-11-21 13:10:43Functions:121392.3 %
Branches:182090.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngine.sol +
95.9%95.9%
+
95.9 %47 / 4992.3 %12 / 1390.0 %18 / 20
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/index-sort-l.html b/doc/test/coverage/src/index-sort-l.html new file mode 100644 index 0000000..a2f9800 --- /dev/null +++ b/doc/test/coverage/src/index-sort-l.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - srcHitTotalCoverage
Test:lcov.infoLines:474995.9 %
Date:2023-11-21 13:10:43Functions:121392.3 %
Branches:182090.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngine.sol +
95.9%95.9%
+
95.9 %47 / 4992.3 %12 / 1390.0 %18 / 20
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/index.html b/doc/test/coverage/src/index.html new file mode 100644 index 0000000..d452980 --- /dev/null +++ b/doc/test/coverage/src/index.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - src + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - srcHitTotalCoverage
Test:lcov.infoLines:474995.9 %
Date:2023-11-21 13:10:43Functions:121392.3 %
Branches:182090.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngine.sol +
95.9%95.9%
+
95.9 %47 / 4992.3 %12 / 1390.0 %18 / 20
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/modules/MetaTxModuleStandalone.sol.func-sort-c.html b/doc/test/coverage/src/modules/MetaTxModuleStandalone.sol.func-sort-c.html new file mode 100644 index 0000000..8576efa --- /dev/null +++ b/doc/test/coverage/src/modules/MetaTxModuleStandalone.sol.func-sort-c.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - src/modules/MetaTxModuleStandalone.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/modules - MetaTxModuleStandalone.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1250.0 %
Date:2023-11-21 13:10:43Functions:1250.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
MetaTxModuleStandalone._msgData0
MetaTxModuleStandalone._msgSender92
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/modules/MetaTxModuleStandalone.sol.func.html b/doc/test/coverage/src/modules/MetaTxModuleStandalone.sol.func.html new file mode 100644 index 0000000..d1a0432 --- /dev/null +++ b/doc/test/coverage/src/modules/MetaTxModuleStandalone.sol.func.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - src/modules/MetaTxModuleStandalone.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/modules - MetaTxModuleStandalone.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1250.0 %
Date:2023-11-21 13:10:43Functions:1250.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
MetaTxModuleStandalone._msgData0
MetaTxModuleStandalone._msgSender92
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/modules/MetaTxModuleStandalone.sol.gcov.html b/doc/test/coverage/src/modules/MetaTxModuleStandalone.sol.gcov.html new file mode 100644 index 0000000..da4c72c --- /dev/null +++ b/doc/test/coverage/src/modules/MetaTxModuleStandalone.sol.gcov.html @@ -0,0 +1,119 @@ + + + + + + + LCOV - lcov.info - src/modules/MetaTxModuleStandalone.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/modules - MetaTxModuleStandalone.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1250.0 %
Date:2023-11-21 13:10:43Functions:1250.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : //SPDX-License-Identifier: MPL-2.0
+       2                 :            : 
+       3                 :            : pragma solidity ^0.8.20;
+       4                 :            : 
+       5                 :            : import "../../lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol";
+       6                 :            : 
+       7                 :            : /**
+       8                 :            :  * @dev Meta transaction (gasless) module.
+       9                 :            :  */
+      10                 :            : abstract contract MetaTxModuleStandalone is ERC2771Context {
+      11                 :            :     constructor(address trustedForwarder) ERC2771Context(trustedForwarder) {
+      12                 :            :         // Nothing to do
+      13                 :            :     }
+      14                 :            : 
+      15                 :            :     function _msgSender()
+      16                 :            :         internal
+      17                 :            :         view
+      18                 :            :         virtual
+      19                 :            :         override
+      20                 :            :         returns (address sender)
+      21                 :            :     {
+      22                 :         92 :         return ERC2771Context._msgSender();
+      23                 :            :     }
+      24                 :            : 
+      25                 :            :     function _msgData()
+      26                 :            :         internal
+      27                 :            :         view
+      28                 :            :         virtual
+      29                 :            :         override
+      30                 :            :         returns (bytes calldata)
+      31                 :            :     {
+      32                 :          0 :         return ERC2771Context._msgData();
+      33                 :            :     }
+      34                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/modules/index-sort-b.html b/doc/test/coverage/src/modules/index-sort-b.html new file mode 100644 index 0000000..a088ac9 --- /dev/null +++ b/doc/test/coverage/src/modules/index-sort-b.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - src/modules + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/modulesHitTotalCoverage
Test:lcov.infoLines:1250.0 %
Date:2023-11-21 13:10:43Functions:1250.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
MetaTxModuleStandalone.sol +
50.0%50.0%
+
50.0 %1 / 250.0 %1 / 2-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/modules/index-sort-f.html b/doc/test/coverage/src/modules/index-sort-f.html new file mode 100644 index 0000000..c1d3706 --- /dev/null +++ b/doc/test/coverage/src/modules/index-sort-f.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - src/modules + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/modulesHitTotalCoverage
Test:lcov.infoLines:1250.0 %
Date:2023-11-21 13:10:43Functions:1250.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
MetaTxModuleStandalone.sol +
50.0%50.0%
+
50.0 %1 / 250.0 %1 / 2-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/modules/index-sort-l.html b/doc/test/coverage/src/modules/index-sort-l.html new file mode 100644 index 0000000..375425e --- /dev/null +++ b/doc/test/coverage/src/modules/index-sort-l.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - src/modules + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/modulesHitTotalCoverage
Test:lcov.infoLines:1250.0 %
Date:2023-11-21 13:10:43Functions:1250.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
MetaTxModuleStandalone.sol +
50.0%50.0%
+
50.0 %1 / 250.0 %1 / 2-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/modules/index.html b/doc/test/coverage/src/modules/index.html new file mode 100644 index 0000000..bf323f0 --- /dev/null +++ b/doc/test/coverage/src/modules/index.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - src/modules + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/modulesHitTotalCoverage
Test:lcov.infoLines:1250.0 %
Date:2023-11-21 13:10:43Functions:1250.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
MetaTxModuleStandalone.sol +
50.0%50.0%
+
50.0 %1 / 250.0 %1 / 2-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/rules/RuleSanctionList.sol.func-sort-c.html b/doc/test/coverage/src/rules/RuleSanctionList.sol.func-sort-c.html new file mode 100644 index 0000000..8cbcf47 --- /dev/null +++ b/doc/test/coverage/src/rules/RuleSanctionList.sol.func-sort-c.html @@ -0,0 +1,109 @@ + + + + + + + LCOV - lcov.info - src/rules/RuleSanctionList.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/rules - RuleSanctionList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:151693.8 %
Date:2023-11-21 13:10:43Functions:6785.7 %
Branches:1010100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleSanctionList._msgData0
RuleSanctionList._msgSender2
RuleSanctionList.setOracle2
RuleSanctionList.canReturnTransferRestrictionCode3
RuleSanctionList.detectTransferRestriction3
RuleSanctionList.messageForTransferRestriction3
RuleSanctionList.validateTransfer4
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/rules/RuleSanctionList.sol.func.html b/doc/test/coverage/src/rules/RuleSanctionList.sol.func.html new file mode 100644 index 0000000..f3accdc --- /dev/null +++ b/doc/test/coverage/src/rules/RuleSanctionList.sol.func.html @@ -0,0 +1,109 @@ + + + + + + + LCOV - lcov.info - src/rules/RuleSanctionList.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/rules - RuleSanctionList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:151693.8 %
Date:2023-11-21 13:10:43Functions:6785.7 %
Branches:1010100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleSanctionList._msgData0
RuleSanctionList._msgSender2
RuleSanctionList.canReturnTransferRestrictionCode3
RuleSanctionList.detectTransferRestriction3
RuleSanctionList.messageForTransferRestriction3
RuleSanctionList.setOracle2
RuleSanctionList.validateTransfer4
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/rules/RuleSanctionList.sol.gcov.html b/doc/test/coverage/src/rules/RuleSanctionList.sol.gcov.html new file mode 100644 index 0000000..34d6650 --- /dev/null +++ b/doc/test/coverage/src/rules/RuleSanctionList.sol.gcov.html @@ -0,0 +1,217 @@ + + + + + + + LCOV - lcov.info - src/rules/RuleSanctionList.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/rules - RuleSanctionList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:151693.8 %
Date:2023-11-21 13:10:43Functions:6785.7 %
Branches:1010100.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : 
+       3                 :            : pragma solidity ^0.8.20;
+       4                 :            : import "../../lib/openzeppelin-contracts/contracts/access/AccessControl.sol";
+       5                 :            : import "../../lib/CMTAT/contracts/mocks/RuleEngine/interfaces/IRule.sol";
+       6                 :            : import "../modules/MetaTxModuleStandalone.sol";
+       7                 :            : import "./abstract/RuleSanctionListInvariantStorage.sol";
+       8                 :            : interface SanctionsList {
+       9                 :            :     function isSanctioned(address addr) external view returns (bool);
+      10                 :            : }
+      11                 :            : 
+      12                 :            : contract RuleSanctionList is IRule, AccessControl, MetaTxModuleStandalone,  RuleSanctionlistInvariantStorage {
+      13                 :            :     SanctionsList  public sanctionsList;
+      14                 :            : 
+      15                 :            :     /**
+      16                 :            :     * @param admin Address of the contract (Access Control)
+      17                 :            :     * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
+      18                 :            :     */
+      19                 :            :     constructor(
+      20                 :            :         address admin,
+      21                 :            :         address forwarderIrrevocable
+      22                 :            :     ) MetaTxModuleStandalone(forwarderIrrevocable) {
+      23                 :            :         if(admin == address(0)){
+      24                 :            :             revert RuleSanctionList_AdminWithAddressZeroNotAllowed();
+      25                 :            :         }
+      26                 :            :         _grantRole(DEFAULT_ADMIN_ROLE, admin);
+      27                 :            :         _grantRole(SANCTIONLIST_ROLE, admin);
+      28                 :            :     }
+      29                 :            : 
+      30                 :            :     /**
+      31                 :            :      * @notice Set the oracle contract
+      32                 :            :      * @param sanctionContractOracle_ address of your oracle contract
+      33                 :            :      * @dev zero address is authorized to authorize all transfers
+      34                 :            :      */
+      35                 :            :     function setOracle(
+      36                 :            :        address sanctionContractOracle_
+      37                 :            :     ) public onlyRole(SANCTIONLIST_ROLE) {
+      38                 :          1 :         sanctionsList = SanctionsList(sanctionContractOracle_);
+      39                 :            :     }
+      40                 :            : 
+      41                 :            :     /** 
+      42                 :            :     * @notice Validate a transfer
+      43                 :            :     * @param _from the origin address
+      44                 :            :     * @param _to the destination address
+      45                 :            :     * @param _amount to transfer
+      46                 :            :     * @return isValid => true if the transfer is valid, false otherwise
+      47                 :            :     **/
+      48                 :            :     function validateTransfer(
+      49                 :            :         address _from,
+      50                 :            :         address _to,
+      51                 :            :         uint256 _amount
+      52                 :            :     ) public view override returns (bool isValid) {
+      53                 :          4 :         return
+      54                 :            :             detectTransferRestriction(_from, _to, _amount) ==
+      55                 :            :             uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+      56                 :            :     }
+      57                 :            : 
+      58                 :            :     /** 
+      59                 :            :     * @notice Check if an addres is in the whitelist or not
+      60                 :            :     * @param _from the origin address
+      61                 :            :     * @param _to the destination address
+      62                 :            :     * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
+      63                 :            :     **/
+      64                 :            :     function detectTransferRestriction(
+      65                 :            :         address _from,
+      66                 :            :         address _to,
+      67                 :            :         uint256 /*_amount */
+      68                 :            :     ) public view override returns (uint8) {
+      69         [ +  + ]:          7 :         if(address(sanctionsList) != address(0)){
+      70         [ +  + ]:          7 :             if (sanctionsList.isSanctioned(_from)) {
+      71                 :          2 :                 return CODE_ADDRESS_FROM_IS_SANCTIONED;
+      72         [ +  + ]:          5 :             } else if (sanctionsList.isSanctioned(_to)) {
+      73                 :          2 :                 return  CODE_ADDRESS_TO_IS_SANCTIONED;
+      74                 :            :             }
+      75                 :            :         }
+      76                 :          3 :         return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+      77                 :            :     }
+      78                 :            : 
+      79                 :            :     /** 
+      80                 :            :     * @notice To know if the restriction code is valid for this rule or not.
+      81                 :            :     * @param _restrictionCode The target restriction code
+      82                 :            :     * @return true if the restriction code is known, false otherwise
+      83                 :            :     **/
+      84                 :            :     function canReturnTransferRestrictionCode(
+      85                 :            :         uint8 _restrictionCode
+      86                 :            :     ) external pure override returns (bool) {
+      87                 :          3 :         return
+      88                 :            :             _restrictionCode ==  CODE_ADDRESS_FROM_IS_SANCTIONED ||
+      89                 :            :             _restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED;
+      90                 :            :     }
+      91                 :            : 
+      92                 :            :     /** 
+      93                 :            :     * @notice Return the corresponding message
+      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 pure override returns (string memory) {
+     100         [ +  + ]:          3 :         if (_restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED) {
+     101                 :          1 :             return TEXT_ADDRESS_FROM_IS_SANCTIONED;
+     102         [ +  + ]:          2 :         } else if (_restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED) {
+     103                 :          1 :             return TEXT_ADDRESS_TO_IS_SANCTIONED;
+     104                 :            :         } else {
+     105                 :          1 :             return TEXT_CODE_NOT_FOUND;
+     106                 :            :         }
+     107                 :            :     }
+     108                 :            : 
+     109                 :            :         /** 
+     110                 :            :     * @dev This surcharge is not necessary if you do not use the MetaTxModule
+     111                 :            :     */
+     112                 :            :     function _msgSender()
+     113                 :            :         internal
+     114                 :            :         view
+     115                 :            :         override(MetaTxModuleStandalone, Context)
+     116                 :            :         returns (address sender)
+     117                 :            :     {
+     118                 :          2 :         return MetaTxModuleStandalone._msgSender();
+     119                 :            :     }
+     120                 :            : 
+     121                 :            :     /** 
+     122                 :            :     * @dev This surcharge is not necessary if you do not use the MetaTxModule
+     123                 :            :     */
+     124                 :            :     function _msgData()
+     125                 :            :         internal
+     126                 :            :         view
+     127                 :            :         override(MetaTxModuleStandalone, Context)
+     128                 :            :         returns (bytes calldata)
+     129                 :            :     {
+     130                 :          0 :         return MetaTxModuleStandalone._msgData();
+     131                 :            :     }
+     132                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/rules/RuleWhitelist.sol.func-sort-c.html b/doc/test/coverage/src/rules/RuleWhitelist.sol.func-sort-c.html new file mode 100644 index 0000000..6d88893 --- /dev/null +++ b/doc/test/coverage/src/rules/RuleWhitelist.sol.func-sort-c.html @@ -0,0 +1,129 @@ + + + + + + + LCOV - lcov.info - src/rules/RuleWhitelist.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/rules - RuleWhitelist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:373897.4 %
Date:2023-11-21 13:10:43Functions:111291.7 %
Branches:141687.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelist._msgData0
RuleWhitelist.removeAddressFromTheWhitelist3
RuleWhitelist.validateTransfer3
RuleWhitelist.removeAddressesFromTheWhitelist4
RuleWhitelist.messageForTransferRestriction7
RuleWhitelist.canReturnTransferRestrictionCode8
RuleWhitelist.addAddressesToTheWhitelist13
RuleWhitelist.detectTransferRestriction20
RuleWhitelist.numberWhitelistedAddress20
RuleWhitelist.addAddressToTheWhitelist22
RuleWhitelist.addressIsWhitelisted50
RuleWhitelist._msgSender52
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/rules/RuleWhitelist.sol.func.html b/doc/test/coverage/src/rules/RuleWhitelist.sol.func.html new file mode 100644 index 0000000..0b40c22 --- /dev/null +++ b/doc/test/coverage/src/rules/RuleWhitelist.sol.func.html @@ -0,0 +1,129 @@ + + + + + + + LCOV - lcov.info - src/rules/RuleWhitelist.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/rules - RuleWhitelist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:373897.4 %
Date:2023-11-21 13:10:43Functions:111291.7 %
Branches:141687.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelist._msgData0
RuleWhitelist._msgSender52
RuleWhitelist.addAddressToTheWhitelist22
RuleWhitelist.addAddressesToTheWhitelist13
RuleWhitelist.addressIsWhitelisted50
RuleWhitelist.canReturnTransferRestrictionCode8
RuleWhitelist.detectTransferRestriction20
RuleWhitelist.messageForTransferRestriction7
RuleWhitelist.numberWhitelistedAddress20
RuleWhitelist.removeAddressFromTheWhitelist3
RuleWhitelist.removeAddressesFromTheWhitelist4
RuleWhitelist.validateTransfer3
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/rules/RuleWhitelist.sol.gcov.html b/doc/test/coverage/src/rules/RuleWhitelist.sol.gcov.html new file mode 100644 index 0000000..4bfa160 --- /dev/null +++ b/doc/test/coverage/src/rules/RuleWhitelist.sol.gcov.html @@ -0,0 +1,304 @@ + + + + + + + LCOV - lcov.info - src/rules/RuleWhitelist.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/rules - RuleWhitelist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:373897.4 %
Date:2023-11-21 13:10:43Functions:111291.7 %
Branches:141687.5 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : 
+       3                 :            : pragma solidity ^0.8.20;
+       4                 :            : 
+       5                 :            : import "../../lib/openzeppelin-contracts/contracts/access/AccessControl.sol";
+       6                 :            : import "../../lib/CMTAT/contracts/mocks/RuleEngine/interfaces/IRule.sol";
+       7                 :            : import "./../modules/MetaTxModuleStandalone.sol";
+       8                 :            : import "./abstract/RuleWhitelistInvariantStorage.sol";
+       9                 :            : /**
+      10                 :            : @title a whitelist manager
+      11                 :            : */
+      12                 :            : 
+      13                 :            : contract RuleWhitelist is IRule, AccessControl, MetaTxModuleStandalone, RuleWhitelistInvariantStorage {
+      14                 :            :      mapping(address => bool) whitelist;
+      15                 :            :     // Number of addresses in the whitelist at the moment
+      16                 :            :     uint256 private numAddressesWhitelisted;
+      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                 :            :     ) MetaTxModuleStandalone(forwarderIrrevocable) {
+      26                 :            :         if(admin == address(0)){
+      27                 :            :             revert RuleWhitelist_AdminWithAddressZeroNotAllowed();
+      28                 :            :         }
+      29                 :            :         _grantRole(DEFAULT_ADMIN_ROLE, admin);
+      30                 :            :         _grantRole(WHITELIST_ROLE, admin);
+      31                 :            :     }
+      32                 :            : 
+      33                 :            :     /**
+      34                 :            :      * @notice Add addresses to the whitelist
+      35                 :            :      * If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert).
+      36                 :            :      * @param listWhitelistedAddress an array with the addresses to whitelist
+      37                 :            :      */
+      38                 :            :     function addAddressesToTheWhitelist(
+      39                 :            :         address[] calldata listWhitelistedAddress
+      40                 :            :     ) public onlyRole(WHITELIST_ROLE) {
+      41                 :         12 :         uint256 numAddressesWhitelistedLocal = numAddressesWhitelisted;
+      42                 :         12 :         for (uint256 i = 0; i < listWhitelistedAddress.length; ) {
+      43         [ #  + ]:         26 :             if (!whitelist[listWhitelistedAddress[i]]) {
+      44                 :         24 :                 whitelist[listWhitelistedAddress[i]] = true;
+      45                 :         24 :                 ++numAddressesWhitelistedLocal;
+      46                 :            :             }
+      47                 :            :             unchecked {
+      48                 :         26 :                 ++i;
+      49                 :            :             }
+      50                 :            :         }
+      51                 :         12 :         numAddressesWhitelisted = numAddressesWhitelistedLocal;
+      52                 :            :     }
+      53                 :            : 
+      54                 :            :     /**
+      55                 :            :      * @notice Remove addresses from the whitelist
+      56                 :            :      * If the address does not exist in the whitelist, there is no change for this address. 
+      57                 :            :      * The transaction remains valid (no revert).
+      58                 :            :      * @param listWhitelistedAddress an array with the addresses to remove
+      59                 :            :      */
+      60                 :            :     function removeAddressesFromTheWhitelist(
+      61                 :            :         address[] calldata listWhitelistedAddress
+      62                 :            :     ) public onlyRole(WHITELIST_ROLE) {
+      63                 :          3 :         uint256 numAddressesWhitelistedLocal = numAddressesWhitelisted;
+      64                 :          3 :         for (uint256 i = 0; i < listWhitelistedAddress.length; ) {
+      65         [ #  + ]:          7 :             if (whitelist[listWhitelistedAddress[i]]) {
+      66                 :          6 :                 whitelist[listWhitelistedAddress[i]] = false;
+      67                 :          6 :                 --numAddressesWhitelistedLocal;
+      68                 :            :             }
+      69                 :            :             unchecked {
+      70                 :          7 :                 ++i;
+      71                 :            :             }
+      72                 :            :         }
+      73                 :          3 :         numAddressesWhitelisted = numAddressesWhitelistedLocal;
+      74                 :            :     }
+      75                 :            : 
+      76                 :            :     /**
+      77                 :            :      * @notice Add one address to the whitelist
+      78                 :            :      * If the address already exists, the transaction is reverted to save gas.
+      79                 :            :      * @param _newWhitelistAddress The address to whitelist
+      80                 :            :      */
+      81                 :            :     function addAddressToTheWhitelist(
+      82                 :            :         address _newWhitelistAddress
+      83                 :            :     ) public onlyRole(WHITELIST_ROLE) {
+      84         [ +  + ]:         21 :         if(whitelist[_newWhitelistAddress])
+      85                 :            :         {
+      86                 :          1 :             revert RuleWhitelist_AddressAlreadyWhitelisted();
+      87                 :            :         }
+      88                 :         20 :         whitelist[_newWhitelistAddress] = true;
+      89                 :         20 :         ++numAddressesWhitelisted;
+      90                 :            :     }
+      91                 :            : 
+      92                 :            :     /**
+      93                 :            :      * @notice Remove one address from the whitelist
+      94                 :            :      * If the address does not exist in the whitelist, the transaction is reverted to save gas.
+      95                 :            :      * @param _removeWhitelistAddress The address to remove
+      96                 :            :      *
+      97                 :            :      */
+      98                 :            :     function removeAddressFromTheWhitelist(
+      99                 :            :         address _removeWhitelistAddress
+     100                 :            :     ) public onlyRole(WHITELIST_ROLE) {
+     101         [ +  + ]:          2 :         if(!whitelist[_removeWhitelistAddress]){
+     102                 :          1 :             revert RuleWhitelist_AddressNotPresent();
+     103                 :            :         }
+     104                 :          1 :         whitelist[_removeWhitelistAddress] = false;
+     105                 :          1 :         --numAddressesWhitelisted;
+     106                 :            :     }
+     107                 :            : 
+     108                 :            :     /**
+     109                 :            :      * @notice Get the number of whitelisted addresses
+     110                 :            :      * @return Number of whitelisted addresses
+     111                 :            :      *
+     112                 :            :      */
+     113                 :            :     function numberWhitelistedAddress() external view returns (uint256) {
+     114                 :         20 :         return numAddressesWhitelisted;
+     115                 :            :     }
+     116                 :            : 
+     117                 :            :     /**
+     118                 :            :      * @notice Know if an address is whitelisted or not
+     119                 :            :      * @param _targetAddress The concerned address
+     120                 :            :      * @return True if the address is whitelisted, false otherwise
+     121                 :            :      *
+     122                 :            :      */
+     123                 :            :     function addressIsWhitelisted(
+     124                 :            :         address _targetAddress
+     125                 :            :     ) external view returns (bool) {
+     126                 :         50 :         return whitelist[_targetAddress];
+     127                 :            :     }
+     128                 :            : 
+     129                 :            :     /** 
+     130                 :            :     * @notice Validate a transfer
+     131                 :            :     * @param _from the origin address
+     132                 :            :     * @param _to the destination address
+     133                 :            :     * @param _amount to transfer
+     134                 :            :     * @return isValid => true if the transfer is valid, false otherwise
+     135                 :            :     **/
+     136                 :            :     function validateTransfer(
+     137                 :            :         address _from,
+     138                 :            :         address _to,
+     139                 :            :         uint256 _amount
+     140                 :            :     ) public view override returns (bool isValid) {
+     141                 :          3 :         return
+     142                 :            :             detectTransferRestriction(_from, _to, _amount) ==
+     143                 :            :             uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+     144                 :            :     }
+     145                 :            : 
+     146                 :            :     /** 
+     147                 :            :     * @notice Check if an addres is in the whitelist or not
+     148                 :            :     * @param _from the origin address
+     149                 :            :     * @param _to the destination address
+     150                 :            :     * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
+     151                 :            :     **/
+     152                 :            :     function detectTransferRestriction(
+     153                 :            :         address _from,
+     154                 :            :         address _to,
+     155                 :            :         uint256 /*_amount */
+     156                 :            :     ) public view override returns (uint8) {
+     157         [ +  + ]:         23 :         if (!whitelist[_from]) {
+     158                 :         11 :             return CODE_ADDRESS_FROM_NOT_WHITELISTED;
+     159         [ +  + ]:         12 :         } else if (!whitelist[_to]) {
+     160                 :          4 :             return CODE_ADDRESS_TO_NOT_WHITELISTED;
+     161                 :            :         } else {
+     162                 :          8 :             return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+     163                 :            :         }
+     164                 :            :     }
+     165                 :            : 
+     166                 :            :     /** 
+     167                 :            :     * @notice To know if the restriction code is valid for this rule or not.
+     168                 :            :     * @param _restrictionCode The target restriction code
+     169                 :            :     * @return true if the restriction code is known, false otherwise
+     170                 :            :     **/
+     171                 :            :     function canReturnTransferRestrictionCode(
+     172                 :            :         uint8 _restrictionCode
+     173                 :            :     ) external pure override returns (bool) {
+     174                 :          8 :         return
+     175                 :            :             _restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED ||
+     176                 :            :             _restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED;
+     177                 :            :     }
+     178                 :            : 
+     179                 :            :     /** 
+     180                 :            :     * @notice Return the corresponding message
+     181                 :            :     * @param _restrictionCode The target restriction code
+     182                 :            :     * @return true if the transfer is valid, false otherwise
+     183                 :            :     **/
+     184                 :            :     function messageForTransferRestriction(
+     185                 :            :         uint8 _restrictionCode
+     186                 :            :     ) external pure override returns (string memory) {
+     187         [ +  + ]:          7 :         if (_restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) {
+     188                 :          4 :             return TEXT_ADDRESS_FROM_NOT_WHITELISTED;
+     189         [ +  + ]:          3 :         } else if (_restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) {
+     190                 :          2 :             return TEXT_ADDRESS_TO_NOT_WHITELISTED;
+     191                 :            :         } else {
+     192                 :          1 :             return TEXT_CODE_NOT_FOUND;
+     193                 :            :         }
+     194                 :            :     }
+     195                 :            : 
+     196                 :            :     /** 
+     197                 :            :     * @dev This surcharge is not necessary if you do not use the MetaTxModule
+     198                 :            :     */
+     199                 :            :     function _msgSender()
+     200                 :            :         internal
+     201                 :            :         view
+     202                 :            :         override(MetaTxModuleStandalone, Context)
+     203                 :            :         returns (address sender)
+     204                 :            :     {
+     205                 :         52 :         return MetaTxModuleStandalone._msgSender();
+     206                 :            :     }
+     207                 :            : 
+     208                 :            :     /** 
+     209                 :            :     * @dev This surcharge is not necessary if you do not use the MetaTxModule
+     210                 :            :     */
+     211                 :            :     function _msgData()
+     212                 :            :         internal
+     213                 :            :         view
+     214                 :            :         override(MetaTxModuleStandalone, Context)
+     215                 :            :         returns (bytes calldata)
+     216                 :            :     {
+     217                 :          0 :         return MetaTxModuleStandalone._msgData();
+     218                 :            :     }
+     219                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/rules/index-sort-b.html b/doc/test/coverage/src/rules/index-sort-b.html new file mode 100644 index 0000000..cb998f5 --- /dev/null +++ b/doc/test/coverage/src/rules/index-sort-b.html @@ -0,0 +1,119 @@ + + + + + + + LCOV - lcov.info - src/rules + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/rulesHitTotalCoverage
Test:lcov.infoLines:525496.3 %
Date:2023-11-21 13:10:43Functions:171989.5 %
Branches:242692.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleWhitelist.sol +
97.4%97.4%
+
97.4 %37 / 3891.7 %11 / 1287.5 %14 / 16
RuleSanctionList.sol +
93.8%93.8%
+
93.8 %15 / 1685.7 %6 / 7100.0 %10 / 10
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/rules/index-sort-f.html b/doc/test/coverage/src/rules/index-sort-f.html new file mode 100644 index 0000000..700086c --- /dev/null +++ b/doc/test/coverage/src/rules/index-sort-f.html @@ -0,0 +1,119 @@ + + + + + + + LCOV - lcov.info - src/rules + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/rulesHitTotalCoverage
Test:lcov.infoLines:525496.3 %
Date:2023-11-21 13:10:43Functions:171989.5 %
Branches:242692.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleSanctionList.sol +
93.8%93.8%
+
93.8 %15 / 1685.7 %6 / 7100.0 %10 / 10
RuleWhitelist.sol +
97.4%97.4%
+
97.4 %37 / 3891.7 %11 / 1287.5 %14 / 16
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/rules/index-sort-l.html b/doc/test/coverage/src/rules/index-sort-l.html new file mode 100644 index 0000000..bab51ca --- /dev/null +++ b/doc/test/coverage/src/rules/index-sort-l.html @@ -0,0 +1,119 @@ + + + + + + + LCOV - lcov.info - src/rules + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/rulesHitTotalCoverage
Test:lcov.infoLines:525496.3 %
Date:2023-11-21 13:10:43Functions:171989.5 %
Branches:242692.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleSanctionList.sol +
93.8%93.8%
+
93.8 %15 / 1685.7 %6 / 7100.0 %10 / 10
RuleWhitelist.sol +
97.4%97.4%
+
97.4 %37 / 3891.7 %11 / 1287.5 %14 / 16
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/src/rules/index.html b/doc/test/coverage/src/rules/index.html new file mode 100644 index 0000000..060773a --- /dev/null +++ b/doc/test/coverage/src/rules/index.html @@ -0,0 +1,119 @@ + + + + + + + LCOV - lcov.info - src/rules + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/rulesHitTotalCoverage
Test:lcov.infoLines:525496.3 %
Date:2023-11-21 13:10:43Functions:171989.5 %
Branches:242692.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleSanctionList.sol +
93.8%93.8%
+
93.8 %15 / 1685.7 %6 / 7100.0 %10 / 10
RuleWhitelist.sol +
97.4%97.4%
+
97.4 %37 / 3891.7 %11 / 1287.5 %14 / 16
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + 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 new file mode 100644 index 0000000..fd37951 --- /dev/null +++ b/doc/test/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - lcov.info - test/utils/SanctionListOracle.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test/utils - SanctionListOracle.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1333.3 %
Date:2023-11-21 13:10:43Functions:1333.3 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
SanctionListOracle.addToSanctionsList0
SanctionListOracle.removeFromSanctionsList0
SanctionListOracle.isSanctioned12
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/test/utils/SanctionListOracle.sol.func.html b/doc/test/coverage/test/utils/SanctionListOracle.sol.func.html new file mode 100644 index 0000000..1fd3f30 --- /dev/null +++ b/doc/test/coverage/test/utils/SanctionListOracle.sol.func.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - lcov.info - test/utils/SanctionListOracle.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test/utils - SanctionListOracle.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1333.3 %
Date:2023-11-21 13:10:43Functions:1333.3 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
SanctionListOracle.addToSanctionsList0
SanctionListOracle.isSanctioned12
SanctionListOracle.removeFromSanctionsList0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/test/utils/SanctionListOracle.sol.gcov.html b/doc/test/coverage/test/utils/SanctionListOracle.sol.gcov.html new file mode 100644 index 0000000..7068b2c --- /dev/null +++ b/doc/test/coverage/test/utils/SanctionListOracle.sol.gcov.html @@ -0,0 +1,111 @@ + + + + + + + LCOV - lcov.info - test/utils/SanctionListOracle.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test/utils - SanctionListOracle.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1333.3 %
Date:2023-11-21 13:10:43Functions:1333.3 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : pragma solidity ^0.8.20;
+       3                 :            : 
+       4                 :            : /**
+       5                 :            : * @notice Test contract from
+       6                 :            : https://etherscan.io/address/0x40c57923924b5c5c5455c48d93317139addac8fb#code
+       7                 :            : */
+       8                 :            : contract SanctionListOracle {
+       9                 :            : 
+      10                 :            :   constructor() {}
+      11                 :            : 
+      12                 :            :   mapping(address => bool) private sanctionedAddresses;
+      13                 :            : 
+      14                 :            : 
+      15                 :            :   function addToSanctionsList(address newSanction) public{
+      16                 :          0 :       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                 :         12 :     return sanctionedAddresses[addr] == true ;
+      25                 :            :   }
+      26                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/test/utils/index-sort-b.html b/doc/test/coverage/test/utils/index-sort-b.html new file mode 100644 index 0000000..9f67453 --- /dev/null +++ b/doc/test/coverage/test/utils/index-sort-b.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - test/utils + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test/utilsHitTotalCoverage
Test:lcov.infoLines:1333.3 %
Date:2023-11-21 13:10:43Functions:1333.3 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
SanctionListOracle.sol +
33.3%33.3%
+
33.3 %1 / 333.3 %1 / 3-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/test/utils/index-sort-f.html b/doc/test/coverage/test/utils/index-sort-f.html new file mode 100644 index 0000000..f68895a --- /dev/null +++ b/doc/test/coverage/test/utils/index-sort-f.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - test/utils + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test/utilsHitTotalCoverage
Test:lcov.infoLines:1333.3 %
Date:2023-11-21 13:10:43Functions:1333.3 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
SanctionListOracle.sol +
33.3%33.3%
+
33.3 %1 / 333.3 %1 / 3-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/test/utils/index-sort-l.html b/doc/test/coverage/test/utils/index-sort-l.html new file mode 100644 index 0000000..811a542 --- /dev/null +++ b/doc/test/coverage/test/utils/index-sort-l.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - test/utils + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test/utilsHitTotalCoverage
Test:lcov.infoLines:1333.3 %
Date:2023-11-21 13:10:43Functions:1333.3 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
SanctionListOracle.sol +
33.3%33.3%
+
33.3 %1 / 333.3 %1 / 3-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/test/utils/index.html b/doc/test/coverage/test/utils/index.html new file mode 100644 index 0000000..2812067 --- /dev/null +++ b/doc/test/coverage/test/utils/index.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - test/utils + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test/utilsHitTotalCoverage
Test:lcov.infoLines:1333.3 %
Date:2023-11-21 13:10:43Functions:1333.3 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
SanctionListOracle.sol +
33.3%33.3%
+
33.3 %1 / 333.3 %1 / 3-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/test/coverage/updown.png b/doc/test/coverage/updown.png new file mode 100644 index 0000000..aa56a23 Binary files /dev/null and b/doc/test/coverage/updown.png differ diff --git a/doc/test/lcov.info b/doc/test/lcov.info new file mode 100644 index 0000000..5bdcc2d --- /dev/null +++ b/doc/test/lcov.info @@ -0,0 +1,325 @@ +TN: +SF:script/CMTATWithRuleEngineScript.s.sol +FN:14,CMTATWithRuleEngineScript.run +FNDA:0,CMTATWithRuleEngineScript.run +DA:16,0 +DA:17,0 +DA:18,0 +DA:19,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:24,0 +DA:37,0 +DA:39,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:50,0 +FNF:1 +FNH:0 +LF:16 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:script/RuleEngineScript.s.sol +FN:16,RuleEngineScript.run +FNDA:0,RuleEngineScript.run +DA:18,0 +DA:19,0 +DA:20,0 +DA:21,0 +DA:23,0 +DA:24,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:30,0 +DA:33,0 +BRDA:33,0,0,- +BRDA:33,0,1,- +DA:34,0 +FNF:1 +FNH:0 +LF:12 +LH:0 +BRF:2 +BRH:0 +end_of_record +TN: +SF:src/RuleEngine.sol +FN:53,RuleEngine.setRules +FNDA:10,RuleEngine.setRules +DA:56,9 +BRDA:56,0,0,1 +BRDA:56,0,1,8 +DA:57,1 +DA:59,8 +DA:60,15 +BRDA:60,1,0,1 +BRDA:60,1,1,14 +DA:61,1 +DA:63,14 +BRDA:63,2,0,1 +BRDA:63,2,1,13 +DA:64,1 +DA:66,13 +DA:67,13 +DA:69,13 +DA:72,6 +FN:79,RuleEngine.clearRules +FNDA:3,RuleEngine.clearRules +DA:80,2 +DA:81,2 +FN:89,RuleEngine.addRule +FNDA:9,RuleEngine.addRule +DA:90,8 +BRDA:90,3,0,1 +BRDA:90,3,1,7 +DA:92,1 +DA:94,7 +BRDA:94,4,0,1 +BRDA:94,4,1,6 +DA:96,1 +DA:98,6 +DA:99,6 +DA:100,6 +FN:113,RuleEngine.removeRule +FNDA:6,RuleEngine.removeRule +DA:117,5 +BRDA:117,5,0,1 +BRDA:117,5,1,4 +DA:119,1 +DA:121,4 +BRDA:121,6,0,- +BRDA:121,6,1,2 +DA:122,2 +DA:124,4 +DA:125,4 +DA:126,4 +FN:132,RuleEngine.rulesCount +FNDA:20,RuleEngine.rulesCount +DA:133,20 +FN:140,RuleEngine.getRuleIndex +FNDA:3,RuleEngine.getRuleIndex +DA:141,0 +DA:142,5 +BRDA:142,7,0,3 +BRDA:142,7,1,3 +DA:143,5 +DA:146,3 +DA:149,1 +FN:157,RuleEngine.rule +FNDA:1,RuleEngine.rule +DA:158,1 +FN:165,RuleEngine.rules +FNDA:4,RuleEngine.rules +DA:166,4 +FN:176,RuleEngine.detectTransferRestriction +FNDA:7,RuleEngine.detectTransferRestriction +DA:181,17 +DA:182,17 +DA:187,17 +BRDA:187,8,0,12 +BRDA:187,8,1,5 +DA:188,12 +DA:191,5 +DA:194,5 +FN:204,RuleEngine.validateTransfer +FNDA:10,RuleEngine.validateTransfer +DA:209,10 +FN:217,RuleEngine.messageForTransferRestriction +FNDA:6,RuleEngine.messageForTransferRestriction +DA:220,6 +DA:221,5 +BRDA:221,9,0,- +BRDA:221,9,1,4 +DA:222,4 +DA:226,1 +DA:229,2 +FN:235,RuleEngine._msgSender +FNDA:38,RuleEngine._msgSender +DA:241,38 +FN:247,RuleEngine._msgData +FNDA:0,RuleEngine._msgData +DA:253,0 +FNF:13 +FNH:12 +LF:49 +LH:47 +BRF:20 +BRH:18 +end_of_record +TN: +SF:src/modules/MetaTxModuleStandalone.sol +FN:15,MetaTxModuleStandalone._msgSender +FNDA:92,MetaTxModuleStandalone._msgSender +DA:22,92 +FN:25,MetaTxModuleStandalone._msgData +FNDA:0,MetaTxModuleStandalone._msgData +DA:32,0 +FNF:2 +FNH:1 +LF:2 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/RuleSanctionList.sol +FN:35,RuleSanctionList.setOracle +FNDA:2,RuleSanctionList.setOracle +DA:38,1 +FN:48,RuleSanctionList.validateTransfer +FNDA:4,RuleSanctionList.validateTransfer +DA:53,4 +FN:64,RuleSanctionList.detectTransferRestriction +FNDA:3,RuleSanctionList.detectTransferRestriction +DA:69,7 +BRDA:69,0,0,2 +BRDA:69,0,1,3 +DA:70,7 +BRDA:70,1,0,2 +BRDA:70,1,1,5 +DA:71,2 +DA:72,5 +BRDA:72,2,0,2 +BRDA:72,2,1,3 +DA:73,2 +DA:76,3 +FN:84,RuleSanctionList.canReturnTransferRestrictionCode +FNDA:3,RuleSanctionList.canReturnTransferRestrictionCode +DA:87,3 +FN:97,RuleSanctionList.messageForTransferRestriction +FNDA:3,RuleSanctionList.messageForTransferRestriction +DA:100,3 +BRDA:100,3,0,1 +BRDA:100,3,1,2 +DA:101,1 +DA:102,2 +BRDA:102,4,0,1 +BRDA:102,4,1,1 +DA:103,1 +DA:105,1 +FN:112,RuleSanctionList._msgSender +FNDA:2,RuleSanctionList._msgSender +DA:118,2 +FN:124,RuleSanctionList._msgData +FNDA:0,RuleSanctionList._msgData +DA:130,0 +FNF:7 +FNH:6 +LF:16 +LH:15 +BRF:10 +BRH:10 +end_of_record +TN: +SF:src/rules/RuleWhitelist.sol +FN:38,RuleWhitelist.addAddressesToTheWhitelist +FNDA:13,RuleWhitelist.addAddressesToTheWhitelist +DA:41,12 +DA:42,12 +DA:43,26 +BRDA:43,0,0,- +BRDA:43,0,1,24 +DA:44,24 +DA:45,24 +DA:48,26 +DA:51,12 +FN:60,RuleWhitelist.removeAddressesFromTheWhitelist +FNDA:4,RuleWhitelist.removeAddressesFromTheWhitelist +DA:63,3 +DA:64,3 +DA:65,7 +BRDA:65,1,0,- +BRDA:65,1,1,6 +DA:66,6 +DA:67,6 +DA:70,7 +DA:73,3 +FN:81,RuleWhitelist.addAddressToTheWhitelist +FNDA:22,RuleWhitelist.addAddressToTheWhitelist +DA:84,21 +BRDA:84,2,0,1 +BRDA:84,2,1,20 +DA:86,1 +DA:88,20 +DA:89,20 +FN:98,RuleWhitelist.removeAddressFromTheWhitelist +FNDA:3,RuleWhitelist.removeAddressFromTheWhitelist +DA:101,2 +BRDA:101,3,0,1 +BRDA:101,3,1,1 +DA:102,1 +DA:104,1 +DA:105,1 +FN:113,RuleWhitelist.numberWhitelistedAddress +FNDA:20,RuleWhitelist.numberWhitelistedAddress +DA:114,20 +FN:123,RuleWhitelist.addressIsWhitelisted +FNDA:50,RuleWhitelist.addressIsWhitelisted +DA:126,50 +FN:136,RuleWhitelist.validateTransfer +FNDA:3,RuleWhitelist.validateTransfer +DA:141,3 +FN:152,RuleWhitelist.detectTransferRestriction +FNDA:20,RuleWhitelist.detectTransferRestriction +DA:157,23 +BRDA:157,4,0,11 +BRDA:157,4,1,12 +DA:158,11 +DA:159,12 +BRDA:159,5,0,4 +BRDA:159,5,1,8 +DA:160,4 +DA:162,8 +FN:171,RuleWhitelist.canReturnTransferRestrictionCode +FNDA:8,RuleWhitelist.canReturnTransferRestrictionCode +DA:174,8 +FN:184,RuleWhitelist.messageForTransferRestriction +FNDA:7,RuleWhitelist.messageForTransferRestriction +DA:187,7 +BRDA:187,6,0,4 +BRDA:187,6,1,3 +DA:188,4 +DA:189,3 +BRDA:189,7,0,2 +BRDA:189,7,1,1 +DA:190,2 +DA:192,1 +FN:199,RuleWhitelist._msgSender +FNDA:52,RuleWhitelist._msgSender +DA:205,52 +FN:211,RuleWhitelist._msgData +FNDA:0,RuleWhitelist._msgData +DA:217,0 +FNF:12 +FNH:11 +LF:38 +LH:37 +BRF:16 +BRH:14 +end_of_record +TN: +SF:test/utils/SanctionListOracle.sol +FN:15,SanctionListOracle.addToSanctionsList +FNDA:0,SanctionListOracle.addToSanctionsList +DA:16,0 +FN:19,SanctionListOracle.removeFromSanctionsList +FNDA:0,SanctionListOracle.removeFromSanctionsList +DA:20,0 +FN:23,SanctionListOracle.isSanctioned +FNDA:12,SanctionListOracle.isSanctioned +DA:24,12 +FNF:3 +FNH:1 +LF:3 +LH:1 +BRF:0 +BRH:0 +end_of_record diff --git a/doc/test/test-report-2023-23-05.png b/doc/test/test-report-2023-23-05.png deleted file mode 100644 index 6d66611..0000000 Binary files a/doc/test/test-report-2023-23-05.png and /dev/null differ diff --git a/doc/test/UML-test.svg b/doc/test/v1.0.2/UML-test.svg similarity index 100% rename from doc/test/UML-test.svg rename to doc/test/v1.0.2/UML-test.svg diff --git a/doc/test/coverage-2023-05-23.png b/doc/test/v1.0.2/coverage-2023-05-23.png similarity index 100% rename from doc/test/coverage-2023-05-23.png rename to doc/test/v1.0.2/coverage-2023-05-23.png diff --git a/doc/test/lcov-2023-22.05.info b/doc/test/v1.0.2/lcov-2023-22.05.info similarity index 100% rename from doc/test/lcov-2023-22.05.info rename to doc/test/v1.0.2/lcov-2023-22.05.info diff --git a/doc/test/test.odt b/doc/test/v1.0.2/test.odt similarity index 100% rename from doc/test/test.odt rename to doc/test/v1.0.2/test.odt diff --git a/doc/test/test.pdf b/doc/test/v1.0.2/test.pdf similarity index 100% rename from doc/test/test.pdf rename to doc/test/v1.0.2/test.pdf diff --git a/foundry.toml b/foundry.toml index 065ce0b..cae35aa 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,5 +1,5 @@ [profile.default] -solc = "0.8.17" +solc = "0.8.20" src = 'src' out = 'out' libs = ['lib'] diff --git a/hardhat.config.js b/hardhat.config.js index 589a7db..b2dd4be 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -2,7 +2,7 @@ require("@nomicfoundation/hardhat-foundry"); require('solidity-docgen'); module.exports = { - solidity: "0.8.17", + solidity: "0.8.20", settings: { optimizer: { enabled: true, diff --git a/lib/CMTAT b/lib/CMTAT index 66f37fa..5a8e27b 160000 --- a/lib/CMTAT +++ b/lib/CMTAT @@ -1 +1 @@ -Subproject commit 66f37fafb242263deddd5c47629ddd77f994f51e +Subproject commit 5a8e27bca89902e57d20021f538c691fc43980bb diff --git a/lib/forge-std b/lib/forge-std index 683e701..bdea49f 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 683e701fdb64a5bc1f4f69b5a5552c4b18cd4a65 +Subproject commit bdea49f9bb3c58c8c35850c3bdc17eaeea756e9a diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts index 0457042..932fddf 160000 --- a/lib/openzeppelin-contracts +++ b/lib/openzeppelin-contracts @@ -1 +1 @@ -Subproject commit 0457042d93d9dfd760dbaa06a4d2f1216fdbe297 +Subproject commit 932fddf69a699a9a80fd2396fd1a2ab91cdda123 diff --git a/package.json b/package.json index f53a3ec..32a6588 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "uml": "npx sol2uml class src", "uml:test": "npx sol2uml class test", "surya:report": "npx surya mdreport surya_report_ruleEngine.md src/RuleEngine.sol && npx surya mdreport surya_report_ruleWhitelist.md src/RuleWhitelist.sol", - "surya:graph": "npx surya graph src/RuleWhitelist.sol | dot -Tpng > surya_graph_Whitelist.png && npx surya graph src/RuleEngine.sol | dot -Tpng > surya_graph_RuleEngine.png", + "surya:graph": "npx surya graph src/rules/RuleWhitelist.sol | dot -Tpng > surya_graph_Whitelist.png && npx surya graph src/RuleEngine.sol | dot -Tpng > surya_graph_RuleEngine.png && npx surya graph src/rules/RuleSanctionList.sol | dot -Tpng > surya_graph_SanctionList.png", "docgen": "npx hardhat docgen" }, diff --git a/script/CMTATWithRuleEngineScript.s.sol b/script/CMTATWithRuleEngineScript.s.sol index 248fac9..c06c63a 100644 --- a/script/CMTATWithRuleEngineScript.s.sol +++ b/script/CMTATWithRuleEngineScript.s.sol @@ -6,7 +6,7 @@ pragma solidity ^0.8.17; import "forge-std/Script.sol"; import "CMTAT/CMTAT_STANDALONE.sol"; import "src/RuleEngine.sol"; -import "src/RuleWhitelist.sol"; +import "src/rules/RuleWhitelist.sol"; /** @title Deploy a CMTAT, a RuleWhitelist and a RuleEngine */ @@ -18,12 +18,16 @@ contract CMTATWithRuleEngineScript is Script { address trustedForwarder = address(0x0); vm.startBroadcast(deployerPrivateKey); uint256 flag = 5; + uint48 initialDelay = 0; + uint8 decimals = 0; // CMTAT CMTAT_STANDALONE CMTAT_CONTRACT = new CMTAT_STANDALONE( trustedForwarder, ADMIN, + initialDelay, "CMTA Token", "CMTAT", + decimals, "CMTAT_ISIN", "https://cmta.ch", IRuleEngine(address(0)), diff --git a/script/RuleEngineScript.s.sol b/script/RuleEngineScript.s.sol index 16d2bd5..71f6ff9 100644 --- a/script/RuleEngineScript.s.sol +++ b/script/RuleEngineScript.s.sol @@ -6,8 +6,8 @@ pragma solidity ^0.8.17; import "forge-std/Script.sol"; import "CMTAT/CMTAT_STANDALONE.sol"; import "src/RuleEngine.sol"; -import "src/RuleWhitelist.sol"; -import "CMTAT/modules/wrapper/optional/ValidationModule.sol"; +import "src/rules/RuleWhitelist.sol"; +import "CMTAT/modules/wrapper/controllers/ValidationModule.sol"; /** @title Deploy a RuleWhitelist and a RuleEngine. The CMTAT is considred already deployed diff --git a/slither-report.md b/slither-report.md new file mode 100644 index 0000000..e69de29 diff --git a/src/RuleEngine.sol b/src/RuleEngine.sol index b10a10b..6ff9a72 100644 --- a/src/RuleEngine.sol +++ b/src/RuleEngine.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.20; import "CMTAT/mocks/RuleEngine/interfaces/IRule.sol"; import "CMTAT/mocks/RuleEngine/interfaces/IRuleEngine.sol"; @@ -11,6 +11,11 @@ import "../lib/openzeppelin-contracts/contracts/access/AccessControl.sol"; @title Implementation of a ruleEngine defined by the CMTAT */ contract RuleEngine is IRuleEngine, AccessControl, MetaTxModuleStandalone { + error RuleEngine_RuleAddressZeroNotAllowed(); + error RuleEngine_RuleAlreadyExists(); + error RuleEngine_RuleDoNotMatch(); + error RuleEngine_AdminWithAddressZeroNotAllowed(); + error RuleEngine_ArrayIsEmpty(); /// @dev Role to manage the ruleEngine bytes32 public constant RULE_ENGINE_ROLE = keccak256("RULE_ENGINE_ROLE"); /// @dev Indicate if a rule already exists @@ -32,7 +37,10 @@ contract RuleEngine is IRuleEngine, AccessControl, MetaTxModuleStandalone { address admin, address forwarderIrrevocable ) MetaTxModuleStandalone(forwarderIrrevocable) { - require(admin != address(0), "Address 0 not allowed"); + if(admin == address(0)) + { + revert RuleEngine_AdminWithAddressZeroNotAllowed(); + } _grantRole(DEFAULT_ADMIN_ROLE, admin); _grantRole(RULE_ENGINE_ROLE, admin); } @@ -45,13 +53,16 @@ contract RuleEngine is IRuleEngine, AccessControl, MetaTxModuleStandalone { function setRules( IRule[] calldata rules_ ) external override onlyRole(RULE_ENGINE_ROLE) { - require(rules_.length != 0, "The array is empty"); + if(rules_.length == 0){ + revert RuleEngine_ArrayIsEmpty(); + } for (uint256 i = 0; i < rules_.length; ) { - require( - address(rules_[i]) != address(0x0), - "One of the rules is a zero address" - ); - require(!_ruleIsPresent[rules_[i]], "The rule is already present"); + if( address(rules_[i]) == address(0x0)){ + revert RuleEngine_RuleAddressZeroNotAllowed(); + } + if(_ruleIsPresent[rules_[i]]){ + revert RuleEngine_RuleAlreadyExists(); + } _ruleIsPresent[rules_[i]] = true; emit AddRule(rules_[i]); unchecked { @@ -76,11 +87,14 @@ contract RuleEngine is IRuleEngine, AccessControl, MetaTxModuleStandalone { * */ function addRule(IRule rule_) public onlyRole(RULE_ENGINE_ROLE) { - require( - address(rule_) != address(0x0), - "The rule can't be a zero address" - ); - require(!_ruleIsPresent[rule_], "The rule is already present"); + if( address(rule_) == address(0x0)) + { + revert RuleEngine_RuleAddressZeroNotAllowed(); + } + if( _ruleIsPresent[rule_]) + { + revert RuleEngine_RuleAlreadyExists(); + } _rules.push(rule_); _ruleIsPresent[rule_] = true; emit AddRule(rule_); @@ -100,7 +114,10 @@ contract RuleEngine is IRuleEngine, AccessControl, MetaTxModuleStandalone { IRule rule_, uint256 index ) public onlyRole(RULE_ENGINE_ROLE) { - require(_rules[index] == rule_, "The rule don't match"); + if(_rules[index] != rule_) + { + revert RuleEngine_RuleDoNotMatch(); + } if (index != _rules.length - 1) { _rules[index] = _rules[_rules.length - 1]; } @@ -121,7 +138,8 @@ contract RuleEngine is IRuleEngine, AccessControl, MetaTxModuleStandalone { * @return index if the rule is found, _rules.length otherwise */ function getRuleIndex(IRule rule_) external view returns (uint256 index) { - for (index = 0; index < _rules.length; ) { + uint256 rulesLength = _rules.length; + for (index = 0; index < rulesLength; ) { if (_rules[index] == rule_) { return index; } @@ -161,7 +179,8 @@ contract RuleEngine is IRuleEngine, AccessControl, MetaTxModuleStandalone { address _to, uint256 _amount ) public view override returns (uint8) { - for (uint256 i = 0; i < _rules.length; ) { + uint256 rulesLength = _rules.length; + for (uint256 i = 0; i < rulesLength; ) { uint8 restriction = _rules[i].detectTransferRestriction( _from, _to, @@ -200,7 +219,8 @@ contract RuleEngine is IRuleEngine, AccessControl, MetaTxModuleStandalone { function messageForTransferRestriction( uint8 _restrictionCode ) external view override returns (string memory) { - for (uint256 i = 0; i < _rules.length; ) { + uint256 rulesLength = _rules.length; + for (uint256 i = 0; i < rulesLength; ) { if (_rules[i].canReturnTransferRestrictionCode(_restrictionCode)) { return _rules[i].messageForTransferRestriction(_restrictionCode); diff --git a/src/modules/MetaTxModuleStandalone.sol b/src/modules/MetaTxModuleStandalone.sol index 8e6db2d..db5155a 100644 --- a/src/modules/MetaTxModuleStandalone.sol +++ b/src/modules/MetaTxModuleStandalone.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.20; import "../../lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol"; diff --git a/src/rules/RuleSanctionList.sol b/src/rules/RuleSanctionList.sol new file mode 100644 index 0000000..b10e5b2 --- /dev/null +++ b/src/rules/RuleSanctionList.sol @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: MPL-2.0 +/** + +This code is not audited !!! + +*/ + + +pragma solidity ^0.8.20; +import "../../lib/openzeppelin-contracts/contracts/access/AccessControl.sol"; +import "../../lib/CMTAT/contracts/mocks/RuleEngine/interfaces/IRule.sol"; +import "../modules/MetaTxModuleStandalone.sol"; +import "./abstract/RuleSanctionListInvariantStorage.sol"; +interface SanctionsList { + function isSanctioned(address addr) external view returns (bool); +} + +contract RuleSanctionList is IRule, AccessControl, MetaTxModuleStandalone, RuleSanctionlistInvariantStorage { + SanctionsList public sanctionsList; + + /** + * @param admin Address of the contract (Access Control) + * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + */ + constructor( + address admin, + address forwarderIrrevocable + ) MetaTxModuleStandalone(forwarderIrrevocable) { + if(admin == address(0)){ + revert RuleSanctionList_AdminWithAddressZeroNotAllowed(); + } + _grantRole(DEFAULT_ADMIN_ROLE, admin); + _grantRole(SANCTIONLIST_ROLE, admin); + } + + /** + * @notice Set the oracle contract + * @param sanctionContractOracle_ address of your oracle contract + * @dev zero address is authorized to authorize all transfers + */ + function setSanctionListOracle( + address sanctionContractOracle_ + ) public onlyRole(SANCTIONLIST_ROLE) { + sanctionsList = SanctionsList(sanctionContractOracle_); + } + + /** + * @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, + uint256 _amount + ) public view override returns (bool isValid) { + return + detectTransferRestriction(_from, _to, _amount) == + uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + /** + * @notice Check if an addres is in the whitelist or not + * @param _from the origin address + * @param _to the destination address + * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + **/ + function detectTransferRestriction( + address _from, + address _to, + uint256 /*_amount */ + ) public view override returns (uint8) { + if(address(sanctionsList) != address(0)){ + if (sanctionsList.isSanctioned(_from)) { + return CODE_ADDRESS_FROM_IS_SANCTIONED; + } else if (sanctionsList.isSanctioned(_to)) { + return CODE_ADDRESS_TO_IS_SANCTIONED; + } + } + return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + /** + * @notice To know if the restriction code is valid for this rule or not. + * @param _restrictionCode The target restriction code + * @return true if the restriction code is known, false otherwise + **/ + function canReturnTransferRestrictionCode( + uint8 _restrictionCode + ) external pure override returns (bool) { + return + _restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED || + _restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED; + } + + /** + * @notice Return the corresponding message + * @param _restrictionCode The target restriction code + * @return true if the transfer is valid, false otherwise + **/ + function messageForTransferRestriction( + uint8 _restrictionCode + ) external pure override returns (string memory) { + if (_restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED) { + return TEXT_ADDRESS_FROM_IS_SANCTIONED; + } else if (_restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED) { + return TEXT_ADDRESS_TO_IS_SANCTIONED; + } else { + return TEXT_CODE_NOT_FOUND; + } + } + + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ + function _msgSender() + internal + view + override(MetaTxModuleStandalone, Context) + returns (address sender) + { + return MetaTxModuleStandalone._msgSender(); + } + + /** + * @dev This surcharge is not necessary if you do not use the MetaTxModule + */ + function _msgData() + internal + view + override(MetaTxModuleStandalone, Context) + returns (bytes calldata) + { + return MetaTxModuleStandalone._msgData(); + } +} \ No newline at end of file diff --git a/src/RuleWhitelist.sol b/src/rules/RuleWhitelist.sol similarity index 85% rename from src/RuleWhitelist.sol rename to src/rules/RuleWhitelist.sol index c6fa07c..48716cd 100644 --- a/src/RuleWhitelist.sol +++ b/src/rules/RuleWhitelist.sol @@ -1,33 +1,20 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; - -import "../lib/openzeppelin-contracts/contracts/access/AccessControl.sol"; -import "../lib/CMTAT/contracts/mocks/RuleEngine/interfaces/IRule.sol"; -import "./modules/MetaTxModuleStandalone.sol"; +pragma solidity ^0.8.20; +import "../../lib/openzeppelin-contracts/contracts/access/AccessControl.sol"; +import "../../lib/CMTAT/contracts/mocks/RuleEngine/interfaces/IRule.sol"; +import "./../modules/MetaTxModuleStandalone.sol"; +import "./abstract/RuleWhitelistInvariantStorage.sol"; /** @title a whitelist manager */ -contract RuleWhitelist is IRule, AccessControl, MetaTxModuleStandalone { - bytes32 public constant WHITELIST_ROLE = keccak256("WHITELIST_ROLE"); +contract RuleWhitelist is IRule, AccessControl, MetaTxModuleStandalone, RuleWhitelistInvariantStorage { + mapping(address => bool) whitelist; // Number of addresses in the whitelist at the moment uint256 private numAddressesWhitelisted; - - string constant TEXT_CODE_NOT_FOUND = "Code not found"; - string constant TEXT_ADDRESS_FROM_NOT_WHITELISTED = - "The sender is not in the whitelist"; - string constant TEXT_ADDRESS_TO_NOT_WHITELISTED = - "The recipient is not in the whitelist"; - - // Code - // It is very important that each rule uses an unique code - uint8 public constant CODE_ADDRESS_FROM_NOT_WHITELISTED = 20; - uint8 public constant CODE_ADDRESS_TO_NOT_WHITELISTED = 30; - - mapping(address => bool) whitelist; - + /** * @param admin Address of the contract (Access Control) * @param forwarderIrrevocable Address of the forwarder, required for the gasless support @@ -36,7 +23,9 @@ contract RuleWhitelist is IRule, AccessControl, MetaTxModuleStandalone { address admin, address forwarderIrrevocable ) MetaTxModuleStandalone(forwarderIrrevocable) { - require(admin != address(0), "Address 0 not allowed"); + if(admin == address(0)){ + revert RuleWhitelist_AdminWithAddressZeroNotAllowed(); + } _grantRole(DEFAULT_ADMIN_ROLE, admin); _grantRole(WHITELIST_ROLE, admin); } @@ -92,10 +81,10 @@ contract RuleWhitelist is IRule, AccessControl, MetaTxModuleStandalone { function addAddressToTheWhitelist( address _newWhitelistAddress ) public onlyRole(WHITELIST_ROLE) { - require( - !whitelist[_newWhitelistAddress], - "Address is already in the whitelist" - ); + if(whitelist[_newWhitelistAddress]) + { + revert RuleWhitelist_AddressAlreadyWhitelisted(); + } whitelist[_newWhitelistAddress] = true; ++numAddressesWhitelisted; } @@ -109,10 +98,9 @@ contract RuleWhitelist is IRule, AccessControl, MetaTxModuleStandalone { function removeAddressFromTheWhitelist( address _removeWhitelistAddress ) public onlyRole(WHITELIST_ROLE) { - require( - whitelist[_removeWhitelistAddress], - "Address is not in the whitelist" - ); + if(!whitelist[_removeWhitelistAddress]){ + revert RuleWhitelist_AddressNotPresent(); + } whitelist[_removeWhitelistAddress] = false; --numAddressesWhitelisted; } diff --git a/src/rules/abstract/RuleCommonInvariantStorage.sol b/src/rules/abstract/RuleCommonInvariantStorage.sol new file mode 100644 index 0000000..b5edd06 --- /dev/null +++ b/src/rules/abstract/RuleCommonInvariantStorage.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +abstract contract RuleCommonInvariantStorage { + // Text + string constant TEXT_CODE_NOT_FOUND = "Code not found"; +} \ No newline at end of file diff --git a/src/rules/abstract/RuleSanctionListInvariantStorage.sol b/src/rules/abstract/RuleSanctionListInvariantStorage.sol new file mode 100644 index 0000000..36a1fc9 --- /dev/null +++ b/src/rules/abstract/RuleSanctionListInvariantStorage.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +import "./RuleCommonInvariantStorage.sol"; +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/abstract/RuleWhitelistInvariantStorage.sol b/src/rules/abstract/RuleWhitelistInvariantStorage.sol new file mode 100644 index 0000000..cae2eea --- /dev/null +++ b/src/rules/abstract/RuleWhitelistInvariantStorage.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +import "./RuleCommonInvariantStorage.sol"; +abstract contract RuleWhitelistInvariantStorage is RuleCommonInvariantStorage { + // custom errors + error RuleWhitelist_AdminWithAddressZeroNotAllowed(); + error RuleWhitelist_AddressAlreadyWhitelisted(); + error RuleWhitelist_AddressNotPresent(); + + // Role + bytes32 public constant WHITELIST_ROLE = keccak256("WHITELIST_ROLE"); + + // String + string constant TEXT_ADDRESS_FROM_NOT_WHITELISTED = + "The sender is not in the whitelist"; + string constant TEXT_ADDRESS_TO_NOT_WHITELISTED = + "The recipient is not in the whitelist"; + + // Code + // It is very important that each rule uses an unique code + uint8 public constant CODE_ADDRESS_FROM_NOT_WHITELISTED = 21; + uint8 public constant CODE_ADDRESS_TO_NOT_WHITELISTED = 22; +} \ No newline at end of file diff --git a/test/CMTATIntegration.t.sol b/test/CMTATIntegration.t.sol index 03659ca..2f85b06 100644 --- a/test/CMTATIntegration.t.sol +++ b/test/CMTATIntegration.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "CMTAT/CMTAT_STANDALONE.sol"; @@ -29,12 +29,16 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(DEFAULT_ADMIN_ADDRESS); ruleWhitelist = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); // global arrange + uint48 initialDelay = 0; + uint8 decimals = 0; vm.prank(DEFAULT_ADMIN_ADDRESS); CMTAT_CONTRACT = new CMTAT_STANDALONE( ZERO_ADDRESS, DEFAULT_ADMIN_ADDRESS, + initialDelay, "CMTA Token", "CMTAT", + decimals, "CMTAT_ISIN", "https://cmta.ch", IRuleEngine(address(0)), @@ -62,29 +66,36 @@ contract CMTATIntegration is Test, HelperContract { function testCannotTransferWithoutAddressWhitelisted() public { // Arrange vm.prank(ADDRESS1); - vm.expectRevert(bytes("CMTAT: transfer rejected by validation module")); + 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.addAddressToTheWhitelist(ADDRESS2); vm.prank(ADDRESS1); - vm.expectRevert(bytes("CMTAT: transfer rejected by validation module")); + vm.expectRevert( + abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount)); // Act - CMTAT_CONTRACT.transfer(ADDRESS2, 21); + CMTAT_CONTRACT.transfer(ADDRESS2, amount); } function testCannotTransferWithoutToAddressWhitelisted() public { + // Arrange + uint256 amount = 21; vm.prank(DEFAULT_ADMIN_ADDRESS); ruleWhitelist.addAddressToTheWhitelist(ADDRESS1); vm.prank(ADDRESS1); - vm.expectRevert(bytes("CMTAT: transfer rejected by validation module")); + vm.expectRevert( + abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount)); // Act - CMTAT_CONTRACT.transfer(ADDRESS2, 21); + CMTAT_CONTRACT.transfer(ADDRESS2, amount); } function testCanMakeATransfer() public { diff --git a/test/HelperContract.sol b/test/HelperContract.sol index 041dccc..a0a43c4 100644 --- a/test/HelperContract.sol +++ b/test/HelperContract.sol @@ -1,50 +1,56 @@ //SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "CMTAT/CMTAT_STANDALONE.sol"; -import "src/RuleWhitelist.sol"; - +import "src/rules/RuleWhitelist.sol"; +import "src/rules/abstract/RuleWhitelistInvariantStorage.sol"; +import "src/rules/abstract/RuleSanctionListInvariantStorage.sol"; /** @title Constants used by the tests */ -abstract contract HelperContract { +abstract contract HelperContract is RuleWhitelistInvariantStorage,RuleSanctionlistInvariantStorage { + // EOA to perform tests address constant ZERO_ADDRESS = address(0); address constant DEFAULT_ADMIN_ADDRESS = address(1); address constant WHITELIST_OPERATOR_ADDRESS = address(2); address constant RULE_ENGINE_OPERATOR_ADDRESS = address(3); + address constant SANCTIONLIST_OPERATOR_ADDRESS = address(8); address constant ATTACKER = address(4); address constant ADDRESS1 = address(5); address constant ADDRESS2 = address(6); address constant ADDRESS3 = address(7); + // role string string constant RULE_ENGINE_ROLE_HASH = "0x774b3c5f4a8b37a7da21d72b7f2429e4a6d49c4de0ac5f2b831a1a539d0f0fd2"; string constant WHITELIST_ROLE_HASH = "0xdc72ed553f2544c34465af23b847953efeb813428162d767f9ba5f4013be6760"; string constant DEFAULT_ADMIN_ROLE_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000"; + + // contract RuleWhitelist ruleWhitelist; CMTAT_STANDALONE CMTAT_CONTRACT; + bytes32 public constant RULE_ENGINE_ROLE = keccak256("RULE_ENGINE_ROLE"); - // RuleWhiteList message - string constant TEXT_CODE_NOT_FOUND = "Code not found"; - string constant TEXT_ADDRESS_FROM_NOT_WHITELISTED = - "The sender is not in the whitelist"; - string constant TEXT_ADDRESS_TO_NOT_WHITELISTED = - "The recipient is not in the whitelist"; - // RuleWhiteList code list - uint8 constant CODE_ADDRESS_FROM_NOT_WHITELISTED = 20; - uint8 constant CODE_ADDRESS_TO_NOT_WHITELISTED = 30; uint8 constant NO_ERROR = 0; - // RuleWhiteList role - bytes32 public constant WHITELIST_ROLE = keccak256("WHITELIST_ROLE"); + // Forwarder + string ERC2771ForwarderDomain = 'ERC2771ForwarderDomain'; // RuleEngine event event AddRule(IRule indexed rule); event RemoveRule(IRule indexed rule); event ClearRules(IRule[] rulesRemoved); + // Custom error RuleEngine + error RuleEngine_RuleAddressZeroNotAllowed(); + error RuleEngine_RuleAlreadyExists(); + error RuleEngine_RuleDoNotMatch(); + error RuleEngine_AdminWithAddressZeroNotAllowed(); + error RuleEngine_ArrayIsEmpty(); + + constructor() {} } diff --git a/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol b/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol index 3fc2d0e..2700af1 100644 --- a/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol +++ b/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../../HelperContract.sol"; @@ -9,6 +9,8 @@ import "src/RuleEngine.sol"; @title Tests on the Access Control */ contract RuleEngineAccessControlTest is Test, HelperContract { + // Custom error openZeppelin + error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); RuleEngine ruleEngineMock; uint8 resUint8; uint256 resUint256; @@ -36,7 +38,7 @@ contract RuleEngineAccessControlTest is Test, HelperContract { assertEq(resUint256, 1); } - function testCannnotAttackerSetRules() public { + function testCannotAttackerSetRules() public { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); RuleWhitelist ruleWhitelist1 = new RuleWhitelist( @@ -54,15 +56,8 @@ contract RuleEngineAccessControlTest is Test, HelperContract { // Act vm.prank(ATTACKER); - string memory message = string( - abi.encodePacked( - "AccessControl: account ", - vm.toString(ATTACKER), - " is missing role ", - RULE_ENGINE_ROLE_HASH - ) - ); - vm.expectRevert(bytes(message)); + vm.expectRevert( + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_ENGINE_ROLE)); (bool success, ) = address(ruleEngineMock).call( abi.encodeCall(RuleEngine.setRules, ruleWhitelistTab) ); @@ -76,15 +71,8 @@ contract RuleEngineAccessControlTest is Test, HelperContract { function testCannnotAttackerClearRules() public { // Act vm.prank(ATTACKER); - string memory message = string( - abi.encodePacked( - "AccessControl: account ", - vm.toString(ATTACKER), - " is missing role ", - RULE_ENGINE_ROLE_HASH - ) - ); - vm.expectRevert(bytes(message)); + vm.expectRevert( + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_ENGINE_ROLE)); ruleEngineMock.clearRules(); // Assert @@ -95,15 +83,8 @@ contract RuleEngineAccessControlTest is Test, HelperContract { function testCannotAttackerAddRule() public { // Act vm.prank(ATTACKER); - string memory message = string( - abi.encodePacked( - "AccessControl: account ", - vm.toString(ATTACKER), - " is missing role ", - RULE_ENGINE_ROLE_HASH - ) - ); - vm.expectRevert(bytes(message)); + vm.expectRevert( + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_ENGINE_ROLE)); ruleEngineMock.addRule(ruleWhitelist); // Assert @@ -114,15 +95,8 @@ contract RuleEngineAccessControlTest is Test, HelperContract { function testCannotAttackerRemoveRule() public { // Act vm.prank(ATTACKER); - string memory message = string( - abi.encodePacked( - "AccessControl: account ", - vm.toString(ATTACKER), - " is missing role ", - RULE_ENGINE_ROLE_HASH - ) - ); - vm.expectRevert(bytes(message)); + vm.expectRevert( + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_ENGINE_ROLE)); ruleEngineMock.removeRule(ruleWhitelist, 0); // Assert diff --git a/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol b/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol index 2f9199f..640a494 100644 --- a/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol +++ b/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../../../lib/openzeppelin-contracts/contracts/access/AccessControl.sol"; @@ -80,17 +80,10 @@ contract RuleEngineAccessControlTest is Test, HelperContract, AccessControl { assertFalse(res1); // Act - string memory message = string( - abi.encodePacked( - "AccessControl: account ", - vm.toString(ADDRESS2), - " is missing role ", - DEFAULT_ADMIN_ROLE_HASH - ) - ); - vm.expectRevert(bytes(message)); + vm.expectRevert( + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ADDRESS2, DEFAULT_ADMIN_ROLE)); vm.prank(ADDRESS2); - ruleEngineMock.grantRole(RULE_ENGINE_ROLE, ADDRESS1); + ruleEngineMock.grantRole(RULE_ENGINE_ROLE, ADDRESS2); // Assert bool res2 = ruleEngineMock.hasRole(RULE_ENGINE_ROLE, ADDRESS1); assertFalse(res2); @@ -110,15 +103,8 @@ contract RuleEngineAccessControlTest is Test, HelperContract, AccessControl { // Act vm.prank(ADDRESS2); - string memory message = string( - abi.encodePacked( - "AccessControl: account ", - vm.toString(ADDRESS2), - " is missing role ", - DEFAULT_ADMIN_ROLE_HASH - ) - ); - vm.expectRevert(bytes(message)); + vm.expectRevert( + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ADDRESS2, DEFAULT_ADMIN_ROLE)); ruleEngineMock.revokeRole(RULE_ENGINE_ROLE, ADDRESS1); // Assert diff --git a/test/RuleEngine/RuleEngine.t.sol b/test/RuleEngine/RuleEngine.t.sol index b83af76..ac219fc 100644 --- a/test/RuleEngine/RuleEngine.t.sol +++ b/test/RuleEngine/RuleEngine.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; @@ -80,7 +80,7 @@ contract RuleEngineTest is Test, HelperContract { // Act vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - vm.expectRevert("The rule is already present"); + vm.expectRevert(RuleEngine_RuleAlreadyExists.selector); (bool resCallBool, ) = address(ruleEngineMock).call( abi.encodeCall(RuleEngine.setRules, ruleWhitelistTab) ); @@ -196,7 +196,7 @@ contract RuleEngineTest is Test, HelperContract { function testCannotAddRuleZeroAddress() public { // Act - vm.expectRevert("The rule can't be a zero address"); + vm.expectRevert(RuleEngine_RuleAddressZeroNotAllowed.selector); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); ruleEngineMock.addRule(IRule(address(0x0))); @@ -207,7 +207,7 @@ contract RuleEngineTest is Test, HelperContract { function testCannotAddARuleAlreadyPresent() public { // Act - vm.expectRevert("The rule is already present"); + vm.expectRevert(RuleEngine_RuleAlreadyExists.selector); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); ruleEngineMock.addRule(ruleWhitelist); @@ -246,7 +246,7 @@ contract RuleEngineTest is Test, HelperContract { ); // Act - vm.expectRevert("The rule don't match"); + vm.expectRevert(RuleEngine_RuleDoNotMatch.selector); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); ruleEngineMock.removeRule(ruleWhitelist1, 0); diff --git a/test/RuleEngine/RuleEngineDeployment.t.sol b/test/RuleEngine/RuleEngineDeployment.t.sol index 00e946b..da68dbc 100644 --- a/test/RuleEngine/RuleEngineDeployment.t.sol +++ b/test/RuleEngine/RuleEngineDeployment.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; @@ -27,7 +27,7 @@ contract RuleEngineTest is Test, HelperContract { vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); MinimalForwarderMock forwarder = new MinimalForwarderMock( ); - forwarder.initialize(); + forwarder.initialize(ERC2771ForwarderDomain); // Act ruleEngineMock = new RuleEngine( @@ -41,4 +41,18 @@ contract RuleEngineTest is Test, HelperContract { resBool = ruleEngineMock.isTrustedForwarder(address(forwarder)); assertEq(resBool, true); } + + function testCannotDeployContractifAdminAddressIsZero() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + MinimalForwarderMock forwarder = new MinimalForwarderMock( + ); + forwarder.initialize(ERC2771ForwarderDomain); + vm.expectRevert(RuleEngine_AdminWithAddressZeroNotAllowed.selector); + // Act + ruleEngineMock = new RuleEngine( + address(0x0), + address(forwarder) + ); + } } diff --git a/test/RuleEngine/RuleEngineRestriction.t.sol b/test/RuleEngine/RuleEngineRestriction.t.sol index f6dbcfe..94c98ec 100644 --- a/test/RuleEngine/RuleEngineRestriction.t.sol +++ b/test/RuleEngine/RuleEngineRestriction.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; diff --git a/test/RuleSanctionList/RuleSanctionListAdd.t.sol b/test/RuleSanctionList/RuleSanctionListAdd.t.sol new file mode 100644 index 0000000..1965762 --- /dev/null +++ b/test/RuleSanctionList/RuleSanctionListAdd.t.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import "forge-std/Test.sol"; +import "../HelperContract.sol"; +import "src/RuleEngine.sol"; +import "src/rules/RuleSanctionList.sol"; +import "../utils/SanctionListOracle.sol"; +/** +@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; + bool resCallBool; + string resString; + uint8 CODE_NONEXISTENT = 255; + SanctionListOracle sanctionlistOracle; + RuleSanctionList ruleSanctionList; + // Arrange + function setUp() public { + vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); + sanctionlistOracle = new SanctionListOracle(); + sanctionlistOracle.addToSanctionsList(ATTACKER); + ruleSanctionList = new RuleSanctionList( + SANCTIONLIST_OPERATOR_ADDRESS, + ZERO_ADDRESS + ); + + } + + function testCanSetOracle() public { + vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); + ruleSanctionList.setSanctionListOracle(address(sanctionlistOracle)); + } + + function testCannotAttackerSetOracle() public { + vm.prank(ATTACKER); + vm.expectRevert( + 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 new file mode 100644 index 0000000..e7c870a --- /dev/null +++ b/test/RuleSanctionList/RuleSanctionListDeployment.t.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import "forge-std/Test.sol"; +import "../HelperContract.sol"; +import "src/rules/RuleSanctionList.sol"; +import "CMTAT/mocks/MinimalForwarderMock.sol"; +/** +@title General functions of the ruleSanctionList +*/ +contract RuleSanctionListDeploymentTest is Test, HelperContract { + uint256 resUint256; + uint8 resUint8; + bool resBool; + bool resCallBool; + string resString; + uint8 CODE_NONEXISTENT = 255; + RuleSanctionList ruleSanctionList; + // Arrange + function setUp() public { + + } + + function testRightDeployment() public { + // Arrange + vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); + MinimalForwarderMock forwarder = new MinimalForwarderMock( + ); + forwarder.initialize(ERC2771ForwarderDomain); + vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); + ruleSanctionList = new RuleSanctionList( + SANCTIONLIST_OPERATOR_ADDRESS, + address(forwarder) + ); + + // assert + resBool = ruleSanctionList.hasRole(SANCTIONLIST_ROLE, SANCTIONLIST_OPERATOR_ADDRESS); + assertEq(resBool, true); + resBool = ruleSanctionList.isTrustedForwarder(address(forwarder)); + assertEq(resBool, true); + } + + function testCannotDeployContractIfAdminAddressIsZero() public { + // Arrange + vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); + MinimalForwarderMock forwarder = new MinimalForwarderMock( + ); + forwarder.initialize(ERC2771ForwarderDomain); + vm.expectRevert(RuleSanctionList_AdminWithAddressZeroNotAllowed.selector); + vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); + ruleSanctionList = new RuleSanctionList( + address(0), + address(forwarder) + ); + } +} diff --git a/test/RuleSanctionList/RuleSanctionListTest.t.sol b/test/RuleSanctionList/RuleSanctionListTest.t.sol new file mode 100644 index 0000000..b55a6a9 --- /dev/null +++ b/test/RuleSanctionList/RuleSanctionListTest.t.sol @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import "forge-std/Test.sol"; +import "../HelperContract.sol"; +import "src/RuleEngine.sol"; +import "src/rules/RuleSanctionList.sol"; +import "../utils/SanctionListOracle.sol"; +/** +@title General functions of the ruleSanctionList +*/ +contract RuleSanctionlistTest is Test, HelperContract { + uint256 resUint256; + uint8 resUint8; + bool resBool; + bool resCallBool; + string resString; + uint8 CODE_NONEXISTENT = 255; + SanctionListOracle sanctionlistOracle; + RuleSanctionList ruleSanctionList; + // Arrange + function setUp() public { + vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); + sanctionlistOracle = new SanctionListOracle(); + sanctionlistOracle.addToSanctionsList(ATTACKER); + ruleSanctionList = new RuleSanctionList( + SANCTIONLIST_OPERATOR_ADDRESS, + ZERO_ADDRESS + ); + vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); + ruleSanctionList.setSanctionListOracle(address(sanctionlistOracle)); + } + + function testCanReturnTransferRestrictionCode() public { + // Act + resBool = ruleSanctionList.canReturnTransferRestrictionCode( + CODE_ADDRESS_FROM_IS_SANCTIONED + ); + // Assert + assertEq(resBool, true); + // Act + resBool = ruleSanctionList.canReturnTransferRestrictionCode( + CODE_ADDRESS_TO_IS_SANCTIONED + ); + // Assert + assertEq(resBool, true); + // Act + resBool = ruleSanctionList.canReturnTransferRestrictionCode( + CODE_NONEXISTENT + ); + // Assert + assertFalse(resBool); + } + + function testReturnTheRightMessageForAGivenCode() public { + // Assert + resString = ruleSanctionList.messageForTransferRestriction( + CODE_ADDRESS_FROM_IS_SANCTIONED + ); + // Assert + assertEq(resString, TEXT_ADDRESS_FROM_IS_SANCTIONED); + // Act + resString = ruleSanctionList.messageForTransferRestriction( + CODE_ADDRESS_TO_IS_SANCTIONED + ); + // Assert + assertEq(resString, TEXT_ADDRESS_TO_IS_SANCTIONED); + // Act + resString = ruleSanctionList.messageForTransferRestriction( + CODE_NONEXISTENT + ); + // Assert + assertEq(resString, TEXT_CODE_NOT_FOUND); + } + + function testValidateTransfer() public { + // Act + // ADDRESS1 -> ADDRESS2 + resBool = ruleSanctionList.validateTransfer(ADDRESS1, ADDRESS2, 20); + assertEq(resBool, true); + // ADDRESS2 -> ADDRESS1 + resBool = ruleSanctionList.validateTransfer(ADDRESS2, ADDRESS1, 20); + assertEq(resBool, true); + } + + function testTransferFromDetectedAsInvalid() public { + // Act + resBool = ruleSanctionList.validateTransfer(ATTACKER, ADDRESS2, 20); + // Assert + assertFalse(resBool); + } + + function testTransferToDetectedAsInvalid() public { + // Act + resBool = ruleSanctionList.validateTransfer(ADDRESS1, ATTACKER, 20); + // Assert + assertFalse(resBool); + } + + function testDetectTransferRestrictionFrom() public { + // Act + resUint8 = ruleSanctionList.detectTransferRestriction( + ATTACKER, + ADDRESS2, + 20 + ); + // Assert + assertEq(resUint8, CODE_ADDRESS_FROM_IS_SANCTIONED); + } + + function testDetectTransferRestrictionTo() public { + // Act + resUint8 = ruleSanctionList.detectTransferRestriction( + ADDRESS1, + ATTACKER, + 20 + ); + // Assert + assertEq(resUint8, CODE_ADDRESS_TO_IS_SANCTIONED); + } + + function testDetectTransferRestrictionOk() public { + // Act + resUint8 = ruleSanctionList.detectTransferRestriction( + ADDRESS1, + ADDRESS2, + 20 + ); + // Assert + assertEq(resUint8, NO_ERROR); + } +} diff --git a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol index 5adc20e..27087ab 100644 --- a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol +++ b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../../HelperContract.sol"; @@ -9,6 +9,8 @@ import "src/RuleEngine.sol"; @title Tests on the Access Control */ contract RuleWhitelistAccessControl is Test, HelperContract { + // Custom error openZeppelin + error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); // Defined in CMTAT.sol uint8 constant TRANSFER_OK = 0; string constant TEXT_TRANSFER_OK = "No restriction"; @@ -29,16 +31,8 @@ contract RuleWhitelistAccessControl is Test, HelperContract { } function testCannotAttackerAddAddressToTheWhitelist() public { - // Act - string memory message = string( - abi.encodePacked( - "AccessControl: account ", - vm.toString(ATTACKER), - " is missing role ", - WHITELIST_ROLE_HASH - ) - ); - vm.expectRevert(bytes(message)); + vm.expectRevert( + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, WHITELIST_ROLE)); vm.prank(ATTACKER); ruleWhitelist.addAddressToTheWhitelist(ADDRESS1); @@ -58,15 +52,8 @@ contract RuleWhitelistAccessControl is Test, HelperContract { whitelist[1] = ADDRESS2; // Act - string memory message = string( - abi.encodePacked( - "AccessControl: account ", - vm.toString(ATTACKER), - " is missing role ", - WHITELIST_ROLE_HASH - ) - ); - vm.expectRevert(bytes(message)); + vm.expectRevert( + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, WHITELIST_ROLE)); vm.prank(ATTACKER); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( @@ -97,15 +84,8 @@ contract RuleWhitelistAccessControl is Test, HelperContract { assertEq(resBool, true); // Act - string memory message = string( - abi.encodePacked( - "AccessControl: account ", - vm.toString(ATTACKER), - " is missing role ", - WHITELIST_ROLE_HASH - ) - ); - vm.expectRevert(bytes(message)); + vm.expectRevert( + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, WHITELIST_ROLE)); vm.prank(ATTACKER); ruleWhitelist.removeAddressFromTheWhitelist(ADDRESS1); @@ -136,15 +116,8 @@ contract RuleWhitelistAccessControl is Test, HelperContract { assertEq(resBool, true); // Act - string memory message = string( - abi.encodePacked( - "AccessControl: account ", - vm.toString(ATTACKER), - " is missing role ", - WHITELIST_ROLE_HASH - ) - ); - vm.expectRevert(bytes(message)); + vm.expectRevert( + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, WHITELIST_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 4cb0886..8859337 100644 --- a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol +++ b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../../HelperContract.sol"; @@ -62,17 +62,10 @@ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl { // Arrange - Assert bool res1 = ruleWhitelist.hasRole(WHITELIST_ROLE, ADDRESS1); assertFalse(res1); - + // Act - string memory message = string( - abi.encodePacked( - "AccessControl: account ", - vm.toString(ADDRESS2), - " is missing role ", - DEFAULT_ADMIN_ROLE_HASH - ) - ); - vm.expectRevert(bytes(message)); + vm.expectRevert( + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ADDRESS2, DEFAULT_ADMIN_ROLE)); vm.prank(ADDRESS2); ruleWhitelist.grantRole(WHITELIST_ROLE, ADDRESS1); // Assert @@ -94,15 +87,8 @@ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl { // Act vm.prank(ADDRESS2); - string memory message = string( - abi.encodePacked( - "AccessControl: account ", - vm.toString(ADDRESS2), - " is missing role ", - DEFAULT_ADMIN_ROLE_HASH - ) - ); - vm.expectRevert(bytes(message)); + vm.expectRevert( + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ADDRESS2, DEFAULT_ADMIN_ROLE)); ruleWhitelist.revokeRole(WHITELIST_ROLE, ADDRESS1); // Assert diff --git a/test/RuleWhitelist/Rulewhitelist.t.sol b/test/RuleWhitelist/RuleWhitelist.t.sol similarity index 99% rename from test/RuleWhitelist/Rulewhitelist.t.sol rename to test/RuleWhitelist/RuleWhitelist.t.sol index a1527c7..575b01d 100644 --- a/test/RuleWhitelist/Rulewhitelist.t.sol +++ b/test/RuleWhitelist/RuleWhitelist.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; diff --git a/test/RuleWhitelist/RuleWhitelistAdd.t.sol b/test/RuleWhitelist/RuleWhitelistAdd.t.sol index 3e868e6..48bae33 100644 --- a/test/RuleWhitelist/RuleWhitelistAdd.t.sol +++ b/test/RuleWhitelist/RuleWhitelistAdd.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; @@ -125,7 +125,7 @@ contract RuleWhitelistAddTest is Test, HelperContract { resBool = ruleWhitelist.addressIsWhitelisted(ADDRESS1); assertEq(resBool, true); /// Arrange - vm.expectRevert(bytes("Address is already in the whitelist")); + vm.expectRevert(RuleWhitelist_AddressAlreadyWhitelisted.selector); // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); ruleWhitelist.addAddressToTheWhitelist(ADDRESS1); diff --git a/test/RuleWhitelist/RulewhitelistDeployment.t.sol b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol similarity index 70% rename from test/RuleWhitelist/RulewhitelistDeployment.t.sol rename to test/RuleWhitelist/RuleWhitelistDeployment.t.sol index 650ca1e..93aa49f 100644 --- a/test/RuleWhitelist/RulewhitelistDeployment.t.sol +++ b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; @@ -18,11 +18,6 @@ contract RuleWhitelistTest is Test, HelperContract { // Arrange function setUp() public { - vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist = new RuleWhitelist( - WHITELIST_OPERATOR_ADDRESS, - ZERO_ADDRESS - ); } function testRightDeployment() public { @@ -30,7 +25,7 @@ contract RuleWhitelistTest is Test, HelperContract { vm.prank(WHITELIST_OPERATOR_ADDRESS); MinimalForwarderMock forwarder = new MinimalForwarderMock( ); - forwarder.initialize(); + forwarder.initialize(ERC2771ForwarderDomain); vm.prank(WHITELIST_OPERATOR_ADDRESS); ruleWhitelist = new RuleWhitelist( WHITELIST_OPERATOR_ADDRESS, @@ -43,4 +38,18 @@ contract RuleWhitelistTest is Test, HelperContract { resBool = ruleWhitelist.isTrustedForwarder(address(forwarder)); assertEq(resBool, true); } + + function testCannotDeployContractIfAdminAddressIsZero() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + MinimalForwarderMock forwarder = new MinimalForwarderMock( + ); + forwarder.initialize(ERC2771ForwarderDomain); + vm.expectRevert(RuleWhitelist_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 dfd278b..85aaa8e 100644 --- a/test/RuleWhitelist/RuleWhitelistRemove.t.sol +++ b/test/RuleWhitelist/RuleWhitelistRemove.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; @@ -90,7 +90,7 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { // Arrange resBool = ruleWhitelist.addressIsWhitelisted(ADDRESS1); assertFalse(resBool); - vm.expectRevert(bytes("Address is not in the whitelist")); + vm.expectRevert(RuleWhitelist_AddressNotPresent.selector); // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); @@ -126,7 +126,7 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { address[] memory whitelistRemove = new address[](3); whitelistRemove[0] = ADDRESS1; whitelistRemove[1] = ADDRESS2; - // Target Address - Not Prsent in the whitelist + // Target Address - Not Present in the whitelist whitelistRemove[2] = ADDRESS3; // Act diff --git a/test/utils/SanctionListOracle.sol b/test/utils/SanctionListOracle.sol new file mode 100644 index 0000000..bbae931 --- /dev/null +++ b/test/utils/SanctionListOracle.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +/** +* @notice Test contract from +https://etherscan.io/address/0x40c57923924b5c5c5455c48d93317139addac8fb#code +*/ +contract SanctionListOracle { + + constructor() {} + + mapping(address => bool) private sanctionedAddresses; + + + function addToSanctionsList(address newSanction) public{ + sanctionedAddresses[newSanction] = true; + } + + function removeFromSanctionsList(address removeSanction) public{ + sanctionedAddresses[removeSanction] = true; + } + + function isSanctioned(address addr) public view returns (bool) { + return sanctionedAddresses[addr] == true ; + } +} \ No newline at end of file