From 08ce082514bf6aa0207301291e70bc35f3603617 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Tue, 14 Oct 2025 16:13:05 +0200 Subject: [PATCH 01/25] Update CMTAT (v.3.0.0), RuleEngine library, adapt rules to the new RuleEngine, remove operation rule --- lib/CMTAT | 2 +- lib/RuleEngine | 2 +- ...ransfer.sol => RuleConditionalTransferOld} | 0 ...uleConditionalTransferInvariantStorageOld} | 0 ...sol => RuleConditionalTransferOperatorOld} | 0 src/rules/validation/RuleBlacklist.sol | 26 +- src/rules/validation/RuleSanctionList.sol | 29 +- src/rules/validation/RuleWhitelist.sol | 10 +- src/rules/validation/RuleWhitelistWrapper.sol | 21 +- .../RuleBlacklistInvariantStorage.sol | 6 + .../RuleWhitelistInvariantStorage.sol | 6 + .../RuleSanctionListInvariantStorage.sol | 6 + .../abstract/RuleValidateTransfer.sol | 18 +- .../abstract/RuleWhitelistCommon.sol | 23 + test/HelperContract.sol | 14 +- test/RuleBlacklist/CMTATIntegration.t.sol | 31 +- .../CMTATIntegration.t.sol | 160 --- .../CMTATIntegrationConditionalTransfer.t.sol | 321 ------ .../CMTATIntegrationTest2.t.sol | 182 ---- .../RuleConditionalTransfer.t.sol | 979 ------------------ ...RuleConditionalTransferAccessControl.t.sol | 246 ----- .../RuleConditionalTransferDeployment.t.sol | 80 -- .../RuleConditionalTransferReset.t.sol | 440 -------- .../RuleConditionalTransferRestriction.t.sol | 117 --- .../utils/CMTATIntegrationShare.sol | 482 --------- .../utils/RuleCTDeployment.sol | 56 - test/RuleWhitelist/CMTATIntegration.t.sol | 17 +- .../CMTATIntegrationWhitelistWrapper.t.sol | 23 +- test/utils/CMTATDeployment.sol | 50 - 29 files changed, 166 insertions(+), 3181 deletions(-) rename src/rules/operation/{RuleConditionalTransfer.sol => RuleConditionalTransferOld} (100%) rename src/rules/operation/abstract/{RuleConditionalTransferInvariantStorage.sol => RuleConditionalTransferInvariantStorageOld} (100%) rename src/rules/operation/abstract/{RuleConditionalTransferOperator.sol => RuleConditionalTransferOperatorOld} (100%) delete mode 100644 test/RuleConditionalTransfer/CMTATIntegration.t.sol delete mode 100644 test/RuleConditionalTransfer/CMTATIntegrationConditionalTransfer.t.sol delete mode 100644 test/RuleConditionalTransfer/CMTATIntegrationTest2.t.sol delete mode 100644 test/RuleConditionalTransfer/RuleConditionalTransfer.t.sol delete mode 100644 test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol delete mode 100644 test/RuleConditionalTransfer/RuleConditionalTransferDeployment.t.sol delete mode 100644 test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol delete mode 100644 test/RuleConditionalTransfer/RuleConditionalTransferRestriction.t.sol delete mode 100644 test/RuleConditionalTransfer/utils/CMTATIntegrationShare.sol delete mode 100644 test/RuleConditionalTransfer/utils/RuleCTDeployment.sol delete mode 100644 test/utils/CMTATDeployment.sol diff --git a/lib/CMTAT b/lib/CMTAT index 305351b..69eecc9 160000 --- a/lib/CMTAT +++ b/lib/CMTAT @@ -1 +1 @@ -Subproject commit 305351bb1cff10cd87ff4bda6e263628c34b9543 +Subproject commit 69eecc9735ce8ada84fd35801888b05747658939 diff --git a/lib/RuleEngine b/lib/RuleEngine index 461d32f..f3283c3 160000 --- a/lib/RuleEngine +++ b/lib/RuleEngine @@ -1 +1 @@ -Subproject commit 461d32fca6cf501d6c15f3aed5f18855b2a6581c +Subproject commit f3283c3b8a99089c3c6f674150831003a6bd2927 diff --git a/src/rules/operation/RuleConditionalTransfer.sol b/src/rules/operation/RuleConditionalTransferOld similarity index 100% rename from src/rules/operation/RuleConditionalTransfer.sol rename to src/rules/operation/RuleConditionalTransferOld diff --git a/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol b/src/rules/operation/abstract/RuleConditionalTransferInvariantStorageOld similarity index 100% rename from src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol rename to src/rules/operation/abstract/RuleConditionalTransferInvariantStorageOld diff --git a/src/rules/operation/abstract/RuleConditionalTransferOperator.sol b/src/rules/operation/abstract/RuleConditionalTransferOperatorOld similarity index 100% rename from src/rules/operation/abstract/RuleConditionalTransferOperator.sol rename to src/rules/operation/abstract/RuleConditionalTransferOperatorOld diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol index e057a22..5def3ab 100644 --- a/src/rules/validation/RuleBlacklist.sol +++ b/src/rules/validation/RuleBlacklist.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.20; import "./abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol"; import "./abstract/RuleAddressList/RuleAddressList.sol"; import "./abstract/RuleValidateTransfer.sol"; - +//import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; /** * @title a blacklist manager */ @@ -15,6 +15,7 @@ contract RuleBlacklist is RuleAddressList, RuleBlacklistInvariantStorage { + /** * @param admin Address of the contract (Access Control) * @param forwarderIrrevocable Address of the forwarder, required for the gasless support @@ -40,7 +41,7 @@ contract RuleBlacklist is } else if (addressIsListed(to)) { return CODE_ADDRESS_TO_IS_BLACKLISTED; } else { - return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); } } @@ -91,4 +92,25 @@ contract RuleBlacklist is return TEXT_CODE_NOT_FOUND; } } + + function transferred(address from, address to, uint256 value) public view { + uint8 code = this.detectTransferRestriction(from, to, value); + require( + code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + RuleBlacklist_InvalidTransfer(from, to, value, code) + ); + } + + function transferred( + address spender, + address from, + address to, + uint256 value + ) public view { + uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); + require( + code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + RuleBlacklist_InvalidTransfer(from, to, value, code) + ); + } } diff --git a/src/rules/validation/RuleSanctionList.sol b/src/rules/validation/RuleSanctionList.sol index 66a7e1a..5834ef1 100644 --- a/src/rules/validation/RuleSanctionList.sol +++ b/src/rules/validation/RuleSanctionList.sol @@ -7,6 +7,7 @@ import "../../modules/MetaTxModuleStandalone.sol"; import "./abstract/RuleSanctionListInvariantStorage.sol"; import "./abstract/RuleValidateTransfer.sol"; + interface SanctionsList { function isSanctioned(address addr) external view returns (bool); } @@ -17,6 +18,7 @@ contract RuleSanctionList is RuleValidateTransfer, RuleSanctionlistInvariantStorage { + SanctionsList public sanctionsList; /** @@ -49,7 +51,7 @@ contract RuleSanctionList is } /** - * @notice Check if an addres is in the whitelist or not + * @notice Check if an addres is in the SanctionsList or not * @param from the origin address * @param to the destination address * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK @@ -119,6 +121,27 @@ contract RuleSanctionList is } } + function transferred(address from, address to, uint256 value) public view { + uint8 code = this.detectTransferRestriction(from, to, value); + require( + code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + RuleSanctionsList_InvalidTransfer(from, to, value, code) + ); + } + + function transferred( + address spender, + address from, + address to, + uint256 value + ) public view { + uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); + require( + code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + RuleSanctionsList_InvalidTransfer(from, to, value, code) + ); + } + /* ============ ACCESS CONTROL ============ */ /** * @dev Returns `true` if `account` has been granted `role`. @@ -130,8 +153,10 @@ contract RuleSanctionList is // The Default Admin has all roles if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { return true; + } else{ + return AccessControl.hasRole(role, account); } - return AccessControl.hasRole(role, account); + } /*////////////////////////////////////////////////////////////// diff --git a/src/rules/validation/RuleWhitelist.sol b/src/rules/validation/RuleWhitelist.sol index 5b658cb..213bf67 100644 --- a/src/rules/validation/RuleWhitelist.sol +++ b/src/rules/validation/RuleWhitelist.sol @@ -5,6 +5,8 @@ pragma solidity ^0.8.20; import "./abstract/RuleAddressList/RuleAddressList.sol"; import "./abstract/RuleWhitelistCommon.sol"; +import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; + /** * @title a whitelist manager */ @@ -18,6 +20,8 @@ contract RuleWhitelist is RuleAddressList, RuleWhitelistCommon { address forwarderIrrevocable ) RuleAddressList(admin, forwarderIrrevocable) {} + + /** * @notice Check if an addres is in the whitelist or not * @param from the origin address @@ -44,10 +48,12 @@ contract RuleWhitelist is RuleAddressList, RuleWhitelistCommon { address to, uint256 value ) public view override returns (uint8) { - if (addressIsListed(spender)) { + if (!addressIsListed(spender)) { return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; } else { - return detectTransferRestriction(from,to,value); + return detectTransferRestriction(from, to, value); } } + + } diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol index 21f3e7f..e499ba7 100644 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -3,16 +3,17 @@ pragma solidity ^0.8.20; import "OZ/access/AccessControl.sol"; -import "RuleEngine/modules/RuleEngineValidationCommon.sol"; import "../../modules/MetaTxModuleStandalone.sol"; import "./abstract/RuleAddressList/RuleAddressList.sol"; import "./abstract/RuleWhitelistCommon.sol"; - +import {RulesManagementModule} from "RuleEngine/modules/RulesManagementModule.sol"; +import {RuleEngineInvariantStorage} from "RuleEngine/modules/library/RuleEngineInvariantStorage.sol"; +import {IRule} from "RuleEngine/interfaces/IRule.sol"; /** * @title Wrapper to call several different whitelist rules */ contract RuleWhitelistWrapper is - RuleEngineValidationCommon, + RulesManagementModule, MetaTxModuleStandalone, RuleWhitelistCommon { @@ -25,7 +26,7 @@ contract RuleWhitelistWrapper is address forwarderIrrevocable ) MetaTxModuleStandalone(forwarderIrrevocable) { if (admin == address(0)) { - revert RuleEngine_AdminWithAddressZeroNotAllowed(); + revert RuleEngineInvariantStorage.RuleEngine_AdminWithAddressZeroNotAllowed(); } _grantRole(DEFAULT_ADMIN_ROLE, admin); } @@ -46,11 +47,11 @@ contract RuleWhitelistWrapper is bool[] memory result = new bool[](2); targetAddress[0] = from; targetAddress[1] = to; - uint256 rulesLength = _rulesValidation.length; + uint256 rulesLength = rulesCount(); // For each whitelist rule, we ask if from or to are in the whitelist for (uint256 i = 0; i < rulesLength; ++i) { // External call - isListed = RuleAddressList(_rulesValidation[i]) + isListed = RuleAddressList(rule(i)) .addressIsListedBatch(targetAddress); if (isListed[0] && !result[0]) { // Update if from is in the list @@ -85,11 +86,11 @@ contract RuleWhitelistWrapper is targetAddress[0] = from; targetAddress[1] = to; targetAddress[2] = spender; - uint256 rulesLength = _rulesValidation.length; + uint256 rulesLength = rulesCount(); // For each whitelist rule, we ask if from or to are in the whitelist for (uint256 i = 0; i < rulesLength; ++i) { // External call - isListed = RuleAddressList(_rulesValidation[i]) + isListed = RuleAddressList(rule(i)) .addressIsListedBatch(targetAddress); if (isListed[0] && !result[0]) { // Update if from is in the list @@ -129,8 +130,10 @@ contract RuleWhitelistWrapper is // The Default Admin has all roles if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { return true; + } else { + return AccessControl.hasRole(role, account); } - return AccessControl.hasRole(role, account); + } /*////////////////////////////////////////////////////////////// diff --git a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol index f5d8d04..c645ed1 100644 --- a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol @@ -5,6 +5,12 @@ pragma solidity ^0.8.20; import "../../RuleCommonInvariantStorage.sol"; abstract contract RuleBlacklistInvariantStorage is RuleCommonInvariantStorage { + error RuleBlacklist_InvalidTransfer( + address from, + address to, + uint256 value, + uint8 code + ); /* ============ String message ============ */ string constant TEXT_ADDRESS_FROM_IS_BLACKLISTED = "The sender is blacklisted"; diff --git a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol index e2bcdbc..73869a5 100644 --- a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol @@ -5,6 +5,12 @@ pragma solidity ^0.8.20; import "../../RuleCommonInvariantStorage.sol"; abstract contract RuleWhitelistInvariantStorage is RuleCommonInvariantStorage { + error RuleWhitelist_InvalidTransfer( + address from, + address to, + uint256 value, + uint8 code + ); /* ============ String message ============ */ string constant TEXT_ADDRESS_FROM_NOT_WHITELISTED = "The sender is not in the whitelist"; diff --git a/src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol b/src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol index e8798c4..491566c 100644 --- a/src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol @@ -7,6 +7,12 @@ import "./RuleCommonInvariantStorage.sol"; abstract contract RuleSanctionlistInvariantStorage is RuleCommonInvariantStorage { + error RuleSanctionsList_InvalidTransfer( + address from, + address to, + uint256 value, + uint8 code + ); /* ============ Event ============ */ event SetSanctionListOracle(address newOracle); /* ============ Custom errors ============ */ diff --git a/src/rules/validation/abstract/RuleValidateTransfer.sol b/src/rules/validation/abstract/RuleValidateTransfer.sol index 2df3a33..958ee49 100644 --- a/src/rules/validation/abstract/RuleValidateTransfer.sol +++ b/src/rules/validation/abstract/RuleValidateTransfer.sol @@ -2,9 +2,13 @@ pragma solidity ^0.8.20; -import {IRuleValidation} from "RuleEngine/interfaces/IRuleValidation.sol"; -import {IERC1404} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; -abstract contract RuleValidateTransfer is IRuleValidation { +import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; +import {IERC3643ComplianceRead} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; +import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol"; +import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; +import {IRule} from "RuleEngine/interfaces/IRule.sol"; + +abstract contract RuleValidateTransfer is IERC3643ComplianceRead, IERC7551Compliance,IRule { /** * @notice Validate a transfer * @param _from the origin address @@ -16,11 +20,11 @@ abstract contract RuleValidateTransfer is IRuleValidation { address _from, address _to, uint256 _amount - ) public view override returns (bool isValid) { + ) public view override(IERC3643ComplianceRead) returns (bool isValid) { // does not work without `this` keyword => "Undeclared identifier" return this.detectTransferRestriction(_from, _to, _amount) == - uint8(REJECTED_CODE_BASE.TRANSFER_OK); + uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); } function canTransferFrom( @@ -28,8 +32,8 @@ abstract contract RuleValidateTransfer is IRuleValidation { address from, address to, uint256 value - ) public view virtual override returns (bool) { + ) public view virtual override(IERC7551Compliance) returns (bool) { return this.detectTransferRestrictionFrom(spender, from, to, value) == - uint8(REJECTED_CODE_BASE.TRANSFER_OK); + uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); } } diff --git a/src/rules/validation/abstract/RuleWhitelistCommon.sol b/src/rules/validation/abstract/RuleWhitelistCommon.sol index dedd371..d73073d 100644 --- a/src/rules/validation/abstract/RuleWhitelistCommon.sol +++ b/src/rules/validation/abstract/RuleWhitelistCommon.sol @@ -5,10 +5,12 @@ pragma solidity ^0.8.20; import "./RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol"; import "./RuleValidateTransfer.sol"; + abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInvariantStorage { + /** * @notice To know if the restriction code is valid for this rule or not * @param _restrictionCode The target restriction code @@ -41,4 +43,25 @@ abstract contract RuleWhitelistCommon is return TEXT_CODE_NOT_FOUND; } } + + function transferred(address from, address to, uint256 value) public view { + uint8 code = this.detectTransferRestriction(from, to, value); + require( + code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + RuleWhitelist_InvalidTransfer(from, to, value, code) + ); + } + + function transferred( + address spender, + address from, + address to, + uint256 value + ) public view { + uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); + require( + code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + RuleWhitelist_InvalidTransfer(from, to, value, code) + ); + } } diff --git a/test/HelperContract.sol b/test/HelperContract.sol index c6f487e..dc2ca07 100644 --- a/test/HelperContract.sol +++ b/test/HelperContract.sol @@ -6,11 +6,9 @@ import "CMTAT/deployment/CMTATStandalone.sol"; import "CMTAT/libraries/Errors.sol"; // RuleEngine -import {RuleEngineInvariantStorage} from "RuleEngine/modules/RuleEngineInvariantStorage.sol"; +import {RuleEngineInvariantStorage} from "RuleEngine/modules/library/RuleEngineInvariantStorage.sol"; import {RuleEngine} from "RuleEngine/RuleEngine.sol"; -// RuleConditionalTransfer -import {RuleConditionalTransferInvariantStorage} from "src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol"; -import {RuleConditionalTransfer} from "src/rules/operation/RuleConditionalTransfer.sol"; + // RuleSanctionList import {RuleSanctionList} from "src/rules/validation/RuleSanctionList.sol"; // RUleBlackList @@ -24,11 +22,9 @@ import {RuleAddressListInvariantStorage} from "src/rules/validation/abstract/Rul import {RuleSanctionlistInvariantStorage}from "src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol"; // Rule interface -import {IRuleValidation} from "RuleEngine/interfaces/IRuleValidation.sol"; -import {IRuleOperation} from "RuleEngine/interfaces/IRuleOperation.sol"; // utils -import "./utils/CMTATDeployment.sol"; +import "RuleEngine/../test/utils/CMTATDeployment.sol"; /** * @title Constants used by the tests @@ -38,8 +34,7 @@ abstract contract HelperContract is RuleBlacklistInvariantStorage, RuleAddressListInvariantStorage, RuleSanctionlistInvariantStorage, - RuleEngineInvariantStorage, - RuleConditionalTransferInvariantStorage + RuleEngineInvariantStorage { // Test result uint256 internal resUint256; @@ -71,7 +66,6 @@ abstract contract HelperContract is // contract RuleBlacklist public ruleBlacklist; RuleWhitelist public ruleWhitelist; - RuleConditionalTransfer public ruleConditionalTransfer; // CMTAT CMTATDeployment cmtatDeployment; diff --git a/test/RuleBlacklist/CMTATIntegration.t.sol b/test/RuleBlacklist/CMTATIntegration.t.sol index 6314514..0b51d22 100644 --- a/test/RuleBlacklist/CMTATIntegration.t.sol +++ b/test/RuleBlacklist/CMTATIntegration.t.sol @@ -33,7 +33,7 @@ contract CMTATIntegration is Test, HelperContract { address(CMTAT_CONTRACT) ); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock.addRuleValidation(ruleBlacklist); + ruleEngineMock.addRule(ruleBlacklist); vm.prank(DEFAULT_ADMIN_ADDRESS); CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT); vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -47,10 +47,6 @@ contract CMTATIntegration is Test, HelperContract { /******* Transfer *******/ function testCanTransferIfAddressNotBlacklisted() public { - // Arrange - /*vm.prank(ADDRESS1); - vm.expectRevert( - abi.encodeWithSelector(RuleEngine_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21)); */ // Act vm.prank(ADDRESS1); CMTAT_CONTRACT.transfer(ADDRESS2, 21); @@ -65,10 +61,11 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, + RuleBlacklist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, - amount + amount, + CODE_ADDRESS_TO_IS_BLACKLISTED ) ); // Act @@ -84,10 +81,11 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, + RuleBlacklist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, - amount + amount, + CODE_ADDRESS_FROM_IS_BLACKLISTED ) ); // Act @@ -113,10 +111,11 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, + RuleBlacklist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, - amount + amount, + CODE_ADDRESS_FROM_IS_BLACKLISTED ) ); CMTAT_CONTRACT.transfer(ADDRESS2, amount); @@ -228,22 +227,20 @@ contract CMTATIntegration is Test, HelperContract { function testCannotMintIfAddressIsInTheBlacklist() public { uint256 amount = 11; // Arrange - // Add address zero to the blacklist - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleBlacklist.addAddressToTheList(ZERO_ADDRESS); vm.prank(DEFAULT_ADMIN_ADDRESS); ruleBlacklist.addAddressToTheList(ADDRESS1); // Arrange - Assert - resBool = ruleBlacklist.addressIsListed(ZERO_ADDRESS); + resBool = ruleBlacklist.addressIsListed(ADDRESS1); assertEq(resBool, true); // Act vm.expectRevert( abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, + RuleBlacklist_InvalidTransfer.selector, ZERO_ADDRESS, ADDRESS1, - amount + amount, + CODE_ADDRESS_TO_IS_BLACKLISTED ) ); vm.prank(DEFAULT_ADMIN_ADDRESS); diff --git a/test/RuleConditionalTransfer/CMTATIntegration.t.sol b/test/RuleConditionalTransfer/CMTATIntegration.t.sol deleted file mode 100644 index 3768ef3..0000000 --- a/test/RuleConditionalTransfer/CMTATIntegration.t.sol +++ /dev/null @@ -1,160 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "CMTAT/deployment/CMTATStandalone.sol"; -import "../HelperContract.sol"; -import "./utils/CMTATIntegrationShare.sol"; - -/** - * @title Integration test with the CMTAT - */ -contract CMTATIntegrationConditionalTransfer is Test, HelperContract, CMTATIntegrationShare { - // Arrange - function setUp() public { - TIME_LIMIT memory timeLimit_ = TIME_LIMIT({ - timeLimitToApprove: 7 days, - timeLimitToTransfer: 30 days - }); - ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval: true, - authorizedBurnWithoutApproval: true - }); - - AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ - isActivate: false, - timeLimitBeforeAutomaticApproval: 0 - }); - - AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate: false, - cmtat: IERC20(address(0)) - }); - OPTION memory options = OPTION({ - issuance: issuanceOption_, - timeLimit: timeLimit_, - automaticApproval: automaticApproval_, - automaticTransfer: automaticTransfer_ - }); - - // global arrange - cmtatDeployment = new CMTATDeployment(); - CMTAT_CONTRACT = cmtatDeployment.cmtat(); - - // RuleEngine - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock = new RuleEngine( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS, - address(CMTAT_CONTRACT) - ); - - // RuleConditionalTransfer - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer = new RuleConditionalTransfer( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - // specific arrange - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer.grantRole( - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS - ); - - // RuleEngine - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock.addRuleOperation(ruleConditionalTransfer); - - // Mint - vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT); - vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.mint(ADDRESS2, ADDRESS2_BALANCE_INIT); - vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.mint(ADDRESS3, ADDRESS3_BALANCE_INIT); - vm.prank(DEFAULT_ADMIN_ADDRESS); - - // We set the Rule Engine - CMTAT_CONTRACT.setRuleEngine(ruleEngineMock); - } - - function _createTransferRequest() internal { - vm.prank(ADDRESS1); - // Act - vm.expectEmit(true, true, true, true); - emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); - } - - /******* Transfer *******/ - function testCannotTransferWithoutApproval() public { - CMTATIntegrationShare.testShareCannotTransferWithoutApproval(); - } - - function testCanMakeATransferIfApproved() public { - CMTATIntegrationShare.testShareCanMakeATransferIfApproved(); - } - - function testCanMakeAPartialTransferIfPartiallyApproved() public { - CMTATIntegrationShare.testShareCanMakeAPartialTransferIfPartiallyApproved(); - } - - function testCannotMakeAWholeTransferIfPartiallyApproved() public { - CMTATIntegrationShare.testShareCannotMakeAWholeTransferIfPartiallyApproved(); - } - function testCannotMakeATransferIfDelayExceeded() public { - // // +30 days and one second - CMTATIntegrationShare.testShareCannotMakeATransferIfDelayExceeded(2592001); - } - - function testCannotMakeATransferIfDelayJustInTime() public { - // 30 days - CMTATIntegrationShare.testShareCannotMakeATransferIfDelayJustInTime(2592000); - } - - function testCanSetTimeLimitWithTransferExceeded() public { - // Assert - // Timeout - // >1 days - CMTATIntegrationShare.testShareCanSetTimeLimitWithTransferExceeded(1 days + 1 seconds); - } - - function testCanMintWithoutApproval() public { - CMTATIntegrationShare.testShareCanMintWithoutApproval(); - } - - function testCanBurnWithoutApproval() public { - CMTATIntegrationShare.testShareCanBurnWithoutApproval(); - } - - function testCannotMintWithoutApproval() public { - CMTATIntegrationShare.testShareCannotMintWithoutApproval(); - } - - function testCannotBurnWithoutApproval() public { - CMTATIntegrationShare.testShareCannotBurnWithoutApproval(); - } - - function testAutomaticTransferIfOptionsSet() public { - CMTATIntegrationShare.testShareAutomaticTransferIfOptionsSet(); - } - - function testCanTransferIfAutomaticApprovalSetAndTimeExceedsJustInTime() - public - { - CMTATIntegrationShare.testShareCanTransferIfAutomaticApprovalSetAndTimeExceedsJustInTime(); - } - - function testCanTransferIfAutomaticApprovalSetAndTimeExceeds() public { - CMTATIntegrationShare.testShareCanTransferIfAutomaticApprovalSetAndTimeExceeds(); - } - - function testCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds() - public - { - CMTATIntegrationShare.testShareCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds(); - } -} diff --git a/test/RuleConditionalTransfer/CMTATIntegrationConditionalTransfer.t.sol b/test/RuleConditionalTransfer/CMTATIntegrationConditionalTransfer.t.sol deleted file mode 100644 index d1a289a..0000000 --- a/test/RuleConditionalTransfer/CMTATIntegrationConditionalTransfer.t.sol +++ /dev/null @@ -1,321 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "CMTAT/deployment/CMTATStandalone.sol"; -import "../HelperContract.sol"; -import "./utils/CMTATIntegrationShare.sol"; - -/** - * @title Integration test with the CMTAT - */ -contract CMTATIntegrationConditionalTransfer is Test, HelperContract, CMTATIntegrationShare { - - // Arrange - function setUp() public { - TIME_LIMIT memory timeLimit_ = TIME_LIMIT({ - timeLimitToApprove: 7 days, - timeLimitToTransfer: 30 days - }); - ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval: true, - authorizedBurnWithoutApproval: true - }); - - AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ - isActivate: false, - timeLimitBeforeAutomaticApproval: 0 - }); - - AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate: false, - cmtat: IERC20(address(0)) - }); - OPTION memory options = OPTION({ - issuance: issuanceOption_, - timeLimit: timeLimit_, - automaticApproval: automaticApproval_, - automaticTransfer: automaticTransfer_ - }); - - // global arrange - cmtatDeployment = new CMTATDeployment(); - CMTAT_CONTRACT = cmtatDeployment.cmtat(); - - // Whitelist - ruleWhitelist = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); - - // RuleEngine - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock = new RuleEngine( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS, - address(CMTAT_CONTRACT) - ); - - // RuleConditionalTransfer - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer = new RuleConditionalTransfer( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - // Add whitelist - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer.setConditionalWhitelist(ruleWhitelist); - // specific arrange - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer.grantRole( - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS - ); - - // RuleEngine - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock.addRuleOperation(ruleConditionalTransfer); - - // Mint - vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT); - vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.mint(ADDRESS2, ADDRESS2_BALANCE_INIT); - vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.mint(ADDRESS3, ADDRESS3_BALANCE_INIT); - vm.prank(DEFAULT_ADMIN_ADDRESS); - - // We set the Rule Engine - CMTAT_CONTRACT.setRuleEngine(ruleEngineMock); - } - - function _createTransferRequest() internal { - vm.prank(ADDRESS1); - // Act - vm.expectEmit(true, true, true, true); - emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); - } - - /******* Transfer *******/ - function testCanMakeATransferWithoutApprovalIfFromAndToAreInTheWhitelist() - public - { - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS2); - // Arrange - // Act - vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2, 21); - } - - function testCannotMakeATransferWithoutApprovalIfOnlyFromIsInTheWhitelist() - public - { - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); - // Arrange - // Act - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - 21 - ) - ); - vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2, 21); - } - - function testCannotMakeATransferWithoutApprovalIfOnlyToIsInTheWhitelist() - public - { - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS2); - // Arrange - // Act - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - 21 - ) - ); - vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2, 21); - } - - function testCanSetANewWhitelist() public { - RuleWhitelist ruleWhitelist2 = new RuleWhitelist( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS - ); - vm.prank(DEFAULT_ADMIN_ADDRESS); - vm.expectEmit(true, false, false, false); - emit WhitelistConditionalTransfer(ruleWhitelist2); - ruleConditionalTransfer.setConditionalWhitelist(ruleWhitelist2); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist2.addAddressToTheList(ADDRESS1); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist2.addAddressToTheList(ADDRESS2); - - // Arrange - // Act - vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2, 21); - } - - function testCanUnSetWhitelist() public { - // Arrange - RuleWhitelist ruleWhitelist2 = new RuleWhitelist( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS - ); - vm.prank(DEFAULT_ADMIN_ADDRESS); - vm.expectEmit(true, false, false, false); - emit WhitelistConditionalTransfer(ruleWhitelist2); - ruleConditionalTransfer.setConditionalWhitelist(ruleWhitelist2); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist2.addAddressToTheList(ADDRESS1); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist2.addAddressToTheList(ADDRESS2); - - // Act - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer.setConditionalWhitelist( - RuleWhitelist(ZERO_ADDRESS) - ); - - // Assert - vm.prank(ADDRESS1); - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - 21 - ) - ); - CMTAT_CONTRACT.transfer(ADDRESS2, 21); - } - - function testCanDetectTransferRestrictionOKWithWhitelist() public { - // Arrange - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS2); - - // Act - uint8 resUint8 = ruleConditionalTransfer.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - defaultValue - ); - - // Assert - assertEq(resUint8, 0); - } - - function testCanDetectTransferRestrictionWithOnlyFromInTheWhitelist() - public - { - // Arrange - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); - - // Act - uint8 resUint8 = ruleConditionalTransfer.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - defaultValue - ); - - // Assert - assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED); - } - - function testCanDetectTransferRestrictionWithOnlyToInTheWhitelist() public { - // Arrange - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS2); - - // Act - uint8 resUint8 = ruleConditionalTransfer.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - defaultValue - ); - - // Assert - assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED); - } - - /***** Test from CMTAT integration */ - - function testCannotTransferWithoutApproval() public { - CMTATIntegrationShare.testShareCannotTransferWithoutApproval(); - } - - function testCanMakeATransferIfApproved() public { - CMTATIntegrationShare.testShareCanMakeATransferIfApproved(); - } - function testCanMakeAPartialTransferIfPartiallyApproved() public { - CMTATIntegrationShare.testShareCanMakeAPartialTransferIfPartiallyApproved(); - } - - function testCannotMakeAWholeTransferIfPartiallyApproved() public { - CMTATIntegrationShare.testShareCannotMakeAWholeTransferIfPartiallyApproved(); - } - - function testCannotMakeATransferIfDelayExceeded() public { - CMTATIntegrationShare.testShareCannotMakeATransferIfDelayExceeded(2592001); - } - - function testCannotMakeATransferIfDelayJustInTime() public { - // 30 days - CMTATIntegrationShare.testShareCannotMakeATransferIfDelayJustInTime(2592000); - } - - function testCanSetTimeLimitWithTransferExceeded() public { - CMTATIntegrationShare.testShareCanSetTimeLimitWithTransferExceeded(1 days + 1 seconds); - } - - function testCanMintWithoutApproval() public { - CMTATIntegrationShare.testShareCanMintWithoutApproval(); - } - - function testCanBurnWithoutApproval() public { - CMTATIntegrationShare.testShareCanBurnWithoutApproval(); - } - - function testCannotMintWithoutApproval() public { - CMTATIntegrationShare.testShareCannotMintWithoutApproval(); - } - - function testCannotBurnWithoutApproval() public { - CMTATIntegrationShare.testShareCannotBurnWithoutApproval(); - } - function testAutomaticTransferIfOptionsSet() public { - CMTATIntegrationShare.testShareAutomaticTransferIfOptionsSet(); - } - - function testCanTransferIfAutomaticApprovalSetAndTimeExceedsJustInTime() - public - { - CMTATIntegrationShare.testShareCanTransferIfAutomaticApprovalSetAndTimeExceedsJustInTime(); - } - - function testCanTransferIfAutomaticApprovalSetAndTimeExceeds() public { - CMTATIntegrationShare.testShareCanTransferIfAutomaticApprovalSetAndTimeExceeds(); - } - - function testCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds() - public - { - CMTATIntegrationShare.testShareCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds(); - } -} diff --git a/test/RuleConditionalTransfer/CMTATIntegrationTest2.t.sol b/test/RuleConditionalTransfer/CMTATIntegrationTest2.t.sol deleted file mode 100644 index 12cddb3..0000000 --- a/test/RuleConditionalTransfer/CMTATIntegrationTest2.t.sol +++ /dev/null @@ -1,182 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "CMTAT/deployment/CMTATStandalone.sol"; -import "../HelperContract.sol"; -import "RuleEngine/RuleEngine.sol"; -import "./utils/CMTATIntegrationShare.sol"; - -/** - * @title Integration test with the CMTAT - * @dev set blocktimestamp to a value different from 0 - */ -contract CMTATIntegrationConditionalTransferWithTimeStampSet is Test, HelperContract, CMTATIntegrationShare { - uint256 TIME_LIMIT_AUTO_APPROVAL = 259200; //3 days; - uint256 TIME_LIMIT_TO_APPROVE = 432000; //5 days; - uint256 TIME_LIMIT_TO_TRANSFER = 259200; //3 days - // Arrange - function setUp() public { - // global arrange - cmtatDeployment = new CMTATDeployment(); - CMTAT_CONTRACT = cmtatDeployment.cmtat(); - - TIME_LIMIT memory timeLimit_ = TIME_LIMIT({ - timeLimitToApprove: TIME_LIMIT_TO_APPROVE, // 5days - timeLimitToTransfer: TIME_LIMIT_TO_TRANSFER - }); - ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval: true, - authorizedBurnWithoutApproval: true - }); - - AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ - isActivate: true, - timeLimitBeforeAutomaticApproval: TIME_LIMIT_AUTO_APPROVAL - }); - - AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate: true, - cmtat: IERC20(address(CMTAT_CONTRACT)) - }); - OPTION memory options = OPTION({ - issuance: issuanceOption_, - timeLimit: timeLimit_, - automaticApproval: automaticApproval_, - automaticTransfer: automaticTransfer_ - }); - - - - // RuleEngine - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock = new RuleEngine( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS, - address(CMTAT_CONTRACT) - ); - - // RuleConditionalTransfer - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer = new RuleConditionalTransfer( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - // specific arrange - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer.grantRole( - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS - ); - - // RuleEngine - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock.addRuleOperation(ruleConditionalTransfer); - - // Mint - vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT); - vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.mint(ADDRESS2, ADDRESS2_BALANCE_INIT); - vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.mint(ADDRESS3, ADDRESS3_BALANCE_INIT); - vm.prank(DEFAULT_ADMIN_ADDRESS); - - // We set the Rule Engine - CMTAT_CONTRACT.setRuleEngine(ruleEngineMock); - - vm.warp(1734531338); - } - - function _createTransferRequest() internal { - vm.prank(ADDRESS1); - // Act - vm.expectEmit(true, true, true, true); - emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); - } - - /******* Transfer *******/ - function testCannotTransferWithoutApproval() public { - // Arrange - Assert - // ConditionalTransfer - resUint8 = ruleConditionalTransfer.detectTransferRestriction( - address(0xD65Fb7036518F4B34482E0a1905Dc6e3Fc379FF0), - address(0xD65Fb7036518F4B34482E0a1905Dc6e3Fc379FF0), - defaultValue - ); - assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED); - resUint8 = ruleConditionalTransfer.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 5 - ); - assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED); - // Assert - // Arrange - CMTATIntegrationShare.testShareCannotTransferWithoutApproval(); - } - - function testCanMakeATransferIfApproved() public { - CMTATIntegrationShare.testShareCanMakeATransferIfApproved(); - } - - function testCanMakeAPartialTransferIfPartiallyApproved() public { - CMTATIntegrationShare.testShareCanMakeAPartialTransferIfPartiallyApproved(); - } - - function testCannotMakeAWholeTransferIfPartiallyApproved() public { - CMTATIntegrationShare.testShareCannotMakeAWholeTransferIfPartiallyApproved(); - - } - - function testCannotMakeATransferIfDelayExceeded() public { - CMTATIntegrationShare.testShareCannotMakeATransferIfDelayExceeded(TIME_LIMIT_TO_TRANSFER + 1 seconds); - } - - function testCanMakeATransferIfDelayJustInTime() public { - CMTATIntegrationShare.testShareCannotMakeATransferIfDelayJustInTime(TIME_LIMIT_TO_TRANSFER); - } - - function testCanSetTimeLimitWithTransferExceeded() public { - CMTATIntegrationShare.testShareCanSetTimeLimitWithTransferExceeded(1 days + 1 seconds); - } - - function testCanMintWithoutApproval() public { - CMTATIntegrationShare.testShareCanMintWithoutApproval(); - } - - function testCanBurnWithoutApproval() public { - CMTATIntegrationShare.testShareCanBurnWithoutApproval(); - } - - function testCannotMintWithoutApproval() public { - CMTATIntegrationShare.testShareCannotMintWithoutApproval(); - } - - function testCannotBurnWithoutApproval() public { - CMTATIntegrationShare.testShareCannotBurnWithoutApproval(); - } - - function testAutomaticTransferIfOptionsSet() public { - CMTATIntegrationShare.testShareAutomaticTransferIfOptionsSet(); - } - - function testCanTransferIfAutomaticApprovalSetAndTimeExceedsJustInTime() - public - { - CMTATIntegrationShare.testShareCanTransferIfAutomaticApprovalSetAndTimeExceedsJustInTime(); - } - - function testCanTransferIfAutomaticApprovalSetAndTimeExceeds() public { - CMTATIntegrationShare.testShareCanTransferIfAutomaticApprovalSetAndTimeExceeds(); - } - - function testCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds() - public - { - CMTATIntegrationShare.testShareCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds(); - } -} diff --git a/test/RuleConditionalTransfer/RuleConditionalTransfer.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransfer.t.sol deleted file mode 100644 index 01047df..0000000 --- a/test/RuleConditionalTransfer/RuleConditionalTransfer.t.sol +++ /dev/null @@ -1,979 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../HelperContract.sol"; -import "OZ/token/ERC20/IERC20.sol"; -/** - * @title General functions of the RuleWhitelist - */ -contract RuleConditionalTransferTest is Test, HelperContract { - uint256 defaultValue = 10; - bytes32 defaultKey = - keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); - - // Batch test - uint256 value2 = 1; - uint256 value3 = 2; - uint256 value4 = 1000; - uint256 value5 = 2000; - bytes32 key2 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value2)); - bytes32 key3 = keccak256(abi.encode(ADDRESS2, ADDRESS1, value3)); - bytes32 key4 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value4)); - bytes32 key5 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value5)); - - TransferRequestKeyElement transferRequestInput2 = - TransferRequestKeyElement({ - from: ADDRESS1, - to: ADDRESS2, - value: value2 - }); - - TransferRequestKeyElement transferRequestInput3 = - TransferRequestKeyElement({ - from: ADDRESS2, - to: ADDRESS1, - value: value3 - }); - - TransferRequestKeyElement transferRequestInput4 = - TransferRequestKeyElement({ - from: ADDRESS1, - to: ADDRESS2, - value: value4 - }); - TransferRequestKeyElement transferRequestInput5 = - TransferRequestKeyElement({ - from: ADDRESS1, - to: ADDRESS2, - value: value5 - }); - TransferRequestKeyElement transferRequestInput = - TransferRequestKeyElement({ - from: ADDRESS1, - to: ADDRESS2, - value: defaultValue - }); - - // Arrange - function setUp() public { - TIME_LIMIT memory timeLimit_ = TIME_LIMIT({ - timeLimitToApprove: 3 days, - timeLimitToTransfer: 30 days - }); - - AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ - isActivate: false, - timeLimitBeforeAutomaticApproval: 0 - }); - - ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval: false, - authorizedBurnWithoutApproval: false - }); - AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate: false, - cmtat: IERC20(address(0)) - }); - - OPTION memory options = OPTION({ - issuance: issuanceOption_, - timeLimit: timeLimit_, - automaticApproval: automaticApproval_, - automaticTransfer: automaticTransfer_ - }); - ruleEngineMock = new RuleEngine( - RULE_ENGINE_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ZERO_ADDRESS - ); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer = new RuleConditionalTransfer( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer.grantRole( - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS - ); - } - - function _createTransferRequest() internal { - vm.prank(ADDRESS1); - // Act - vm.expectEmit(true, true, true, true); - emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); - - // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer - .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); - assertEq(transferRequest.key, defaultKey); - assertEq(transferRequest.id, 0); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, defaultValue); - assertEq(uint256(transferRequest.status), uint256(STATUS.WAIT)); - - TransferRequest[] memory transferRequests = ruleConditionalTransfer - .getRequestByStatus(STATUS.WAIT); - assertEq(transferRequests[0].key, defaultKey); - assertEq(transferRequests.length, 1); - } - - function _createTransferRequestBatch() public { - // Arrange - _createTransferRequest(); - - // Second and third request - vm.prank(ADDRESS1); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, value2); - vm.prank(ADDRESS2); - ruleConditionalTransfer.createTransferRequest(ADDRESS1, value3); - //Fourth request => will be not validated - vm.prank(ADDRESS1); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, value4); - //fifth request => will not be treated - vm.prank(ADDRESS1); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, value5); - } - - function _checkRequestPartial() internal view { - TransferRequest memory transferRequest = ruleConditionalTransfer - .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); - assertEq(transferRequest.key, defaultKey); - assertEq(transferRequest.id, 0); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, defaultValue); - assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED)); - - // 2 - transferRequest = ruleConditionalTransfer.getRequestTrade( - ADDRESS1, - ADDRESS2, - value2 - ); - assertEq(transferRequest.key, key2); - assertEq(transferRequest.id, 1); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, value2); - assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED)); - - // 3 - transferRequest = ruleConditionalTransfer.getRequestTrade( - ADDRESS2, - ADDRESS1, - value3 - ); - assertEq(transferRequest.key, key3); - assertEq(transferRequest.id, 2); - assertEq(transferRequest.keyElement.from, ADDRESS2); - assertEq(transferRequest.keyElement.to, ADDRESS1); - assertEq(transferRequest.keyElement.value, value3); - assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED)); - - // 4 - transferRequest = ruleConditionalTransfer.getRequestTrade( - ADDRESS1, - ADDRESS2, - value4 - ); - assertEq(transferRequest.key, key4); - assertEq(transferRequest.id, 3); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, value4); - assertEq(uint256(transferRequest.status), uint256(STATUS.DENIED)); - } - - function _checkRequestBatch() internal view { - _checkRequestPartial(); - - // 5 - TransferRequest memory transferRequest = ruleConditionalTransfer - .getRequestTrade(ADDRESS1, ADDRESS2, value5); - assertEq(transferRequest.key, key5); - assertEq(transferRequest.id, 4); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, value5); - assertEq(uint256(transferRequest.status), uint256(STATUS.WAIT)); - } - - function testCanCreateTransferRequest() public { - _createTransferRequest(); - } - - /** - * @dev test first - */ - function testCanCreateTransferRequestWithApproval() public { - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - // Act - vm.expectEmit(true, true, true, true); - emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequestWithApproval( - transferRequestInput - ); - } - - function testCanCreateTransferRequestWithApprovalBatch() public { - // Arrange - TransferRequestKeyElement[] - memory transferRequestKeyElements = new TransferRequestKeyElement[]( - 4 - ); - transferRequestKeyElements[0] = transferRequestInput; - transferRequestKeyElements[1] = transferRequestInput2; - transferRequestKeyElements[2] = transferRequestInput3; - transferRequestKeyElements[3] = transferRequestInput4; - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - vm.expectEmit(true, true, true, true); - emit transferApproved(key2, ADDRESS1, ADDRESS2, value2, 1); - vm.expectEmit(true, true, true, true); - emit transferApproved(key3, ADDRESS2, ADDRESS1, value3, 2); - vm.expectEmit(true, true, true, true); - emit transferApproved(key4, ADDRESS1, ADDRESS2, value4, 3); - ruleConditionalTransfer.createTransferRequestWithApprovalBatch( - transferRequestKeyElements - ); - } - - function testCanCreateTransferRequestWithApprovalBatchWithEmptyArray() - public - { - // Arrange - TransferRequestKeyElement[] - memory transferRequestKeyElements = new TransferRequestKeyElement[]( - 0 - ); - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector); - ruleConditionalTransfer.createTransferRequestWithApprovalBatch( - transferRequestKeyElements - ); - } - - /** - * @dev test overwrite branch, previous approval - */ - function testCanCreateTransferRequestWithApprovalAgain() public { - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - // Arrange - bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); - vm.expectEmit(true, true, true, true); - emit transferApproved(key, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequestWithApproval( - transferRequestInput - ); - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferApproved(key, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequestWithApproval( - transferRequestInput - ); - } - - /**** Request approval ****** */ - function testCanHolderCreateRequestBatch() public { - // Arrange - uint256[] memory values = new uint256[](3); - values[0] = defaultValue; - values[1] = value2; - values[2] = value4; - address[] memory addresses = new address[](3); - addresses[0] = ADDRESS2; - addresses[1] = ADDRESS2; - addresses[2] = ADDRESS2; - - // Act - vm.prank(ADDRESS1); - vm.expectEmit(true, true, true, true); - emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - vm.expectEmit(true, true, true, true); - emit transferWaiting(key2, ADDRESS1, ADDRESS2, value2, 1); - vm.expectEmit(true, true, true, true); - emit transferWaiting(key4, ADDRESS1, ADDRESS2, value4, 2); - ruleConditionalTransfer.createTransferRequestBatch(addresses, values); - } - - function testCannotHolderCreateRequestBatchEmptyArray() public { - // Arrange - uint256[] memory values = new uint256[](0); - address[] memory addresses = new address[](0); - - // Act - vm.prank(ADDRESS1); - vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector); - ruleConditionalTransfer.createTransferRequestBatch(addresses, values); - } - - function testCannotHolderCreateRequestBatchIfLEngthMismatch() public { - // Arrange - uint256[] memory values = new uint256[](3); - address[] memory addresses = new address[](1); - - // Act - vm.prank(ADDRESS1); - vm.expectRevert(RuleConditionalTransfer_InvalidLengthArray.selector); - ruleConditionalTransfer.createTransferRequestBatch(addresses, values); - } - - function testCanApproveRequestCreatedByHolder() public { - // Arrange - _createTransferRequest(); - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - true - ); - } - - function testCanPartiallyApproveRequestCreatedByHolder() public { - // Arrange - _createTransferRequest(); - uint256 partialValue = 5; - bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, partialValue)); - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - emit transferWaiting(key, ADDRESS1, ADDRESS2, partialValue, 1); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - partialValue, - true - ); - } - - function testCannotPartiallyDeniedRequestCreatedByHolder() public { - // Arrange - _createTransferRequest(); - uint256 partialValue = 5; - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_CannotDeniedPartially.selector); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - partialValue, - false - ); - } - - function testCannotPartiallyApprovedRequestCreatedByHolderIfPartialValueIsBiggerThanValue() - public - { - // Arrange - _createTransferRequest(); - uint256 partialValue = 5000; - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_InvalidValueApproved.selector); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - partialValue, - false - ); - } - - function testCanCreateAndApproveRequestCreatedByHolderAgain() public { - // Arrange - // First request - _createTransferRequest(); - - // First approval - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - true - ); - - // Second request - vm.prank(ADDRESS1); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); - - // Second approval - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - true - ); - - // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer - .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); - assertEq(transferRequest.key, defaultKey); - assertEq(transferRequest.id, 0); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, defaultValue); - assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED)); - } - - /*** Batch */ - function testCanCreateAndApproveRequestCreatedByHolderInBatch() public { - // Arrange - _createTransferRequestBatch(); - uint256[] memory partialValues = new uint256[](4); - partialValues[0] = 0; - partialValues[1] = 0; - partialValues[2] = 0; - partialValues[3] = 0; - bool[] memory isApproveds = new bool[](4); - isApproveds[0] = true; - isApproveds[1] = true; - isApproveds[2] = true; - isApproveds[3] = false; - - TransferRequestKeyElement[] - memory transferRequestKeyElements = new TransferRequestKeyElement[]( - 4 - ); - transferRequestKeyElements[0] = transferRequestInput; - transferRequestKeyElements[1] = transferRequestInput2; - transferRequestKeyElements[2] = transferRequestInput3; - transferRequestKeyElements[3] = transferRequestInput4; - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - vm.expectEmit(true, true, true, true); - emit transferApproved(key2, ADDRESS1, ADDRESS2, value2, 1); - vm.expectEmit(true, true, true, true); - emit transferApproved(key3, ADDRESS2, ADDRESS1, value3, 2); - vm.expectEmit(true, true, true, true); - emit transferDenied(key4, ADDRESS1, ADDRESS2, value4, 3); - ruleConditionalTransfer.approveTransferRequestBatch( - transferRequestKeyElements, - partialValues, - isApproveds - ); - - // Assert - _checkRequestBatch(); - } - - function testCannotCreateAndApproveRequestCreatedByHolderInBatchWithLenghtMismatch() - public - { - // Arrange - uint256[] memory partialValues = new uint256[](4); - // Lenght mismatch - bool[] memory isApproveds = new bool[](3); - - TransferRequestKeyElement[] - memory transferRequestKeyElements = new TransferRequestKeyElement[]( - 4 - ); - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_InvalidLengthArray.selector); - ruleConditionalTransfer.approveTransferRequestBatch( - transferRequestKeyElements, - partialValues, - isApproveds - ); - - // Act - uint256[] memory partialValuesV2 = new uint256[](1); - partialValuesV2[0] = 0; - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_InvalidLengthArray.selector); - ruleConditionalTransfer.approveTransferRequestBatch( - transferRequestKeyElements, - partialValuesV2, - isApproveds - ); - - // Act - uint256[] memory partialValuesV3 = new uint256[](4); - // Lenght mismatch - bool[] memory isApprovedsV3 = new bool[](4); - TransferRequestKeyElement[] - memory transferRequestKeyElementsV3 = new TransferRequestKeyElement[]( - 2 - ); - transferRequestKeyElementsV3[0] = transferRequestInput; - transferRequestKeyElementsV3[1] = transferRequestInput2; - vm.expectRevert(RuleConditionalTransfer_InvalidLengthArray.selector); - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.approveTransferRequestBatch( - transferRequestKeyElementsV3, - partialValuesV3, - isApprovedsV3 - ); - } - - function testCannotCreateAndApproveRequestCreatedByHolderInBatchWithEmptyArry() - public - { - // Arrange - uint256[] memory partialValues = new uint256[](0); - // Lenght mismatch - bool[] memory isApproveds = new bool[](0); - - TransferRequestKeyElement[] - memory transferRequestKeyElements = new TransferRequestKeyElement[]( - 0 - ); - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector); - ruleConditionalTransfer.approveTransferRequestBatch( - transferRequestKeyElements, - partialValues, - isApproveds - ); - } - - function testCanCreateAndApproveRequestCreatedByHolderInBatchWithPartialValues() - public - { - // Arrange - _createTransferRequestBatch(); - uint256[] memory partialValues = new uint256[](5); - partialValues[0] = 0; - partialValues[1] = 0; - partialValues[2] = 0; - partialValues[3] = 0; - // partial value - partialValues[4] = 500; - bytes32 key5PartialValue = keccak256( - abi.encode(ADDRESS1, ADDRESS2, partialValues[4]) - ); - bool[] memory isApproveds = new bool[](5); - isApproveds[0] = true; - isApproveds[1] = true; - isApproveds[2] = true; - isApproveds[3] = false; - isApproveds[4] = true; - - TransferRequestKeyElement[] - memory transferRequestKeyElements = new TransferRequestKeyElement[]( - 5 - ); - transferRequestKeyElements[0] = transferRequestInput; - transferRequestKeyElements[1] = transferRequestInput2; - transferRequestKeyElements[2] = transferRequestInput3; - transferRequestKeyElements[3] = transferRequestInput4; - transferRequestKeyElements[4] = transferRequestInput5; - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - vm.expectEmit(true, true, true, true); - emit transferApproved(key2, ADDRESS1, ADDRESS2, value2, 1); - vm.expectEmit(true, true, true, true); - emit transferApproved(key3, ADDRESS2, ADDRESS1, value3, 2); - vm.expectEmit(true, true, true, true); - emit transferDenied(key4, ADDRESS1, ADDRESS2, value4, 3); - //partial value - vm.expectEmit(true, true, true, true); - emit transferDenied(key5, ADDRESS1, ADDRESS2, value5, 4); - vm.expectEmit(true, true, true, true); - emit transferApproved( - key5PartialValue, - ADDRESS1, - ADDRESS2, - partialValues[4], - 5 - ); - ruleConditionalTransfer.approveTransferRequestBatch( - transferRequestKeyElements, - partialValues, - isApproveds - ); - - // Assert - - _checkRequestPartial(); - // 5 - TransferRequest memory transferRequest = ruleConditionalTransfer - .getRequestTrade(ADDRESS1, ADDRESS2, value5); - assertEq(transferRequest.key, key5); - assertEq(transferRequest.id, 4); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, value5); - assertEq(uint256(transferRequest.status), uint256(STATUS.DENIED)); - // new request - transferRequest = ruleConditionalTransfer.getRequestTrade( - ADDRESS1, - ADDRESS2, - partialValues[4] - ); - assertEq(transferRequest.key, key5PartialValue); - assertEq(transferRequest.id, 5); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, partialValues[4]); - assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED)); - } - - /****** ID *******/ - function testCanApproveRequestCreatedByHolderWithId() public { - // Arrange - _createTransferRequest(); - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequestWithId(0, true); - - // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer - .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); - assertEq(transferRequest.key, defaultKey); - assertEq(transferRequest.id, 0); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, defaultValue); - assertEq(uint256(transferRequest.status), uint256(STATUS.APPROVED)); - } - - /***** Batch */ - - function testCanApproveRequestInBatchCreatedByHolderWithId() public { - _createTransferRequestBatch(); - uint256[] memory ids = new uint256[](4); - ids[0] = 0; - ids[1] = 1; - ids[2] = 2; - ids[3] = 3; - bool[] memory isApproveds = new bool[](4); - isApproveds[0] = true; - isApproveds[1] = true; - isApproveds[2] = true; - isApproveds[3] = false; - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - vm.expectEmit(true, true, true, true); - emit transferApproved(key2, ADDRESS1, ADDRESS2, value2, 1); - vm.expectEmit(true, true, true, true); - emit transferApproved(key3, ADDRESS2, ADDRESS1, value3, 2); - vm.expectEmit(true, true, true, true); - emit transferDenied(key4, ADDRESS1, ADDRESS2, value4, 3); - ruleConditionalTransfer.approveTransferRequestBatchWithId( - ids, - isApproveds - ); - - // Assert - _checkRequestBatch(); - } - - function testCannotApproveRequestInBatchCreatedByHolderWithIdWithinvalidLength() - public - { - _createTransferRequestBatch(); - uint256[] memory ids = new uint256[](4); - // Wrong length here - bool[] memory isApproveds = new bool[](3); - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_InvalidLengthArray.selector); - ruleConditionalTransfer.approveTransferRequestBatchWithId( - ids, - isApproveds - ); - } - - function testCannotApproveRequestInBatchCreatedByHolderWithIdWithEmptyArray() - public - { - _createTransferRequestBatch(); - uint256[] memory ids = new uint256[](0); - // Wrong length here - bool[] memory isApproveds = new bool[](0); - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector); - ruleConditionalTransfer.approveTransferRequestBatchWithId( - ids, - isApproveds - ); - } - - function testCannotApproveRequestInBatchCreatedByHolderWithWrongId() - public - { - _createTransferRequestBatch(); - uint256[] memory ids = new uint256[](4); - ids[0] = 0; - ids[1] = 1; - ////// Wrong id here !!! - ids[2] = 6; - ids[3] = 3; - bool[] memory isApproveds = new bool[](4); - isApproveds[0] = true; - isApproveds[1] = true; - isApproveds[2] = true; - isApproveds[3] = false; - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_InvalidId.selector); - ruleConditionalTransfer.approveTransferRequestBatchWithId( - ids, - isApproveds - ); - } - - function testCannotApproveRequestInBatchCreatedByHolderIfTimeExceed() - public - { - _createTransferRequestBatch(); - // Jump - vm.warp(block.timestamp + 604801); - uint256[] memory ids = new uint256[](4); - ids[0] = 0; - ids[1] = 1; - ids[2] = 2; - ids[3] = 3; - bool[] memory isApproveds = new bool[](4); - isApproveds[0] = true; - isApproveds[1] = true; - isApproveds[2] = true; - isApproveds[3] = false; - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_timeExceeded.selector); - ruleConditionalTransfer.approveTransferRequestBatchWithId( - ids, - isApproveds - ); - } - - function testCannotApproveOrDeniedRequestCreatedByHolderWithWrongId() - public - { - // Arrange - _createTransferRequest(); - - // Act - // Approve - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_InvalidId.selector); - ruleConditionalTransfer.approveTransferRequestWithId(1, true); - // Denied - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_InvalidId.selector); - ruleConditionalTransfer.approveTransferRequestWithId(1, false); - } - - function testCanDeniedRequestCreatedByHolderWithId() public { - // Arrange - _createTransferRequest(); - // can still approve - vm.warp(block.timestamp + 1); - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequestWithId(0, false); - - // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer - .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); - assertEq(transferRequest.key, defaultKey); - assertEq(transferRequest.id, 0); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, defaultValue); - assertEq(uint256(transferRequest.status), uint256(STATUS.DENIED)); - } - - /***** with key ******/ - function testCanDeniedRequestCreatedByHolder() public { - // Arrange - _createTransferRequest(); - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - false - ); - - // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer - .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); - assertEq(transferRequest.key, defaultKey); - assertEq(transferRequest.id, 0); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, defaultValue); - assertEq(uint256(transferRequest.status), uint256(STATUS.DENIED)); - - TransferRequest[] memory transferRequests = ruleConditionalTransfer - .getRequestByStatus(STATUS.DENIED); - assertEq(transferRequests[0].key, defaultKey); - assertEq(transferRequests.length, 1); - } - - function testCannotHolderCreateRequestIfDenied() public { - // Arrange - _createTransferRequest(); - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - false - ); - - // Act - vm.prank(ADDRESS1); - vm.expectRevert(RuleConditionalTransfer_TransferDenied.selector); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); - } - - /****** Getter *****/ - function testCanReturnTradeByStatus() public { - // Arrange - // First request - _createTransferRequest(); - - // Change the status request to APPROVE - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - false - ); - - // Second request - uint256 value = 100; - vm.prank(ADDRESS1); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, value); - - // Act - TransferRequest[] memory transferRequest = ruleConditionalTransfer - .getRequestByStatus(STATUS.WAIT); - // Assert - assertEq(transferRequest.length, 1); - bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, value)); - assertEq(transferRequest[0].key, key); - assertEq(transferRequest[0].id, 1); - assertEq(transferRequest[0].keyElement.from, ADDRESS1); - assertEq(transferRequest[0].keyElement.to, ADDRESS2); - assertEq(transferRequest[0].keyElement.value, value); - assertEq(uint256(transferRequest[0].status), uint256(STATUS.WAIT)); - - // third request - uint256 valueThird = 200; - vm.prank(ADDRESS1); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, valueThird); - - // Act - transferRequest = ruleConditionalTransfer.getRequestByStatus( - STATUS.WAIT - ); - // Assert - assertEq(transferRequest.length, 2); - bytes32 keyThird = keccak256( - abi.encode(ADDRESS1, ADDRESS2, valueThird) - ); - assertEq(transferRequest[1].key, keyThird); - assertEq(transferRequest[1].id, 2); - assertEq(transferRequest[1].keyElement.from, ADDRESS1); - assertEq(transferRequest[1].keyElement.to, ADDRESS2); - assertEq(transferRequest[1].keyElement.value, valueThird); - assertEq(uint256(transferRequest[1].status), uint256(STATUS.WAIT)); - } - - function testCannotApproveRequestIfTimeExceeded() public { - // Arrange - _createTransferRequest(); - - // Timeout - // 7 days *24*60*60 = 604800 seconds - vm.warp(block.timestamp + 604801); - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_timeExceeded.selector); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - true - ); - } - - /*** Edge case ******/ - - function testCannotApproveRequestIfWrongStatus() public { - // Arrange - // No create request - - // Timeout - // 7 days *24*60*60 = 604800 seconds - vm.warp(block.timestamp + 604801); - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_Wrong_Status.selector); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - true - ); - } - - function testCanSetTimeLimitWithTransferApprovalExceeded() public { - TIME_LIMIT memory timeLimit_ = TIME_LIMIT({ - timeLimitToApprove: 1 days, - timeLimitToTransfer: 1 days - }); - // Arrange - _createTransferRequest(); - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.setTimeLimit(timeLimit_); - - // Assert - // Timeout - // >1 days - vm.warp(block.timestamp + 1 days + 1 seconds); - - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_timeExceeded.selector); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - true - ); - } -} diff --git a/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol deleted file mode 100644 index 2c4b93c..0000000 --- a/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol +++ /dev/null @@ -1,246 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../HelperContract.sol"; -import "./utils/RuleCTDeployment.sol"; - -/** - * @title Tests on the Access Control - */ -contract RuleConditionalTransferAccessControl is Test, HelperContract { - // Custom error openZeppelin - error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); - uint256 defaultValue = 10; - bytes32 defaultKey = - keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); - - TransferRequestKeyElement transferRequestInput = - TransferRequestKeyElement({ - from: ADDRESS1, - to: ADDRESS2, - value: defaultValue - }); - RuleCTDeployment ruleCTDeployment; - - // Arrange - function setUp() public { - ruleCTDeployment = new RuleCTDeployment(); - ruleEngineMock = ruleCTDeployment.ruleEngineMock(); - ruleConditionalTransfer = ruleCTDeployment.ruleConditionalTransfer(); - } - - function _createTransferRequest() internal { - vm.prank(ADDRESS1); - // Act - vm.expectEmit(true, true, true, true); - emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); - } - - function testCannotAttackerApproveARequestCreatedByTokenHolder() public { - _createTransferRequest(); - - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE - ) - ); - vm.prank(ATTACKER); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - true - ); - } - - function testCannotAttackerApproveWithIdARequestCreatedByTokenHolder() - public - { - _createTransferRequest(); - - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE - ) - ); - vm.prank(ATTACKER); - ruleConditionalTransfer.approveTransferRequestWithId(0, true); - } - - function testCannotAttackerResetARequest() public { - _createTransferRequest(); - - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE - ) - ); - vm.prank(ATTACKER); - ruleConditionalTransfer.resetRequestStatus(0); - } - - function testCannotAttackerCreateTransferRequestWithApproval() public { - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE - ) - ); - vm.prank(ATTACKER); - ruleConditionalTransfer.createTransferRequestWithApproval( - transferRequestInput - ); - } - - /*** Batch */ - - function testCannotAttackerApproveBatchWithIdARequestCreatedByTokenHolder() - public - { - _createTransferRequest(); - uint256[] memory ids = new uint256[](1); - ids[0] = 0; - bool[] memory isApproveds = new bool[](1); - isApproveds[0] = true; - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE - ) - ); - vm.prank(ATTACKER); - ruleConditionalTransfer.approveTransferRequestBatchWithId( - ids, - isApproveds - ); - } - - function testCannotAttackerApproveBatchRequestCreatedByTokenHolder() - public - { - TransferRequestKeyElement[] - memory keyElements = new TransferRequestKeyElement[](0); - uint256[] memory partialValues = new uint256[](0); - bool[] memory boolIsApproved = new bool[](0); - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE - ) - ); - vm.prank(ATTACKER); - ruleConditionalTransfer.approveTransferRequestBatch( - keyElements, - partialValues, - boolIsApproved - ); - } - - function testCannotAttackerResetBatch() public { - uint256[] memory ids = new uint256[](0); - bool[] memory boolIsApproved = new bool[](0); - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE - ) - ); - vm.prank(ATTACKER); - ruleConditionalTransfer.approveTransferRequestBatchWithId( - ids, - boolIsApproved - ); - } - - function testCannotAttackerCreateTransferRequestWithApprovalBatch() public { - TransferRequestKeyElement[] - memory keyElements = new TransferRequestKeyElement[](0); - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE - ) - ); - vm.prank(ATTACKER); - ruleConditionalTransfer.createTransferRequestWithApprovalBatch( - keyElements - ); - } - - /******** OPTIONS CONFIGURATION *********/ - function testCannotAttackerSetTimeLimit() public { - TIME_LIMIT memory timeLimit_ = TIME_LIMIT({ - timeLimitToApprove: 7 days, - timeLimitToTransfer: 200 days - }); - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE - ) - ); - vm.prank(ATTACKER); - ruleConditionalTransfer.setTimeLimit(timeLimit_); - } - - function testCannotAttackerSetAutomaticTransfer() public { - AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate: false, - cmtat: IERC20(address(0)) - }); - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE - ) - ); - vm.prank(ATTACKER); - ruleConditionalTransfer.setAutomaticTransfer(automaticTransfer_); - } - - function testCannotAttackerSetIssuanceOptions() public { - ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval: false, - authorizedBurnWithoutApproval: false - }); - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE - ) - ); - vm.prank(ATTACKER); - ruleConditionalTransfer.setIssuanceOptions(issuanceOption_); - } - - function testCannotAttackerSetAuomaticApproval() public { - AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ - isActivate: false, - timeLimitBeforeAutomaticApproval: 0 - }); - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE - ) - ); - vm.prank(ATTACKER); - ruleConditionalTransfer.setAutomaticApproval(automaticApproval_); - } -} diff --git a/test/RuleConditionalTransfer/RuleConditionalTransferDeployment.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransferDeployment.t.sol deleted file mode 100644 index 2adef6d..0000000 --- a/test/RuleConditionalTransfer/RuleConditionalTransferDeployment.t.sol +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../HelperContract.sol"; -import "./utils/RuleCTDeployment.sol"; - -/** - * @title General functions of the RuleWhitelist - */ -contract RuleConditionalTransferDeploymentTest is Test, HelperContract { - RuleCTDeployment ruleCTDeployment; - - // Arrange - function setUp() public {} - - function testSetMaxLimitIfZeroForAutomaticApprovalAndAutomaticTransfer() - public - { - TIME_LIMIT memory timeLimit_ = TIME_LIMIT({ - timeLimitToApprove: 7 days, - timeLimitToTransfer: 30 days - }); - - AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ - isActivate: false, - timeLimitBeforeAutomaticApproval: 0 - }); - - ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval: false, - authorizedBurnWithoutApproval: false - }); - AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate: false, - cmtat: IERC20(address(0)) - }); - - OPTION memory options = OPTION({ - issuance: issuanceOption_, - timeLimit: timeLimit_, - automaticApproval: automaticApproval_, - automaticTransfer: automaticTransfer_ - }); - ruleEngineMock = new RuleEngine( - RULE_ENGINE_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ZERO_ADDRESS - ); - // Test 1 - vm.prank(DEFAULT_ADMIN_ADDRESS); - vm.expectRevert( - abi.encodeWithSelector( - RuleConditionalTransfer_AdminWithAddressZeroNotAllowed.selector - ) - ); - ruleConditionalTransfer = new RuleConditionalTransfer( - ZERO_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - - // Test 2 - ruleCTDeployment = new RuleCTDeployment(); - ruleConditionalTransfer = ruleCTDeployment.ruleConditionalTransfer(); - ISSUANCE memory issuance; - TIME_LIMIT memory timeLimit; - AUTOMATIC_APPROVAL memory automaticApproval; - AUTOMATIC_TRANSFER memory automaticTransfer; - ( - issuance, - timeLimit, - automaticApproval, - automaticTransfer - ) = ruleConditionalTransfer.options(); - assertEq(timeLimit.timeLimitToApprove, 7 days); - assertEq(timeLimit.timeLimitToTransfer, 30 days); - } -} diff --git a/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol deleted file mode 100644 index d6cb62a..0000000 --- a/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol +++ /dev/null @@ -1,440 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../HelperContract.sol"; -import "OZ/token/ERC20/IERC20.sol"; -/** - * @title General functions of the RuleWhitelist - */ -contract RuleConditionalTransferResetTest is Test, HelperContract { - uint256 defaultValue = 10; - bytes32 defaultKey = - keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); - - TransferRequestKeyElement transferRequestInput = - TransferRequestKeyElement({ - from: ADDRESS1, - to: ADDRESS2, - value: defaultValue - }); - - uint256 value2 = 1; - uint256 value3 = 2; - uint256 value4 = 1000; - uint256 value5 = 2000; - bytes32 key2 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value2)); - bytes32 key3 = keccak256(abi.encode(ADDRESS2, ADDRESS1, value3)); - bytes32 key3Hodler = keccak256(abi.encode(ADDRESS1, ADDRESS2, value3)); - bytes32 key4 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value4)); - bytes32 key5 = keccak256(abi.encode(ADDRESS1, ADDRESS2, value5)); - - TransferRequestKeyElement transferRequestInput2 = - TransferRequestKeyElement({ - from: ADDRESS1, - to: ADDRESS2, - value: value2 - }); - - TransferRequestKeyElement transferRequestInput3 = - TransferRequestKeyElement({ - from: ADDRESS2, - to: ADDRESS1, - value: value3 - }); - - // Arrange - function setUp() public { - TIME_LIMIT memory timeLimit_ = TIME_LIMIT({ - timeLimitToApprove: 7 days, - timeLimitToTransfer: 30 days - }); - - AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ - isActivate: false, - timeLimitBeforeAutomaticApproval: 0 - }); - - ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval: false, - authorizedBurnWithoutApproval: false - }); - AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate: false, - cmtat: IERC20(address(0)) - }); - - OPTION memory options = OPTION({ - issuance: issuanceOption_, - timeLimit: timeLimit_, - automaticApproval: automaticApproval_, - automaticTransfer: automaticTransfer_ - }); - ruleEngineMock = new RuleEngine( - RULE_ENGINE_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ZERO_ADDRESS - ); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer = new RuleConditionalTransfer( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer.grantRole( - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS - ); - } - - function _createTransferRequestBatch() public { - // Arrange - _createTransferRequest(); - - // Second and third request - vm.prank(ADDRESS1); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, value2); - vm.prank(ADDRESS2); - ruleConditionalTransfer.createTransferRequest(ADDRESS1, value3); - } - - function _createTransferRequestBatchByHodler() public { - // Arrange - _createTransferRequest(); - - // Second and third request - vm.prank(ADDRESS1); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, value2); - vm.prank(ADDRESS1); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, value3); - } - - function _createTransferRequest() internal { - vm.prank(ADDRESS1); - // Act - vm.expectEmit(true, true, true, true); - emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); - - // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer - .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); - assertEq(transferRequest.key, defaultKey); - assertEq(transferRequest.id, 0); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, defaultValue); - assertEq(uint256(transferRequest.status), uint256(STATUS.WAIT)); - - TransferRequest[] memory transferRequests = ruleConditionalTransfer - .getRequestByStatus(STATUS.WAIT); - assertEq(transferRequests[0].key, defaultKey); - assertEq(transferRequests.length, 1); - } - - /***** Reset ********/ - - function testHolderCanResetHisRequest() public { - // Arrange - _createTransferRequest(); - - // Act - // Reset - vm.prank(ADDRESS1); - vm.expectEmit(true, true, true, true); - emit transferReset(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.cancelTransferRequest(0); - - // Arrange - // Second request with approval - vm.prank(ADDRESS1); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - true - ); - - // Reset - vm.prank(ADDRESS1); - vm.expectEmit(true, true, true, true); - emit transferReset(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.cancelTransferRequest(0); - - // Can create a new request - // Id different from 0 - vm.prank(ADDRESS1); - // Act - vm.expectEmit(true, true, true, true); - emit transferWaiting(key2, ADDRESS1, ADDRESS2, value2, 1); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, value2); - - // Can be cancel again - vm.prank(ADDRESS1); - vm.expectEmit(true, true, true, true); - emit transferReset(key2, ADDRESS1, ADDRESS2, value2, 1); - ruleConditionalTransfer.cancelTransferRequest(1); - } - - function testHolderCanBatchResetHisRequest() public { - // Arrange - _createTransferRequestBatchByHodler(); - uint256[] memory ids = new uint256[](3); - ids[0] = 0; - ids[1] = 1; - ids[2] = 2; - // Act - // Reset - vm.prank(ADDRESS1); - vm.expectEmit(true, true, true, true); - emit transferReset(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - vm.expectEmit(true, true, true, true); - emit transferReset(key2, ADDRESS1, ADDRESS2, value2, 1); - vm.expectEmit(true, true, true, true); - emit transferReset(key3Hodler, ADDRESS1, ADDRESS2, value3, 2); - ruleConditionalTransfer.cancelTransferRequestBatch(ids); - } - - function testHolderCannotBatchResetHisRequestWithWrongId() public { - // Arrange - _createTransferRequestBatchByHodler(); - uint256[] memory ids = new uint256[](3); - ids[0] = 0; - ids[1] = 4; - ids[2] = 2; - // Act - // Reset - vm.prank(ADDRESS1); - vm.expectRevert(RuleConditionalTransfer_InvalidId.selector); - ruleConditionalTransfer.cancelTransferRequestBatch(ids); - } - - function testHolderCannotBatchResetHisRequestWithEmptyArray() public { - // Arrange - _createTransferRequestBatchByHodler(); - uint256[] memory ids = new uint256[](0); - // Act - // Reset - vm.prank(ADDRESS1); - vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector); - ruleConditionalTransfer.cancelTransferRequestBatch(ids); - } - - function testHolderCannotResetRequestCreatedByOther() public { - // Arrange - _createTransferRequest(); - - // Act - // Reset - vm.prank(ADDRESS2); - vm.expectRevert(RuleConditionalTransfer_InvalidSender.selector); - ruleConditionalTransfer.cancelTransferRequest(0); - } - - function testCannotHolderResetRequestWithWrongId() public { - // Arrange - _createTransferRequest(); - - // Act - // Reset - vm.prank(ADDRESS1); - vm.expectRevert(RuleConditionalTransfer_InvalidId.selector); - ruleConditionalTransfer.cancelTransferRequest(1); - } - - function testCannotHolderResetRequestWithWrongStatus() public { - // Arrange - _createTransferRequest(); - - // Denied - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - false - ); - - // Act - // Reset - vm.prank(ADDRESS1); - vm.expectRevert(RuleConditionalTransfer_Wrong_Status.selector); - ruleConditionalTransfer.cancelTransferRequest(0); - } - - /***** Reset */ - - function testCanResetADeniedRequestCreatedByHolder() public { - // Arrange - _createTransferRequest(); - - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - false - ); - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferReset(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.resetRequestStatus(0); - - // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer - .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); - assertEq(transferRequest.key, defaultKey); - assertEq(transferRequest.id, 0); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, defaultValue); - assertEq(uint256(transferRequest.status), uint256(STATUS.NONE)); - - // Assert - vm.prank(ADDRESS1); - // Act - vm.expectEmit(true, true, true, true); - emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); - - // Assert - transferRequest = ruleConditionalTransfer.getRequestTrade( - ADDRESS1, - ADDRESS2, - defaultValue - ); - assertEq(transferRequest.key, defaultKey); - assertEq(transferRequest.id, 0); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, defaultValue); - assertEq(uint256(transferRequest.status), uint256(STATUS.WAIT)); - - // Id different from 0 - vm.prank(ADDRESS1); - // Act - vm.expectEmit(true, true, true, true); - emit transferWaiting(key2, ADDRESS1, ADDRESS2, value2, 1); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, value2); - } - - function testCanBatchResetADeniedRequestCreatedByHolder() public { - // Arrange - _createTransferRequestBatchByHodler(); - uint256[] memory ids = new uint256[](3); - ids[0] = 0; - ids[1] = 1; - ids[2] = 2; - - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - false - ); - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferReset(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - vm.expectEmit(true, true, true, true); - emit transferReset(key2, ADDRESS1, ADDRESS2, value2, 1); - vm.expectEmit(true, true, true, true); - emit transferReset(key3Hodler, ADDRESS1, ADDRESS2, value3, 2); - ruleConditionalTransfer.resetRequestStatusBatch(ids); - - // Assert - TransferRequest memory transferRequest = ruleConditionalTransfer - .getRequestTrade(ADDRESS1, ADDRESS2, defaultValue); - assertEq(transferRequest.key, defaultKey); - assertEq(transferRequest.id, 0); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, defaultValue); - assertEq(uint256(transferRequest.status), uint256(STATUS.NONE)); - - transferRequest = ruleConditionalTransfer.getRequestTrade( - ADDRESS1, - ADDRESS2, - value2 - ); - assertEq(transferRequest.key, key2); - assertEq(transferRequest.id, 1); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, value2); - assertEq(uint256(transferRequest.status), uint256(STATUS.NONE)); - - transferRequest = ruleConditionalTransfer.getRequestTrade( - ADDRESS1, - ADDRESS2, - value3 - ); - assertEq(transferRequest.key, key3Hodler); - assertEq(transferRequest.id, 2); - assertEq(transferRequest.keyElement.from, ADDRESS1); - assertEq(transferRequest.keyElement.to, ADDRESS2); - assertEq(transferRequest.keyElement.value, value3); - assertEq(uint256(transferRequest.status), uint256(STATUS.NONE)); - } - - function testCannotBatchResetADeniedRequestCreatedByHolderWithWrongId() - public - { - // Arrange - _createTransferRequestBatchByHodler(); - uint256[] memory ids = new uint256[](3); - ids[0] = 3; - ids[1] = 1; - ids[2] = 2; - - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - false - ); - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_InvalidId.selector); - ruleConditionalTransfer.resetRequestStatusBatch(ids); - } - - function testCannotBatchResetADeniedRequestCreatedByHolderWithEmptyArray() - public - { - // Arrange - _createTransferRequestBatchByHodler(); - uint256[] memory ids = new uint256[](0); - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - false - ); - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_EmptyArray.selector); - ruleConditionalTransfer.resetRequestStatusBatch(ids); - } - - function testCannotResetARequestIfWrongId() public { - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectRevert(RuleConditionalTransfer_InvalidId.selector); - ruleConditionalTransfer.resetRequestStatus(10); - } -} diff --git a/test/RuleConditionalTransfer/RuleConditionalTransferRestriction.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransferRestriction.t.sol deleted file mode 100644 index 6ccec96..0000000 --- a/test/RuleConditionalTransfer/RuleConditionalTransferRestriction.t.sol +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../HelperContract.sol"; -import "OZ/token/ERC20/IERC20.sol"; -//ADmin, forwarder irrect /RuleEngine -/** - * @title General functions of the RuleEngine - */ -contract RuleEngineOperationTest is Test, HelperContract { - uint256 defaultValue = 20; - - TIME_LIMIT timeLimit_ = - TIME_LIMIT({ - timeLimitToApprove: DEFAULT_TIME_LIMIT_TO_APPROVE, - timeLimitToTransfer: DEFAULT_TIME_LIMIT_TO_TRANSFER - }); - ISSUANCE issuanceOption_ = - ISSUANCE({ - authorizedMintWithoutApproval: false, - authorizedBurnWithoutApproval: false - }); - - AUTOMATIC_APPROVAL automaticApproval_ = - AUTOMATIC_APPROVAL({ - isActivate: false, - timeLimitBeforeAutomaticApproval: 0 - }); - AUTOMATIC_TRANSFER automaticTransfer_ = - AUTOMATIC_TRANSFER({isActivate: false, cmtat: IERC20(address(0))}); - OPTION options = - OPTION({ - issuance: issuanceOption_, - timeLimit: timeLimit_, - automaticApproval: automaticApproval_, - automaticTransfer: automaticTransfer_ - }); - - TransferRequestKeyElement transferRequestInput = - TransferRequestKeyElement({ - from: ADDRESS1, - to: ADDRESS2, - value: defaultValue - }); - - // Arrange - function setUp() public { - ruleConditionalTransfer = new RuleConditionalTransfer( - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - } - - function testCanDetectTransferRestrictionOK() public { - // Arrange - Assert - resUint8 = ruleConditionalTransfer.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - defaultValue - ); - - // Assert - assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED); - // Arrange - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); - vm.expectEmit(true, true, true, true); - emit transferApproved(key, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequestWithApproval( - transferRequestInput - ); - // Act - resUint8 = ruleConditionalTransfer.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - defaultValue - ); - - // Assert - assertEq(resUint8, 0); - } - - function testCanDetectTransferRestrictionNotOk() public { - // Act - resUint8 = ruleConditionalTransfer.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 20 - ); - - // Assert - assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED); - } - - function testMessageForTransferRestrictionWithUnknownRestrictionCode() - public - { - // Act - resString = ruleConditionalTransfer.messageForTransferRestriction(50); - - // Assert - assertEq(resString, "Unknown restriction code"); - } - - function testMessageForTransferRestrictionWithValidRC() public { - // Act - resString = ruleConditionalTransfer.messageForTransferRestriction( - CODE_TRANSFER_REQUEST_NOT_APPROVED - ); - - // Assert - assertEq(resString, TEXT_TRANSFER_REQUEST_NOT_APPROVED); - } -} diff --git a/test/RuleConditionalTransfer/utils/CMTATIntegrationShare.sol b/test/RuleConditionalTransfer/utils/CMTATIntegrationShare.sol deleted file mode 100644 index aed15f1..0000000 --- a/test/RuleConditionalTransfer/utils/CMTATIntegrationShare.sol +++ /dev/null @@ -1,482 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import {CMTATStandalone} from "CMTAT/deployment/CMTATStandalone.sol"; -import "../../HelperContract.sol"; -import "OZ/token/ERC20/IERC20.sol"; -/** - * @title Integration testShare with the CMTAT - */ -contract CMTATIntegrationShare is Test, HelperContract { - uint256 ADDRESS1_BALANCE_INIT = 31; - uint256 ADDRESS2_BALANCE_INIT = 32; - uint256 ADDRESS3_BALANCE_INIT = 33; - - uint256 FLAG = 5; - - uint256 defaultValue = 10; - bytes32 defaultKey = - keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); - - TransferRequestKeyElement transferRequestInput = - TransferRequestKeyElement({ - from: ADDRESS1, - to: ADDRESS2, - value: defaultValue - }); - - function _createTransferRequestShare() internal { - vm.prank(ADDRESS1); - // Act - vm.expectEmit(true, true, true, true); - emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); - } - - /******* Transfer *******/ - function testShareCannotTransferWithoutApproval() internal { - // Arrange - vm.prank(ADDRESS1); - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - 21 - ) - ); - // Act - CMTAT_CONTRACT.transfer(ADDRESS2, 21); - } - - function testShareCanMakeATransferIfApproved() internal { - // Arrange - Assert - // ConditionalTransfer - resUint8 = ruleConditionalTransfer.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - defaultValue - ); - // Assert - assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED); - // CMTAT - // Arrange - Assert - resUint8 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - defaultValue - ); - // Assert - assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED); - // Arrange - vm.prank(ADDRESS1); - // Act - bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferApproved(key, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - true - ); - - // Act - vm.expectEmit(true, true, true, true); - emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); - - // Assert - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); - assertEq(resUint256, ADDRESS1_BALANCE_INIT - defaultValue); - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS2); - assertEq(resUint256, ADDRESS2_BALANCE_INIT + defaultValue); - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS3); - assertEq(resUint256, 33); - } - - function testShareCanMakeAPartialTransferIfPartiallyApproved() internal { - // Arrange - _createTransferRequestShare(); - - uint256 partialValue = 5; - bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, partialValue)); - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferApproved(key, ADDRESS1, ADDRESS2, partialValue, 1); - emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - partialValue, - true - ); - - // Act - vm.expectEmit(true, true, true, true); - emit transferProcessed(key, ADDRESS1, ADDRESS2, partialValue, 1); - vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2, partialValue); - - // Assert - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); - assertEq(resUint256, ADDRESS1_BALANCE_INIT - partialValue); - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS2); - assertEq(resUint256, ADDRESS2_BALANCE_INIT + partialValue); - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS3); - assertEq(resUint256, 33); - } - - function testShareCannotMakeAWholeTransferIfPartiallyApproved() internal { - // Arrange - _createTransferRequestShare(); - uint256 partialValue = 5; - bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, partialValue)); - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferApproved(key, ADDRESS1, ADDRESS2, partialValue, 1); - emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - partialValue, - true - ); - - // Act - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - defaultValue - ) - ); - vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); - } - - function testShareCannotMakeATransferIfDelayExceeded(uint256 timeDelay) internal { - // Arrange - vm.prank(ADDRESS1); - // Act - bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue)); - ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue); - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferApproved(key, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - true - ); - - - vm.warp(block.timestamp + timeDelay); - // Act - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - defaultValue - ) - ); - vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); - } - - function testShareCannotMakeATransferIfDelayJustInTime(uint256 timeDelay) internal { - // Arrange - _createTransferRequestShare(); - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - true - ); - // 30 days - vm.warp(block.timestamp + timeDelay); - // Act - vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); - } - - function testShareCanSetTimeLimitWithTransferExceeded(uint256 timeDelay) internal { - TIME_LIMIT memory timeLimit_ = TIME_LIMIT({ - timeLimitToApprove: 1 days, - timeLimitToTransfer: 1 days - }); - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.setTimeLimit(timeLimit_); - // Arrange - _createTransferRequestShare(); - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - true - ); - - // Assert - // Timeout - // >1 days - vm.warp(block.timestamp + timeDelay); - - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - defaultValue - ) - ); - vm.prank(ADDRESS1); - CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); - } - - function testShareCanMintWithoutApproval() internal { - // Act - vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.mint(ADDRESS1, 11); - - // Assert - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); - assertEq(resUint256, ADDRESS1_BALANCE_INIT + 11); - } - - function testShareCanBurnWithoutApproval() internal { - // Act - vm.prank(DEFAULT_ADMIN_ADDRESS); - CMTAT_CONTRACT.burn(ADDRESS1, defaultValue, "testShare"); - - // Assert - resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); - assertEq(resUint256, ADDRESS1_BALANCE_INIT - defaultValue); - } - - function testShareCannotMintWithoutApproval() internal { - ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval: false, - authorizedBurnWithoutApproval: true - }); - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.setIssuanceOptions(issuanceOption_); - // Act - vm.prank(DEFAULT_ADMIN_ADDRESS); - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ZERO_ADDRESS, - ADDRESS1, - 11 - ) - ); - CMTAT_CONTRACT.mint(ADDRESS1, 11); - } - - function testShareCannotBurnWithoutApproval() internal { - ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval: true, - authorizedBurnWithoutApproval: false - }); - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.setIssuanceOptions(issuanceOption_); - // Act - vm.prank(DEFAULT_ADMIN_ADDRESS); - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ADDRESS1, - ZERO_ADDRESS, - defaultValue - ) - ); - CMTAT_CONTRACT.burn(ADDRESS1, defaultValue, "testShare"); - } - - function testShareAutomaticTransferIfOptionsSet() internal { - AUTOMATIC_TRANSFER memory automaticTransfertestShare = AUTOMATIC_TRANSFER({ - isActivate: true, - cmtat: IERC20(address(CMTAT_CONTRACT)) - }); - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.setAutomaticTransfer(automaticTransfertestShare); - - // Aproval - vm.prank(ADDRESS1); - CMTAT_CONTRACT.approve(address(ruleConditionalTransfer), defaultValue); - - // Arrange - _createTransferRequestShare(); - - // Act - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - vm.expectEmit(true, true, true, true); - emit transferApproved(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - vm.expectEmit(true, true, true, true); - emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - ruleConditionalTransfer.approveTransferRequest( - transferRequestInput, - 0, - true - ); - } - - function testShareCanTransferIfAutomaticApprovalSetAndTimeExceedsJustInTime() - internal - { - AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ - isActivate: true, - timeLimitBeforeAutomaticApproval: 90 days - }); - - resBool = ruleConditionalTransfer.canTransfer( - ADDRESS1, - ADDRESS2, - defaultValue - ); - assertFalse(resBool); - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.setAutomaticApproval(automaticApproval_); - - resBool = ruleConditionalTransfer.canTransfer( - ADDRESS1, - ADDRESS2, - defaultValue - ); - assertFalse(resBool); - // Arrange - _createTransferRequestShare(); - - resBool = ruleConditionalTransfer.canTransfer( - ADDRESS1, - ADDRESS2, - defaultValue - ); - assertFalse(resBool); - - vm.warp(block.timestamp + 90 days); - // Act - resBool = ruleConditionalTransfer.canTransfer( - ADDRESS1, - ADDRESS2, - defaultValue - ); - assertEq(resBool, true); - vm.prank(ADDRESS1); - vm.expectEmit(true, true, true, true); - emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); - } - - function testShareCanTransferIfAutomaticApprovalSetAndTimeExceeds() internal { - AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ - isActivate: true, - timeLimitBeforeAutomaticApproval: 90 days - }); - - resBool = ruleConditionalTransfer.canTransfer( - ADDRESS1, - ADDRESS2, - defaultValue - ); - assertFalse(resBool); - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.setAutomaticApproval(automaticApproval_); - - resBool = ruleConditionalTransfer.canTransfer( - ADDRESS1, - ADDRESS2, - defaultValue - ); - assertFalse(resBool); - // Arrange - _createTransferRequestShare(); - - resBool = ruleConditionalTransfer.canTransfer( - ADDRESS1, - ADDRESS2, - defaultValue - ); - assertFalse(resBool); - - vm.warp(block.timestamp + 91 days); - // Act - resBool = ruleConditionalTransfer.canTransfer( - ADDRESS1, - ADDRESS2, - defaultValue - ); - assertEq(resBool, true); - vm.prank(ADDRESS1); - vm.expectEmit(true, true, true, true); - emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0); - CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); - } - - function testShareCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds() - internal - { - AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ - isActivate: true, - timeLimitBeforeAutomaticApproval: 90 days - }); - resBool = ruleConditionalTransfer.canTransfer( - ADDRESS1, - ADDRESS2, - defaultValue - ); - assertFalse(resBool); - vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); - ruleConditionalTransfer.setAutomaticApproval(automaticApproval_); - - resBool = ruleConditionalTransfer.canTransfer( - ADDRESS1, - ADDRESS2, - defaultValue - ); - assertFalse(resBool); - // Arrange - _createTransferRequestShare(); - - resBool = ruleConditionalTransfer.canTransfer( - ADDRESS1, - ADDRESS2, - defaultValue - ); - assertFalse(resBool); - - resBool = CMTAT_CONTRACT.canTransfer( - ADDRESS1, - ADDRESS2, - defaultValue - ); - assertFalse(resBool); - // Time not exceeds - vm.warp(block.timestamp + 85 days); - // Act - vm.prank(ADDRESS1); - vm.expectRevert( - abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - defaultValue - ) - ); - CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue); - } -} diff --git a/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol b/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol deleted file mode 100644 index 25ab9b8..0000000 --- a/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "../../HelperContract.sol"; -import "OZ/token/ERC20/IERC20.sol"; -/** - * @title Tests on the Access Control - */ -contract RuleCTDeployment is Test, HelperContract { - // Arrange - constructor() { - TIME_LIMIT memory timeLimit_ = TIME_LIMIT({ - timeLimitToApprove: 7 days, - timeLimitToTransfer: 30 days - }); - - AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({ - isActivate: false, - timeLimitBeforeAutomaticApproval: 0 - }); - - ISSUANCE memory issuanceOption_ = ISSUANCE({ - authorizedMintWithoutApproval: false, - authorizedBurnWithoutApproval: false - }); - AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({ - isActivate: false, - cmtat: IERC20(address(0)) - }); - - OPTION memory options = OPTION({ - issuance: issuanceOption_, - timeLimit: timeLimit_, - automaticApproval: automaticApproval_, - automaticTransfer: automaticTransfer_ - }); - ruleEngineMock = new RuleEngine( - RULE_ENGINE_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ZERO_ADDRESS - ); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer = new RuleConditionalTransfer( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS, - ruleEngineMock, - options - ); - vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleConditionalTransfer.grantRole( - RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, - CONDITIONAL_TRANSFER_OPERATOR_ADDRESS - ); - } -} diff --git a/test/RuleWhitelist/CMTATIntegration.t.sol b/test/RuleWhitelist/CMTATIntegration.t.sol index 669cdda..13f1f34 100644 --- a/test/RuleWhitelist/CMTATIntegration.t.sol +++ b/test/RuleWhitelist/CMTATIntegration.t.sol @@ -31,7 +31,7 @@ contract CMTATIntegration is Test, HelperContract { address(CMTAT_CONTRACT) ); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelist); + ruleEngineMock.addRule(ruleWhitelist); vm.prank(DEFAULT_ADMIN_ADDRESS); CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT); vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -49,10 +49,11 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, + RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, - 21 + 21, + CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -68,10 +69,11 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, + RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, - amount + amount, + CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -87,10 +89,11 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, + RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, - amount + amount, + CODE_ADDRESS_TO_NOT_WHITELISTED ) ); // Act diff --git a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol index a06d4d7..b09d60a 100644 --- a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol +++ b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol @@ -29,11 +29,11 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { ZERO_ADDRESS ); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelistWrapper.addRuleValidation(ruleWhitelist); + ruleWhitelistWrapper.addRule(ruleWhitelist); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelistWrapper.addRuleValidation(ruleWhitelist2); + ruleWhitelistWrapper.addRule(ruleWhitelist2); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelistWrapper.addRuleValidation(ruleWhitelist3); + ruleWhitelistWrapper.addRule(ruleWhitelist3); // global arrange cmtatDeployment = new CMTATDeployment(); CMTAT_CONTRACT = cmtatDeployment.cmtat(); @@ -45,7 +45,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { address(CMTAT_CONTRACT) ); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock.addRuleValidation(ruleWhitelistWrapper); + ruleEngineMock.addRule(ruleWhitelistWrapper); vm.prank(DEFAULT_ADMIN_ADDRESS); CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT); vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -74,10 +74,11 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, + RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, - 21 + 21, + CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -93,10 +94,11 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, + RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, - amount + amount, + CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -112,10 +114,11 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleEngine_InvalidTransfer.selector, + RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, - amount + amount, + CODE_ADDRESS_TO_NOT_WHITELISTED ) ); // Act diff --git a/test/utils/CMTATDeployment.sol b/test/utils/CMTATDeployment.sol deleted file mode 100644 index 1f7d310..0000000 --- a/test/utils/CMTATDeployment.sol +++ /dev/null @@ -1,50 +0,0 @@ -//SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "OZ/access/AccessControl.sol"; -import {ICMTATConstructor, CMTATStandalone} from "CMTAT/deployment/CMTATStandalone.sol"; -import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; -import {ISnapshotEngine} from "CMTAT/interfaces/engine/ISnapshotEngine.sol"; -import {IDocumentEngine} from "CMTAT/interfaces/engine/IDocumentEngine.sol"; -import {IERC1643CMTAT} from "CMTAT/interfaces/tokenization/draft-IERC1643CMTAT.sol"; -contract CMTATDeployment { - // Share with helper contract - address constant ZERO_ADDRESS = address(0); - address constant DEFAULT_ADMIN_ADDRESS = address(1); - - CMTATStandalone public cmtat; - - constructor() { - // CMTAT - ICMTATConstructor.ERC20Attributes - memory erc20Attributes = ICMTATConstructor.ERC20Attributes( - "CMTA Token", - "CMTAT", - 0 - ); - ICMTATConstructor.ExtraInformationAttributes - memory ExtraInformationAttributes = ICMTATConstructor - .ExtraInformationAttributes( - "CMTAT_ISIN", - IERC1643CMTAT.DocumentInfo( - "Terms", - "https://cmta.ch", - 0x9ff867f6592aa9d6d039e7aad6bd71f1659720cbc4dd9eae1554f6eab490098b - ), - "CMTAT_info" - ); - ICMTATConstructor.Engine memory engines = ICMTATConstructor.Engine( - IRuleEngine(ZERO_ADDRESS), - ISnapshotEngine(ZERO_ADDRESS), - IDocumentEngine(ZERO_ADDRESS) - ); - cmtat = new CMTATStandalone( - ZERO_ADDRESS, - DEFAULT_ADMIN_ADDRESS, - erc20Attributes, - ExtraInformationAttributes, - engines - ); - } -} From cbbbdd348c26378f16e4dd3a254b7216d850e9be Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Thu, 23 Oct 2025 15:08:51 +0200 Subject: [PATCH 02/25] Update code and test --- src/rules/interfaces/IIdentityRegistry.sol | 14 ++ src/rules/interfaces/ISanctionsList.sol | 7 + src/rules/validation/RuleBlacklist.sol | 14 +- ...SanctionList.sol => RuleSanctionsList.sol} | 31 ++- src/rules/validation/RuleWhitelist.sol | 99 ++++++-- src/rules/validation/RuleWhitelistWrapper.sol | 16 +- .../RuleAddressList/RuleAddressList.sol | 176 -------------- .../RuleAddressListInternal.sol | 101 -------- .../RuleAddressListInvariantStorage.sol | 20 -- .../RuleAddressSet/RuleAddressSet.sol | 229 ++++++++++++++++++ .../RuleAddressSet/RuleAddressSetInternal.sol | 87 +++++++ .../RuleAddressSetInvariantStorage.sol | 26 ++ .../RuleBlacklistInvariantStorage.sol | 0 .../RuleWhitelistInvariantStorage.sol | 0 ... => RuleSanctionsListInvariantStorage.sol} | 6 +- .../abstract/RuleWhitelistCommon.sol | 81 +++++-- test/HelperContract.sol | 14 +- test/RuleBlacklist/CMTATIntegration.t.sol | 20 +- .../RuleSanctionListAddTest.t.sol | 20 +- .../RuleSanctionListDeploymentTest.t.sol | 18 +- .../RuleSanctionListTest.t.sol | 10 +- .../RuleWhitelistAccessControl.t.sol | 50 ++-- test/RuleWhitelist/CMTATIntegration.t.sol | 22 +- .../CMTATIntegrationWhitelistWrapper.t.sol | 34 +-- test/RuleWhitelist/RuleWhitelist.t.sol | 52 ++-- test/RuleWhitelist/RuleWhitelistAdd.t.sol | 82 +++---- .../RuleWhitelistDeployment.t.sol | 2 +- test/RuleWhitelist/RuleWhitelistRemove.t.sol | 66 ++--- test/utils/SanctionListOracle.sol | 3 +- 29 files changed, 725 insertions(+), 575 deletions(-) create mode 100644 src/rules/interfaces/IIdentityRegistry.sol create mode 100644 src/rules/interfaces/ISanctionsList.sol rename src/rules/validation/{RuleSanctionList.sol => RuleSanctionsList.sol} (87%) delete mode 100644 src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol delete mode 100644 src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol delete mode 100644 src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol create mode 100644 src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol create mode 100644 src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol create mode 100644 src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol rename src/rules/validation/abstract/{RuleAddressList => RuleAddressSet}/invariantStorage/RuleBlacklistInvariantStorage.sol (100%) rename src/rules/validation/abstract/{RuleAddressList => RuleAddressSet}/invariantStorage/RuleWhitelistInvariantStorage.sol (100%) rename src/rules/validation/abstract/{RuleSanctionListInvariantStorage.sol => RuleSanctionsListInvariantStorage.sol} (87%) diff --git a/src/rules/interfaces/IIdentityRegistry.sol b/src/rules/interfaces/IIdentityRegistry.sol new file mode 100644 index 0000000..0212538 --- /dev/null +++ b/src/rules/interfaces/IIdentityRegistry.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + + +interface IIdentityRegistryVerified { + // registry consultation + function isVerified(address _userAddress) external view returns (bool); +} + +interface IIdentityRegistryContains { + // registry consultation + function contains(address _userAddress) external view returns (bool); +} \ No newline at end of file diff --git a/src/rules/interfaces/ISanctionsList.sol b/src/rules/interfaces/ISanctionsList.sol new file mode 100644 index 0000000..2159bd0 --- /dev/null +++ b/src/rules/interfaces/ISanctionsList.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +interface ISanctionsList { + function isSanctioned(address addr) external view returns (bool); +} \ No newline at end of file diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol index 5def3ab..c596d3c 100644 --- a/src/rules/validation/RuleBlacklist.sol +++ b/src/rules/validation/RuleBlacklist.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.20; -import "./abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol"; -import "./abstract/RuleAddressList/RuleAddressList.sol"; +import "./abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol"; +import "./abstract/RuleAddressSet/RuleAddressSet.sol"; import "./abstract/RuleValidateTransfer.sol"; //import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; /** @@ -12,7 +12,7 @@ import "./abstract/RuleValidateTransfer.sol"; contract RuleBlacklist is RuleValidateTransfer, - RuleAddressList, + RuleAddressSet, RuleBlacklistInvariantStorage { @@ -23,7 +23,7 @@ contract RuleBlacklist is constructor( address admin, address forwarderIrrevocable - ) RuleAddressList(admin, forwarderIrrevocable) {} + ) RuleAddressSet(admin, forwarderIrrevocable) {} /** * @notice Check if an addres is in the whitelist or not @@ -36,9 +36,9 @@ contract RuleBlacklist is address to, uint256 /* value */ ) public view override returns (uint8) { - if (addressIsListed(from)) { + if (isAddressListed(from)) { return CODE_ADDRESS_FROM_IS_BLACKLISTED; - } else if (addressIsListed(to)) { + } else if (isAddressListed(to)) { return CODE_ADDRESS_TO_IS_BLACKLISTED; } else { return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); @@ -51,7 +51,7 @@ contract RuleBlacklist is address to, uint256 value ) public view override returns (uint8) { - if(addressIsListed(spender)){ + if(isAddressListed(spender)){ return CODE_ADDRESS_SPENDER_IS_BLACKLISTED; } else { return detectTransferRestriction(from, to, value); diff --git a/src/rules/validation/RuleSanctionList.sol b/src/rules/validation/RuleSanctionsList.sol similarity index 87% rename from src/rules/validation/RuleSanctionList.sol rename to src/rules/validation/RuleSanctionsList.sol index 5834ef1..70515a5 100644 --- a/src/rules/validation/RuleSanctionList.sol +++ b/src/rules/validation/RuleSanctionsList.sol @@ -2,24 +2,21 @@ pragma solidity ^0.8.20; -import "OZ/access/AccessControl.sol"; -import "../../modules/MetaTxModuleStandalone.sol"; -import "./abstract/RuleSanctionListInvariantStorage.sol"; -import "./abstract/RuleValidateTransfer.sol"; +import {AccessControl} from "OZ/access/AccessControl.sol"; +import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../modules/MetaTxModuleStandalone.sol"; +import {RuleSanctionsListInvariantStorage} from "./abstract/RuleSanctionsListInvariantStorage.sol"; +import {RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol"; +import {ISanctionsList } from "../interfaces/ISanctionsList.sol"; -interface SanctionsList { - function isSanctioned(address addr) external view returns (bool); -} - -contract RuleSanctionList is +contract RuleSanctionsList is AccessControl, MetaTxModuleStandalone, RuleValidateTransfer, - RuleSanctionlistInvariantStorage + RuleSanctionsListInvariantStorage { - SanctionsList public sanctionsList; + ISanctionsList public sanctionsList; /** * @param admin Address of the contract (Access Control) @@ -28,12 +25,12 @@ contract RuleSanctionList is constructor( address admin, address forwarderIrrevocable, - address sanctionContractOracle_ + ISanctionsList sanctionContractOracle_ ) MetaTxModuleStandalone(forwarderIrrevocable) { if (admin == address(0)) { revert RuleSanctionList_AdminWithAddressZeroNotAllowed(); } - if (sanctionContractOracle_ != address(0)) { + if (address(sanctionContractOracle_) != address(0)) { _setSanctionListOracle(sanctionContractOracle_); } _grantRole(DEFAULT_ADMIN_ROLE, admin); @@ -45,7 +42,7 @@ contract RuleSanctionList is * @dev zero address is authorized to authorize all transfers */ function setSanctionListOracle( - address sanctionContractOracle_ + ISanctionsList sanctionContractOracle_ ) public onlyRole(SANCTIONLIST_ROLE) { _setSanctionListOracle(sanctionContractOracle_); } @@ -163,9 +160,9 @@ contract RuleSanctionList is INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ - function _setSanctionListOracle(address sanctionContractOracle_) internal { - sanctionsList = SanctionsList(sanctionContractOracle_); - emit SetSanctionListOracle(address(sanctionContractOracle_)); + function _setSanctionListOracle(ISanctionsList sanctionContractOracle_) internal { + sanctionsList = sanctionContractOracle_; + emit SetSanctionListOracle(sanctionContractOracle_); } /*////////////////////////////////////////////////////////////// diff --git a/src/rules/validation/RuleWhitelist.sol b/src/rules/validation/RuleWhitelist.sol index 213bf67..8a53cc3 100644 --- a/src/rules/validation/RuleWhitelist.sol +++ b/src/rules/validation/RuleWhitelist.sol @@ -1,59 +1,108 @@ // SPDX-License-Identifier: MPL-2.0 - pragma solidity ^0.8.20; -import "./abstract/RuleAddressList/RuleAddressList.sol"; -import "./abstract/RuleWhitelistCommon.sol"; - +import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol"; +import {RuleWhitelistCommon} from "./abstract/RuleWhitelistCommon.sol"; import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; - +import {IIdentityRegistryVerified} from "../interfaces/IIdentityRegistry.sol"; /** - * @title a whitelist manager + * @title Rule Whitelist + * @notice Manages a whitelist of authorized addresses and enforces whitelist-based transfer restrictions. + * @dev + * - Inherits core address management logic from {RuleAddressSet}. + * - Integrates restriction code logic from {RuleWhitelistCommon}. + * - Implements {IERC1404} to return specific restriction codes for non-whitelisted transfers. */ -contract RuleWhitelist is RuleAddressList, RuleWhitelistCommon { +contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistryVerified{ + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + /** - * @param admin Address of the contract (Access Control) - * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + * @notice Initializes the RuleWhitelist contract. + * @param admin Address that will be granted the default admin role. + * @param forwarderIrrevocable Address of the ERC2771 trusted forwarder (for gasless transactions). */ constructor( address admin, address forwarderIrrevocable - ) RuleAddressList(admin, forwarderIrrevocable) {} - + ) RuleAddressSet(admin, forwarderIrrevocable) {} + /*////////////////////////////////////////////////////////////// + TRANSFER RESTRICTION LOGIC + //////////////////////////////////////////////////////////////*/ /** - * @notice Check if an addres is in the whitelist or not - * @param from the origin address - * @param to the destination address - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - **/ + * @notice Detects whether a transfer between two addresses is allowed under the whitelist rule. + * @dev + * - Returns a restriction code indicating why a transfer is blocked. + * - Implements the `IERC1404.detectTransferRestriction` interface. + * @param from The address sending tokens. + * @param to The address receiving tokens. + * @param value The amount being transferred (unused in this check). + * @return code Restriction code (e.g., `TRANSFER_OK` or specific whitelist rejection). + * + * | Condition | Returned Code | + * |------------|---------------| + * | `from` not whitelisted | `CODE_ADDRESS_FROM_NOT_WHITELISTED` | + * | `to` not whitelisted | `CODE_ADDRESS_TO_NOT_WHITELISTED` | + * | Both whitelisted | `TRANSFER_OK` | + */ function detectTransferRestriction( address from, address to, - uint256 /*value */ - ) public view override returns (uint8) { - if (!addressIsListed(from)) { + uint256 value + ) public view override returns (uint8 code) { + if (!isAddressListed(from)) { return CODE_ADDRESS_FROM_NOT_WHITELISTED; - } else if (!addressIsListed(to)) { + } else if (!isAddressListed(to)) { return CODE_ADDRESS_TO_NOT_WHITELISTED; } else { return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } } + /** + * @notice Detects transfer restriction for delegated transfers (`transferFrom`). + * @dev + * - Checks the `spender`, `from`, and `to` addresses for whitelist compliance. + * - Implements `IERC1404Extend.detectTransferRestrictionFrom`. + * @param spender The address initiating the transfer on behalf of another. + * @param from The address from which tokens are transferred. + * @param to The address receiving the tokens. + * @param value The amount being transferred (unused in this check). + * @return code Restriction code, or `TRANSFER_OK` if all parties are whitelisted. + * + * | Condition | Returned Code | + * |------------|---------------| + * | `spender` not whitelisted | `CODE_ADDRESS_SPENDER_NOT_WHITELISTED` | + * | `from` or `to` not whitelisted | respective restriction code from `detectTransferRestriction` | + * | All whitelisted | `TRANSFER_OK` | + */ function detectTransferRestrictionFrom( address spender, address from, address to, uint256 value - ) public view override returns (uint8) { - if (!addressIsListed(spender)) { + ) public view override returns (uint8 code) { + if (!isAddressListed(spender)) { return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; - } else { - return detectTransferRestriction(from, to, value); } + return detectTransferRestriction(from, to, value); } + /** + * @notice Checks whether a specific address is currently listed. + * @param targetAddress The address to check. + * @return isListed True if listed, false otherwise. + */ + function isVerified(address targetAddress) + public + view + override(IIdentityRegistryVerified) + returns (bool isListed) + { + isListed = _isAddressListed(targetAddress); + } -} +} \ No newline at end of file diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol index e499ba7..a4c3114 100644 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -2,10 +2,10 @@ pragma solidity ^0.8.20; -import "OZ/access/AccessControl.sol"; -import "../../modules/MetaTxModuleStandalone.sol"; -import "./abstract/RuleAddressList/RuleAddressList.sol"; -import "./abstract/RuleWhitelistCommon.sol"; +import {AccessControl} from "OZ/access/AccessControl.sol"; +import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../modules/MetaTxModuleStandalone.sol"; +import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol"; +import {RuleWhitelistCommon} from "./abstract/RuleWhitelistCommon.sol"; import {RulesManagementModule} from "RuleEngine/modules/RulesManagementModule.sol"; import {RuleEngineInvariantStorage} from "RuleEngine/modules/library/RuleEngineInvariantStorage.sol"; import {IRule} from "RuleEngine/interfaces/IRule.sol"; @@ -51,8 +51,8 @@ contract RuleWhitelistWrapper is // For each whitelist rule, we ask if from or to are in the whitelist for (uint256 i = 0; i < rulesLength; ++i) { // External call - isListed = RuleAddressList(rule(i)) - .addressIsListedBatch(targetAddress); + isListed = RuleAddressSet(rule(i)) + .areAddressesListed(targetAddress); if (isListed[0] && !result[0]) { // Update if from is in the list result[0] = true; @@ -90,8 +90,8 @@ contract RuleWhitelistWrapper is // For each whitelist rule, we ask if from or to are in the whitelist for (uint256 i = 0; i < rulesLength; ++i) { // External call - isListed = RuleAddressList(rule(i)) - .addressIsListedBatch(targetAddress); + isListed = RuleAddressSet(rule(i)) + .areAddressesListed(targetAddress); if (isListed[0] && !result[0]) { // Update if from is in the list result[0] = true; diff --git a/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol b/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol deleted file mode 100644 index ddcdb54..0000000 --- a/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -import "OZ/access/AccessControl.sol"; -import "./../../../../modules/MetaTxModuleStandalone.sol"; -import "./RuleAddressListInternal.sol"; -import "./invariantStorage/RuleAddressListInvariantStorage.sol"; - -/** -@title an addresses list manager -*/ - -abstract contract RuleAddressList is - AccessControl, - MetaTxModuleStandalone, - RuleAddressListInternal, - RuleAddressListInvariantStorage -{ - // Number of addresses in the list at the moment - uint256 private numAddressesWhitelisted; - - /** - * @param admin Address of the contract (Access Control) - * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - */ - constructor( - address admin, - address forwarderIrrevocable - ) MetaTxModuleStandalone(forwarderIrrevocable) { - if (admin == address(0)) { - revert RuleAddressList_AdminWithAddressZeroNotAllowed(); - } - _grantRole(DEFAULT_ADMIN_ROLE, admin); - } - - /** - * @notice Add addresses to the list - * If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert). - * @param listTargetAddresses an array with the addresses to list - */ - function addAddressesToTheList( - address[] calldata listTargetAddresses - ) public onlyRole(ADDRESS_LIST_ADD_ROLE) { - _addAddressesToThelist(listTargetAddresses); - emit AddAddressesToTheList(listTargetAddresses); - } - - /** - * @notice Remove addresses from the list - * If the address does not exist in the list, there is no change for this address. - * The transaction remains valid (no revert). - * @param listTargetAddresses an array with the addresses to remove - */ - function removeAddressesFromTheList( - address[] calldata listTargetAddresses - ) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) { - _removeAddressesFromThelist(listTargetAddresses); - emit RemoveAddressesFromTheList(listTargetAddresses); - } - - /** - * @notice Add one address to the list - * If the address already exists, the transaction is reverted to save gas. - * @param targetAddress The address to list - */ - function addAddressToTheList( - address targetAddress - ) public onlyRole(ADDRESS_LIST_ADD_ROLE) { - _addAddressToThelist(targetAddress); - emit AddAddressToTheList(targetAddress); - } - - /** - * @notice Remove one address from the list - * If the address does not exist in the list, the transaction is reverted to save gas. - * @param targetAddress The address to remove - * - */ - function removeAddressFromTheList( - address targetAddress - ) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) { - _removeAddressFromThelist(targetAddress); - emit RemoveAddressFromTheList(targetAddress); - } - - /** - * @notice Get the number of listed addresses - * @return Number of listed addresses - * - */ - function numberListedAddress() public view returns (uint256) { - return _numberListedAddress(); - } - - /** - * @notice Know if an address is listed or not - * @param _targetAddress The concerned address - * @return True if the address is listed, false otherwise - * - */ - function addressIsListed( - address _targetAddress - ) public view returns (bool) { - return _addressIsListed(_targetAddress); - } - - /** - * @notice batch version of {addressIsListed} - * - */ - function addressIsListedBatch( - address[] memory _targetAddresses - ) public view returns (bool[] memory) { - bool[] memory isListed = new bool[](_targetAddresses.length); - for (uint256 i = 0; i < _targetAddresses.length; ++i) { - isListed[i] = _addressIsListed(_targetAddresses[i]); - } - return isListed; - } - - /* ============ ACCESS CONTROL ============ */ - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole( - bytes32 role, - address account - ) public view virtual override(AccessControl) returns (bool) { - // The Default Admin has all roles - if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { - return true; - } - return AccessControl.hasRole(role, account); - } - - /*////////////////////////////////////////////////////////////// - ERC-2771 - //////////////////////////////////////////////////////////////*/ - - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - */ - function _msgSender() - internal - view - override(ERC2771Context, Context) - returns (address sender) - { - return ERC2771Context._msgSender(); - } - - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - */ - function _msgData() - internal - view - override(ERC2771Context, Context) - returns (bytes calldata) - { - return ERC2771Context._msgData(); - } - - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - */ - function _contextSuffixLength() - internal - view - override(ERC2771Context, Context) - returns (uint256) - { - return ERC2771Context._contextSuffixLength(); - } -} diff --git a/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol b/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol deleted file mode 100644 index 02cbd38..0000000 --- a/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -/** - * @title a list manager - */ - -abstract contract RuleAddressListInternal { - error Rulelist_AddressAlreadylisted(); - error Rulelist_AddressNotPresent(); - - mapping(address => bool) private list; - // Number of addresses in the list at the moment - uint256 private numAddressesList; - - /** - * @notice Add addresses to the list - * If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert). - * @param listTargetAddresses an array with the addresses to list - */ - function _addAddressesToThelist( - address[] calldata listTargetAddresses - ) internal { - uint256 numAddressesListLocal = numAddressesList; - for (uint256 i = 0; i < listTargetAddresses.length; ++i) { - if (!list[listTargetAddresses[i]]) { - list[listTargetAddresses[i]] = true; - ++numAddressesListLocal; - } - } - numAddressesList = numAddressesListLocal; - } - - /** - * @notice Remove addresses from the list - * If the address does not exist in the list, there is no change for this address. - * The transaction remains valid (no revert). - * @param listTargetAddresses an array with the addresses to remove - */ - function _removeAddressesFromThelist( - address[] calldata listTargetAddresses - ) internal { - uint256 numAddressesListLocal = numAddressesList; - for (uint256 i = 0; i < listTargetAddresses.length; ++i) { - if (list[listTargetAddresses[i]]) { - list[listTargetAddresses[i]] = false; - --numAddressesListLocal; - } - } - numAddressesList = numAddressesListLocal; - } - - /** - * @notice Add one address to the list - * If the address already exists, the transaction is reverted to save gas. - * @param targetAddress The address to list - */ - function _addAddressToThelist(address targetAddress) internal { - if (list[targetAddress]) { - revert Rulelist_AddressAlreadylisted(); - } - list[targetAddress] = true; - ++numAddressesList; - } - - /** - * @notice Remove one address from the list - * If the address does not exist in the list, the transaction is reverted to save gas. - * @param targetAddress The address to remove - * - */ - function _removeAddressFromThelist(address targetAddress) internal { - if (!list[targetAddress]) { - revert Rulelist_AddressNotPresent(); - } - list[targetAddress] = false; - --numAddressesList; - } - - /** - * @notice Get the number of listed addresses - * @return Number of listed addresses - * - */ - function _numberListedAddress() internal view returns (uint256) { - return numAddressesList; - } - - /** - * @notice Know if an address is listed or not - * @param _targetAddress The concerned address - * @return True if the address is listed, false otherwise - * - */ - function _addressIsListed( - address _targetAddress - ) internal view returns (bool) { - return list[_targetAddress]; - } -} diff --git a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol deleted file mode 100644 index 75f5c3c..0000000 --- a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -abstract contract RuleAddressListInvariantStorage { - /* ============ Events ============ */ - event AddAddressesToTheList(address[] listTargetAddresses); - event RemoveAddressesFromTheList(address[] listTargetAddresses); - event AddAddressToTheList(address targetAddress); - event RemoveAddressFromTheList(address targetAddress); - - /* ============ Custom errors ============ */ - error RuleAddressList_AdminWithAddressZeroNotAllowed(); - - /* ============ Role ============ */ - bytes32 public constant ADDRESS_LIST_REMOVE_ROLE = - keccak256("ADDRESS_LIST_REMOVE_ROLE"); - bytes32 public constant ADDRESS_LIST_ADD_ROLE = - keccak256("ADDRESS_LIST_ADD_ROLE"); -} diff --git a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol new file mode 100644 index 0000000..7b2a94c --- /dev/null +++ b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {AccessControl} from "OZ/access/AccessControl.sol"; +import {MetaTxModuleStandalone, ERC2771Context, Context} from "./../../../../modules/MetaTxModuleStandalone.sol"; +import {RuleAddressSetInternal} from "./RuleAddressSetInternal.sol"; +import {RuleAddressSetInvariantStorage} from "./invariantStorage/RuleAddressSetInvariantStorage.sol"; +import {IIdentityRegistryContains} from "../../../interfaces/IIdentityRegistry.sol"; +/** + * @title Rule Address Set + * @notice Manages a permissioned set of addresses related to rule logic. + * @dev + * - Provides controlled functions for adding and removing addresses. + * - Integrates `AccessControl` for role-based access. + * - Supports gasless transactions via ERC-2771 meta-transactions. + * - Extends internal logic defined in {RuleAddressSetInternal}. + */ +abstract contract RuleAddressSet is + AccessControl, + MetaTxModuleStandalone, + RuleAddressSetInternal, + RuleAddressSetInvariantStorage, + IIdentityRegistryContains +{ + /*////////////////////////////////////////////////////////////// + STATE + //////////////////////////////////////////////////////////////*/ + + /// @notice Cached number of currently listed addresses. + uint256 private _listedAddressCountCache; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Initializes the RuleAddressSet contract. + * @param admin The address granted the default admin role. + * @param forwarderIrrevocable Address of the ERC2771 forwarder (for meta-transactions). + * @dev Reverts if the admin address is the zero address. + */ + constructor( + address admin, + address forwarderIrrevocable + ) MetaTxModuleStandalone(forwarderIrrevocable) { + if (admin == address(0)) { + revert RuleAddressSet_AdminWithAddressZeroNotAllowed(); + } + _grantRole(DEFAULT_ADMIN_ROLE, admin); + } + + /*////////////////////////////////////////////////////////////// + CORE LOGIC + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Adds multiple addresses to the set. + * @dev + * - Does not revert if an address is already listed. + * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`. + * @param targetAddresses Array of addresses to be added. + */ + function addAddresses( + address[] calldata targetAddresses + ) public onlyRole(ADDRESS_LIST_ADD_ROLE) { + _addAddresses(targetAddresses); + emit AddAddresses(targetAddresses); + } + + /** + * @notice Removes multiple addresses from the set. + * @dev + * - Does not revert if an address is not listed. + * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`. + * @param targetAddresses Array of addresses to remove. + */ + function removeAddresses( + address[] calldata targetAddresses + ) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) { + _removeAddresses(targetAddresses); + emit RemoveAddresses(targetAddresses); + } + + /** + * @notice Adds a single address to the set. + * @dev + * - Reverts if the address is already listed. + * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`. + * @param targetAddress The address to be added. + */ + function addAddress(address targetAddress) + public + onlyRole(ADDRESS_LIST_ADD_ROLE) + { + if (_isAddressListed(targetAddress)) { + revert RuleAddressSet_AddressAlreadyListed(); + } + _addAddress(targetAddress); + emit AddAddress(targetAddress); + } + + /** + * @notice Removes a single address from the set. + * @dev + * - Reverts if the address is not listed. + * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`. + * @param targetAddress The address to be removed. + */ + function removeAddress(address targetAddress) + public + onlyRole(ADDRESS_LIST_REMOVE_ROLE) + { + if (!_isAddressListed(targetAddress)) { + revert RuleAddressSet_AddressNotFound(); + } + _removeAddress(targetAddress); + emit RemoveAddress(targetAddress); + } + + /** + * @notice Returns the total number of currently listed addresses. + * @return count The number of listed addresses. + */ + function listedAddressCount() public view returns (uint256 count) { + count = _listedAddressCount(); + } + + /** + * @notice Checks whether a specific address is currently listed. + * @param targetAddress The address to check. + * @return isListed True if listed, false otherwise. + */ + function contains(address targetAddress) + public + view + override(IIdentityRegistryContains) + returns (bool isListed) + { + isListed = _isAddressListed(targetAddress); + } + + /** + * @notice Checks whether a specific address is currently listed. + * @param targetAddress The address to check. + * @return isListed True if listed, false otherwise. + */ + function isAddressListed(address targetAddress) + public + view + returns (bool isListed) + { + isListed = _isAddressListed(targetAddress); + } + + /** + * @notice Checks multiple addresses in a single call. + * @param targetAddresses Array of addresses to check. + * @return results Array of booleans corresponding to listing status. + */ + function areAddressesListed( + address[] memory targetAddresses + ) public view returns (bool[] memory results) { + results = new bool[](targetAddresses.length); + for (uint256 i = 0; i < targetAddresses.length; ++i) { + results[i] = _isAddressListed(targetAddresses[i]); + } + } + + + + + + + + /*////////////////////////////////////////////////////////////// + ACCESS CONTROL + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Returns `true` if `account` has been granted `role`. + * @dev + * The `DEFAULT_ADMIN_ROLE` implicitly grants all roles. + * @param role The role identifier. + * @param account The account address to check. + */ + function hasRole( + bytes32 role, + address account + ) public view virtual override(AccessControl) returns (bool) { + if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { + return true; + } + return AccessControl.hasRole(role, account); + } + + /*////////////////////////////////////////////////////////////// + ERC-2771 META TX + //////////////////////////////////////////////////////////////*/ + + /// @inheritdoc ERC2771Context + function _msgSender() + internal + view + override(ERC2771Context, Context) + returns (address sender) + { + return ERC2771Context._msgSender(); + } + + /// @inheritdoc ERC2771Context + function _msgData() + internal + view + override(ERC2771Context, Context) + returns (bytes calldata) + { + return ERC2771Context._msgData(); + } + + /// @inheritdoc ERC2771Context + function _contextSuffixLength() + internal + view + override(ERC2771Context, Context) + returns (uint256) + { + return ERC2771Context._contextSuffixLength(); + } +} \ No newline at end of file diff --git a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol new file mode 100644 index 0000000..4bf256e --- /dev/null +++ b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {EnumerableSet} from "OZ/utils/structs/EnumerableSet.sol"; + +/** + * @title Rule Address Set (Internal) + * @notice Internal utility for managing a set of rule-related addresses. + * @dev + * - Uses OpenZeppelin's EnumerableSet for efficient enumeration. + * - Designed for internal inheritance and logic composition. + * - Batch operations do not revert when individual entries are invalid. + */ +abstract contract RuleAddressSetInternal { + using EnumerableSet for EnumerableSet.AddressSet; + + + /*////////////////////////////////////////////////////////////// + STATE VARIABLES + //////////////////////////////////////////////////////////////*/ + + /// @dev Storage for all listed addresses. + EnumerableSet.AddressSet private _listedAddresses; + + /*////////////////////////////////////////////////////////////// + CORE LOGIC + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Adds multiple addresses to the set. + * @dev + * - Does not revert if an address is already listed. + * - Skips existing entries silently. + * @param addressesToAdd The array of addresses to add. + */ + function _addAddresses(address[] calldata addressesToAdd) internal { + for (uint256 i = 0; i < addressesToAdd.length; ++i) { + _listedAddresses.add(addressesToAdd[i]); + } + } + + /** + * @notice Removes multiple addresses from the set. + * @dev + * - Does not revert if an address is not found. + * - Skips non-existing entries silently. + * @param addressesToRemove The array of addresses to remove. + */ + function _removeAddresses(address[] calldata addressesToRemove) internal { + for (uint256 i = 0; i < addressesToRemove.length; ++i) { + _listedAddresses.remove(addressesToRemove[i]); + } + } + + /** + * @notice Adds a single address to the set. + * @param targetAddress The address to add. + */ + function _addAddress(address targetAddress) internal { + _listedAddresses.add(targetAddress); + } + + /** + * @notice Removes a single address from the set. + * @param targetAddress The address to remove. + */ + function _removeAddress(address targetAddress) internal { + _listedAddresses.remove(targetAddress); + } + + /** + * @notice Returns the total number of listed addresses. + * @return count The number of listed addresses. + */ + function _listedAddressCount() internal view returns (uint256 count) { + count = _listedAddresses.length(); + } + + /** + * @notice Checks if an address is listed. + * @param targetAddress The address to check. + * @return isListed True if the address is listed, false otherwise. + */ + function _isAddressListed(address targetAddress) internal view returns (bool isListed) { + isListed = _listedAddresses.contains(targetAddress); + } +} \ No newline at end of file diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol new file mode 100644 index 0000000..a1f349b --- /dev/null +++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +abstract contract RuleAddressSetInvariantStorage { + /* ============ Events ============ */ + event AddAddresses(address[] listTargetAddresses); + event RemoveAddresses(address[] listTargetAddresses); + event AddAddress(address targetAddress); + event RemoveAddress(address targetAddress); + + /* ============ Custom errors ============ */ + error RuleAddressSet_AdminWithAddressZeroNotAllowed(); + + /// @notice Thrown when trying to add an address that is already listed. + error RuleAddressSet_AddressAlreadyListed(); + + /// @notice Thrown when trying to remove an address that is not listed. + error RuleAddressSet_AddressNotFound(); + + /* ============ Role ============ */ + bytes32 public constant ADDRESS_LIST_REMOVE_ROLE = + keccak256("ADDRESS_LIST_REMOVE_ROLE"); + bytes32 public constant ADDRESS_LIST_ADD_ROLE = + keccak256("ADDRESS_LIST_ADD_ROLE"); +} diff --git a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol similarity index 100% rename from src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol rename to src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol diff --git a/src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol similarity index 100% rename from src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol rename to src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol diff --git a/src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol similarity index 87% rename from src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol rename to src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol index 491566c..9869092 100644 --- a/src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.20; import "./RuleCommonInvariantStorage.sol"; - -abstract contract RuleSanctionlistInvariantStorage is +import {ISanctionsList } from "../../interfaces/ISanctionsList.sol"; +abstract contract RuleSanctionsListInvariantStorage is RuleCommonInvariantStorage { error RuleSanctionsList_InvalidTransfer( @@ -14,7 +14,7 @@ abstract contract RuleSanctionlistInvariantStorage is uint8 code ); /* ============ Event ============ */ - event SetSanctionListOracle(address newOracle); + event SetSanctionListOracle(ISanctionsList newOracle); /* ============ Custom errors ============ */ error RuleSanctionList_AdminWithAddressZeroNotAllowed(); error RuleSanctionList_AddressAlreadyWhitelisted(); diff --git a/src/rules/validation/abstract/RuleWhitelistCommon.sol b/src/rules/validation/abstract/RuleWhitelistCommon.sol index d73073d..901f1d0 100644 --- a/src/rules/validation/abstract/RuleWhitelistCommon.sol +++ b/src/rules/validation/abstract/RuleWhitelistCommon.sol @@ -1,49 +1,76 @@ // SPDX-License-Identifier: MPL-2.0 - pragma solidity ^0.8.20; -import "./RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol"; +import "./RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol"; import "./RuleValidateTransfer.sol"; - +/** + * @title Rule Whitelist Common + * @notice Provides common logic for validating whitelist-based transfer restrictions. + * @dev + * - Implements ERC-3643–compatible `transferred` hooks to enforce whitelist checks. + * - Defines utility functions for restriction code validation and message mapping. + * - Inherits restriction code constants and messages from {RuleWhitelistInvariantStorage}. + */ abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInvariantStorage { + /*////////////////////////////////////////////////////////////// + RESTRICTION CODE LOGIC + //////////////////////////////////////////////////////////////*/ /** - * @notice To know if the restriction code is valid for this rule or not - * @param _restrictionCode The target restriction code - * @return true if the restriction code is known, false otherwise - **/ + * @notice Checks whether a restriction code is recognized by this rule. + * @dev + * Used to verify if a returned restriction code belongs to the whitelist rule. + * @param restrictionCode The restriction code to validate. + * @return isKnown True if the restriction code is recognized by this rule, false otherwise. + */ function canReturnTransferRestrictionCode( - uint8 _restrictionCode - ) external pure override returns (bool) { + uint8 restrictionCode + ) external pure override returns (bool isKnown) { return - _restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED || - _restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED || - _restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED; + restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED || + restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED || + restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED; } /** - * @notice Return the corresponding message - * @param _restrictionCode The target restriction code - * @return true if the transfer is valid, false otherwise - **/ + * @notice Returns the human-readable message corresponding to a restriction code. + * @dev + * Returns a descriptive text that explains why a transfer was restricted. + * @param restrictionCode The restriction code to decode. + * @return message A human-readable explanation of the restriction. + */ function messageForTransferRestriction( - uint8 _restrictionCode - ) external pure override returns (string memory) { - if (_restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) { + uint8 restrictionCode + ) external pure override returns (string memory message) { + if (restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) { return TEXT_ADDRESS_FROM_NOT_WHITELISTED; - } else if (_restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) { + } else if (restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) { return TEXT_ADDRESS_TO_NOT_WHITELISTED; - } else if (_restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED) { + } else if (restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED) { return TEXT_ADDRESS_SPENDER_NOT_WHITELISTED; } else { return TEXT_CODE_NOT_FOUND; } } + /*////////////////////////////////////////////////////////////// + ERC-3643 HOOKS + //////////////////////////////////////////////////////////////*/ + + /** + * @notice ERC-3643 hook called when a transfer occurs. + * @dev + * - Validates that both `from` and `to` addresses are whitelisted. + * - Reverts if any restriction code other than `TRANSFER_OK` is returned. + * - Should be called during token transfer logic to enforce whitelist compliance. + * @param from The address sending tokens. + * @param to The address receiving tokens. + * @param value The token amount being transferred. + */ function transferred(address from, address to, uint256 value) public view { uint8 code = this.detectTransferRestriction(from, to, value); require( @@ -52,6 +79,16 @@ abstract contract RuleWhitelistCommon is ); } + /** + * @notice ERC-3643 hook called when a delegated transfer occurs (`transferFrom`). + * @dev + * - Validates that `spender`, `from`, and `to` are all whitelisted. + * - Reverts if any restriction code other than `TRANSFER_OK` is returned. + * @param spender The address performing the transfer on behalf of another. + * @param from The address from which tokens are transferred. + * @param to The recipient address. + * @param value The token amount being transferred. + */ function transferred( address spender, address from, @@ -64,4 +101,4 @@ abstract contract RuleWhitelistCommon is RuleWhitelist_InvalidTransfer(from, to, value, code) ); } -} +} \ No newline at end of file diff --git a/test/HelperContract.sol b/test/HelperContract.sol index dc2ca07..f05a9a0 100644 --- a/test/HelperContract.sol +++ b/test/HelperContract.sol @@ -10,17 +10,17 @@ import {RuleEngineInvariantStorage} from "RuleEngine/modules/library/RuleEngineI import {RuleEngine} from "RuleEngine/RuleEngine.sol"; // RuleSanctionList -import {RuleSanctionList} from "src/rules/validation/RuleSanctionList.sol"; +import {RuleSanctionsList} from "src/rules/validation/RuleSanctionsList.sol"; // RUleBlackList import {RuleBlacklist} from "src/rules/validation/RuleBlacklist.sol"; -import {RuleBlacklistInvariantStorage} from "src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol"; +import {RuleBlacklistInvariantStorage} from "src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol"; // RuleWhitelist import {RuleWhitelist} from "src/rules/validation/RuleWhitelist.sol"; import {RuleWhitelistWrapper} from "src/rules/validation/RuleWhitelistWrapper.sol"; -import {RuleWhitelistInvariantStorage} from "src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol"; -import {RuleAddressListInvariantStorage} from "src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol"; +import {RuleWhitelistInvariantStorage} from "src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol"; +import {RuleAddressSetInvariantStorage} from "src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol"; -import {RuleSanctionlistInvariantStorage}from "src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol"; +import {RuleSanctionsListInvariantStorage}from "src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol"; // Rule interface // utils @@ -32,8 +32,8 @@ import "RuleEngine/../test/utils/CMTATDeployment.sol"; abstract contract HelperContract is RuleWhitelistInvariantStorage, RuleBlacklistInvariantStorage, - RuleAddressListInvariantStorage, - RuleSanctionlistInvariantStorage, + RuleAddressSetInvariantStorage, + RuleSanctionsListInvariantStorage, RuleEngineInvariantStorage { // Test result diff --git a/test/RuleBlacklist/CMTATIntegration.t.sol b/test/RuleBlacklist/CMTATIntegration.t.sol index 0b51d22..4d6681c 100644 --- a/test/RuleBlacklist/CMTATIntegration.t.sol +++ b/test/RuleBlacklist/CMTATIntegration.t.sol @@ -56,7 +56,7 @@ contract CMTATIntegration is Test, HelperContract { // Arrange uint256 amount = 21; vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleBlacklist.addAddressToTheList(ADDRESS2); + ruleBlacklist.addAddress(ADDRESS2); vm.prank(ADDRESS1); vm.expectRevert( @@ -76,7 +76,7 @@ contract CMTATIntegration is Test, HelperContract { // Arrange uint256 amount = 21; vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleBlacklist.addAddressToTheList(ADDRESS1); + ruleBlacklist.addAddress(ADDRESS1); vm.prank(ADDRESS1); vm.expectRevert( @@ -101,7 +101,7 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(DEFAULT_ADMIN_ADDRESS); (bool success, ) = address(ruleBlacklist).call( abi.encodeWithSignature( - "addAddressesToTheList(address[])", + "addAddresses(address[])", blacklist ) ); @@ -124,8 +124,8 @@ contract CMTATIntegration is Test, HelperContract { /******* detectTransferRestriction & messageForTransferRestriction *******/ function testDetectAndMessageWithToBlacklisted() public { vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleBlacklist.addAddressToTheList(ADDRESS2); - resBool = ruleBlacklist.addressIsListed(ADDRESS2); + ruleBlacklist.addAddress(ADDRESS2); + resBool = ruleBlacklist.isAddressListed(ADDRESS2); // Assert assertEq(resBool, true); uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( @@ -146,9 +146,9 @@ contract CMTATIntegration is Test, HelperContract { // Arrange // We add the sender to the whitelist vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleBlacklist.addAddressToTheList(ADDRESS1); + ruleBlacklist.addAddress(ADDRESS1); // Arrange - Assert - resBool = ruleBlacklist.addressIsListed(ADDRESS1); + resBool = ruleBlacklist.isAddressListed(ADDRESS1); assertEq(resBool, true); // Act uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( @@ -193,7 +193,7 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(DEFAULT_ADMIN_ADDRESS); (bool success, ) = address(ruleBlacklist).call( abi.encodeWithSignature( - "addAddressesToTheList(address[])", + "addAddresses(address[])", blacklist ) ); @@ -228,9 +228,9 @@ contract CMTATIntegration is Test, HelperContract { uint256 amount = 11; // Arrange vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleBlacklist.addAddressToTheList(ADDRESS1); + ruleBlacklist.addAddress(ADDRESS1); // Arrange - Assert - resBool = ruleBlacklist.addressIsListed(ADDRESS1); + resBool = ruleBlacklist.isAddressListed(ADDRESS1); assertEq(resBool, true); // Act diff --git a/test/RuleSanctionList/RuleSanctionListAddTest.t.sol b/test/RuleSanctionList/RuleSanctionListAddTest.t.sol index 80fc08f..4a473c5 100644 --- a/test/RuleSanctionList/RuleSanctionListAddTest.t.sol +++ b/test/RuleSanctionList/RuleSanctionListAddTest.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; import "../utils/SanctionListOracle.sol"; -import {RuleSanctionList, SanctionsList} from "src/rules/validation/RuleSanctionList.sol"; +import {RuleSanctionsList, ISanctionsList} from "src/rules/validation/RuleSanctionsList.sol"; /** * @title General functions of the ruleSanctionList */ @@ -12,27 +12,27 @@ contract RuleSanctionlistAddTest is Test, HelperContract { // Custom error openZeppelin error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); SanctionListOracle sanctionlistOracle; - RuleSanctionList ruleSanctionList; + RuleSanctionsList ruleSanctionList; // Arrange function setUp() public { vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); sanctionlistOracle = new SanctionListOracle(); sanctionlistOracle.addToSanctionsList(ATTACKER); - ruleSanctionList = new RuleSanctionList( + ruleSanctionList = new RuleSanctionsList( SANCTIONLIST_OPERATOR_ADDRESS, ZERO_ADDRESS, - ZERO_ADDRESS + ISanctionsList(ZERO_ADDRESS) ); } function testCanSetandRemoveOracle() public { // ADD vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - emit SetSanctionListOracle(address(sanctionlistOracle)); - ruleSanctionList.setSanctionListOracle(address(sanctionlistOracle)); + emit SetSanctionListOracle(sanctionlistOracle); + ruleSanctionList.setSanctionListOracle(sanctionlistOracle); - SanctionsList sanctionListOracleGet = ruleSanctionList.sanctionsList(); + ISanctionsList sanctionListOracleGet = ruleSanctionList.sanctionsList(); // Assert vm.assertEq( address(sanctionListOracleGet), @@ -40,8 +40,8 @@ contract RuleSanctionlistAddTest is Test, HelperContract { ); // Remove vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - emit SetSanctionListOracle(ZERO_ADDRESS); - ruleSanctionList.setSanctionListOracle(ZERO_ADDRESS); + emit SetSanctionListOracle(ISanctionsList(ZERO_ADDRESS)); + ruleSanctionList.setSanctionListOracle(ISanctionsList(ZERO_ADDRESS)); // Assert sanctionListOracleGet = ruleSanctionList.sanctionsList(); vm.assertEq(address(sanctionListOracleGet), address(ZERO_ADDRESS)); @@ -56,6 +56,6 @@ contract RuleSanctionlistAddTest is Test, HelperContract { SANCTIONLIST_ROLE ) ); - ruleSanctionList.setSanctionListOracle(address(sanctionlistOracle)); + ruleSanctionList.setSanctionListOracle(sanctionlistOracle); } } diff --git a/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol b/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol index ee2e75f..e627ebc 100644 --- a/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol +++ b/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol @@ -5,12 +5,12 @@ import "forge-std/Test.sol"; import "../HelperContract.sol"; import "CMTAT/mocks/MinimalForwarderMock.sol"; import "../utils/SanctionListOracle.sol"; -import {RuleSanctionList, SanctionsList} from "src/rules/validation/RuleSanctionList.sol"; +import {RuleSanctionsList, ISanctionsList} from "src/rules/validation/RuleSanctionsList.sol"; /** * @title General functions of the ruleSanctionList */ contract RuleSanctionListDeploymentTest is Test, HelperContract { - RuleSanctionList ruleSanctionList; + RuleSanctionsList ruleSanctionList; SanctionListOracle sanctionlistOracle; event Testa(); @@ -23,10 +23,10 @@ contract RuleSanctionListDeploymentTest is Test, HelperContract { MinimalForwarderMock forwarder = new MinimalForwarderMock(); forwarder.initialize(ERC2771ForwarderDomain); vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - ruleSanctionList = new RuleSanctionList( + ruleSanctionList = new RuleSanctionsList( SANCTIONLIST_OPERATOR_ADDRESS, address(forwarder), - ZERO_ADDRESS + ISanctionsList(ZERO_ADDRESS) ); // assert @@ -48,10 +48,10 @@ contract RuleSanctionListDeploymentTest is Test, HelperContract { RuleSanctionList_AdminWithAddressZeroNotAllowed.selector ); vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - ruleSanctionList = new RuleSanctionList( + ruleSanctionList = new RuleSanctionsList( address(0), address(forwarder), - ZERO_ADDRESS + ISanctionsList(ZERO_ADDRESS) ); } @@ -59,12 +59,12 @@ contract RuleSanctionListDeploymentTest is Test, HelperContract { sanctionlistOracle = new SanctionListOracle(); vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); // TODO: Event seems not checked by Foundry at deployment - emit SetSanctionListOracle(address(sanctionlistOracle)); + emit SetSanctionListOracle(sanctionlistOracle); - ruleSanctionList = new RuleSanctionList( + ruleSanctionList = new RuleSanctionsList( SANCTIONLIST_OPERATOR_ADDRESS, ZERO_ADDRESS, - address(sanctionlistOracle) + sanctionlistOracle ); assertEq( address(ruleSanctionList.sanctionsList()), diff --git a/test/RuleSanctionList/RuleSanctionListTest.t.sol b/test/RuleSanctionList/RuleSanctionListTest.t.sol index 2bd239e..eea479d 100644 --- a/test/RuleSanctionList/RuleSanctionListTest.t.sol +++ b/test/RuleSanctionList/RuleSanctionListTest.t.sol @@ -4,26 +4,26 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; import "../utils/SanctionListOracle.sol"; -import {RuleSanctionList, SanctionsList} from "src/rules/validation/RuleSanctionList.sol"; +import {RuleSanctionsList, ISanctionsList} from "src/rules/validation/RuleSanctionsList.sol"; /** * @title General functions of the ruleSanctionList */ contract RuleSanctionlistTest is Test, HelperContract { SanctionListOracle sanctionlistOracle; - RuleSanctionList ruleSanctionList; + RuleSanctionsList ruleSanctionList; // Arrange function setUp() public { vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); sanctionlistOracle = new SanctionListOracle(); sanctionlistOracle.addToSanctionsList(ATTACKER); - ruleSanctionList = new RuleSanctionList( + ruleSanctionList = new RuleSanctionsList( SANCTIONLIST_OPERATOR_ADDRESS, ZERO_ADDRESS, - ZERO_ADDRESS + ISanctionsList(ZERO_ADDRESS) ); vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - ruleSanctionList.setSanctionListOracle(address(sanctionlistOracle)); + ruleSanctionList.setSanctionListOracle(sanctionlistOracle); } function testCanReturnTransferRestrictionCode() public { diff --git a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol index 5e5aff6..c6130de 100644 --- a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol +++ b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol @@ -20,7 +20,7 @@ contract RuleWhitelistAccessControl is Test, HelperContract { ); } - function testCannotAttackerAddAddressToTheList() public { + function testCannotAttackeraddAddress() public { vm.expectRevert( abi.encodeWithSelector( AccessControlUnauthorizedAccount.selector, @@ -29,18 +29,18 @@ contract RuleWhitelistAccessControl is Test, HelperContract { ) ); vm.prank(ATTACKER); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); // Assert - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, false); - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 0); } - function testCannotAttackerAddAddressesToTheList() public { + function testCannotAttackeraddAddresses() public { // Arrange - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 0); address[] memory whitelist = new address[](2); whitelist[0] = ADDRESS1; @@ -57,30 +57,30 @@ contract RuleWhitelistAccessControl is Test, HelperContract { vm.prank(ATTACKER); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "addAddressesToTheList(address[])", + "addAddresses(address[])", whitelist ) ); // Assert assertEq(resCallBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, false); - resBool = ruleWhitelist.addressIsListed(ADDRESS2); + resBool = ruleWhitelist.isAddressListed(ADDRESS2); assertEq(resBool, false); - resBool = ruleWhitelist.addressIsListed(ADDRESS3); + resBool = ruleWhitelist.isAddressListed(ADDRESS3); assertFalse(resBool); - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 0); } - function testCannotAttackerRemoveAddressFromTheList() public { + function testCannotAttackerremoveAddress() public { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); // Arrange - Assert - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); // Act @@ -92,16 +92,16 @@ contract RuleWhitelistAccessControl is Test, HelperContract { ) ); vm.prank(ATTACKER); - ruleWhitelist.removeAddressFromTheList(ADDRESS1); + ruleWhitelist.removeAddress(ADDRESS1); // Assert - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 1); } - function testCannotAttackerRemoveAddressesFromTheList() public { + function testCannotAttackerremoveAddresses() public { // Arrange address[] memory whitelist = new address[](2); whitelist[0] = ADDRESS1; @@ -109,15 +109,15 @@ contract RuleWhitelistAccessControl is Test, HelperContract { vm.prank(WHITELIST_OPERATOR_ADDRESS); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "addAddressesToTheList(address[])", + "addAddresses(address[])", whitelist ) ); assertEq(resCallBool, true); // Arrange - Assert - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS2); + resBool = ruleWhitelist.isAddressListed(ADDRESS2); assertEq(resBool, true); // Act @@ -131,17 +131,17 @@ contract RuleWhitelistAccessControl is Test, HelperContract { vm.prank(ATTACKER); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "removeAddressesFromTheList(address[])", + "removeAddresses(address[])", whitelist ) ); // Assert assertEq(resCallBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS2); + resBool = ruleWhitelist.isAddressListed(ADDRESS2); assertEq(resBool, true); - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 2); } } diff --git a/test/RuleWhitelist/CMTATIntegration.t.sol b/test/RuleWhitelist/CMTATIntegration.t.sol index 13f1f34..43a6400 100644 --- a/test/RuleWhitelist/CMTATIntegration.t.sol +++ b/test/RuleWhitelist/CMTATIntegration.t.sol @@ -64,7 +64,7 @@ contract CMTATIntegration is Test, HelperContract { // Arrange uint256 amount = 21; vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS2); + ruleWhitelist.addAddress(ADDRESS2); vm.prank(ADDRESS1); vm.expectRevert( @@ -84,7 +84,7 @@ contract CMTATIntegration is Test, HelperContract { // Arrange uint256 amount = 21; vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); vm.prank(ADDRESS1); vm.expectRevert( @@ -108,7 +108,7 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(DEFAULT_ADMIN_ADDRESS); (bool success, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "addAddressesToTheList(address[])", + "addAddresses(address[])", whitelist ) ); @@ -130,8 +130,8 @@ contract CMTATIntegration is Test, HelperContract { /******* detectTransferRestriction & messageForTransferRestriction *******/ function testDetectAndMessageWithFromNotWhitelisted() public { vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS2); - resBool = ruleWhitelist.addressIsListed(ADDRESS2); + ruleWhitelist.addAddress(ADDRESS2); + resBool = ruleWhitelist.isAddressListed(ADDRESS2); // Assert assertEq(resBool, true); uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( @@ -152,9 +152,9 @@ contract CMTATIntegration is Test, HelperContract { // Arrange // We add the sender to the whitelist vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); // Arrange - Assert - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); // Act uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( @@ -200,7 +200,7 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(DEFAULT_ADMIN_ADDRESS); (bool success, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "addAddressesToTheList(address[])", + "addAddresses(address[])", whitelist ) ); @@ -225,11 +225,11 @@ contract CMTATIntegration is Test, HelperContract { // Arrange // Add address zero to the whitelist vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ZERO_ADDRESS); + ruleWhitelist.addAddress(ZERO_ADDRESS); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); // Arrange - Assert - resBool = ruleWhitelist.addressIsListed(ZERO_ADDRESS); + resBool = ruleWhitelist.isAddressListed(ZERO_ADDRESS); assertEq(resBool, true); // Act diff --git a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol index b09d60a..57c3cba 100644 --- a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol +++ b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol @@ -89,7 +89,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { // Arrange uint256 amount = 21; vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS2); + ruleWhitelist.addAddress(ADDRESS2); vm.prank(ADDRESS1); vm.expectRevert( @@ -109,7 +109,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { // Arrange uint256 amount = 21; vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); vm.prank(ADDRESS1); vm.expectRevert( @@ -128,14 +128,14 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { function testCanMakeATransferIfWhitelistedInSeveralDifferentList() public { // Arrange vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist3.addAddressToTheList(ADDRESS1); + ruleWhitelist3.addAddress(ADDRESS1); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist2.addAddressToTheList(ADDRESS2); + ruleWhitelist2.addAddress(ADDRESS2); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist3.addAddressToTheList(ADDRESS2); + ruleWhitelist3.addAddress(ADDRESS2); // Act vm.prank(ADDRESS1); @@ -153,10 +153,10 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { function testCanMakeATransferIfWhitelistedInDifferentList() public { // Arrange vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist2.addAddressToTheList(ADDRESS2); + ruleWhitelist2.addAddress(ADDRESS2); // Act vm.prank(ADDRESS1); @@ -179,7 +179,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { vm.prank(DEFAULT_ADMIN_ADDRESS); (bool success, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "addAddressesToTheList(address[])", + "addAddresses(address[])", whitelist ) ); @@ -201,8 +201,8 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { /******* detectTransferRestriction & messageForTransferRestriction *******/ function testDetectAndMessageWithFromNotWhitelisted() public { vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS2); - resBool = ruleWhitelist.addressIsListed(ADDRESS2); + ruleWhitelist.addAddress(ADDRESS2); + resBool = ruleWhitelist.isAddressListed(ADDRESS2); // Assert assertEq(resBool, true); uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( @@ -223,9 +223,9 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { // Arrange // We add the sender to the whitelist vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); // Arrange - Assert - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); // Act uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( @@ -281,7 +281,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { vm.prank(DEFAULT_ADMIN_ADDRESS); (bool success, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "addAddressesToTheList(address[])", + "addAddresses(address[])", whitelist ) ); @@ -306,11 +306,11 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { // Arrange // Add address zero to the whitelist vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ZERO_ADDRESS); + ruleWhitelist.addAddress(ZERO_ADDRESS); vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); // Arrange - Assert - resBool = ruleWhitelist.addressIsListed(ZERO_ADDRESS); + resBool = ruleWhitelist.isAddressListed(ZERO_ADDRESS); assertEq(resBool, true); // Act diff --git a/test/RuleWhitelist/RuleWhitelist.t.sol b/test/RuleWhitelist/RuleWhitelist.t.sol index 26f1cc1..b1f7ab9 100644 --- a/test/RuleWhitelist/RuleWhitelist.t.sol +++ b/test/RuleWhitelist/RuleWhitelist.t.sol @@ -17,73 +17,73 @@ contract RuleWhitelistTest is Test, HelperContract { ); } - function _addAddressesToTheList() internal { + function _addAddresses() internal { address[] memory whitelist = new address[](2); whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; vm.prank(WHITELIST_OPERATOR_ADDRESS); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "addAddressesToTheList(address[])", + "addAddresses(address[])", whitelist ) ); // Assert - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 2); assertEq(resCallBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS2); + resBool = ruleWhitelist.isAddressListed(ADDRESS2); assertEq(resBool, true); } function testReturnFalseIfAddressNotWhitelisted() public { // Act - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); // Assert assertFalse(resBool); // Act - resBool = ruleWhitelist.addressIsListed(ADDRESS2); + resBool = ruleWhitelist.isAddressListed(ADDRESS2); // Assert assertFalse(resBool); // Act - resBool = ruleWhitelist.addressIsListed(ADDRESS3); + resBool = ruleWhitelist.isAddressListed(ADDRESS3); // Assert assertFalse(resBool); // Act - resBool = ruleWhitelist.addressIsListed(address(0x0)); + resBool = ruleWhitelist.isAddressListed(address(0x0)); // Assert assertFalse(resBool); } function testAddressIsIndicatedAsWhitelisted() public { // Arrange - Assert - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertFalse(resBool); // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); // Assert - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); } function testAddressesIsIndicatedAsWhitelisted() public { // Arrange - _addAddressesToTheList(); + _addAddresses(); // Act - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); // Assert assertEq(resBool, true); // Act - resBool = ruleWhitelist.addressIsListed(ADDRESS2); + resBool = ruleWhitelist.isAddressListed(ADDRESS2); // Assert assertEq(resBool, true); // Act - resBool = ruleWhitelist.addressIsListed(ADDRESS3); + resBool = ruleWhitelist.isAddressListed(ADDRESS3); // Assert assertFalse(resBool); } @@ -132,7 +132,7 @@ contract RuleWhitelistTest is Test, HelperContract { function testcanTransfer() public { // Arrange - _addAddressesToTheList(); + _addAddresses(); // Act // ADDRESS1 -> ADDRESS2 resBool = ruleWhitelist.canTransfer(ADDRESS1, ADDRESS2, 20); @@ -149,9 +149,9 @@ contract RuleWhitelistTest is Test, HelperContract { assertFalse(resBool); } - function testNumberListedAddress() public { + function testlistedAddressCount() public { // Act - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); // Assert assertEq(resUint256, 0); @@ -162,27 +162,27 @@ contract RuleWhitelistTest is Test, HelperContract { vm.prank(WHITELIST_OPERATOR_ADDRESS); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "addAddressesToTheList(address[])", + "addAddresses(address[])", whitelist ) ); assertEq(resCallBool, true); // Act - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); // Assert assertEq(resUint256, 2); // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "removeAddressesFromTheList(address[])", + "removeAddresses(address[])", whitelist ) ); // Arrange - Assert assertEq(resCallBool, true); // Act - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); // Assert assertEq(resUint256, 0); } @@ -201,7 +201,7 @@ contract RuleWhitelistTest is Test, HelperContract { function testDetectTransferRestrictionTo() public { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); // Act resUint8 = ruleWhitelist.detectTransferRestriction( ADDRESS1, @@ -215,9 +215,9 @@ contract RuleWhitelistTest is Test, HelperContract { function testDetectTransferRestrictionOk() public { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS2); + ruleWhitelist.addAddress(ADDRESS2); // Act resUint8 = ruleWhitelist.detectTransferRestriction( ADDRESS1, diff --git a/test/RuleWhitelist/RuleWhitelistAdd.t.sol b/test/RuleWhitelist/RuleWhitelistAdd.t.sol index 054af69..be18e66 100644 --- a/test/RuleWhitelist/RuleWhitelistAdd.t.sol +++ b/test/RuleWhitelist/RuleWhitelistAdd.t.sol @@ -17,29 +17,29 @@ contract RuleWhitelistAddTest is Test, HelperContract { ); } - function _addAddressesToTheList() internal { + function _addAddresses() internal { address[] memory whitelist = new address[](2); whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; vm.prank(WHITELIST_OPERATOR_ADDRESS); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "addAddressesToTheList(address[])", + "addAddresses(address[])", whitelist ) ); // Assert - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 2); assertEq(resCallBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS2); + resBool = ruleWhitelist.isAddressListed(ADDRESS2); assertEq(resBool, true); address[] memory addressesListInput = new address[](2); addressesListInput[0] = ADDRESS1; addressesListInput[1] = ADDRESS2; - bool[] memory resBools = ruleWhitelist.addressIsListedBatch( + bool[] memory resBools = ruleWhitelist.areAddressesListed( addressesListInput ); assertEq(resBools[0], true); @@ -47,57 +47,57 @@ contract RuleWhitelistAddTest is Test, HelperContract { assertEq(resBools.length, 2); } - function testAddAddressToTheList() public { + function testaddAddress() public { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit AddAddressToTheList(ADDRESS1); - ruleWhitelist.addAddressToTheList(ADDRESS1); + emit AddAddress(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); // Assert - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); address[] memory addressesListInput = new address[](1); addressesListInput[0] = ADDRESS1; - bool[] memory resBools = ruleWhitelist.addressIsListedBatch( + bool[] memory resBools = ruleWhitelist.areAddressesListed( addressesListInput ); assertEq(resBools[0], true); assertEq(resBools.length, 1); - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 1); } - function testAddAddressesToTheList() public { + function testaddAddresses() public { // Arrange - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 0); // Act - _addAddressesToTheList(); + _addAddresses(); // Assert - resBool = ruleWhitelist.addressIsListed(ADDRESS3); + resBool = ruleWhitelist.isAddressListed(ADDRESS3); assertFalse(resBool); - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 2); } function testCanAddAddressZeroToTheWhitelist() public { // Arrange - Assert - resBool = ruleWhitelist.addressIsListed(address(0x0)); + resBool = ruleWhitelist.isAddressListed(address(0x0)); assertEq(resBool, false); // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit AddAddressToTheList(address(0x0)); - ruleWhitelist.addAddressToTheList(address(0x0)); + emit AddAddress(address(0x0)); + ruleWhitelist.addAddress(address(0x0)); // Assert - resBool = ruleWhitelist.addressIsListed(address(0x0)); + resBool = ruleWhitelist.isAddressListed(address(0x0)); assertEq(resBool, true); } function testCanAddAddressesZeroToTheWhitelist() public { // Arrange - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 0); address[] memory whitelist = new address[](3); whitelist[0] = ADDRESS1; @@ -107,10 +107,10 @@ contract RuleWhitelistAddTest is Test, HelperContract { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit AddAddressesToTheList(whitelist); + emit AddAddresses(whitelist); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "addAddressesToTheList(address[])", + "addAddresses(address[])", whitelist ) ); @@ -118,43 +118,43 @@ contract RuleWhitelistAddTest is Test, HelperContract { // Assert - Main // Seem that call returns true even if the function is reverted // TODO : check the return value of call - resBool = ruleWhitelist.addressIsListed(address(0x0)); + resBool = ruleWhitelist.isAddressListed(address(0x0)); assertEq(resBool, true); // Assert - Secondary - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS2); + resBool = ruleWhitelist.isAddressListed(ADDRESS2); assertEq(resBool, true); - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 3); } function testAddAddressTwiceToTheWhitelist() public { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); // Arrange - Assert - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); /// Arrange - vm.expectRevert(Rulelist_AddressAlreadylisted.selector); + vm.expectRevert(RuleAddressSet_AddressAlreadyListed.selector); // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); // no change - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 1); } function testAddAddressesTwiceToTheWhitelist() public { // Arrange // Arrange - first addition - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 0); - _addAddressesToTheList(); + _addAddresses(); // Arrange - second addition address[] memory whitelistDuplicate = new address[](3); // Duplicate address @@ -166,21 +166,21 @@ contract RuleWhitelistAddTest is Test, HelperContract { vm.prank(WHITELIST_OPERATOR_ADDRESS); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "addAddressesToTheList(address[])", + "addAddresses(address[])", whitelistDuplicate ) ); // Assert // no change assertEq(resCallBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS2); + resBool = ruleWhitelist.isAddressListed(ADDRESS2); assertEq(resBool, true); // ADDRESS3 is whitelisted - resBool = ruleWhitelist.addressIsListed(ADDRESS3); + resBool = ruleWhitelist.isAddressListed(ADDRESS3); assertEq(resBool, true); - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 3); } } diff --git a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol index ef219a9..fd19a22 100644 --- a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol +++ b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol @@ -44,7 +44,7 @@ contract RuleWhitelistDeploymentTest is Test, HelperContract { MinimalForwarderMock forwarder = new MinimalForwarderMock(); forwarder.initialize(ERC2771ForwarderDomain); vm.expectRevert( - RuleAddressList_AdminWithAddressZeroNotAllowed.selector + RuleAddressSet_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 f992563..c69228b 100644 --- a/test/RuleWhitelist/RuleWhitelistRemove.t.sol +++ b/test/RuleWhitelist/RuleWhitelistRemove.t.sol @@ -17,50 +17,50 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { ); } - function _addAddressesToTheList() internal { + function _addAddresses() internal { address[] memory whitelist = new address[](2); whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit AddAddressesToTheList(whitelist); + emit AddAddresses(whitelist); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "addAddressesToTheList(address[])", + "addAddresses(address[])", whitelist ) ); // Assert - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 2); assertEq(resCallBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS2); + resBool = ruleWhitelist.isAddressListed(ADDRESS2); assertEq(resBool, true); } - function testremoveAddressFromTheList() public { + function testRemoveAddress() public { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist.addAddressToTheList(ADDRESS1); + ruleWhitelist.addAddress(ADDRESS1); // Arrange - Assert - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit RemoveAddressFromTheList(ADDRESS1); - ruleWhitelist.removeAddressFromTheList(ADDRESS1); + emit RemoveAddress(ADDRESS1); + ruleWhitelist.removeAddress(ADDRESS1); // Assert - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertFalse(resBool); - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 0); } - function testremoveAddressesFromTheList() public { + function testRemoveAddressWhenArrayContainSeveralAddresses() public { // Arrange address[] memory whitelist = new address[](2); whitelist[0] = ADDRESS1; @@ -68,56 +68,56 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { vm.prank(WHITELIST_OPERATOR_ADDRESS); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "addAddressesToTheList(address[])", + "addAddresses(address[])", whitelist ) ); assertEq(resCallBool, true); // Arrange - Assert - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS2); + resBool = ruleWhitelist.isAddressListed(ADDRESS2); assertEq(resBool, true); // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit RemoveAddressesFromTheList(whitelist); + emit RemoveAddresses(whitelist); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "removeAddressesFromTheList(address[])", + "removeAddresses(address[])", whitelist ) ); // Assert assertEq(resCallBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertFalse(resBool); - resBool = ruleWhitelist.addressIsListed(ADDRESS2); + resBool = ruleWhitelist.isAddressListed(ADDRESS2); assertFalse(resBool); - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 0); } function testRemoveAddressNotPresentFromTheWhitelist() public { // Arrange - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertFalse(resBool); - vm.expectRevert(Rulelist_AddressNotPresent.selector); + vm.expectRevert(RuleAddressSet_AddressNotFound.selector); // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit RemoveAddressFromTheList(ADDRESS1); - ruleWhitelist.removeAddressFromTheList(ADDRESS1); + emit RemoveAddress(ADDRESS1); + ruleWhitelist.removeAddress(ADDRESS1); // Assert // no change - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertFalse(resBool); } function testRemoveAddressesNotPresentFromTheWhitelist() public { // Arrange - _addAddressesToTheList(); + _addAddresses(); // Arrange address[] memory whitelistRemove = new address[](3); whitelistRemove[0] = ADDRESS1; @@ -127,20 +127,20 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit RemoveAddressesFromTheList(whitelistRemove); + emit RemoveAddresses(whitelistRemove); (resCallBool, ) = address(ruleWhitelist).call( abi.encodeWithSignature( - "removeAddressesFromTheList(address[])", + "removeAddresses(address[])", whitelistRemove ) ); // Assert assertEq(resCallBool, true); - resBool = ruleWhitelist.addressIsListed(ADDRESS1); + resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertFalse(resBool); - resBool = ruleWhitelist.addressIsListed(ADDRESS2); + resBool = ruleWhitelist.isAddressListed(ADDRESS2); assertFalse(resBool); - resUint256 = ruleWhitelist.numberListedAddress(); + resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 0); } } diff --git a/test/utils/SanctionListOracle.sol b/test/utils/SanctionListOracle.sol index 2edaee7..28adcf9 100644 --- a/test/utils/SanctionListOracle.sol +++ b/test/utils/SanctionListOracle.sol @@ -1,11 +1,12 @@ // SPDX-License-Identifier: MPL-2.0 pragma solidity ^0.8.20; +import {ISanctionsList} from "../../src/rules/interfaces/ISanctionsList.sol"; /** * @notice Test contract from * https://etherscan.io/address/0x40c57923924b5c5c5455c48d93317139addac8fb#code */ -contract SanctionListOracle { +contract SanctionListOracle is ISanctionsList { constructor() {} mapping(address => bool) private sanctionedAddresses; From bde9c92334443e8cf4570437a185d8f0fdacb759 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Thu, 23 Oct 2025 15:28:30 +0200 Subject: [PATCH 03/25] Improve spender check in Whitelist rules --- src/rules/validation/RuleBlacklist.sol | 2 +- src/rules/validation/RuleWhitelist.sol | 17 ++-- src/rules/validation/RuleWhitelistWrapper.sol | 83 +++++++++++-------- .../abstract/RuleWhitelistCommon.sol | 9 +- .../RuleWhitelistAccessControl.t.sol | 3 +- .../RuleWhitelistAccessControlOZ.t.sol | 3 +- test/RuleWhitelist/CMTATIntegration.t.sol | 2 +- .../CMTATIntegrationWhitelistWrapper.t.sol | 12 +-- test/RuleWhitelist/RuleWhitelist.t.sol | 3 +- test/RuleWhitelist/RuleWhitelistAdd.t.sol | 3 +- .../RuleWhitelistDeployment.t.sol | 5 +- test/RuleWhitelist/RuleWhitelistRemove.t.sol | 3 +- 12 files changed, 84 insertions(+), 61 deletions(-) diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol index c596d3c..2633cbf 100644 --- a/src/rules/validation/RuleBlacklist.sol +++ b/src/rules/validation/RuleBlacklist.sol @@ -52,7 +52,7 @@ contract RuleBlacklist is uint256 value ) public view override returns (uint8) { if(isAddressListed(spender)){ - return CODE_ADDRESS_SPENDER_IS_BLACKLISTED; + return CODE_ADDRESS_SPENDER_IS_BLACKLISTED; } else { return detectTransferRestriction(from, to, value); } diff --git a/src/rules/validation/RuleWhitelist.sol b/src/rules/validation/RuleWhitelist.sol index 8a53cc3..1a4845b 100644 --- a/src/rules/validation/RuleWhitelist.sol +++ b/src/rules/validation/RuleWhitelist.sol @@ -14,19 +14,20 @@ import {IIdentityRegistryVerified} from "../interfaces/IIdentityRegistry.sol"; * - Implements {IERC1404} to return specific restriction codes for non-whitelisted transfers. */ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistryVerified{ - /*////////////////////////////////////////////////////////////// + /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ - /** - * @notice Initializes the RuleWhitelist contract. - * @param admin Address that will be granted the default admin role. - * @param forwarderIrrevocable Address of the ERC2771 trusted forwarder (for gasless transactions). + * @param admin Address of the contract (Access Control) + * @param forwarderIrrevocable Address of the forwarder, required for the gasless support */ constructor( address admin, - address forwarderIrrevocable - ) RuleAddressSet(admin, forwarderIrrevocable) {} + address forwarderIrrevocable, + bool checkSpender + ) RuleAddressSet(admin, forwarderIrrevocable) { + _checkSpender = checkSpender; + } /*////////////////////////////////////////////////////////////// TRANSFER RESTRICTION LOGIC @@ -85,7 +86,7 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry address to, uint256 value ) public view override returns (uint8 code) { - if (!isAddressListed(spender)) { + if (_checkSpender && !isAddressListed(spender)) { return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; } return detectTransferRestriction(from, to, value); diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol index a4c3114..799cae1 100644 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -17,17 +17,23 @@ contract RuleWhitelistWrapper is MetaTxModuleStandalone, RuleWhitelistCommon { + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ /** * @param admin Address of the contract (Access Control) * @param forwarderIrrevocable Address of the forwarder, required for the gasless support */ constructor( address admin, - address forwarderIrrevocable + address forwarderIrrevocable, + bool checkSpender ) MetaTxModuleStandalone(forwarderIrrevocable) { if (admin == address(0)) { revert RuleEngineInvariantStorage.RuleEngine_AdminWithAddressZeroNotAllowed(); } + _checkSpender = checkSpender; _grantRole(DEFAULT_ADMIN_ROLE, admin); } @@ -78,45 +84,50 @@ contract RuleWhitelistWrapper is address spender, address from, address to, - uint256 /*value*/ + uint256 value ) public view override returns (uint8) { - address[] memory targetAddress = new address[](3); - bool[] memory isListed = new bool[](3); - bool[] memory result = new bool[](3); - targetAddress[0] = from; - targetAddress[1] = to; - targetAddress[2] = spender; - uint256 rulesLength = rulesCount(); - // For each whitelist rule, we ask if from or to are in the whitelist - for (uint256 i = 0; i < rulesLength; ++i) { - // External call - isListed = RuleAddressSet(rule(i)) - .areAddressesListed(targetAddress); - if (isListed[0] && !result[0]) { - // Update if from is in the list - result[0] = true; - } - if (isListed[1] && !result[1]) { - // Update if to is in the list - result[1] = true; - } - if (isListed[2] && !result[2]) { - // Update if spender is in the list - result[2] = true; + if(!_checkSpender){ + return detectTransferRestriction(from, to, value); + } else { + address[] memory targetAddress = new address[](3); + bool[] memory isListed = new bool[](3); + bool[] memory result = new bool[](3); + targetAddress[0] = from; + targetAddress[1] = to; + targetAddress[2] = spender; + uint256 rulesLength = rulesCount(); + // For each whitelist rule, we ask if from or to are in the whitelist + for (uint256 i = 0; i < rulesLength; ++i) { + // External call + isListed = RuleAddressSet(rule(i)) + .areAddressesListed(targetAddress); + if (isListed[0] && !result[0]) { + // Update if from is in the list + result[0] = true; + } + if (isListed[1] && !result[1]) { + // Update if to is in the list + result[1] = true; + } + if (isListed[2] && !result[2]) { + // Update if spender is in the list + result[2] = true; + } + if (result[0] && result[1] && result[2]) { + break; + } } - if (result[0] && result[1] && result[2]) { - break; + if (!result[0]) { + return CODE_ADDRESS_FROM_NOT_WHITELISTED; + } else if (!result[1]) { + return CODE_ADDRESS_TO_NOT_WHITELISTED; + } else if (!result[2]) { + return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; + } else { + return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } } - if (!result[0]) { - return CODE_ADDRESS_FROM_NOT_WHITELISTED; - } else if (!result[1]) { - return CODE_ADDRESS_TO_NOT_WHITELISTED; - } else if (!result[2]) { - return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; - } else { - return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - } + } /* ============ ACCESS CONTROL ============ */ diff --git a/src/rules/validation/abstract/RuleWhitelistCommon.sol b/src/rules/validation/abstract/RuleWhitelistCommon.sol index 901f1d0..6105601 100644 --- a/src/rules/validation/abstract/RuleWhitelistCommon.sol +++ b/src/rules/validation/abstract/RuleWhitelistCommon.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MPL-2.0 pragma solidity ^0.8.20; -import "./RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol"; -import "./RuleValidateTransfer.sol"; +import {RuleWhitelistInvariantStorage} from "./RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol"; +import {RuleValidateTransfer} from "./RuleValidateTransfer.sol"; /** * @title Rule Whitelist Common @@ -16,10 +16,13 @@ abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInvariantStorage { + bool internal _checkSpender; + + + /*////////////////////////////////////////////////////////////// RESTRICTION CODE LOGIC //////////////////////////////////////////////////////////////*/ - /** * @notice Checks whether a restriction code is recognized by this rule. * @dev diff --git a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol index c6130de..9c5c1e4 100644 --- a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol +++ b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol @@ -16,7 +16,8 @@ contract RuleWhitelistAccessControl is Test, HelperContract { vm.prank(WHITELIST_OPERATOR_ADDRESS); ruleWhitelist = new RuleWhitelist( WHITELIST_OPERATOR_ADDRESS, - ZERO_ADDRESS + ZERO_ADDRESS, + true ); } diff --git a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol index 2fb3bbe..8726afb 100644 --- a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol +++ b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol @@ -14,7 +14,8 @@ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl { vm.prank(WHITELIST_OPERATOR_ADDRESS); ruleWhitelist = new RuleWhitelist( WHITELIST_OPERATOR_ADDRESS, - ZERO_ADDRESS + ZERO_ADDRESS, + true ); } diff --git a/test/RuleWhitelist/CMTATIntegration.t.sol b/test/RuleWhitelist/CMTATIntegration.t.sol index 43a6400..a123fb8 100644 --- a/test/RuleWhitelist/CMTATIntegration.t.sol +++ b/test/RuleWhitelist/CMTATIntegration.t.sol @@ -18,7 +18,7 @@ contract CMTATIntegration is Test, HelperContract { // Arrange function setUp() public { vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); + ruleWhitelist = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true); // global arrange cmtatDeployment = new CMTATDeployment(); CMTAT_CONTRACT = cmtatDeployment.cmtat(); diff --git a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol index 57c3cba..4e4d750 100644 --- a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol +++ b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol @@ -21,12 +21,13 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { // Arrange function setUp() public { vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleWhitelist = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); - ruleWhitelist2 = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); - ruleWhitelist3 = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); + ruleWhitelist = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true); + ruleWhitelist2 = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true); + ruleWhitelist3 = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true); ruleWhitelistWrapper = new RuleWhitelistWrapper( DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS + ZERO_ADDRESS, + true ); vm.prank(DEFAULT_ADMIN_ADDRESS); ruleWhitelistWrapper.addRule(ruleWhitelist); @@ -64,7 +65,8 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { vm.expectRevert(RuleEngine_AdminWithAddressZeroNotAllowed.selector); ruleWhitelistWrapper = new RuleWhitelistWrapper( ZERO_ADDRESS, - ZERO_ADDRESS + ZERO_ADDRESS, + true ); } diff --git a/test/RuleWhitelist/RuleWhitelist.t.sol b/test/RuleWhitelist/RuleWhitelist.t.sol index b1f7ab9..cbea6be 100644 --- a/test/RuleWhitelist/RuleWhitelist.t.sol +++ b/test/RuleWhitelist/RuleWhitelist.t.sol @@ -13,7 +13,8 @@ contract RuleWhitelistTest is Test, HelperContract { vm.prank(WHITELIST_OPERATOR_ADDRESS); ruleWhitelist = new RuleWhitelist( WHITELIST_OPERATOR_ADDRESS, - ZERO_ADDRESS + ZERO_ADDRESS, + true ); } diff --git a/test/RuleWhitelist/RuleWhitelistAdd.t.sol b/test/RuleWhitelist/RuleWhitelistAdd.t.sol index be18e66..d66aa9b 100644 --- a/test/RuleWhitelist/RuleWhitelistAdd.t.sol +++ b/test/RuleWhitelist/RuleWhitelistAdd.t.sol @@ -13,7 +13,8 @@ contract RuleWhitelistAddTest is Test, HelperContract { vm.prank(WHITELIST_OPERATOR_ADDRESS); ruleWhitelist = new RuleWhitelist( WHITELIST_OPERATOR_ADDRESS, - ZERO_ADDRESS + ZERO_ADDRESS, + true ); } diff --git a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol index fd19a22..1592843 100644 --- a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol +++ b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol @@ -20,7 +20,8 @@ contract RuleWhitelistDeploymentTest is Test, HelperContract { vm.prank(WHITELIST_OPERATOR_ADDRESS); ruleWhitelist = new RuleWhitelist( WHITELIST_OPERATOR_ADDRESS, - address(forwarder) + address(forwarder), + true ); // assert @@ -47,6 +48,6 @@ contract RuleWhitelistDeploymentTest is Test, HelperContract { RuleAddressSet_AdminWithAddressZeroNotAllowed.selector ); vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist = new RuleWhitelist(address(0), address(forwarder)); + ruleWhitelist = new RuleWhitelist(address(0), address(forwarder), true); } } diff --git a/test/RuleWhitelist/RuleWhitelistRemove.t.sol b/test/RuleWhitelist/RuleWhitelistRemove.t.sol index c69228b..9689f65 100644 --- a/test/RuleWhitelist/RuleWhitelistRemove.t.sol +++ b/test/RuleWhitelist/RuleWhitelistRemove.t.sol @@ -13,7 +13,8 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { vm.prank(WHITELIST_OPERATOR_ADDRESS); ruleWhitelist = new RuleWhitelist( WHITELIST_OPERATOR_ADDRESS, - ZERO_ADDRESS + ZERO_ADDRESS, + true ); } From bca72292952e345298ff2d951ca9c5771a1a886d Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Thu, 23 Oct 2025 15:44:09 +0200 Subject: [PATCH 04/25] WhitelistWrapper: Reduce contract code size --- src/rules/validation/RuleWhitelistWrapper.sol | 121 +++++++++--------- 1 file changed, 57 insertions(+), 64 deletions(-) diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol index 799cae1..99fa578 100644 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -49,33 +49,16 @@ contract RuleWhitelistWrapper is uint256 /*value*/ ) public view override returns (uint8) { address[] memory targetAddress = new address[](2); - bool[] memory isListed = new bool[](2); - bool[] memory result = new bool[](2); targetAddress[0] = from; targetAddress[1] = to; - uint256 rulesLength = rulesCount(); - // For each whitelist rule, we ask if from or to are in the whitelist - for (uint256 i = 0; i < rulesLength; ++i) { - // External call - isListed = RuleAddressSet(rule(i)) - .areAddressesListed(targetAddress); - if (isListed[0] && !result[0]) { - // Update if from is in the list - result[0] = true; - } - if (isListed[1] && !result[1]) { - // Update if to is in the list - result[1] = true; - } - if (result[0] && result[1]) { - break; - } - } - if (!result[0]) { + + bool[] memory result = _detectTransferRestriction(targetAddress); + + if (!result[0]){ return CODE_ADDRESS_FROM_NOT_WHITELISTED; - } else if (!result[1]) { + } else if (!result[1]){ return CODE_ADDRESS_TO_NOT_WHITELISTED; - } else { + } else{ return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } } @@ -86,48 +69,26 @@ contract RuleWhitelistWrapper is address to, uint256 value ) public view override returns (uint8) { - if(!_checkSpender){ - return detectTransferRestriction(from, to, value); - } else { - address[] memory targetAddress = new address[](3); - bool[] memory isListed = new bool[](3); - bool[] memory result = new bool[](3); - targetAddress[0] = from; - targetAddress[1] = to; - targetAddress[2] = spender; - uint256 rulesLength = rulesCount(); - // For each whitelist rule, we ask if from or to are in the whitelist - for (uint256 i = 0; i < rulesLength; ++i) { - // External call - isListed = RuleAddressSet(rule(i)) - .areAddressesListed(targetAddress); - if (isListed[0] && !result[0]) { - // Update if from is in the list - result[0] = true; - } - if (isListed[1] && !result[1]) { - // Update if to is in the list - result[1] = true; - } - if (isListed[2] && !result[2]) { - // Update if spender is in the list - result[2] = true; - } - if (result[0] && result[1] && result[2]) { - break; - } - } - if (!result[0]) { - return CODE_ADDRESS_FROM_NOT_WHITELISTED; - } else if (!result[1]) { - return CODE_ADDRESS_TO_NOT_WHITELISTED; - } else if (!result[2]) { - return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; - } else { - return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - } + if (!_checkSpender) { + return detectTransferRestriction(from, to, value); + } + + address[] memory targetAddress = new address[](2); + targetAddress[0] = from; + targetAddress[1] = to; + targetAddress[2] = spender; + + bool[] memory result = _detectTransferRestriction(targetAddress); + + if (!result[0]){ + return CODE_ADDRESS_FROM_NOT_WHITELISTED; + } else if (!result[1]){ + return CODE_ADDRESS_TO_NOT_WHITELISTED; + } else if (!result[2]){ + return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; + } else{ + return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } - } /* ============ ACCESS CONTROL ============ */ @@ -147,6 +108,38 @@ contract RuleWhitelistWrapper is } + function _detectTransferRestriction(address[] memory targetAddress) + internal + view + returns (bool[] memory) +{ + uint256 rulesLength = rulesCount(); + bool[] memory result = new bool[](targetAddress.length); + for (uint256 i = 0; i < rulesLength; ++i) { + // Call the whitelist rules + bool[] memory isListed = RuleAddressSet(rule(i)).areAddressesListed(targetAddress); + for (uint256 j = 0; j < targetAddress.length; ++j) { + if (isListed[j]){ + result[j] = true; + } + } + + // Break early if all listed + bool allListed = true; + for (uint256 k = 0; k < result.length; ++k) { + if (!result[k]) { + allListed = false; + break; + } + } + if (allListed){ + break; + } + } + return result; +} + + /*////////////////////////////////////////////////////////////// ERC-2771 //////////////////////////////////////////////////////////////*/ From 0d76457d604f13c74d67f3100912e1effacea856 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Tue, 18 Nov 2025 15:50:45 +0100 Subject: [PATCH 05/25] Improve test and structure --- src/rules/interfaces/IIdentityRegistry.sol | 3 +- src/rules/interfaces/ISanctionsList.sol | 2 +- src/rules/validation/RuleBlacklist.sol | 81 ++++------ src/rules/validation/RuleSanctionsList.sol | 113 +++++--------- src/rules/validation/RuleWhitelist.sol | 47 +++--- src/rules/validation/RuleWhitelistWrapper.sol | 140 +++++++----------- .../RuleAddressSet/RuleAddressSet.sol | 111 ++++---------- .../RuleAddressSet/RuleAddressSetInternal.sol | 9 +- .../RuleAddressSetInvariantStorage.sol | 6 +- .../RuleBlacklistInvariantStorage.sol | 17 +-- .../RuleWhitelistInvariantStorage.sol | 17 +-- .../RuleSanctionsListInvariantStorage.sol | 25 ++-- .../abstract/RuleValidateTransfer.sol | 36 ++--- .../abstract/RuleWhitelistCommon.sol | 63 +++----- test/HelperContract.sol | 20 +-- test/RuleBlacklist/CMTATIntegration.t.sol | 96 +++--------- test/RuleBlacklist/RuleBlacklist.t.sol | 9 +- .../RuleSanctionListAddTest.t.sol | 22 +-- .../RuleSanctionListDeploymentTest.t.sol | 35 ++--- .../RuleSanctionListTest.t.sol | 50 ++----- .../RuleWhitelistAccessControl.t.sol | 51 +------ .../RuleWhitelistAccessControlOZ.t.sol | 34 +---- test/RuleWhitelist/CMTATIntegration.t.sol | 86 +++-------- .../CMTATIntegrationWhitelistWrapper.t.sol | 107 ++++--------- test/RuleWhitelist/RuleWhitelist.t.sol | 69 ++------- test/RuleWhitelist/RuleWhitelistAdd.t.sol | 36 +---- .../RuleWhitelistDeployment.t.sol | 20 +-- test/RuleWhitelist/RuleWhitelistRemove.t.sol | 35 +---- test/utils/SanctionListOracle.sol | 1 + 29 files changed, 397 insertions(+), 944 deletions(-) diff --git a/src/rules/interfaces/IIdentityRegistry.sol b/src/rules/interfaces/IIdentityRegistry.sol index 0212538..86d11d3 100644 --- a/src/rules/interfaces/IIdentityRegistry.sol +++ b/src/rules/interfaces/IIdentityRegistry.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.20; - interface IIdentityRegistryVerified { // registry consultation function isVerified(address _userAddress) external view returns (bool); @@ -11,4 +10,4 @@ interface IIdentityRegistryVerified { interface IIdentityRegistryContains { // registry consultation function contains(address _userAddress) external view returns (bool); -} \ No newline at end of file +} diff --git a/src/rules/interfaces/ISanctionsList.sol b/src/rules/interfaces/ISanctionsList.sol index 2159bd0..8a5775f 100644 --- a/src/rules/interfaces/ISanctionsList.sol +++ b/src/rules/interfaces/ISanctionsList.sol @@ -4,4 +4,4 @@ pragma solidity ^0.8.20; interface ISanctionsList { function isSanctioned(address addr) external view returns (bool); -} \ No newline at end of file +} diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol index 2633cbf..d1d571f 100644 --- a/src/rules/validation/RuleBlacklist.sol +++ b/src/rules/validation/RuleBlacklist.sol @@ -10,32 +10,26 @@ import "./abstract/RuleValidateTransfer.sol"; * @title a blacklist manager */ -contract RuleBlacklist is - RuleValidateTransfer, - RuleAddressSet, - RuleBlacklistInvariantStorage -{ - +contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInvariantStorage { /** * @param admin Address of the contract (Access Control) * @param forwarderIrrevocable Address of the forwarder, required for the gasless support */ - constructor( - address admin, - address forwarderIrrevocable - ) RuleAddressSet(admin, forwarderIrrevocable) {} + constructor(address admin, address forwarderIrrevocable) RuleAddressSet(admin, forwarderIrrevocable) {} /** * @notice Check if an addres is in the whitelist or not * @param from the origin address * @param to the destination address * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - **/ - function detectTransferRestriction( - address from, - address to, - uint256 /* value */ - ) public view override returns (uint8) { + * + */ + function detectTransferRestriction(address from, address to, uint256 /* value */ ) + public + view + override + returns (uint8) + { if (isAddressListed(from)) { return CODE_ADDRESS_FROM_IS_BLACKLISTED; } else if (isAddressListed(to)) { @@ -45,72 +39,55 @@ contract RuleBlacklist is } } - function detectTransferRestrictionFrom( - address spender, - address from, - address to, - uint256 value - ) public view override returns (uint8) { - if(isAddressListed(spender)){ + function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) + public + view + override + returns (uint8) + { + if (isAddressListed(spender)) { return CODE_ADDRESS_SPENDER_IS_BLACKLISTED; } else { return detectTransferRestriction(from, to, value); } } - /** * @notice To know if the restriction code is valid for this rule or not. * @param _restrictionCode The target restriction code * @return true if the restriction code is known, false otherwise - **/ - function canReturnTransferRestrictionCode( - uint8 _restrictionCode - ) external pure override returns (bool) { - return - _restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED || - _restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED - || _restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED; + * + */ + function canReturnTransferRestrictionCode(uint8 _restrictionCode) external pure override returns (bool) { + return _restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED + || _restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED || _restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED; } /** * @notice Return the corresponding message * @param _restrictionCode The target restriction code * @return true if the transfer is valid, false otherwise - **/ - function messageForTransferRestriction( - uint8 _restrictionCode - ) external pure override returns (string memory) { + * + */ + function messageForTransferRestriction(uint8 _restrictionCode) external pure override returns (string memory) { if (_restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED) { return TEXT_ADDRESS_FROM_IS_BLACKLISTED; } else if (_restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED) { return TEXT_ADDRESS_TO_IS_BLACKLISTED; } else if (_restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED) { return TEXT_ADDRESS_SPENDER_IS_BLACKLISTED; - } - else { + } else { return TEXT_CODE_NOT_FOUND; } } function transferred(address from, address to, uint256 value) public view { uint8 code = this.detectTransferRestriction(from, to, value); - require( - code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), - RuleBlacklist_InvalidTransfer(from, to, value, code) - ); + require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleBlacklist_InvalidTransfer(from, to, value, code)); } - function transferred( - address spender, - address from, - address to, - uint256 value - ) public view { + function transferred(address spender, address from, address to, uint256 value) public view { uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); - require( - code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), - RuleBlacklist_InvalidTransfer(from, to, value, code) - ); + require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleBlacklist_InvalidTransfer(from, to, value, code)); } } diff --git a/src/rules/validation/RuleSanctionsList.sol b/src/rules/validation/RuleSanctionsList.sol index 70515a5..b4f388a 100644 --- a/src/rules/validation/RuleSanctionsList.sol +++ b/src/rules/validation/RuleSanctionsList.sol @@ -6,8 +6,7 @@ import {AccessControl} from "OZ/access/AccessControl.sol"; import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../modules/MetaTxModuleStandalone.sol"; import {RuleSanctionsListInvariantStorage} from "./abstract/RuleSanctionsListInvariantStorage.sol"; import {RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol"; -import {ISanctionsList } from "../interfaces/ISanctionsList.sol"; - +import {ISanctionsList} from "../interfaces/ISanctionsList.sol"; contract RuleSanctionsList is AccessControl, @@ -15,18 +14,15 @@ contract RuleSanctionsList is RuleValidateTransfer, RuleSanctionsListInvariantStorage { - ISanctionsList 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, - ISanctionsList sanctionContractOracle_ - ) MetaTxModuleStandalone(forwarderIrrevocable) { + constructor(address admin, address forwarderIrrevocable, ISanctionsList sanctionContractOracle_) + MetaTxModuleStandalone(forwarderIrrevocable) + { if (admin == address(0)) { revert RuleSanctionList_AdminWithAddressZeroNotAllowed(); } @@ -41,9 +37,7 @@ contract RuleSanctionsList is * @param sanctionContractOracle_ address of your oracle contract * @dev zero address is authorized to authorize all transfers */ - function setSanctionListOracle( - ISanctionsList sanctionContractOracle_ - ) public onlyRole(SANCTIONLIST_ROLE) { + function setSanctionListOracle(ISanctionsList sanctionContractOracle_) public onlyRole(SANCTIONLIST_ROLE) { _setSanctionListOracle(sanctionContractOracle_); } @@ -52,12 +46,14 @@ contract RuleSanctionsList is * @param from the origin address * @param to the destination address * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - **/ - function detectTransferRestriction( - address from, - address to, - uint256 /*value */ - ) public view override returns (uint8) { + * + */ + function detectTransferRestriction(address from, address to, uint256 /*value */ ) + public + view + override + returns (uint8) + { if (address(sanctionsList) != address(0)) { if (sanctionsList.isSanctioned(from)) { return CODE_ADDRESS_FROM_IS_SANCTIONED; @@ -68,18 +64,17 @@ contract RuleSanctionsList is return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } - - function detectTransferRestrictionFrom( - address spender, - address from, - address to, - uint256 value - ) public view override returns (uint8) { - if(address(sanctionsList) != address(0)){ + function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) + public + view + override + returns (uint8) + { + if (address(sanctionsList) != address(0)) { if (sanctionsList.isSanctioned(spender)) { return CODE_ADDRESS_SPENDER_IS_SANCTIONED; } else { - return detectTransferRestriction(from,to,value); + return detectTransferRestriction(from, to, value); } } return uint8(REJECTED_CODE_BASE.TRANSFER_OK); @@ -89,24 +84,20 @@ contract RuleSanctionsList is * @notice To know if the restriction code is valid for this rule or not. * @param _restrictionCode The target restriction code * @return true if the restriction code is known, false otherwise - **/ - function canReturnTransferRestrictionCode( - uint8 _restrictionCode - ) external pure override returns (bool) { - return - _restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED || - _restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED|| - _restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED; + * + */ + function canReturnTransferRestrictionCode(uint8 _restrictionCode) external pure override returns (bool) { + return _restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED || _restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED + || _restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED; } /** * @notice Return the corresponding message * @param _restrictionCode The target restriction code * @return true if the transfer is valid, false otherwise - **/ - function messageForTransferRestriction( - uint8 _restrictionCode - ) external pure override returns (string memory) { + * + */ + 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) { @@ -120,40 +111,25 @@ contract RuleSanctionsList is function transferred(address from, address to, uint256 value) public view { uint8 code = this.detectTransferRestriction(from, to, value); - require( - code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), - RuleSanctionsList_InvalidTransfer(from, to, value, code) - ); + require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleSanctionsList_InvalidTransfer(from, to, value, code)); } - function transferred( - address spender, - address from, - address to, - uint256 value - ) public view { + function transferred(address spender, address from, address to, uint256 value) public view { uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); - require( - code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), - RuleSanctionsList_InvalidTransfer(from, to, value, code) - ); + require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleSanctionsList_InvalidTransfer(from, to, value, code)); } /* ============ ACCESS CONTROL ============ */ /** * @dev Returns `true` if `account` has been granted `role`. */ - function hasRole( - bytes32 role, - address account - ) public view virtual override(AccessControl) returns (bool) { + function hasRole(bytes32 role, address account) public view virtual override(AccessControl) returns (bool) { // The Default Admin has all roles if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { return true; - } else{ + } else { return AccessControl.hasRole(role, account); } - } /*////////////////////////////////////////////////////////////// @@ -172,36 +148,21 @@ contract RuleSanctionsList is /** * @dev This surcharge is not necessary if you do not use the MetaTxModule */ - function _msgSender() - internal - view - override(ERC2771Context, Context) - returns (address sender) - { + function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) { return ERC2771Context._msgSender(); } /** * @dev This surcharge is not necessary if you do not use the MetaTxModule */ - function _msgData() - internal - view - override(ERC2771Context, Context) - returns (bytes calldata) - { + function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) { return ERC2771Context._msgData(); } /** * @dev This surcharge is not necessary if you do not use the MetaTxModule */ - function _contextSuffixLength() - internal - view - override(ERC2771Context, Context) - returns (uint256) - { + function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { return ERC2771Context._contextSuffixLength(); } } diff --git a/src/rules/validation/RuleWhitelist.sol b/src/rules/validation/RuleWhitelist.sol index 1a4845b..ae9032e 100644 --- a/src/rules/validation/RuleWhitelist.sol +++ b/src/rules/validation/RuleWhitelist.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.20; import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol"; import {RuleWhitelistCommon} from "./abstract/RuleWhitelistCommon.sol"; import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; -import {IIdentityRegistryVerified} from "../interfaces/IIdentityRegistry.sol"; +import {IIdentityRegistryVerified} from "../interfaces/IIdentityRegistry.sol"; /** * @title Rule Whitelist * @notice Manages a whitelist of authorized addresses and enforces whitelist-based transfer restrictions. @@ -13,19 +13,18 @@ import {IIdentityRegistryVerified} from "../interfaces/IIdentityRegistry.sol"; * - Integrates restriction code logic from {RuleWhitelistCommon}. * - Implements {IERC1404} to return specific restriction codes for non-whitelisted transfers. */ -contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistryVerified{ - /*////////////////////////////////////////////////////////////// + +contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistryVerified { + /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ /** * @param admin Address of the contract (Access Control) * @param forwarderIrrevocable Address of the forwarder, required for the gasless support */ - constructor( - address admin, - address forwarderIrrevocable, - bool checkSpender - ) RuleAddressSet(admin, forwarderIrrevocable) { + constructor(address admin, address forwarderIrrevocable, bool checkSpender) + RuleAddressSet(admin, forwarderIrrevocable) + { _checkSpender = checkSpender; } @@ -35,8 +34,8 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry /** * @notice Detects whether a transfer between two addresses is allowed under the whitelist rule. - * @dev - * - Returns a restriction code indicating why a transfer is blocked. + * @dev + * - Returns a restriction code indicating why a transfer is blocked. * - Implements the `IERC1404.detectTransferRestriction` interface. * @param from The address sending tokens. * @param to The address receiving tokens. @@ -49,11 +48,12 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry * | `to` not whitelisted | `CODE_ADDRESS_TO_NOT_WHITELISTED` | * | Both whitelisted | `TRANSFER_OK` | */ - function detectTransferRestriction( - address from, - address to, - uint256 value - ) public view override returns (uint8 code) { + function detectTransferRestriction(address from, address to, uint256 value) + public + view + override + returns (uint8 code) + { if (!isAddressListed(from)) { return CODE_ADDRESS_FROM_NOT_WHITELISTED; } else if (!isAddressListed(to)) { @@ -65,7 +65,7 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry /** * @notice Detects transfer restriction for delegated transfers (`transferFrom`). - * @dev + * @dev * - Checks the `spender`, `from`, and `to` addresses for whitelist compliance. * - Implements `IERC1404Extend.detectTransferRestrictionFrom`. * @param spender The address initiating the transfer on behalf of another. @@ -80,12 +80,12 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry * | `from` or `to` not whitelisted | respective restriction code from `detectTransferRestriction` | * | All whitelisted | `TRANSFER_OK` | */ - function detectTransferRestrictionFrom( - address spender, - address from, - address to, - uint256 value - ) public view override returns (uint8 code) { + function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) + public + view + override + returns (uint8 code) + { if (_checkSpender && !isAddressListed(spender)) { return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; } @@ -105,5 +105,4 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry { isListed = _isAddressListed(targetAddress); } - -} \ No newline at end of file +} diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol index 99fa578..16730e8 100644 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -12,24 +12,18 @@ import {IRule} from "RuleEngine/interfaces/IRule.sol"; /** * @title Wrapper to call several different whitelist rules */ -contract RuleWhitelistWrapper is - RulesManagementModule, - MetaTxModuleStandalone, - RuleWhitelistCommon -{ - /*////////////////////////////////////////////////////////////// +contract RuleWhitelistWrapper is RulesManagementModule, MetaTxModuleStandalone, RuleWhitelistCommon { + /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ /** * @param admin Address of the contract (Access Control) * @param forwarderIrrevocable Address of the forwarder, required for the gasless support */ - constructor( - address admin, - address forwarderIrrevocable, - bool checkSpender - ) MetaTxModuleStandalone(forwarderIrrevocable) { + constructor(address admin, address forwarderIrrevocable, bool checkSpender) + MetaTxModuleStandalone(forwarderIrrevocable) + { if (admin == address(0)) { revert RuleEngineInvariantStorage.RuleEngine_AdminWithAddressZeroNotAllowed(); } @@ -42,36 +36,38 @@ contract RuleWhitelistWrapper is * @param from the origin address * @param to the destination address * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - **/ - function detectTransferRestriction( - address from, - address to, - uint256 /*value*/ - ) public view override returns (uint8) { + * + */ + function detectTransferRestriction(address from, address to, uint256 /*value*/ ) + public + view + override + returns (uint8) + { address[] memory targetAddress = new address[](2); targetAddress[0] = from; targetAddress[1] = to; - + bool[] memory result = _detectTransferRestriction(targetAddress); - if (!result[0]){ + if (!result[0]) { return CODE_ADDRESS_FROM_NOT_WHITELISTED; - } else if (!result[1]){ + } else if (!result[1]) { return CODE_ADDRESS_TO_NOT_WHITELISTED; - } else{ + } else { return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } } - function detectTransferRestrictionFrom( - address spender, - address from, - address to, - uint256 value - ) public view override returns (uint8) { - if (!_checkSpender) { - return detectTransferRestriction(from, to, value); - } + function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) + public + view + override + returns (uint8) + { + if (!_checkSpender) { + return detectTransferRestriction(from, to, value); + } address[] memory targetAddress = new address[](2); targetAddress[0] = from; @@ -80,13 +76,13 @@ contract RuleWhitelistWrapper is bool[] memory result = _detectTransferRestriction(targetAddress); - if (!result[0]){ + if (!result[0]) { return CODE_ADDRESS_FROM_NOT_WHITELISTED; - } else if (!result[1]){ + } else if (!result[1]) { return CODE_ADDRESS_TO_NOT_WHITELISTED; - } else if (!result[2]){ - return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; - } else{ + } else if (!result[2]) { + return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; + } else { return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } } @@ -95,50 +91,41 @@ contract RuleWhitelistWrapper is /** * @dev Returns `true` if `account` has been granted `role`. */ - function hasRole( - bytes32 role, - address account - ) public view virtual override(AccessControl) returns (bool) { + function hasRole(bytes32 role, address account) public view virtual override(AccessControl) returns (bool) { // The Default Admin has all roles if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { return true; } else { return AccessControl.hasRole(role, account); } - } - function _detectTransferRestriction(address[] memory targetAddress) - internal - view - returns (bool[] memory) -{ - uint256 rulesLength = rulesCount(); - bool[] memory result = new bool[](targetAddress.length); - for (uint256 i = 0; i < rulesLength; ++i) { - // Call the whitelist rules - bool[] memory isListed = RuleAddressSet(rule(i)).areAddressesListed(targetAddress); - for (uint256 j = 0; j < targetAddress.length; ++j) { - if (isListed[j]){ - result[j] = true; - } - } + function _detectTransferRestriction(address[] memory targetAddress) internal view returns (bool[] memory) { + uint256 rulesLength = rulesCount(); + bool[] memory result = new bool[](targetAddress.length); + for (uint256 i = 0; i < rulesLength; ++i) { + // Call the whitelist rules + bool[] memory isListed = RuleAddressSet(rule(i)).areAddressesListed(targetAddress); + for (uint256 j = 0; j < targetAddress.length; ++j) { + if (isListed[j]) { + result[j] = true; + } + } - // Break early if all listed - bool allListed = true; - for (uint256 k = 0; k < result.length; ++k) { - if (!result[k]) { - allListed = false; + // Break early if all listed + bool allListed = true; + for (uint256 k = 0; k < result.length; ++k) { + if (!result[k]) { + allListed = false; + break; + } + } + if (allListed) { break; } } - if (allListed){ - break; - } + return result; } - return result; -} - /*////////////////////////////////////////////////////////////// ERC-2771 @@ -147,36 +134,21 @@ contract RuleWhitelistWrapper is /** * @dev This surcharge is not necessary if you do not use the MetaTxModule */ - function _msgSender() - internal - view - override(ERC2771Context, Context) - returns (address sender) - { + function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) { return ERC2771Context._msgSender(); } /** * @dev This surcharge is not necessary if you do not use the MetaTxModule */ - function _msgData() - internal - view - override(ERC2771Context, Context) - returns (bytes calldata) - { + function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) { return ERC2771Context._msgData(); } /** * @dev This surcharge is not necessary if you do not use the MetaTxModule */ - function _contextSuffixLength() - internal - view - override(ERC2771Context, Context) - returns (uint256) - { + function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { return ERC2771Context._contextSuffixLength(); } } diff --git a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol index 7b2a94c..a32044f 100644 --- a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol +++ b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol @@ -9,12 +9,13 @@ import {IIdentityRegistryContains} from "../../../interfaces/IIdentityRegistry.s /** * @title Rule Address Set * @notice Manages a permissioned set of addresses related to rule logic. - * @dev - * - Provides controlled functions for adding and removing addresses. - * - Integrates `AccessControl` for role-based access. - * - Supports gasless transactions via ERC-2771 meta-transactions. + * @dev + * - Provides controlled functions for adding and removing addresses. + * - Integrates `AccessControl` for role-based access. + * - Supports gasless transactions via ERC-2771 meta-transactions. * - Extends internal logic defined in {RuleAddressSetInternal}. */ + abstract contract RuleAddressSet is AccessControl, MetaTxModuleStandalone, @@ -39,10 +40,7 @@ abstract contract RuleAddressSet is * @param forwarderIrrevocable Address of the ERC2771 forwarder (for meta-transactions). * @dev Reverts if the admin address is the zero address. */ - constructor( - address admin, - address forwarderIrrevocable - ) MetaTxModuleStandalone(forwarderIrrevocable) { + constructor(address admin, address forwarderIrrevocable) MetaTxModuleStandalone(forwarderIrrevocable) { if (admin == address(0)) { revert RuleAddressSet_AdminWithAddressZeroNotAllowed(); } @@ -55,43 +53,36 @@ abstract contract RuleAddressSet is /** * @notice Adds multiple addresses to the set. - * @dev - * - Does not revert if an address is already listed. - * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`. + * @dev + * - Does not revert if an address is already listed. + * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`. * @param targetAddresses Array of addresses to be added. */ - function addAddresses( - address[] calldata targetAddresses - ) public onlyRole(ADDRESS_LIST_ADD_ROLE) { + function addAddresses(address[] calldata targetAddresses) public onlyRole(ADDRESS_LIST_ADD_ROLE) { _addAddresses(targetAddresses); emit AddAddresses(targetAddresses); } /** * @notice Removes multiple addresses from the set. - * @dev - * - Does not revert if an address is not listed. - * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`. + * @dev + * - Does not revert if an address is not listed. + * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`. * @param targetAddresses Array of addresses to remove. */ - function removeAddresses( - address[] calldata targetAddresses - ) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) { + function removeAddresses(address[] calldata targetAddresses) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) { _removeAddresses(targetAddresses); emit RemoveAddresses(targetAddresses); } /** * @notice Adds a single address to the set. - * @dev - * - Reverts if the address is already listed. - * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`. + * @dev + * - Reverts if the address is already listed. + * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`. * @param targetAddress The address to be added. */ - function addAddress(address targetAddress) - public - onlyRole(ADDRESS_LIST_ADD_ROLE) - { + function addAddress(address targetAddress) public onlyRole(ADDRESS_LIST_ADD_ROLE) { if (_isAddressListed(targetAddress)) { revert RuleAddressSet_AddressAlreadyListed(); } @@ -101,15 +92,12 @@ abstract contract RuleAddressSet is /** * @notice Removes a single address from the set. - * @dev - * - Reverts if the address is not listed. - * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`. + * @dev + * - Reverts if the address is not listed. + * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`. * @param targetAddress The address to be removed. */ - function removeAddress(address targetAddress) - public - onlyRole(ADDRESS_LIST_REMOVE_ROLE) - { + function removeAddress(address targetAddress) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) { if (!_isAddressListed(targetAddress)) { revert RuleAddressSet_AddressNotFound(); } @@ -130,12 +118,7 @@ abstract contract RuleAddressSet is * @param targetAddress The address to check. * @return isListed True if listed, false otherwise. */ - function contains(address targetAddress) - public - view - override(IIdentityRegistryContains) - returns (bool isListed) - { + function contains(address targetAddress) public view override(IIdentityRegistryContains) returns (bool isListed) { isListed = _isAddressListed(targetAddress); } @@ -144,11 +127,7 @@ abstract contract RuleAddressSet is * @param targetAddress The address to check. * @return isListed True if listed, false otherwise. */ - function isAddressListed(address targetAddress) - public - view - returns (bool isListed) - { + function isAddressListed(address targetAddress) public view returns (bool isListed) { isListed = _isAddressListed(targetAddress); } @@ -157,36 +136,25 @@ abstract contract RuleAddressSet is * @param targetAddresses Array of addresses to check. * @return results Array of booleans corresponding to listing status. */ - function areAddressesListed( - address[] memory targetAddresses - ) public view returns (bool[] memory results) { + function areAddressesListed(address[] memory targetAddresses) public view returns (bool[] memory results) { results = new bool[](targetAddresses.length); for (uint256 i = 0; i < targetAddresses.length; ++i) { results[i] = _isAddressListed(targetAddresses[i]); } } - - - - - - /*////////////////////////////////////////////////////////////// ACCESS CONTROL //////////////////////////////////////////////////////////////*/ /** * @notice Returns `true` if `account` has been granted `role`. - * @dev - * The `DEFAULT_ADMIN_ROLE` implicitly grants all roles. + * @dev + * The `DEFAULT_ADMIN_ROLE` implicitly grants all roles. * @param role The role identifier. * @param account The account address to check. */ - function hasRole( - bytes32 role, - address account - ) public view virtual override(AccessControl) returns (bool) { + function hasRole(bytes32 role, address account) public view virtual override(AccessControl) returns (bool) { if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { return true; } @@ -198,32 +166,17 @@ abstract contract RuleAddressSet is //////////////////////////////////////////////////////////////*/ /// @inheritdoc ERC2771Context - function _msgSender() - internal - view - override(ERC2771Context, Context) - returns (address sender) - { + function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) { return ERC2771Context._msgSender(); } /// @inheritdoc ERC2771Context - function _msgData() - internal - view - override(ERC2771Context, Context) - returns (bytes calldata) - { + function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) { return ERC2771Context._msgData(); } /// @inheritdoc ERC2771Context - function _contextSuffixLength() - internal - view - override(ERC2771Context, Context) - returns (uint256) - { + function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { return ERC2771Context._contextSuffixLength(); } -} \ No newline at end of file +} diff --git a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol index 4bf256e..b4fb06b 100644 --- a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol +++ b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol @@ -6,7 +6,7 @@ import {EnumerableSet} from "OZ/utils/structs/EnumerableSet.sol"; /** * @title Rule Address Set (Internal) * @notice Internal utility for managing a set of rule-related addresses. - * @dev + * @dev * - Uses OpenZeppelin's EnumerableSet for efficient enumeration. * - Designed for internal inheritance and logic composition. * - Batch operations do not revert when individual entries are invalid. @@ -14,7 +14,6 @@ import {EnumerableSet} from "OZ/utils/structs/EnumerableSet.sol"; abstract contract RuleAddressSetInternal { using EnumerableSet for EnumerableSet.AddressSet; - /*////////////////////////////////////////////////////////////// STATE VARIABLES //////////////////////////////////////////////////////////////*/ @@ -28,7 +27,7 @@ abstract contract RuleAddressSetInternal { /** * @notice Adds multiple addresses to the set. - * @dev + * @dev * - Does not revert if an address is already listed. * - Skips existing entries silently. * @param addressesToAdd The array of addresses to add. @@ -41,7 +40,7 @@ abstract contract RuleAddressSetInternal { /** * @notice Removes multiple addresses from the set. - * @dev + * @dev * - Does not revert if an address is not found. * - Skips non-existing entries silently. * @param addressesToRemove The array of addresses to remove. @@ -84,4 +83,4 @@ abstract contract RuleAddressSetInternal { function _isAddressListed(address targetAddress) internal view returns (bool isListed) { isListed = _listedAddresses.contains(targetAddress); } -} \ No newline at end of file +} diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol index a1f349b..1211aab 100644 --- a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol @@ -19,8 +19,6 @@ abstract contract RuleAddressSetInvariantStorage { error RuleAddressSet_AddressNotFound(); /* ============ Role ============ */ - bytes32 public constant ADDRESS_LIST_REMOVE_ROLE = - keccak256("ADDRESS_LIST_REMOVE_ROLE"); - bytes32 public constant ADDRESS_LIST_ADD_ROLE = - keccak256("ADDRESS_LIST_ADD_ROLE"); + bytes32 public constant ADDRESS_LIST_REMOVE_ROLE = keccak256("ADDRESS_LIST_REMOVE_ROLE"); + bytes32 public constant ADDRESS_LIST_ADD_ROLE = keccak256("ADDRESS_LIST_ADD_ROLE"); } diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol index c645ed1..1e446c6 100644 --- a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol @@ -5,19 +5,12 @@ pragma solidity ^0.8.20; import "../../RuleCommonInvariantStorage.sol"; abstract contract RuleBlacklistInvariantStorage is RuleCommonInvariantStorage { - error RuleBlacklist_InvalidTransfer( - address from, - address to, - uint256 value, - uint8 code - ); + error RuleBlacklist_InvalidTransfer(address from, address to, uint256 value, uint8 code); /* ============ String message ============ */ - string constant TEXT_ADDRESS_FROM_IS_BLACKLISTED = - "The sender is blacklisted"; - string constant TEXT_ADDRESS_TO_IS_BLACKLISTED = - "The recipient is blacklisted"; - string constant TEXT_ADDRESS_SPENDER_IS_BLACKLISTED = - "The spender is blacklisted"; + + string constant TEXT_ADDRESS_FROM_IS_BLACKLISTED = "The sender is blacklisted"; + string constant TEXT_ADDRESS_TO_IS_BLACKLISTED = "The recipient is blacklisted"; + string constant TEXT_ADDRESS_SPENDER_IS_BLACKLISTED = "The spender is blacklisted"; /* ============ Code ============ */ // It is very important that each rule uses an unique code diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol index 73869a5..a724184 100644 --- a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol @@ -5,19 +5,12 @@ pragma solidity ^0.8.20; import "../../RuleCommonInvariantStorage.sol"; abstract contract RuleWhitelistInvariantStorage is RuleCommonInvariantStorage { - error RuleWhitelist_InvalidTransfer( - address from, - address to, - uint256 value, - uint8 code - ); + error RuleWhitelist_InvalidTransfer(address from, address to, uint256 value, uint8 code); /* ============ String message ============ */ - string constant TEXT_ADDRESS_FROM_NOT_WHITELISTED = - "The sender is not in the whitelist"; - string constant TEXT_ADDRESS_TO_NOT_WHITELISTED = - "The recipient is not in the whitelist"; - string constant TEXT_ADDRESS_SPENDER_NOT_WHITELISTED = - "The spender is not in the whitelist"; + + string constant TEXT_ADDRESS_FROM_NOT_WHITELISTED = "The sender is not in the whitelist"; + string constant TEXT_ADDRESS_TO_NOT_WHITELISTED = "The recipient is not in the whitelist"; + string constant TEXT_ADDRESS_SPENDER_NOT_WHITELISTED = "The spender is not in the whitelist"; /* ============ Code ============ */ // It is very important that each rule uses an unique code diff --git a/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol index 9869092..5fb60b0 100644 --- a/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol @@ -3,19 +3,15 @@ pragma solidity ^0.8.20; import "./RuleCommonInvariantStorage.sol"; -import {ISanctionsList } from "../../interfaces/ISanctionsList.sol"; -abstract contract RuleSanctionsListInvariantStorage is - RuleCommonInvariantStorage -{ - error RuleSanctionsList_InvalidTransfer( - address from, - address to, - uint256 value, - uint8 code - ); +import {ISanctionsList} from "../../interfaces/ISanctionsList.sol"; + +abstract contract RuleSanctionsListInvariantStorage is RuleCommonInvariantStorage { + error RuleSanctionsList_InvalidTransfer(address from, address to, uint256 value, uint8 code); /* ============ Event ============ */ + event SetSanctionListOracle(ISanctionsList newOracle); /* ============ Custom errors ============ */ + error RuleSanctionList_AdminWithAddressZeroNotAllowed(); error RuleSanctionList_AddressAlreadyWhitelisted(); @@ -23,12 +19,9 @@ abstract contract RuleSanctionsListInvariantStorage is bytes32 public constant SANCTIONLIST_ROLE = keccak256("SANCTIONLIST_ROLE"); /* ============ String message ============ */ - string constant TEXT_ADDRESS_FROM_IS_SANCTIONED = - "The sender is sanctioned"; - string constant TEXT_ADDRESS_TO_IS_SANCTIONED = - "The recipient is sanctioned"; - string constant TEXT_ADDRESS_SPENDER_IS_SANCTIONED = - "The spender is sanctioned"; + string constant TEXT_ADDRESS_FROM_IS_SANCTIONED = "The sender is sanctioned"; + string constant TEXT_ADDRESS_TO_IS_SANCTIONED = "The recipient is sanctioned"; + string constant TEXT_ADDRESS_SPENDER_IS_SANCTIONED = "The spender is sanctioned"; /* ============ Code ============ */ // It is very important that each rule uses an unique code diff --git a/src/rules/validation/abstract/RuleValidateTransfer.sol b/src/rules/validation/abstract/RuleValidateTransfer.sol index 958ee49..f82f020 100644 --- a/src/rules/validation/abstract/RuleValidateTransfer.sol +++ b/src/rules/validation/abstract/RuleValidateTransfer.sol @@ -8,32 +8,34 @@ import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.s import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; import {IRule} from "RuleEngine/interfaces/IRule.sol"; -abstract contract RuleValidateTransfer is IERC3643ComplianceRead, IERC7551Compliance,IRule { +abstract contract RuleValidateTransfer is IERC3643ComplianceRead, IERC7551Compliance, IRule { /** * @notice Validate a transfer * @param _from the origin address * @param _to the destination address * @param _amount to transfer * @return isValid => true if the transfer is valid, false otherwise - **/ - function canTransfer( - address _from, - address _to, - uint256 _amount - ) public view override(IERC3643ComplianceRead) returns (bool isValid) { + * + */ + function canTransfer(address _from, address _to, uint256 _amount) + public + view + override(IERC3643ComplianceRead) + returns (bool isValid) + { // does not work without `this` keyword => "Undeclared identifier" return - this.detectTransferRestriction(_from, _to, _amount) == - uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); + this.detectTransferRestriction(_from, _to, _amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); } - function canTransferFrom( - address spender, - address from, - address to, - uint256 value - ) public view virtual override(IERC7551Compliance) returns (bool) { - return this.detectTransferRestrictionFrom(spender, from, to, value) == - uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); + function canTransferFrom(address spender, address from, address to, uint256 value) + public + view + virtual + override(IERC7551Compliance) + returns (bool) + { + return this.detectTransferRestrictionFrom(spender, from, to, value) + == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); } } diff --git a/src/rules/validation/abstract/RuleWhitelistCommon.sol b/src/rules/validation/abstract/RuleWhitelistCommon.sol index 6105601..7bbdad1 100644 --- a/src/rules/validation/abstract/RuleWhitelistCommon.sol +++ b/src/rules/validation/abstract/RuleWhitelistCommon.sol @@ -7,48 +7,42 @@ import {RuleValidateTransfer} from "./RuleValidateTransfer.sol"; /** * @title Rule Whitelist Common * @notice Provides common logic for validating whitelist-based transfer restrictions. - * @dev + * @dev * - Implements ERC-3643–compatible `transferred` hooks to enforce whitelist checks. * - Defines utility functions for restriction code validation and message mapping. * - Inherits restriction code constants and messages from {RuleWhitelistInvariantStorage}. */ -abstract contract RuleWhitelistCommon is - RuleValidateTransfer, - RuleWhitelistInvariantStorage -{ +abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInvariantStorage { bool internal _checkSpender; - - /*////////////////////////////////////////////////////////////// RESTRICTION CODE LOGIC //////////////////////////////////////////////////////////////*/ /** * @notice Checks whether a restriction code is recognized by this rule. - * @dev + * @dev * Used to verify if a returned restriction code belongs to the whitelist rule. * @param restrictionCode The restriction code to validate. * @return isKnown True if the restriction code is recognized by this rule, false otherwise. */ - function canReturnTransferRestrictionCode( - uint8 restrictionCode - ) external pure override returns (bool isKnown) { - return - restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED || - restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED || - restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED; + function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override returns (bool isKnown) { + return restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED + || restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED || restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED; } /** * @notice Returns the human-readable message corresponding to a restriction code. - * @dev + * @dev * Returns a descriptive text that explains why a transfer was restricted. * @param restrictionCode The restriction code to decode. * @return message A human-readable explanation of the restriction. */ - function messageForTransferRestriction( - uint8 restrictionCode - ) external pure override returns (string memory message) { + function messageForTransferRestriction(uint8 restrictionCode) + external + pure + override + returns (string memory message) + { if (restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) { return TEXT_ADDRESS_FROM_NOT_WHITELISTED; } else if (restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) { @@ -66,9 +60,9 @@ abstract contract RuleWhitelistCommon is /** * @notice ERC-3643 hook called when a transfer occurs. - * @dev - * - Validates that both `from` and `to` addresses are whitelisted. - * - Reverts if any restriction code other than `TRANSFER_OK` is returned. + * @dev + * - Validates that both `from` and `to` addresses are whitelisted. + * - Reverts if any restriction code other than `TRANSFER_OK` is returned. * - Should be called during token transfer logic to enforce whitelist compliance. * @param from The address sending tokens. * @param to The address receiving tokens. @@ -76,32 +70,21 @@ abstract contract RuleWhitelistCommon is */ function transferred(address from, address to, uint256 value) public view { uint8 code = this.detectTransferRestriction(from, to, value); - require( - code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), - RuleWhitelist_InvalidTransfer(from, to, value, code) - ); + require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleWhitelist_InvalidTransfer(from, to, value, code)); } /** * @notice ERC-3643 hook called when a delegated transfer occurs (`transferFrom`). - * @dev - * - Validates that `spender`, `from`, and `to` are all whitelisted. - * - Reverts if any restriction code other than `TRANSFER_OK` is returned. + * @dev + * - Validates that `spender`, `from`, and `to` are all whitelisted. + * - Reverts if any restriction code other than `TRANSFER_OK` is returned. * @param spender The address performing the transfer on behalf of another. * @param from The address from which tokens are transferred. * @param to The recipient address. * @param value The token amount being transferred. */ - function transferred( - address spender, - address from, - address to, - uint256 value - ) public view { + function transferred(address spender, address from, address to, uint256 value) public view { uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); - require( - code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), - RuleWhitelist_InvalidTransfer(from, to, value, code) - ); + require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleWhitelist_InvalidTransfer(from, to, value, code)); } -} \ No newline at end of file +} diff --git a/test/HelperContract.sol b/test/HelperContract.sol index f05a9a0..5b9b023 100644 --- a/test/HelperContract.sol +++ b/test/HelperContract.sol @@ -13,14 +13,17 @@ import {RuleEngine} from "RuleEngine/RuleEngine.sol"; import {RuleSanctionsList} from "src/rules/validation/RuleSanctionsList.sol"; // RUleBlackList import {RuleBlacklist} from "src/rules/validation/RuleBlacklist.sol"; -import {RuleBlacklistInvariantStorage} from "src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol"; +import {RuleBlacklistInvariantStorage} from + "src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol"; // RuleWhitelist import {RuleWhitelist} from "src/rules/validation/RuleWhitelist.sol"; import {RuleWhitelistWrapper} from "src/rules/validation/RuleWhitelistWrapper.sol"; -import {RuleWhitelistInvariantStorage} from "src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol"; -import {RuleAddressSetInvariantStorage} from "src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol"; +import {RuleWhitelistInvariantStorage} from + "src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol"; +import {RuleAddressSetInvariantStorage} from + "src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol"; -import {RuleSanctionsListInvariantStorage}from "src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol"; +import {RuleSanctionsListInvariantStorage} from "src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol"; // Rule interface // utils @@ -54,12 +57,9 @@ abstract contract HelperContract is address constant ADDRESS2 = address(6); address constant ADDRESS3 = address(7); // role string - string constant RULE_ENGINE_ROLE_HASH = - "0x774b3c5f4a8b37a7da21d72b7f2429e4a6d49c4de0ac5f2b831a1a539d0f0fd2"; - string constant WHITELIST_ROLE_HASH = - "0xdc72ed553f2544c34465af23b847953efeb813428162d767f9ba5f4013be6760"; - string constant DEFAULT_ADMIN_ROLE_HASH = - "0x0000000000000000000000000000000000000000000000000000000000000000"; + string constant RULE_ENGINE_ROLE_HASH = "0x774b3c5f4a8b37a7da21d72b7f2429e4a6d49c4de0ac5f2b831a1a539d0f0fd2"; + string constant WHITELIST_ROLE_HASH = "0xdc72ed553f2544c34465af23b847953efeb813428162d767f9ba5f4013be6760"; + string constant DEFAULT_ADMIN_ROLE_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000"; uint256 DEFAULT_TIME_LIMIT_TO_APPROVE = 7 days; uint256 DEFAULT_TIME_LIMIT_TO_TRANSFER = 7 days; diff --git a/test/RuleBlacklist/CMTATIntegration.t.sol b/test/RuleBlacklist/CMTATIntegration.t.sol index 4d6681c..b6eeec6 100644 --- a/test/RuleBlacklist/CMTATIntegration.t.sol +++ b/test/RuleBlacklist/CMTATIntegration.t.sol @@ -27,11 +27,7 @@ contract CMTATIntegration is Test, HelperContract { // specific arrange vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock = new RuleEngine( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS, - address(CMTAT_CONTRACT) - ); + ruleEngineMock = new RuleEngine(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, address(CMTAT_CONTRACT)); vm.prank(DEFAULT_ADMIN_ADDRESS); ruleEngineMock.addRule(ruleBlacklist); vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -45,7 +41,9 @@ contract CMTATIntegration is Test, HelperContract { CMTAT_CONTRACT.setRuleEngine(ruleEngineMock); } - /******* Transfer *******/ + /** + * Transfer ****** + */ function testCanTransferIfAddressNotBlacklisted() public { // Act vm.prank(ADDRESS1); @@ -61,11 +59,7 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleBlacklist_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - amount, - CODE_ADDRESS_TO_IS_BLACKLISTED + RuleBlacklist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_TO_IS_BLACKLISTED ) ); // Act @@ -81,11 +75,7 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleBlacklist_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - amount, - CODE_ADDRESS_FROM_IS_BLACKLISTED + RuleBlacklist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_IS_BLACKLISTED ) ); // Act @@ -99,45 +89,32 @@ contract CMTATIntegration is Test, HelperContract { blacklist[0] = ADDRESS1; blacklist[1] = ADDRESS2; vm.prank(DEFAULT_ADMIN_ADDRESS); - (bool success, ) = address(ruleBlacklist).call( - abi.encodeWithSignature( - "addAddresses(address[])", - blacklist - ) - ); + (bool success,) = address(ruleBlacklist).call(abi.encodeWithSignature("addAddresses(address[])", blacklist)); require(success); // Act vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleBlacklist_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - amount, - CODE_ADDRESS_FROM_IS_BLACKLISTED + RuleBlacklist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_IS_BLACKLISTED ) ); CMTAT_CONTRACT.transfer(ADDRESS2, amount); } - /******* detectTransferRestriction & messageForTransferRestriction *******/ + /** + * detectTransferRestriction & messageForTransferRestriction ****** + */ function testDetectAndMessageWithToBlacklisted() public { vm.prank(DEFAULT_ADMIN_ADDRESS); ruleBlacklist.addAddress(ADDRESS2); resBool = ruleBlacklist.isAddressListed(ADDRESS2); // Assert assertEq(resBool, true); - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); // Assert assertEq(res1, CODE_ADDRESS_TO_IS_BLACKLISTED); - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); // Assert assertEq(message1, TEXT_ADDRESS_TO_IS_BLACKLISTED); } @@ -151,35 +128,23 @@ contract CMTATIntegration is Test, HelperContract { resBool = ruleBlacklist.isAddressListed(ADDRESS1); assertEq(resBool, true); // Act - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); // Assert assertEq(res1, CODE_ADDRESS_FROM_IS_BLACKLISTED); // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); // Assert assertEq(message1, TEXT_ADDRESS_FROM_IS_BLACKLISTED); } function testDetectAndMessageWithFromAndToNotBlacklisted() public view { // Act - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); // Assert assertEq(res1, TRANSFER_OK); // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); // Assert assertEq(message1, TEXT_TRANSFER_OK); } @@ -191,25 +156,14 @@ contract CMTATIntegration is Test, HelperContract { blacklist[0] = ADDRESS1; blacklist[1] = ADDRESS2; vm.prank(DEFAULT_ADMIN_ADDRESS); - (bool success, ) = address(ruleBlacklist).call( - abi.encodeWithSignature( - "addAddresses(address[])", - blacklist - ) - ); + (bool success,) = address(ruleBlacklist).call(abi.encodeWithSignature("addAddresses(address[])", blacklist)); require(success); // Act - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); // Assert assertEq(res1, CODE_ADDRESS_FROM_IS_BLACKLISTED); // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); // Assert assertEq(message1, TEXT_ADDRESS_FROM_IS_BLACKLISTED); } @@ -236,11 +190,7 @@ contract CMTATIntegration is Test, HelperContract { // Act vm.expectRevert( abi.encodeWithSelector( - RuleBlacklist_InvalidTransfer.selector, - ZERO_ADDRESS, - ADDRESS1, - amount, - CODE_ADDRESS_TO_IS_BLACKLISTED + RuleBlacklist_InvalidTransfer.selector, ZERO_ADDRESS, ADDRESS1, amount, CODE_ADDRESS_TO_IS_BLACKLISTED ) ); vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -249,9 +199,7 @@ contract CMTATIntegration is Test, HelperContract { function testCanReturnMessageNotFoundWithUnknownCodeId() public view { // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - 255 - ); + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(255); // Assert assertEq(message1, TEXT_CODE_NOT_FOUND); diff --git a/test/RuleBlacklist/RuleBlacklist.t.sol b/test/RuleBlacklist/RuleBlacklist.t.sol index 9ad87aa..f52f53c 100644 --- a/test/RuleBlacklist/RuleBlacklist.t.sol +++ b/test/RuleBlacklist/RuleBlacklist.t.sol @@ -15,14 +15,9 @@ contract RuleBlacklistTest is Test, HelperContract { ruleBlacklist = new RuleBlacklist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); } - function testCanRuleBlacklistReturnMessageNotFoundWithUnknownCodeId() - public - view - { + function testCanRuleBlacklistReturnMessageNotFoundWithUnknownCodeId() public view { // Act - string memory message1 = ruleBlacklist.messageForTransferRestriction( - 255 - ); + string memory message1 = ruleBlacklist.messageForTransferRestriction(255); // Assert assertEq(message1, TEXT_CODE_NOT_FOUND); diff --git a/test/RuleSanctionList/RuleSanctionListAddTest.t.sol b/test/RuleSanctionList/RuleSanctionListAddTest.t.sol index 4a473c5..be2477d 100644 --- a/test/RuleSanctionList/RuleSanctionListAddTest.t.sol +++ b/test/RuleSanctionList/RuleSanctionListAddTest.t.sol @@ -8,9 +8,11 @@ import {RuleSanctionsList, ISanctionsList} from "src/rules/validation/RuleSancti /** * @title General functions of the ruleSanctionList */ + contract RuleSanctionlistAddTest is Test, HelperContract { // Custom error openZeppelin error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); + SanctionListOracle sanctionlistOracle; RuleSanctionsList ruleSanctionList; @@ -19,11 +21,8 @@ contract RuleSanctionlistAddTest is Test, HelperContract { vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); sanctionlistOracle = new SanctionListOracle(); sanctionlistOracle.addToSanctionsList(ATTACKER); - ruleSanctionList = new RuleSanctionsList( - SANCTIONLIST_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ISanctionsList(ZERO_ADDRESS) - ); + ruleSanctionList = + new RuleSanctionsList(SANCTIONLIST_OPERATOR_ADDRESS, ZERO_ADDRESS, ISanctionsList(ZERO_ADDRESS)); } function testCanSetandRemoveOracle() public { @@ -34,10 +33,7 @@ contract RuleSanctionlistAddTest is Test, HelperContract { ISanctionsList sanctionListOracleGet = ruleSanctionList.sanctionsList(); // Assert - vm.assertEq( - address(sanctionListOracleGet), - address(sanctionlistOracle) - ); + vm.assertEq(address(sanctionListOracleGet), address(sanctionlistOracle)); // Remove vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); emit SetSanctionListOracle(ISanctionsList(ZERO_ADDRESS)); @@ -49,13 +45,7 @@ contract RuleSanctionlistAddTest is Test, HelperContract { function testCannotAttackerSetOracle() public { vm.prank(ATTACKER); - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - SANCTIONLIST_ROLE - ) - ); + vm.expectRevert(abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, SANCTIONLIST_ROLE)); ruleSanctionList.setSanctionListOracle(sanctionlistOracle); } } diff --git a/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol b/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol index e627ebc..e54284f 100644 --- a/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol +++ b/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol @@ -9,9 +9,11 @@ import {RuleSanctionsList, ISanctionsList} from "src/rules/validation/RuleSancti /** * @title General functions of the ruleSanctionList */ + contract RuleSanctionListDeploymentTest is Test, HelperContract { RuleSanctionsList ruleSanctionList; SanctionListOracle sanctionlistOracle; + event Testa(); // Arrange @@ -23,17 +25,11 @@ contract RuleSanctionListDeploymentTest is Test, HelperContract { MinimalForwarderMock forwarder = new MinimalForwarderMock(); forwarder.initialize(ERC2771ForwarderDomain); vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - ruleSanctionList = new RuleSanctionsList( - SANCTIONLIST_OPERATOR_ADDRESS, - address(forwarder), - ISanctionsList(ZERO_ADDRESS) - ); + ruleSanctionList = + new RuleSanctionsList(SANCTIONLIST_OPERATOR_ADDRESS, address(forwarder), ISanctionsList(ZERO_ADDRESS)); // assert - resBool = ruleSanctionList.hasRole( - SANCTIONLIST_ROLE, - SANCTIONLIST_OPERATOR_ADDRESS - ); + resBool = ruleSanctionList.hasRole(SANCTIONLIST_ROLE, SANCTIONLIST_OPERATOR_ADDRESS); assertEq(resBool, true); resBool = ruleSanctionList.isTrustedForwarder(address(forwarder)); assertEq(resBool, true); @@ -44,15 +40,9 @@ contract RuleSanctionListDeploymentTest is Test, HelperContract { vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); MinimalForwarderMock forwarder = new MinimalForwarderMock(); forwarder.initialize(ERC2771ForwarderDomain); - vm.expectRevert( - RuleSanctionList_AdminWithAddressZeroNotAllowed.selector - ); + vm.expectRevert(RuleSanctionList_AdminWithAddressZeroNotAllowed.selector); vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); - ruleSanctionList = new RuleSanctionsList( - address(0), - address(forwarder), - ISanctionsList(ZERO_ADDRESS) - ); + ruleSanctionList = new RuleSanctionsList(address(0), address(forwarder), ISanctionsList(ZERO_ADDRESS)); } function testCanSetAnOracleAtDeployment() public { @@ -61,14 +51,7 @@ contract RuleSanctionListDeploymentTest is Test, HelperContract { // TODO: Event seems not checked by Foundry at deployment emit SetSanctionListOracle(sanctionlistOracle); - ruleSanctionList = new RuleSanctionsList( - SANCTIONLIST_OPERATOR_ADDRESS, - ZERO_ADDRESS, - sanctionlistOracle - ); - assertEq( - address(ruleSanctionList.sanctionsList()), - address(sanctionlistOracle) - ); + ruleSanctionList = new RuleSanctionsList(SANCTIONLIST_OPERATOR_ADDRESS, ZERO_ADDRESS, sanctionlistOracle); + assertEq(address(ruleSanctionList.sanctionsList()), address(sanctionlistOracle)); } } diff --git a/test/RuleSanctionList/RuleSanctionListTest.t.sol b/test/RuleSanctionList/RuleSanctionListTest.t.sol index eea479d..b00f9f1 100644 --- a/test/RuleSanctionList/RuleSanctionListTest.t.sol +++ b/test/RuleSanctionList/RuleSanctionListTest.t.sol @@ -8,6 +8,7 @@ import {RuleSanctionsList, ISanctionsList} from "src/rules/validation/RuleSancti /** * @title General functions of the ruleSanctionList */ + contract RuleSanctionlistTest is Test, HelperContract { SanctionListOracle sanctionlistOracle; RuleSanctionsList ruleSanctionList; @@ -17,53 +18,38 @@ contract RuleSanctionlistTest is Test, HelperContract { vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); sanctionlistOracle = new SanctionListOracle(); sanctionlistOracle.addToSanctionsList(ATTACKER); - ruleSanctionList = new RuleSanctionsList( - SANCTIONLIST_OPERATOR_ADDRESS, - ZERO_ADDRESS, - ISanctionsList(ZERO_ADDRESS) - ); + ruleSanctionList = + new RuleSanctionsList(SANCTIONLIST_OPERATOR_ADDRESS, ZERO_ADDRESS, ISanctionsList(ZERO_ADDRESS)); vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); ruleSanctionList.setSanctionListOracle(sanctionlistOracle); } function testCanReturnTransferRestrictionCode() public { // Act - resBool = ruleSanctionList.canReturnTransferRestrictionCode( - CODE_ADDRESS_FROM_IS_SANCTIONED - ); + resBool = ruleSanctionList.canReturnTransferRestrictionCode(CODE_ADDRESS_FROM_IS_SANCTIONED); // Assert assertEq(resBool, true); // Act - resBool = ruleSanctionList.canReturnTransferRestrictionCode( - CODE_ADDRESS_TO_IS_SANCTIONED - ); + resBool = ruleSanctionList.canReturnTransferRestrictionCode(CODE_ADDRESS_TO_IS_SANCTIONED); // Assert assertEq(resBool, true); // Act - resBool = ruleSanctionList.canReturnTransferRestrictionCode( - CODE_NONEXISTENT - ); + resBool = ruleSanctionList.canReturnTransferRestrictionCode(CODE_NONEXISTENT); // Assert assertFalse(resBool); } function testReturnTheRightMessageForAGivenCode() public { // Assert - resString = ruleSanctionList.messageForTransferRestriction( - CODE_ADDRESS_FROM_IS_SANCTIONED - ); + resString = ruleSanctionList.messageForTransferRestriction(CODE_ADDRESS_FROM_IS_SANCTIONED); // Assert assertEq(resString, TEXT_ADDRESS_FROM_IS_SANCTIONED); // Act - resString = ruleSanctionList.messageForTransferRestriction( - CODE_ADDRESS_TO_IS_SANCTIONED - ); + resString = ruleSanctionList.messageForTransferRestriction(CODE_ADDRESS_TO_IS_SANCTIONED); // Assert assertEq(resString, TEXT_ADDRESS_TO_IS_SANCTIONED); // Act - resString = ruleSanctionList.messageForTransferRestriction( - CODE_NONEXISTENT - ); + resString = ruleSanctionList.messageForTransferRestriction(CODE_NONEXISTENT); // Assert assertEq(resString, TEXT_CODE_NOT_FOUND); } @@ -94,33 +80,21 @@ contract RuleSanctionlistTest is Test, HelperContract { function testDetectTransferRestrictionFrom() public { // Act - resUint8 = ruleSanctionList.detectTransferRestriction( - ATTACKER, - ADDRESS2, - 20 - ); + resUint8 = ruleSanctionList.detectTransferRestriction(ATTACKER, ADDRESS2, 20); // Assert assertEq(resUint8, CODE_ADDRESS_FROM_IS_SANCTIONED); } function testDetectTransferRestrictionTo() public { // Act - resUint8 = ruleSanctionList.detectTransferRestriction( - ADDRESS1, - ATTACKER, - 20 - ); + resUint8 = ruleSanctionList.detectTransferRestriction(ADDRESS1, ATTACKER, 20); // Assert assertEq(resUint8, CODE_ADDRESS_TO_IS_SANCTIONED); } function testDetectTransferRestrictionOk() public { // Act - resUint8 = ruleSanctionList.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 20 - ); + 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 9c5c1e4..c957d28 100644 --- a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol +++ b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControl.t.sol @@ -14,20 +14,12 @@ contract RuleWhitelistAccessControl is Test, HelperContract { // Arrange function setUp() public { vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist = new RuleWhitelist( - WHITELIST_OPERATOR_ADDRESS, - ZERO_ADDRESS, - true - ); + ruleWhitelist = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true); } function testCannotAttackeraddAddress() public { vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - ADDRESS_LIST_ADD_ROLE - ) + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, ADDRESS_LIST_ADD_ROLE) ); vm.prank(ATTACKER); ruleWhitelist.addAddress(ADDRESS1); @@ -49,19 +41,10 @@ contract RuleWhitelistAccessControl is Test, HelperContract { // Act vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - ADDRESS_LIST_ADD_ROLE - ) + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, ADDRESS_LIST_ADD_ROLE) ); vm.prank(ATTACKER); - (resCallBool, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "addAddresses(address[])", - whitelist - ) - ); + (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist)); // Assert assertEq(resCallBool, true); @@ -86,11 +69,7 @@ contract RuleWhitelistAccessControl is Test, HelperContract { // Act vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - ADDRESS_LIST_REMOVE_ROLE - ) + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, ADDRESS_LIST_REMOVE_ROLE) ); vm.prank(ATTACKER); ruleWhitelist.removeAddress(ADDRESS1); @@ -108,12 +87,7 @@ contract RuleWhitelistAccessControl is Test, HelperContract { whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; vm.prank(WHITELIST_OPERATOR_ADDRESS); - (resCallBool, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "addAddresses(address[])", - whitelist - ) - ); + (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist)); assertEq(resCallBool, true); // Arrange - Assert resBool = ruleWhitelist.isAddressListed(ADDRESS1); @@ -123,19 +97,10 @@ contract RuleWhitelistAccessControl is Test, HelperContract { // Act vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ATTACKER, - ADDRESS_LIST_REMOVE_ROLE - ) + abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, ADDRESS_LIST_REMOVE_ROLE) ); vm.prank(ATTACKER); - (resCallBool, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "removeAddresses(address[])", - whitelist - ) - ); + (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("removeAddresses(address[])", whitelist)); // Assert assertEq(resCallBool, true); resBool = ruleWhitelist.isAddressListed(ADDRESS1); diff --git a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol index 8726afb..6cb6ab2 100644 --- a/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol +++ b/test/RuleWhitelist/AccessControl/RuleWhitelistAccessControlOZ.t.sol @@ -12,22 +12,14 @@ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl { // Arrange function setUp() public { vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist = new RuleWhitelist( - WHITELIST_OPERATOR_ADDRESS, - ZERO_ADDRESS, - true - ); + ruleWhitelist = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true); } function testCanGrantRoleAsAdmin() public { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); vm.expectEmit(true, true, false, true); - emit RoleGranted( - ADDRESS_LIST_ADD_ROLE, - ADDRESS1, - WHITELIST_OPERATOR_ADDRESS - ); + emit RoleGranted(ADDRESS_LIST_ADD_ROLE, ADDRESS1, WHITELIST_OPERATOR_ADDRESS); ruleWhitelist.grantRole(ADDRESS_LIST_ADD_ROLE, ADDRESS1); // Assert bool res1 = ruleWhitelist.hasRole(ADDRESS_LIST_ADD_ROLE, ADDRESS1); @@ -45,11 +37,7 @@ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); vm.expectEmit(true, true, false, true); - emit RoleRevoked( - ADDRESS_LIST_ADD_ROLE, - ADDRESS1, - WHITELIST_OPERATOR_ADDRESS - ); + emit RoleRevoked(ADDRESS_LIST_ADD_ROLE, ADDRESS1, WHITELIST_OPERATOR_ADDRESS); ruleWhitelist.revokeRole(ADDRESS_LIST_ADD_ROLE, ADDRESS1); // Assert bool res2 = ruleWhitelist.hasRole(ADDRESS_LIST_ADD_ROLE, ADDRESS1); @@ -62,13 +50,7 @@ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl { assertFalse(res1); // Act - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ADDRESS2, - DEFAULT_ADMIN_ROLE - ) - ); + vm.expectRevert(abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ADDRESS2, DEFAULT_ADMIN_ROLE)); vm.prank(ADDRESS2); ruleWhitelist.grantRole(ADDRESS_LIST_ADD_ROLE, ADDRESS1); // Assert @@ -90,13 +72,7 @@ contract RuleWhitelistAccessControlOZ is Test, HelperContract, AccessControl { // Act vm.prank(ADDRESS2); - vm.expectRevert( - abi.encodeWithSelector( - AccessControlUnauthorizedAccount.selector, - ADDRESS2, - DEFAULT_ADMIN_ROLE - ) - ); + vm.expectRevert(abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ADDRESS2, DEFAULT_ADMIN_ROLE)); ruleWhitelist.revokeRole(ADDRESS_LIST_ADD_ROLE, ADDRESS1); // Assert diff --git a/test/RuleWhitelist/CMTATIntegration.t.sol b/test/RuleWhitelist/CMTATIntegration.t.sol index a123fb8..5dd66a0 100644 --- a/test/RuleWhitelist/CMTATIntegration.t.sol +++ b/test/RuleWhitelist/CMTATIntegration.t.sol @@ -25,11 +25,7 @@ contract CMTATIntegration is Test, HelperContract { // specific arrange vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock = new RuleEngine( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS, - address(CMTAT_CONTRACT) - ); + ruleEngineMock = new RuleEngine(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, address(CMTAT_CONTRACT)); vm.prank(DEFAULT_ADMIN_ADDRESS); ruleEngineMock.addRule(ruleWhitelist); vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -43,17 +39,15 @@ contract CMTATIntegration is Test, HelperContract { CMTAT_CONTRACT.setRuleEngine(ruleEngineMock); } - /******* Transfer *******/ + /** + * Transfer ****** + */ function testCannotTransferWithoutAddressWhitelisted() public { // Arrange vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - 21, - CODE_ADDRESS_FROM_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21, CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -69,11 +63,7 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - amount, - CODE_ADDRESS_FROM_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -89,11 +79,7 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - amount, - CODE_ADDRESS_TO_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_TO_NOT_WHITELISTED ) ); // Act @@ -106,12 +92,7 @@ contract CMTATIntegration is Test, HelperContract { whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; vm.prank(DEFAULT_ADMIN_ADDRESS); - (bool success, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "addAddresses(address[])", - whitelist - ) - ); + (bool success,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist)); require(success); vm.prank(ADDRESS1); @@ -127,23 +108,19 @@ contract CMTATIntegration is Test, HelperContract { assertEq(resUint256, 33); } - /******* detectTransferRestriction & messageForTransferRestriction *******/ + /** + * detectTransferRestriction & messageForTransferRestriction ****** + */ function testDetectAndMessageWithFromNotWhitelisted() public { vm.prank(DEFAULT_ADMIN_ADDRESS); ruleWhitelist.addAddress(ADDRESS2); resBool = ruleWhitelist.isAddressListed(ADDRESS2); // Assert assertEq(resBool, true); - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); // Assert assertEq(res1, CODE_ADDRESS_FROM_NOT_WHITELISTED); - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); // Assert assertEq(message1, TEXT_ADDRESS_FROM_NOT_WHITELISTED); } @@ -157,35 +134,23 @@ contract CMTATIntegration is Test, HelperContract { resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); // Act - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); // Assert assertEq(res1, CODE_ADDRESS_TO_NOT_WHITELISTED); // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); // Assert assertEq(message1, TEXT_ADDRESS_TO_NOT_WHITELISTED); } function testDetectAndMessageWithFromAndToNotWhitelisted() public view { // Act - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); // Assert assertEq(res1, CODE_ADDRESS_FROM_NOT_WHITELISTED); // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); // Assert assertEq(message1, TEXT_ADDRESS_FROM_NOT_WHITELISTED); @@ -198,25 +163,14 @@ contract CMTATIntegration is Test, HelperContract { whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; vm.prank(DEFAULT_ADMIN_ADDRESS); - (bool success, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "addAddresses(address[])", - whitelist - ) - ); + (bool success,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist)); require(success); // Act - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); // Assert assertEq(res1, TRANSFER_OK); // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); // Assert assertEq(message1, TEXT_TRANSFER_OK); } diff --git a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol index 4e4d750..024158b 100644 --- a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol +++ b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol @@ -24,11 +24,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { ruleWhitelist = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true); ruleWhitelist2 = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true); ruleWhitelist3 = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true); - ruleWhitelistWrapper = new RuleWhitelistWrapper( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS, - true - ); + ruleWhitelistWrapper = new RuleWhitelistWrapper(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true); vm.prank(DEFAULT_ADMIN_ADDRESS); ruleWhitelistWrapper.addRule(ruleWhitelist); vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -40,11 +36,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { CMTAT_CONTRACT = cmtatDeployment.cmtat(); // specific arrange vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock = new RuleEngine( - DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS, - address(CMTAT_CONTRACT) - ); + ruleEngineMock = new RuleEngine(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, address(CMTAT_CONTRACT)); vm.prank(DEFAULT_ADMIN_ADDRESS); ruleEngineMock.addRule(ruleWhitelistWrapper); vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -58,29 +50,24 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { CMTAT_CONTRACT.setRuleEngine(ruleEngineMock); } - /******* Deployment *******/ - + /** + * Deployment ****** + */ function testCannotDeployContractIfAdminAddressIsZero() public { vm.prank(WHITELIST_OPERATOR_ADDRESS); vm.expectRevert(RuleEngine_AdminWithAddressZeroNotAllowed.selector); - ruleWhitelistWrapper = new RuleWhitelistWrapper( - ZERO_ADDRESS, - ZERO_ADDRESS, - true - ); + ruleWhitelistWrapper = new RuleWhitelistWrapper(ZERO_ADDRESS, ZERO_ADDRESS, true); } - /******* Transfer *******/ + /** + * Transfer ****** + */ function testCannotTransferWithoutAddressWhitelisted() public { // Arrange vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - 21, - CODE_ADDRESS_FROM_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21, CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -96,11 +83,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - amount, - CODE_ADDRESS_FROM_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -116,11 +99,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, - ADDRESS1, - ADDRESS2, - amount, - CODE_ADDRESS_TO_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_TO_NOT_WHITELISTED ) ); // Act @@ -179,12 +158,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; vm.prank(DEFAULT_ADMIN_ADDRESS); - (bool success, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "addAddresses(address[])", - whitelist - ) - ); + (bool success,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist)); require(success); // Act @@ -200,23 +174,19 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { assertEq(resUint256, 33); } - /******* detectTransferRestriction & messageForTransferRestriction *******/ + /** + * detectTransferRestriction & messageForTransferRestriction ****** + */ function testDetectAndMessageWithFromNotWhitelisted() public { vm.prank(DEFAULT_ADMIN_ADDRESS); ruleWhitelist.addAddress(ADDRESS2); resBool = ruleWhitelist.isAddressListed(ADDRESS2); // Assert assertEq(resBool, true); - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); // Assert assertEq(res1, CODE_ADDRESS_FROM_NOT_WHITELISTED); - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); // Assert assertEq(message1, TEXT_ADDRESS_FROM_NOT_WHITELISTED); } @@ -230,35 +200,23 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { resBool = ruleWhitelist.isAddressListed(ADDRESS1); assertEq(resBool, true); // Act - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); // Assert assertEq(res1, CODE_ADDRESS_TO_NOT_WHITELISTED); // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); // Assert assertEq(message1, TEXT_ADDRESS_TO_NOT_WHITELISTED); } function testDetectAndMessageWithFromAndToNotWhitelisted() public view { // Act - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); // Assert assertEq(res1, CODE_ADDRESS_FROM_NOT_WHITELISTED); // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); // Assert assertEq(message1, TEXT_ADDRESS_FROM_NOT_WHITELISTED); @@ -266,9 +224,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { function testCanReturnUnknownTextMessage() public view { // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - 200 - ); + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(200); // Assert assertEq(message1, TEXT_CODE_NOT_FOUND); @@ -281,25 +237,14 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; vm.prank(DEFAULT_ADMIN_ADDRESS); - (bool success, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "addAddresses(address[])", - whitelist - ) - ); + (bool success,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist)); require(success); // Act - uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 11 - ); + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); // Assert assertEq(res1, TRANSFER_OK); // Act - string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction( - res1 - ); + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); // Assert assertEq(message1, TEXT_TRANSFER_OK); } diff --git a/test/RuleWhitelist/RuleWhitelist.t.sol b/test/RuleWhitelist/RuleWhitelist.t.sol index cbea6be..98e58ac 100644 --- a/test/RuleWhitelist/RuleWhitelist.t.sol +++ b/test/RuleWhitelist/RuleWhitelist.t.sol @@ -11,11 +11,7 @@ contract RuleWhitelistTest is Test, HelperContract { // Arrange function setUp() public { vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist = new RuleWhitelist( - WHITELIST_OPERATOR_ADDRESS, - ZERO_ADDRESS, - true - ); + ruleWhitelist = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true); } function _addAddresses() internal { @@ -23,12 +19,7 @@ contract RuleWhitelistTest is Test, HelperContract { whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; vm.prank(WHITELIST_OPERATOR_ADDRESS); - (resCallBool, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "addAddresses(address[])", - whitelist - ) - ); + (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist)); // Assert resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 2); @@ -91,42 +82,30 @@ contract RuleWhitelistTest is Test, HelperContract { function testCanReturnTransferRestrictionCode() public { // Act - resBool = ruleWhitelist.canReturnTransferRestrictionCode( - CODE_ADDRESS_FROM_NOT_WHITELISTED - ); + resBool = ruleWhitelist.canReturnTransferRestrictionCode(CODE_ADDRESS_FROM_NOT_WHITELISTED); // Assert assertEq(resBool, true); // Act - resBool = ruleWhitelist.canReturnTransferRestrictionCode( - CODE_ADDRESS_TO_NOT_WHITELISTED - ); + resBool = ruleWhitelist.canReturnTransferRestrictionCode(CODE_ADDRESS_TO_NOT_WHITELISTED); // Assert assertEq(resBool, true); // Act - resBool = ruleWhitelist.canReturnTransferRestrictionCode( - CODE_NONEXISTENT - ); + resBool = ruleWhitelist.canReturnTransferRestrictionCode(CODE_NONEXISTENT); // Assert assertFalse(resBool); } function testReturnTheRightMessageForAGivenCode() public { // Assert - resString = ruleWhitelist.messageForTransferRestriction( - CODE_ADDRESS_FROM_NOT_WHITELISTED - ); + resString = ruleWhitelist.messageForTransferRestriction(CODE_ADDRESS_FROM_NOT_WHITELISTED); // Assert assertEq(resString, TEXT_ADDRESS_FROM_NOT_WHITELISTED); // Act - resString = ruleWhitelist.messageForTransferRestriction( - CODE_ADDRESS_TO_NOT_WHITELISTED - ); + resString = ruleWhitelist.messageForTransferRestriction(CODE_ADDRESS_TO_NOT_WHITELISTED); // Assert assertEq(resString, TEXT_ADDRESS_TO_NOT_WHITELISTED); // Act - resString = ruleWhitelist.messageForTransferRestriction( - CODE_NONEXISTENT - ); + resString = ruleWhitelist.messageForTransferRestriction(CODE_NONEXISTENT); // Assert assertEq(resString, TEXT_CODE_NOT_FOUND); } @@ -161,12 +140,7 @@ contract RuleWhitelistTest is Test, HelperContract { whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; vm.prank(WHITELIST_OPERATOR_ADDRESS); - (resCallBool, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "addAddresses(address[])", - whitelist - ) - ); + (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist)); assertEq(resCallBool, true); // Act resUint256 = ruleWhitelist.listedAddressCount(); @@ -174,12 +148,7 @@ contract RuleWhitelistTest is Test, HelperContract { assertEq(resUint256, 2); // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); - (resCallBool, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "removeAddresses(address[])", - whitelist - ) - ); + (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("removeAddresses(address[])", whitelist)); // Arrange - Assert assertEq(resCallBool, true); // Act @@ -190,11 +159,7 @@ contract RuleWhitelistTest is Test, HelperContract { function testDetectTransferRestrictionFrom() public { // Act - resUint8 = ruleWhitelist.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 20 - ); + resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); // Assert assertEq(resUint8, CODE_ADDRESS_FROM_NOT_WHITELISTED); } @@ -204,11 +169,7 @@ contract RuleWhitelistTest is Test, HelperContract { vm.prank(WHITELIST_OPERATOR_ADDRESS); ruleWhitelist.addAddress(ADDRESS1); // Act - resUint8 = ruleWhitelist.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 20 - ); + resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); // Assert assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED); } @@ -220,11 +181,7 @@ contract RuleWhitelistTest is Test, HelperContract { vm.prank(WHITELIST_OPERATOR_ADDRESS); ruleWhitelist.addAddress(ADDRESS2); // Act - resUint8 = ruleWhitelist.detectTransferRestriction( - ADDRESS1, - ADDRESS2, - 20 - ); + resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); // Assert assertEq(resUint8, NO_ERROR); } diff --git a/test/RuleWhitelist/RuleWhitelistAdd.t.sol b/test/RuleWhitelist/RuleWhitelistAdd.t.sol index d66aa9b..1ae9dd3 100644 --- a/test/RuleWhitelist/RuleWhitelistAdd.t.sol +++ b/test/RuleWhitelist/RuleWhitelistAdd.t.sol @@ -11,11 +11,7 @@ contract RuleWhitelistAddTest is Test, HelperContract { // Arrange function setUp() public { vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist = new RuleWhitelist( - WHITELIST_OPERATOR_ADDRESS, - ZERO_ADDRESS, - true - ); + ruleWhitelist = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true); } function _addAddresses() internal { @@ -23,12 +19,7 @@ contract RuleWhitelistAddTest is Test, HelperContract { whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; vm.prank(WHITELIST_OPERATOR_ADDRESS); - (resCallBool, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "addAddresses(address[])", - whitelist - ) - ); + (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist)); // Assert resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 2); @@ -40,9 +31,7 @@ contract RuleWhitelistAddTest is Test, HelperContract { address[] memory addressesListInput = new address[](2); addressesListInput[0] = ADDRESS1; addressesListInput[1] = ADDRESS2; - bool[] memory resBools = ruleWhitelist.areAddressesListed( - addressesListInput - ); + bool[] memory resBools = ruleWhitelist.areAddressesListed(addressesListInput); assertEq(resBools[0], true); assertEq(resBools[1], true); assertEq(resBools.length, 2); @@ -59,9 +48,7 @@ contract RuleWhitelistAddTest is Test, HelperContract { assertEq(resBool, true); address[] memory addressesListInput = new address[](1); addressesListInput[0] = ADDRESS1; - bool[] memory resBools = ruleWhitelist.areAddressesListed( - addressesListInput - ); + bool[] memory resBools = ruleWhitelist.areAddressesListed(addressesListInput); assertEq(resBools[0], true); assertEq(resBools.length, 1); resUint256 = ruleWhitelist.listedAddressCount(); @@ -109,12 +96,7 @@ contract RuleWhitelistAddTest is Test, HelperContract { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); emit AddAddresses(whitelist); - (resCallBool, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "addAddresses(address[])", - whitelist - ) - ); + (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist)); // Assert - Main // Seem that call returns true even if the function is reverted @@ -165,12 +147,8 @@ contract RuleWhitelistAddTest is Test, HelperContract { whitelistDuplicate[2] = ADDRESS3; // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - (resCallBool, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "addAddresses(address[])", - whitelistDuplicate - ) - ); + (resCallBool,) = + address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelistDuplicate)); // Assert // no change assertEq(resCallBool, true); diff --git a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol index 1592843..bca06ef 100644 --- a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol +++ b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol @@ -18,22 +18,12 @@ contract RuleWhitelistDeploymentTest is Test, HelperContract { MinimalForwarderMock forwarder = new MinimalForwarderMock(); forwarder.initialize(ERC2771ForwarderDomain); vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist = new RuleWhitelist( - WHITELIST_OPERATOR_ADDRESS, - address(forwarder), - true - ); + ruleWhitelist = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, address(forwarder), true); // assert - resBool = ruleWhitelist.hasRole( - ADDRESS_LIST_ADD_ROLE, - WHITELIST_OPERATOR_ADDRESS - ); + resBool = ruleWhitelist.hasRole(ADDRESS_LIST_ADD_ROLE, WHITELIST_OPERATOR_ADDRESS); assertEq(resBool, true); - resBool = ruleWhitelist.hasRole( - ADDRESS_LIST_REMOVE_ROLE, - WHITELIST_OPERATOR_ADDRESS - ); + resBool = ruleWhitelist.hasRole(ADDRESS_LIST_REMOVE_ROLE, WHITELIST_OPERATOR_ADDRESS); assertEq(resBool, true); resBool = ruleWhitelist.isTrustedForwarder(address(forwarder)); assertEq(resBool, true); @@ -44,9 +34,7 @@ contract RuleWhitelistDeploymentTest is Test, HelperContract { vm.prank(WHITELIST_OPERATOR_ADDRESS); MinimalForwarderMock forwarder = new MinimalForwarderMock(); forwarder.initialize(ERC2771ForwarderDomain); - vm.expectRevert( - RuleAddressSet_AdminWithAddressZeroNotAllowed.selector - ); + vm.expectRevert(RuleAddressSet_AdminWithAddressZeroNotAllowed.selector); vm.prank(WHITELIST_OPERATOR_ADDRESS); ruleWhitelist = new RuleWhitelist(address(0), address(forwarder), true); } diff --git a/test/RuleWhitelist/RuleWhitelistRemove.t.sol b/test/RuleWhitelist/RuleWhitelistRemove.t.sol index 9689f65..e3028e3 100644 --- a/test/RuleWhitelist/RuleWhitelistRemove.t.sol +++ b/test/RuleWhitelist/RuleWhitelistRemove.t.sol @@ -11,11 +11,7 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { // Arrange function setUp() public { vm.prank(WHITELIST_OPERATOR_ADDRESS); - ruleWhitelist = new RuleWhitelist( - WHITELIST_OPERATOR_ADDRESS, - ZERO_ADDRESS, - true - ); + ruleWhitelist = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true); } function _addAddresses() internal { @@ -24,12 +20,7 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { whitelist[1] = ADDRESS2; vm.prank(WHITELIST_OPERATOR_ADDRESS); emit AddAddresses(whitelist); - (resCallBool, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "addAddresses(address[])", - whitelist - ) - ); + (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist)); // Assert resUint256 = ruleWhitelist.listedAddressCount(); assertEq(resUint256, 2); @@ -67,12 +58,7 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; vm.prank(WHITELIST_OPERATOR_ADDRESS); - (resCallBool, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "addAddresses(address[])", - whitelist - ) - ); + (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist)); assertEq(resCallBool, true); // Arrange - Assert resBool = ruleWhitelist.isAddressListed(ADDRESS1); @@ -83,12 +69,7 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); emit RemoveAddresses(whitelist); - (resCallBool, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "removeAddresses(address[])", - whitelist - ) - ); + (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("removeAddresses(address[])", whitelist)); // Assert assertEq(resCallBool, true); resBool = ruleWhitelist.isAddressListed(ADDRESS1); @@ -129,12 +110,8 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); emit RemoveAddresses(whitelistRemove); - (resCallBool, ) = address(ruleWhitelist).call( - abi.encodeWithSignature( - "removeAddresses(address[])", - whitelistRemove - ) - ); + (resCallBool,) = + address(ruleWhitelist).call(abi.encodeWithSignature("removeAddresses(address[])", whitelistRemove)); // Assert assertEq(resCallBool, true); resBool = ruleWhitelist.isAddressListed(ADDRESS1); diff --git a/test/utils/SanctionListOracle.sol b/test/utils/SanctionListOracle.sol index 28adcf9..1eab28a 100644 --- a/test/utils/SanctionListOracle.sol +++ b/test/utils/SanctionListOracle.sol @@ -6,6 +6,7 @@ import {ISanctionsList} from "../../src/rules/interfaces/ISanctionsList.sol"; * @notice Test contract from * https://etherscan.io/address/0x40c57923924b5c5c5455c48d93317139addac8fb#code */ + contract SanctionListOracle is ISanctionsList { constructor() {} From 71cf68356f4d98f1a319567ebc7882cb5d2d4f1c Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Mon, 1 Dec 2025 16:23:59 +0100 Subject: [PATCH 06/25] Add new interface for future compatibility with ERC-1155 token --- src/rules/interfaces/IAddressList.sol | 78 +++++++++++++++++++ .../IERC7943NonFungibleCompliance.sol | 26 +++++++ src/rules/validation/RuleBlacklist.sol | 14 +++- src/rules/validation/RuleSanctionsList.sol | 16 +++- src/rules/validation/RuleWhitelist.sol | 21 ++++- src/rules/validation/RuleWhitelistWrapper.sol | 9 +++ .../RuleAddressSet/RuleAddressSet.sol | 3 +- .../RuleAddressSetInvariantStorage.sol | 6 -- .../abstract/RuleValidateTransfer.sol | 34 ++++++-- 9 files changed, 185 insertions(+), 22 deletions(-) create mode 100644 src/rules/interfaces/IAddressList.sol create mode 100644 src/rules/interfaces/IERC7943NonFungibleCompliance.sol diff --git a/src/rules/interfaces/IAddressList.sol b/src/rules/interfaces/IAddressList.sol new file mode 100644 index 0000000..e55a596 --- /dev/null +++ b/src/rules/interfaces/IAddressList.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IIdentityRegistryContains} from "./IIdentityRegistry.sol"; +interface IAddressList is IIdentityRegistryContains { + /* ============ Events ============ */ + /// @notice Emitted when multiple addresses are added. + /// @param targetAddresses The array of added addresses. + event AddAddresses(address[] targetAddresses); + + /// @notice Emitted when multiple addresses are removed. + /// @param targetAddresses The array of removed addresses. + event RemoveAddresses(address[] targetAddresses); + + /// @notice Emitted when a single address is added. + /// @param targetAddress The added address. + event AddAddress(address targetAddress); + + /// @notice Emitted when a single address is removed. + /// @param targetAddress The removed address. + event RemoveAddress(address targetAddress); + + + /* ============ Write ============ */ + /** + * @notice Adds multiple addresses to the set. + * @dev Does not revert if some addresses are already listed. + * @param targetAddresses The addresses to add. + */ + function addAddresses(address[] calldata targetAddresses) external; + + /** + * @notice Removes multiple addresses from the set. + * @dev Does not revert if some addresses are not listed. + * @param targetAddresses The addresses to remove. + */ + function removeAddresses(address[] calldata targetAddresses) external; + + /** + * @notice Adds a single address to the set. + * @dev Reverts if the address is already listed. + * @param targetAddress The address to add. + */ + function addAddress(address targetAddress) external; + + /** + * @notice Removes a single address from the set. + * @dev Reverts if the address is not listed. + * @param targetAddress The address to remove. + */ + function removeAddress(address targetAddress) external; + + + /* ============ Read ============ */ + + /** + * @notice Returns the number of currently listed addresses. + * @return count The number of listed addresses. + */ + function listedAddressCount() external view returns (uint256 count); + + /** + * @notice Checks whether the provided address is listed. + * @param targetAddress The address to check. + * @return isListed True if listed, otherwise false. + */ + function isAddressListed(address targetAddress) external view returns (bool isListed); + + /** + * @notice Checks multiple addresses for listing status. + * @param targetAddresses Array of addresses to check. + * @return results Boolean array aligned by index with listing results. + */ + function areAddressesListed(address[] memory targetAddresses) + external + view + returns (bool[] memory results); +} \ No newline at end of file diff --git a/src/rules/interfaces/IERC7943NonFungibleCompliance.sol b/src/rules/interfaces/IERC7943NonFungibleCompliance.sol new file mode 100644 index 0000000..639d908 --- /dev/null +++ b/src/rules/interfaces/IERC7943NonFungibleCompliance.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +/** +* @dev for ERC-721 amount = 1 + */ +interface IERC7943NonFungibleCompliance { + /// @notice Checks if a transfer is currently possible according to token rules. It enforces validations on the frozen tokens. + /// @dev This may involve checks like allowlists, blocklists, transfer limits and other policy-defined restrictions. + /// @param from The address sending tokens. + /// @param to The address receiving tokens. + /// @param tokenId The ID of the token being transferred. + /// @param amount The amount being transferred. + /// @return allowed True if the transfer is allowed, false otherwise. + function canTransfer(address from, address to, uint256 tokenId, uint256 amount) external view returns (bool allowed); +} + +/** +* @dev for ERC-721 amount = 1 + */ +interface IERC7943NonFungibleComplianceExtend is IERC7943NonFungibleCompliance { + function detectTransferRestriction(address from, address to, uint256 tokenId, uint256 amount ) external view returns(uint8 code); + +} + \ No newline at end of file diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol index d1d571f..26c9c00 100644 --- a/src/rules/validation/RuleBlacklist.sol +++ b/src/rules/validation/RuleBlacklist.sol @@ -5,7 +5,8 @@ pragma solidity ^0.8.20; import "./abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol"; import "./abstract/RuleAddressSet/RuleAddressSet.sol"; import "./abstract/RuleValidateTransfer.sol"; -//import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; +import {IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol"; +import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; /** * @title a blacklist manager */ @@ -39,10 +40,19 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv } } + function detectTransferRestriction(address from, address to, uint256 /* tokenId */, uint256 value ) + public + view + override(IERC7943NonFungibleComplianceExtend) + returns (uint8) + { + return detectTransferRestriction(from, to, value); + } + function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) public view - override + override(IERC1404Extend) returns (uint8) { if (isAddressListed(spender)) { diff --git a/src/rules/validation/RuleSanctionsList.sol b/src/rules/validation/RuleSanctionsList.sol index b4f388a..3b1eb4f 100644 --- a/src/rules/validation/RuleSanctionsList.sol +++ b/src/rules/validation/RuleSanctionsList.sol @@ -7,7 +7,8 @@ import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../modules/Met import {RuleSanctionsListInvariantStorage} from "./abstract/RuleSanctionsListInvariantStorage.sol"; import {RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol"; import {ISanctionsList} from "../interfaces/ISanctionsList.sol"; - +import {IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol"; +import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; contract RuleSanctionsList is AccessControl, MetaTxModuleStandalone, @@ -51,7 +52,7 @@ contract RuleSanctionsList is function detectTransferRestriction(address from, address to, uint256 /*value */ ) public view - override + override(IERC1404) returns (uint8) { if (address(sanctionsList) != address(0)) { @@ -64,10 +65,19 @@ contract RuleSanctionsList is return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } + function detectTransferRestriction(address from, address to, uint256 /* tokenId */, uint256 value ) + public + view + override(IERC7943NonFungibleComplianceExtend) + returns (uint8) + { + return detectTransferRestriction(from, to, value); + } + function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) public view - override + override(IERC1404Extend) returns (uint8) { if (address(sanctionsList) != address(0)) { diff --git a/src/rules/validation/RuleWhitelist.sol b/src/rules/validation/RuleWhitelist.sol index ae9032e..aa8f80b 100644 --- a/src/rules/validation/RuleWhitelist.sol +++ b/src/rules/validation/RuleWhitelist.sol @@ -5,6 +5,8 @@ import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol"; import {RuleWhitelistCommon} from "./abstract/RuleWhitelistCommon.sol"; import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; import {IIdentityRegistryVerified} from "../interfaces/IIdentityRegistry.sol"; +import {IERC7943NonFungibleCompliance, IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol"; + /** * @title Rule Whitelist * @notice Manages a whitelist of authorized addresses and enforces whitelist-based transfer restrictions. @@ -39,7 +41,6 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry * - Implements the `IERC1404.detectTransferRestriction` interface. * @param from The address sending tokens. * @param to The address receiving tokens. - * @param value The amount being transferred (unused in this check). * @return code Restriction code (e.g., `TRANSFER_OK` or specific whitelist rejection). * * | Condition | Returned Code | @@ -48,10 +49,10 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry * | `to` not whitelisted | `CODE_ADDRESS_TO_NOT_WHITELISTED` | * | Both whitelisted | `TRANSFER_OK` | */ - function detectTransferRestriction(address from, address to, uint256 value) + function detectTransferRestriction(address from, address to, uint256 /* value */) public view - override + override(IERC1404) returns (uint8 code) { if (!isAddressListed(from)) { @@ -63,6 +64,18 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry } } + /** + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ + function detectTransferRestriction(address from, address to, uint256 /* tokenId */, uint256 value ) + public + view + override(IERC7943NonFungibleComplianceExtend) + returns (uint8) + { + return detectTransferRestriction(from, to, value); + } + /** * @notice Detects transfer restriction for delegated transfers (`transferFrom`). * @dev @@ -83,7 +96,7 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) public view - override + override(IERC1404Extend) returns (uint8 code) { if (_checkSpender && !isAddressListed(spender)) { diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol index 16730e8..d43276e 100644 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -59,6 +59,15 @@ contract RuleWhitelistWrapper is RulesManagementModule, MetaTxModuleStandalone, } } + function detectTransferRestriction(address from, address to, uint256 /* tokenId */, uint256 value ) + public + view + override + returns (uint8) + { + return detectTransferRestriction(from, to, value); + } + function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) public view diff --git a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol index a32044f..66c34cf 100644 --- a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol +++ b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol @@ -6,6 +6,7 @@ import {MetaTxModuleStandalone, ERC2771Context, Context} from "./../../../../mod import {RuleAddressSetInternal} from "./RuleAddressSetInternal.sol"; import {RuleAddressSetInvariantStorage} from "./invariantStorage/RuleAddressSetInvariantStorage.sol"; import {IIdentityRegistryContains} from "../../../interfaces/IIdentityRegistry.sol"; +import {IAddressList} from "../../../interfaces/IAddressList.sol"; /** * @title Rule Address Set * @notice Manages a permissioned set of addresses related to rule logic. @@ -21,7 +22,7 @@ abstract contract RuleAddressSet is MetaTxModuleStandalone, RuleAddressSetInternal, RuleAddressSetInvariantStorage, - IIdentityRegistryContains + IAddressList { /*////////////////////////////////////////////////////////////// STATE diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol index 1211aab..730f5c5 100644 --- a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol @@ -3,12 +3,6 @@ pragma solidity ^0.8.20; abstract contract RuleAddressSetInvariantStorage { - /* ============ Events ============ */ - event AddAddresses(address[] listTargetAddresses); - event RemoveAddresses(address[] listTargetAddresses); - event AddAddress(address targetAddress); - event RemoveAddress(address targetAddress); - /* ============ Custom errors ============ */ error RuleAddressSet_AdminWithAddressZeroNotAllowed(); diff --git a/src/rules/validation/abstract/RuleValidateTransfer.sol b/src/rules/validation/abstract/RuleValidateTransfer.sol index f82f020..8f74d7e 100644 --- a/src/rules/validation/abstract/RuleValidateTransfer.sol +++ b/src/rules/validation/abstract/RuleValidateTransfer.sol @@ -7,17 +7,39 @@ import {IERC3643ComplianceRead} from "CMTAT/interfaces/tokenization/IERC3643Part import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol"; import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; import {IRule} from "RuleEngine/interfaces/IRule.sol"; +import {IERC7943NonFungibleCompliance, IERC7943NonFungibleComplianceExtend} from "../../interfaces/IERC7943NonFungibleCompliance.sol"; -abstract contract RuleValidateTransfer is IERC3643ComplianceRead, IERC7551Compliance, IRule { +abstract contract RuleValidateTransfer is IERC3643ComplianceRead, IERC7551Compliance, IERC7943NonFungibleComplianceExtend, IRule { /** * @notice Validate a transfer - * @param _from the origin address - * @param _to the destination address - * @param _amount to transfer + * @param from the origin address + * @param to the destination address + * @param tokenId ERC-721 or ERC-1155 token Id + * @param amount to transfer, 1 for NFT * @return isValid => true if the transfer is valid, false otherwise * */ - function canTransfer(address _from, address _to, uint256 _amount) + function canTransfer(address from, address to, uint256 tokenId, uint256 amount) + public + view + override(IERC7943NonFungibleCompliance) + returns (bool isValid) + { + // does not work without `this` keyword => "Undeclared identifier" + return + this.detectTransferRestriction(from, to, tokenId, amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); + } + + + /** + * @notice Validate a transfer + * @param from the origin address + * @param to the destination address + * @param amount to transfer + * @return isValid => true if the transfer is valid, false otherwise + * + */ + function canTransfer(address from, address to, uint256 amount) public view override(IERC3643ComplianceRead) @@ -25,7 +47,7 @@ abstract contract RuleValidateTransfer is IERC3643ComplianceRead, IERC7551Compli { // does not work without `this` keyword => "Undeclared identifier" return - this.detectTransferRestriction(_from, _to, _amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); + this.detectTransferRestriction(from, to, amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); } function canTransferFrom(address spender, address from, address to, uint256 value) From 9df01582f83c16656dea45e237f42bd1060aa262 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Mon, 1 Dec 2025 16:27:33 +0100 Subject: [PATCH 07/25] Update and add new tests for the new features --- test/HelperContract.sol | 1 + test/RuleBlacklist/RuleBlacklist.t.sol | 74 +++++++++++++++++++ .../RuleSanctionListTest.t.sol | 28 +++++++ test/RuleWhitelist/RuleWhitelist.t.sol | 25 +++++++ test/RuleWhitelist/RuleWhitelistAdd.t.sol | 6 +- test/RuleWhitelist/RuleWhitelistRemove.t.sol | 10 +-- 6 files changed, 136 insertions(+), 8 deletions(-) diff --git a/test/HelperContract.sol b/test/HelperContract.sol index 5b9b023..df84c59 100644 --- a/test/HelperContract.sol +++ b/test/HelperContract.sol @@ -25,6 +25,7 @@ import {RuleAddressSetInvariantStorage} from import {RuleSanctionsListInvariantStorage} from "src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol"; // Rule interface +import {IAddressList} from "src/rules/interfaces/IAddressList.sol"; // utils import "RuleEngine/../test/utils/CMTATDeployment.sol"; diff --git a/test/RuleBlacklist/RuleBlacklist.t.sol b/test/RuleBlacklist/RuleBlacklist.t.sol index f52f53c..f206ed2 100644 --- a/test/RuleBlacklist/RuleBlacklist.t.sol +++ b/test/RuleBlacklist/RuleBlacklist.t.sol @@ -22,4 +22,78 @@ contract RuleBlacklistTest is Test, HelperContract { // Assert assertEq(message1, TEXT_CODE_NOT_FOUND); } + + function testDetectTransferRestrictionOk() public { + // Act + resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resUint8, NO_ERROR); + + // With tokenId + resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, NO_ERROR); + + // With tokenId + resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, NO_ERROR); + + // Act + resBool = ruleBlacklist.canTransfer(ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resBool, true); + // Act + resBool = ruleBlacklist.canTransfer(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resBool, true); + } + + function testDetectTransferRestrictionFRom() public { + // Arrange + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleBlacklist.addAddress(ADDRESS1); + // Act + resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_FROM_IS_BLACKLISTED); + + // With tokenId + resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_FROM_IS_BLACKLISTED); + + // Act + resBool = ruleBlacklist.canTransfer(ADDRESS1, ADDRESS2, 20); + // Assert + assertFalse(resBool); + + // Act + resBool = ruleBlacklist.canTransfer(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertFalse(resBool); + } + + function testDetectTransferRestrictionTO() public { + // Arrange + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleBlacklist.addAddress(ADDRESS2); + // Act + resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); + + // With tokenId + resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_TO_IS_BLACKLISTED); + + // Act + resBool = ruleBlacklist.canTransfer(ADDRESS1, ADDRESS2, 20); + // Assert + assertFalse(resBool); + + // Act + resBool = ruleBlacklist.canTransfer(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertFalse(resBool); + } } diff --git a/test/RuleSanctionList/RuleSanctionListTest.t.sol b/test/RuleSanctionList/RuleSanctionListTest.t.sol index b00f9f1..925cf60 100644 --- a/test/RuleSanctionList/RuleSanctionListTest.t.sol +++ b/test/RuleSanctionList/RuleSanctionListTest.t.sol @@ -59,9 +59,13 @@ contract RuleSanctionlistTest is Test, HelperContract { // ADDRESS1 -> ADDRESS2 resBool = ruleSanctionList.canTransfer(ADDRESS1, ADDRESS2, 20); assertEq(resBool, true); + resBool = ruleSanctionList.canTransfer(ADDRESS1, ADDRESS2, 0, 20); + assertEq(resBool, true); // ADDRESS2 -> ADDRESS1 resBool = ruleSanctionList.canTransfer(ADDRESS2, ADDRESS1, 20); assertEq(resBool, true); + resBool = ruleSanctionList.canTransfer(ADDRESS2, ADDRESS1, 0, 20); + assertEq(resBool, true); } function testTransferFromDetectedAsInvalid() public { @@ -69,6 +73,11 @@ contract RuleSanctionlistTest is Test, HelperContract { resBool = ruleSanctionList.canTransfer(ATTACKER, ADDRESS2, 20); // Assert assertFalse(resBool); + + // Act + resBool = ruleSanctionList.canTransfer(ATTACKER, ADDRESS2, 0, 20); + // Assert + assertFalse(resBool); } function testTransferToDetectedAsInvalid() public { @@ -76,6 +85,10 @@ contract RuleSanctionlistTest is Test, HelperContract { resBool = ruleSanctionList.canTransfer(ADDRESS1, ATTACKER, 20); // Assert assertFalse(resBool); + // Act + resBool = ruleSanctionList.canTransfer(ADDRESS1, ATTACKER, 0, 20); + // Assert + assertFalse(resBool); } function testDetectTransferRestrictionFrom() public { @@ -83,6 +96,11 @@ contract RuleSanctionlistTest is Test, HelperContract { resUint8 = ruleSanctionList.detectTransferRestriction(ATTACKER, ADDRESS2, 20); // Assert assertEq(resUint8, CODE_ADDRESS_FROM_IS_SANCTIONED); + + // Act + resUint8 = ruleSanctionList.detectTransferRestriction(ATTACKER, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_FROM_IS_SANCTIONED); } function testDetectTransferRestrictionTo() public { @@ -90,6 +108,11 @@ contract RuleSanctionlistTest is Test, HelperContract { resUint8 = ruleSanctionList.detectTransferRestriction(ADDRESS1, ATTACKER, 20); // Assert assertEq(resUint8, CODE_ADDRESS_TO_IS_SANCTIONED); + + // Act + resUint8 = ruleSanctionList.detectTransferRestriction(ADDRESS1, ATTACKER, 0, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_TO_IS_SANCTIONED); } function testDetectTransferRestrictionOk() public { @@ -97,5 +120,10 @@ contract RuleSanctionlistTest is Test, HelperContract { resUint8 = ruleSanctionList.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); // Assert assertEq(resUint8, NO_ERROR); + + // Act + resUint8 = ruleSanctionList.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, NO_ERROR); } } diff --git a/test/RuleWhitelist/RuleWhitelist.t.sol b/test/RuleWhitelist/RuleWhitelist.t.sol index 98e58ac..a8ceddd 100644 --- a/test/RuleWhitelist/RuleWhitelist.t.sol +++ b/test/RuleWhitelist/RuleWhitelist.t.sol @@ -117,9 +117,14 @@ contract RuleWhitelistTest is Test, HelperContract { // ADDRESS1 -> ADDRESS2 resBool = ruleWhitelist.canTransfer(ADDRESS1, ADDRESS2, 20); assertEq(resBool, true); + resBool = ruleWhitelist.canTransfer(ADDRESS1, ADDRESS2, 0, 20); + assertEq(resBool, true); // ADDRESS2 -> ADDRESS1 resBool = ruleWhitelist.canTransfer(ADDRESS2, ADDRESS1, 20); assertEq(resBool, true); + + resBool = ruleWhitelist.canTransfer(ADDRESS2, ADDRESS1, 0, 20); + assertEq(resBool, true); } function testTransferDetectedAsInvalid() public { @@ -172,6 +177,16 @@ contract RuleWhitelistTest is Test, HelperContract { resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); // Assert assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED); + + // With tokenId + resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED); + + // With tokenId + resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED); } function testDetectTransferRestrictionOk() public { @@ -184,5 +199,15 @@ contract RuleWhitelistTest is Test, HelperContract { resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); // Assert assertEq(resUint8, NO_ERROR); + + // With tokenId + resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, NO_ERROR); + + // With tokenId + resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, NO_ERROR); } } diff --git a/test/RuleWhitelist/RuleWhitelistAdd.t.sol b/test/RuleWhitelist/RuleWhitelistAdd.t.sol index 1ae9dd3..034d8d0 100644 --- a/test/RuleWhitelist/RuleWhitelistAdd.t.sol +++ b/test/RuleWhitelist/RuleWhitelistAdd.t.sol @@ -40,7 +40,7 @@ contract RuleWhitelistAddTest is Test, HelperContract { function testaddAddress() public { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit AddAddress(ADDRESS1); + emit IAddressList.AddAddress(ADDRESS1); ruleWhitelist.addAddress(ADDRESS1); // Assert @@ -75,7 +75,7 @@ contract RuleWhitelistAddTest is Test, HelperContract { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit AddAddress(address(0x0)); + emit IAddressList.AddAddress(address(0x0)); ruleWhitelist.addAddress(address(0x0)); // Assert @@ -95,7 +95,7 @@ contract RuleWhitelistAddTest is Test, HelperContract { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit AddAddresses(whitelist); + emit IAddressList.AddAddresses(whitelist); (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist)); // Assert - Main diff --git a/test/RuleWhitelist/RuleWhitelistRemove.t.sol b/test/RuleWhitelist/RuleWhitelistRemove.t.sol index e3028e3..d0c1bc9 100644 --- a/test/RuleWhitelist/RuleWhitelistRemove.t.sol +++ b/test/RuleWhitelist/RuleWhitelistRemove.t.sol @@ -19,7 +19,7 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { whitelist[0] = ADDRESS1; whitelist[1] = ADDRESS2; vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit AddAddresses(whitelist); + emit IAddressList.AddAddresses(whitelist); (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist)); // Assert resUint256 = ruleWhitelist.listedAddressCount(); @@ -42,7 +42,7 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit RemoveAddress(ADDRESS1); + emit IAddressList.RemoveAddress(ADDRESS1); ruleWhitelist.removeAddress(ADDRESS1); // Assert @@ -68,7 +68,7 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit RemoveAddresses(whitelist); + emit IAddressList.RemoveAddresses(whitelist); (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("removeAddresses(address[])", whitelist)); // Assert assertEq(resCallBool, true); @@ -88,7 +88,7 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit RemoveAddress(ADDRESS1); + emit IAddressList.RemoveAddress(ADDRESS1); ruleWhitelist.removeAddress(ADDRESS1); // Assert @@ -109,7 +109,7 @@ contract RuleWhitelistRemoveTest is Test, HelperContract { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit RemoveAddresses(whitelistRemove); + emit IAddressList.RemoveAddresses(whitelistRemove); (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("removeAddresses(address[])", whitelistRemove)); // Assert From fcf5d2399284560c0776a5581553c86d0cd78951 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Tue, 2 Dec 2025 10:46:43 +0100 Subject: [PATCH 08/25] Add detectTransferRestriction for Spender and Tokenid --- src/modules/AccessControlModule.sol | 48 +++++++++++++++++++ .../IERC7943NonFungibleCompliance.sol | 5 +- src/rules/validation/RuleBlacklist.sol | 9 ++++ src/rules/validation/RuleSanctionsList.sol | 9 ++++ src/rules/validation/RuleWhitelist.sol | 9 ++++ src/rules/validation/RuleWhitelistWrapper.sol | 11 +++++ 6 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/modules/AccessControlModule.sol diff --git a/src/modules/AccessControlModule.sol b/src/modules/AccessControlModule.sol new file mode 100644 index 0000000..978066d --- /dev/null +++ b/src/modules/AccessControlModule.sol @@ -0,0 +1,48 @@ +//SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +/* ==== OpenZeppelin === */ +import {AccessControl} from "OZ/access/AccessControl.sol"; + +abstract contract AccessControlModule is AccessControl { + + + /* ============ Initializer Function ============ */ + /** + * @dev + * + * - The grant to the admin role is done by AccessControlDefaultAdminRules + * - The control of the zero address is done by AccessControlDefaultAdminRules + * + */ + function _AccessControlModule_init(address admin) + internal { + if(admin == address(0)){ + //revert CMTAT_AccessControlModule_AddressZeroNotAllowed(); + } + // we don't check the return value + // _grantRole attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. + // return false only if the admin has already the role + _grantRole(DEFAULT_ADMIN_ROLE, admin); + } + + + /*////////////////////////////////////////////////////////////// + PUBLIC/EXTERNAL FUNCTIONS + //////////////////////////////////////////////////////////////*/ + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole( + bytes32 role, + address account + ) public view virtual override(AccessControl) returns (bool) { + // The Default Admin has all roles + if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { + return true; + } else { + return AccessControl.hasRole(role, account); + } + } +} diff --git a/src/rules/interfaces/IERC7943NonFungibleCompliance.sol b/src/rules/interfaces/IERC7943NonFungibleCompliance.sol index 639d908..5175226 100644 --- a/src/rules/interfaces/IERC7943NonFungibleCompliance.sol +++ b/src/rules/interfaces/IERC7943NonFungibleCompliance.sol @@ -21,6 +21,9 @@ interface IERC7943NonFungibleCompliance { */ interface IERC7943NonFungibleComplianceExtend is IERC7943NonFungibleCompliance { function detectTransferRestriction(address from, address to, uint256 tokenId, uint256 amount ) external view returns(uint8 code); - + function detectTransferRestrictionFrom(address spender, address from, address to, uint256 tokenId, uint256 value) + external + view + returns (uint8 code); } \ No newline at end of file diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol index 26c9c00..4501cb2 100644 --- a/src/rules/validation/RuleBlacklist.sol +++ b/src/rules/validation/RuleBlacklist.sol @@ -62,6 +62,15 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv } } + function detectTransferRestrictionFrom(address spender, address from, address to, uint256 /* tokenId */, uint256 value ) + public + view + override(IERC7943NonFungibleComplianceExtend) + returns (uint8) + { + return detectTransferRestrictionFrom(spender, from, to, value); + } + /** * @notice To know if the restriction code is valid for this rule or not. * @param _restrictionCode The target restriction code diff --git a/src/rules/validation/RuleSanctionsList.sol b/src/rules/validation/RuleSanctionsList.sol index 3b1eb4f..c6224a2 100644 --- a/src/rules/validation/RuleSanctionsList.sol +++ b/src/rules/validation/RuleSanctionsList.sol @@ -90,6 +90,15 @@ contract RuleSanctionsList is return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } + function detectTransferRestrictionFrom(address spender, address from, address to, uint256 /* tokenId */, uint256 value ) + public + view + override(IERC7943NonFungibleComplianceExtend) + returns (uint8) + { + return detectTransferRestrictionFrom(spender, from, to, value); + } + /** * @notice To know if the restriction code is valid for this rule or not. * @param _restrictionCode The target restriction code diff --git a/src/rules/validation/RuleWhitelist.sol b/src/rules/validation/RuleWhitelist.sol index aa8f80b..d97bc17 100644 --- a/src/rules/validation/RuleWhitelist.sol +++ b/src/rules/validation/RuleWhitelist.sol @@ -105,6 +105,15 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry return detectTransferRestriction(from, to, value); } + function detectTransferRestrictionFrom(address spender, address from, address to, uint256 /* tokenId */, uint256 value ) + public + view + override(IERC7943NonFungibleComplianceExtend) + returns (uint8) + { + return detectTransferRestrictionFrom(spender, from, to, value); + } + /** * @notice Checks whether a specific address is currently listed. * @param targetAddress The address to check. diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol index d43276e..c628b7a 100644 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -9,6 +9,8 @@ import {RuleWhitelistCommon} from "./abstract/RuleWhitelistCommon.sol"; import {RulesManagementModule} from "RuleEngine/modules/RulesManagementModule.sol"; import {RuleEngineInvariantStorage} from "RuleEngine/modules/library/RuleEngineInvariantStorage.sol"; import {IRule} from "RuleEngine/interfaces/IRule.sol"; +import {IERC7943NonFungibleCompliance, IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol"; + /** * @title Wrapper to call several different whitelist rules */ @@ -96,6 +98,15 @@ contract RuleWhitelistWrapper is RulesManagementModule, MetaTxModuleStandalone, } } + function detectTransferRestrictionFrom(address spender, address from, address to, uint256 /* tokenId */, uint256 value ) + public + view + override(IERC7943NonFungibleComplianceExtend) + returns (uint8) + { + return detectTransferRestrictionFrom(spender, from, to, value); + } + /* ============ ACCESS CONTROL ============ */ /** * @dev Returns `true` if `account` has been granted `role`. From e733507b15facade12aa2df791cc1f011353c327 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Tue, 2 Dec 2025 11:02:31 +0100 Subject: [PATCH 09/25] Add contract rule address in transfer error --- src/rules/validation/RuleBlacklist.sol | 4 ++-- src/rules/validation/RuleSanctionsList.sol | 4 ++-- src/rules/validation/RuleWhitelistWrapper.sol | 1 - .../invariantStorage/RuleBlacklistInvariantStorage.sol | 2 +- .../invariantStorage/RuleWhitelistInvariantStorage.sol | 2 +- .../validation/abstract/RuleSanctionsListInvariantStorage.sol | 2 +- src/rules/validation/abstract/RuleWhitelistCommon.sol | 4 ++-- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol index 4501cb2..f66dd33 100644 --- a/src/rules/validation/RuleBlacklist.sol +++ b/src/rules/validation/RuleBlacklist.sol @@ -102,11 +102,11 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv function transferred(address from, address to, uint256 value) public view { uint8 code = this.detectTransferRestriction(from, to, value); - require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleBlacklist_InvalidTransfer(from, to, value, code)); + require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleBlacklist_InvalidTransfer(address(this), from, to, value, code)); } function transferred(address spender, address from, address to, uint256 value) public view { uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); - require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleBlacklist_InvalidTransfer(from, to, value, code)); + require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleBlacklist_InvalidTransfer(address(this), from, to, value, code)); } } diff --git a/src/rules/validation/RuleSanctionsList.sol b/src/rules/validation/RuleSanctionsList.sol index c6224a2..d92660c 100644 --- a/src/rules/validation/RuleSanctionsList.sol +++ b/src/rules/validation/RuleSanctionsList.sol @@ -130,12 +130,12 @@ contract RuleSanctionsList is function transferred(address from, address to, uint256 value) public view { uint8 code = this.detectTransferRestriction(from, to, value); - require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleSanctionsList_InvalidTransfer(from, to, value, code)); + require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code)); } function transferred(address spender, address from, address to, uint256 value) public view { uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); - require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleSanctionsList_InvalidTransfer(from, to, value, code)); + require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code)); } /* ============ ACCESS CONTROL ============ */ diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol index c628b7a..fb94fb6 100644 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -51,7 +51,6 @@ contract RuleWhitelistWrapper is RulesManagementModule, MetaTxModuleStandalone, targetAddress[1] = to; bool[] memory result = _detectTransferRestriction(targetAddress); - if (!result[0]) { return CODE_ADDRESS_FROM_NOT_WHITELISTED; } else if (!result[1]) { diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol index 1e446c6..4230ef4 100644 --- a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.20; import "../../RuleCommonInvariantStorage.sol"; abstract contract RuleBlacklistInvariantStorage is RuleCommonInvariantStorage { - error RuleBlacklist_InvalidTransfer(address from, address to, uint256 value, uint8 code); + error RuleBlacklist_InvalidTransfer(address rule, address from, address to, uint256 value, uint8 code); /* ============ String message ============ */ string constant TEXT_ADDRESS_FROM_IS_BLACKLISTED = "The sender is blacklisted"; diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol index a724184..92b8d11 100644 --- a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.20; import "../../RuleCommonInvariantStorage.sol"; abstract contract RuleWhitelistInvariantStorage is RuleCommonInvariantStorage { - error RuleWhitelist_InvalidTransfer(address from, address to, uint256 value, uint8 code); + error RuleWhitelist_InvalidTransfer(address rule, address from, address to, uint256 value, uint8 code); /* ============ String message ============ */ string constant TEXT_ADDRESS_FROM_NOT_WHITELISTED = "The sender is not in the whitelist"; diff --git a/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol index 5fb60b0..439f920 100644 --- a/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol @@ -6,7 +6,7 @@ import "./RuleCommonInvariantStorage.sol"; import {ISanctionsList} from "../../interfaces/ISanctionsList.sol"; abstract contract RuleSanctionsListInvariantStorage is RuleCommonInvariantStorage { - error RuleSanctionsList_InvalidTransfer(address from, address to, uint256 value, uint8 code); + error RuleSanctionsList_InvalidTransfer(address rule, address from, address to, uint256 value, uint8 code); /* ============ Event ============ */ event SetSanctionListOracle(ISanctionsList newOracle); diff --git a/src/rules/validation/abstract/RuleWhitelistCommon.sol b/src/rules/validation/abstract/RuleWhitelistCommon.sol index 7bbdad1..8132879 100644 --- a/src/rules/validation/abstract/RuleWhitelistCommon.sol +++ b/src/rules/validation/abstract/RuleWhitelistCommon.sol @@ -70,7 +70,7 @@ abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInva */ function transferred(address from, address to, uint256 value) public view { uint8 code = this.detectTransferRestriction(from, to, value); - require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleWhitelist_InvalidTransfer(from, to, value, code)); + require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleWhitelist_InvalidTransfer(address(this), from, to, value, code)); } /** @@ -85,6 +85,6 @@ abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInva */ function transferred(address spender, address from, address to, uint256 value) public view { uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); - require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleWhitelist_InvalidTransfer(from, to, value, code)); + require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleWhitelist_InvalidTransfer(address(this), from, to, value, code)); } } From 74a146f8044f13280abf59aa3d0b017edf8b1875 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Tue, 2 Dec 2025 14:01:04 +0100 Subject: [PATCH 10/25] Add explicit override + transferred function for ERC-1155 tokens --- .../IERC7943NonFungibleCompliance.sol | 3 ++ src/rules/validation/RuleBlacklist.sol | 10 ++++-- src/rules/validation/RuleSanctionsList.sol | 10 ++++-- .../abstract/RuleValidateTransfer.sol | 12 ++++++- .../abstract/RuleWhitelistCommon.sol | 12 +++++-- test/RuleBlacklist/CMTATIntegration.t.sol | 8 ++--- test/RuleWhitelist/CMTATIntegration.t.sol | 6 ++-- .../CMTATIntegrationWhitelistWrapper.t.sol | 6 ++-- test/RuleWhitelist/RuleWhitelist.t.sol | 36 +++++++++++++++++-- 9 files changed, 83 insertions(+), 20 deletions(-) diff --git a/src/rules/interfaces/IERC7943NonFungibleCompliance.sol b/src/rules/interfaces/IERC7943NonFungibleCompliance.sol index 5175226..4f13da4 100644 --- a/src/rules/interfaces/IERC7943NonFungibleCompliance.sol +++ b/src/rules/interfaces/IERC7943NonFungibleCompliance.sol @@ -25,5 +25,8 @@ interface IERC7943NonFungibleComplianceExtend is IERC7943NonFungibleCompliance { external view returns (uint8 code); + function canTransferFrom(address spender, address from, address to, uint256 tokenId, uint256 value) external returns (bool); + + function transferred(address spender, address from, address to, uint256 tokenId, uint256 value) external; } \ No newline at end of file diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol index f66dd33..3592add 100644 --- a/src/rules/validation/RuleBlacklist.sol +++ b/src/rules/validation/RuleBlacklist.sol @@ -7,6 +7,8 @@ import "./abstract/RuleAddressSet/RuleAddressSet.sol"; import "./abstract/RuleValidateTransfer.sol"; import {IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol"; import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; +import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; +import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; /** * @title a blacklist manager */ @@ -100,13 +102,17 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv } } - function transferred(address from, address to, uint256 value) public view { + function transferred(address from, address to, uint256 value) public view override(IERC3643IComplianceContract) { uint8 code = this.detectTransferRestriction(from, to, value); require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleBlacklist_InvalidTransfer(address(this), from, to, value, code)); } - function transferred(address spender, address from, address to, uint256 value) public view { + function transferred(address spender, address from, address to, uint256 value) public view override(IRuleEngine) { uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleBlacklist_InvalidTransfer(address(this), from, to, value, code)); } + + function transferred(address spender, address from, address to, uint256 /* tokenId */, uint256 value) public view override(IERC7943NonFungibleComplianceExtend) { + transferred(spender, from, to, value); + } } diff --git a/src/rules/validation/RuleSanctionsList.sol b/src/rules/validation/RuleSanctionsList.sol index d92660c..f6d3948 100644 --- a/src/rules/validation/RuleSanctionsList.sol +++ b/src/rules/validation/RuleSanctionsList.sol @@ -9,6 +9,8 @@ import {RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol"; import {ISanctionsList} from "../interfaces/ISanctionsList.sol"; import {IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol"; import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; +import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; +import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; contract RuleSanctionsList is AccessControl, MetaTxModuleStandalone, @@ -128,16 +130,20 @@ contract RuleSanctionsList is } } - function transferred(address from, address to, uint256 value) public view { + function transferred(address from, address to, uint256 value) public view override(IERC3643IComplianceContract){ uint8 code = this.detectTransferRestriction(from, to, value); require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code)); } - function transferred(address spender, address from, address to, uint256 value) public view { + function transferred(address spender, address from, address to, uint256 value) public view override(IRuleEngine){ uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code)); } + function transferred(address spender, address from, address to, uint256 /* tokenId */, uint256 value) public view override(IERC7943NonFungibleComplianceExtend){ + transferred(spender, from, to, value); + } + /* ============ ACCESS CONTROL ============ */ /** * @dev Returns `true` if `account` has been granted `role`. diff --git a/src/rules/validation/abstract/RuleValidateTransfer.sol b/src/rules/validation/abstract/RuleValidateTransfer.sol index 8f74d7e..2f258ce 100644 --- a/src/rules/validation/abstract/RuleValidateTransfer.sol +++ b/src/rules/validation/abstract/RuleValidateTransfer.sol @@ -9,7 +9,7 @@ import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; import {IRule} from "RuleEngine/interfaces/IRule.sol"; import {IERC7943NonFungibleCompliance, IERC7943NonFungibleComplianceExtend} from "../../interfaces/IERC7943NonFungibleCompliance.sol"; -abstract contract RuleValidateTransfer is IERC3643ComplianceRead, IERC7551Compliance, IERC7943NonFungibleComplianceExtend, IRule { +abstract contract RuleValidateTransfer is IERC7943NonFungibleComplianceExtend, IRule { /** * @notice Validate a transfer * @param from the origin address @@ -60,4 +60,14 @@ abstract contract RuleValidateTransfer is IERC3643ComplianceRead, IERC7551Compli return this.detectTransferRestrictionFrom(spender, from, to, value) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); } + + function canTransferFrom(address spender, address from, address to, uint256 tokenId, uint256 value) + public + view + virtual + override(IERC7943NonFungibleComplianceExtend) + returns (bool) + { + return canTransferFrom(spender, from, to, value); + } } diff --git a/src/rules/validation/abstract/RuleWhitelistCommon.sol b/src/rules/validation/abstract/RuleWhitelistCommon.sol index 8132879..e54fa9c 100644 --- a/src/rules/validation/abstract/RuleWhitelistCommon.sol +++ b/src/rules/validation/abstract/RuleWhitelistCommon.sol @@ -3,7 +3,9 @@ pragma solidity ^0.8.20; import {RuleWhitelistInvariantStorage} from "./RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol"; import {RuleValidateTransfer} from "./RuleValidateTransfer.sol"; - +import {IERC7943NonFungibleCompliance, IERC7943NonFungibleComplianceExtend} from "../../interfaces/IERC7943NonFungibleCompliance.sol"; +import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; +import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; /** * @title Rule Whitelist Common * @notice Provides common logic for validating whitelist-based transfer restrictions. @@ -68,7 +70,7 @@ abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInva * @param to The address receiving tokens. * @param value The token amount being transferred. */ - function transferred(address from, address to, uint256 value) public view { + function transferred(address from, address to, uint256 value) public view override(IERC3643IComplianceContract){ uint8 code = this.detectTransferRestriction(from, to, value); require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleWhitelist_InvalidTransfer(address(this), from, to, value, code)); } @@ -83,8 +85,12 @@ abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInva * @param to The recipient address. * @param value The token amount being transferred. */ - function transferred(address spender, address from, address to, uint256 value) public view { + function transferred(address spender, address from, address to, uint256 value) public view override(IRuleEngine) { uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleWhitelist_InvalidTransfer(address(this), from, to, value, code)); } + + function transferred(address spender, address from, address to, uint256 /* tokenId */, uint256 value) public view override(IERC7943NonFungibleComplianceExtend){ + transferred(spender, from, to, value); + } } diff --git a/test/RuleBlacklist/CMTATIntegration.t.sol b/test/RuleBlacklist/CMTATIntegration.t.sol index b6eeec6..de872f8 100644 --- a/test/RuleBlacklist/CMTATIntegration.t.sol +++ b/test/RuleBlacklist/CMTATIntegration.t.sol @@ -59,7 +59,7 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleBlacklist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_TO_IS_BLACKLISTED + RuleBlacklist_InvalidTransfer.selector, address(ruleBlacklist), ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_TO_IS_BLACKLISTED ) ); // Act @@ -75,7 +75,7 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleBlacklist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_IS_BLACKLISTED + RuleBlacklist_InvalidTransfer.selector, address(ruleBlacklist), ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_IS_BLACKLISTED ) ); // Act @@ -96,7 +96,7 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleBlacklist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_IS_BLACKLISTED + RuleBlacklist_InvalidTransfer.selector, address(ruleBlacklist), ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_IS_BLACKLISTED ) ); CMTAT_CONTRACT.transfer(ADDRESS2, amount); @@ -190,7 +190,7 @@ contract CMTATIntegration is Test, HelperContract { // Act vm.expectRevert( abi.encodeWithSelector( - RuleBlacklist_InvalidTransfer.selector, ZERO_ADDRESS, ADDRESS1, amount, CODE_ADDRESS_TO_IS_BLACKLISTED + RuleBlacklist_InvalidTransfer.selector, address(ruleBlacklist), ZERO_ADDRESS, ADDRESS1, amount, CODE_ADDRESS_TO_IS_BLACKLISTED ) ); vm.prank(DEFAULT_ADMIN_ADDRESS); diff --git a/test/RuleWhitelist/CMTATIntegration.t.sol b/test/RuleWhitelist/CMTATIntegration.t.sol index 5dd66a0..c8ec3a4 100644 --- a/test/RuleWhitelist/CMTATIntegration.t.sol +++ b/test/RuleWhitelist/CMTATIntegration.t.sol @@ -47,7 +47,7 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21, CODE_ADDRESS_FROM_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, address(ruleWhitelist), ADDRESS1, ADDRESS2, 21, CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -63,7 +63,7 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, address(ruleWhitelist),ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -79,7 +79,7 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_TO_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, address(ruleWhitelist), ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_TO_NOT_WHITELISTED ) ); // Act diff --git a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol index 024158b..94d7e43 100644 --- a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol +++ b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol @@ -67,7 +67,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21, CODE_ADDRESS_FROM_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, address(ruleWhitelistWrapper), ADDRESS1, ADDRESS2, 21, CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -83,7 +83,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, address(ruleWhitelistWrapper), ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -99,7 +99,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_TO_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, address(ruleWhitelistWrapper), ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_TO_NOT_WHITELISTED ) ); // Act diff --git a/test/RuleWhitelist/RuleWhitelist.t.sol b/test/RuleWhitelist/RuleWhitelist.t.sol index a8ceddd..bec226e 100644 --- a/test/RuleWhitelist/RuleWhitelist.t.sol +++ b/test/RuleWhitelist/RuleWhitelist.t.sol @@ -182,11 +182,24 @@ contract RuleWhitelistTest is Test, HelperContract { resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED); + } + + function testDetectTransferRestrictionWithSpender() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS1); + + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS2); + // Act + resUint8 = ruleWhitelist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_SPENDER_NOT_WHITELISTED); // With tokenId - resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); + resUint8 = ruleWhitelist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); // Assert - assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED); + assertEq(resUint8, CODE_ADDRESS_SPENDER_NOT_WHITELISTED); } function testDetectTransferRestrictionOk() public { @@ -210,4 +223,23 @@ contract RuleWhitelistTest is Test, HelperContract { // Assert assertEq(resUint8, NO_ERROR); } + + function testDetectTransferRestrictionWithSpenderOk() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS1); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS2); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS3); + // Act + resUint8 = ruleWhitelist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resUint8, NO_ERROR); + + // With tokenId + resUint8 = ruleWhitelist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, NO_ERROR); + } } From bcb7bdfb1c479bc5e87cf1e58e79487d829ec3f1 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Tue, 2 Dec 2025 14:41:00 +0100 Subject: [PATCH 11/25] Add specific module for AccessControl --- ....sol => AccessControlModuleStandalone.sol} | 14 ++- src/rules/validation/RuleBlacklist.sol | 34 +++++-- src/rules/validation/RuleSanctionsList.sol | 91 +++++++++++-------- src/rules/validation/RuleWhitelist.sol | 12 ++- src/rules/validation/RuleWhitelistWrapper.sol | 53 ++++++----- .../RuleAddressSet/RuleAddressSet.sol | 34 ++----- .../RuleAddressSet/RuleAddressSetInternal.sol | 1 + .../RuleBlacklistInvariantStorage.sol | 2 +- .../RuleWhitelistInvariantStorage.sol | 2 +- .../RuleSanctionsListInvariantStorage.sol | 7 +- .../abstract/RuleValidateTransfer.sol | 8 ++ .../abstract/RuleWhitelistCommon.sol | 26 ++++-- 12 files changed, 159 insertions(+), 125 deletions(-) rename src/modules/{AccessControlModule.sol => AccessControlModuleStandalone.sol} (77%) diff --git a/src/modules/AccessControlModule.sol b/src/modules/AccessControlModuleStandalone.sol similarity index 77% rename from src/modules/AccessControlModule.sol rename to src/modules/AccessControlModuleStandalone.sol index 978066d..6cc6485 100644 --- a/src/modules/AccessControlModule.sol +++ b/src/modules/AccessControlModuleStandalone.sol @@ -5,19 +5,17 @@ pragma solidity ^0.8.20; /* ==== OpenZeppelin === */ import {AccessControl} from "OZ/access/AccessControl.sol"; -abstract contract AccessControlModule is AccessControl { - - - /* ============ Initializer Function ============ */ +abstract contract AccessControlModuleStandalone is AccessControl { + /* ============ Constructor ============ */ /** * @dev * - * - The grant to the admin role is done by AccessControlDefaultAdminRules - * - The control of the zero address is done by AccessControlDefaultAdminRules + * Revert if admin is the zero address + * Grant the admin with the admin role * */ - function _AccessControlModule_init(address admin) - internal { + constructor(address admin) + { if(admin == address(0)){ //revert CMTAT_AccessControlModule_AddressZeroNotAllowed(); } diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol index 3592add..f1943a8 100644 --- a/src/rules/validation/RuleBlacklist.sol +++ b/src/rules/validation/RuleBlacklist.sol @@ -2,13 +2,18 @@ pragma solidity ^0.8.20; -import "./abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol"; -import "./abstract/RuleAddressSet/RuleAddressSet.sol"; -import "./abstract/RuleValidateTransfer.sol"; +/* ==== Abtract contracts === */ +import {RuleBlacklistInvariantStorage} from "./abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol"; +import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol"; +import {RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol"; +/* ==== Interfaces === */ import {IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol"; +/* ==== CMTAT === */ import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; +/* ==== IRuleEngine === */ +import {IRule} from "RuleEngine/interfaces/IRule.sol"; /** * @title a blacklist manager */ @@ -30,7 +35,7 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv function detectTransferRestriction(address from, address to, uint256 /* value */ ) public view - override + override(IERC1404) returns (uint8) { if (isAddressListed(from)) { @@ -42,6 +47,9 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv } } + /* + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ function detectTransferRestriction(address from, address to, uint256 /* tokenId */, uint256 value ) public view @@ -51,6 +59,9 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv return detectTransferRestriction(from, to, value); } + /* + * @inheritdoc IERC1404Extend + */ function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) public view @@ -64,6 +75,9 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv } } + /** + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ function detectTransferRestrictionFrom(address spender, address from, address to, uint256 /* tokenId */, uint256 value ) public view @@ -79,7 +93,7 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv * @return true if the restriction code is known, false otherwise * */ - function canReturnTransferRestrictionCode(uint8 _restrictionCode) external pure override returns (bool) { + function canReturnTransferRestrictionCode(uint8 _restrictionCode) public pure virtual override(IRule) returns (bool) { return _restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED || _restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED || _restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED; } @@ -90,7 +104,7 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv * @return true if the transfer is valid, false otherwise * */ - function messageForTransferRestriction(uint8 _restrictionCode) external pure override returns (string memory) { + function messageForTransferRestriction(uint8 _restrictionCode) public pure virtual override(IERC1404) returns (string memory) { if (_restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED) { return TEXT_ADDRESS_FROM_IS_BLACKLISTED; } else if (_restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED) { @@ -102,17 +116,19 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv } } - function transferred(address from, address to, uint256 value) public view override(IERC3643IComplianceContract) { + /* ============ State Functions ============ */ + + function transferred(address from, address to, uint256 value) public view virtual override(IERC3643IComplianceContract) { uint8 code = this.detectTransferRestriction(from, to, value); require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleBlacklist_InvalidTransfer(address(this), from, to, value, code)); } - function transferred(address spender, address from, address to, uint256 value) public view override(IRuleEngine) { + function transferred(address spender, address from, address to, uint256 value) public view virtual override(IRuleEngine) { uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleBlacklist_InvalidTransfer(address(this), from, to, value, code)); } - function transferred(address spender, address from, address to, uint256 /* tokenId */, uint256 value) public view override(IERC7943NonFungibleComplianceExtend) { + function transferred(address spender, address from, address to, uint256 /* tokenId */, uint256 value) public view virtual override(IERC7943NonFungibleComplianceExtend) { transferred(spender, from, to, value); } } diff --git a/src/rules/validation/RuleSanctionsList.sol b/src/rules/validation/RuleSanctionsList.sol index f6d3948..1274c76 100644 --- a/src/rules/validation/RuleSanctionsList.sol +++ b/src/rules/validation/RuleSanctionsList.sol @@ -2,17 +2,22 @@ pragma solidity ^0.8.20; -import {AccessControl} from "OZ/access/AccessControl.sol"; +/* ==== Abtract contracts === */ import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../modules/MetaTxModuleStandalone.sol"; +import {AccessControlModuleStandalone} from "../../modules/AccessControlModuleStandalone.sol"; import {RuleSanctionsListInvariantStorage} from "./abstract/RuleSanctionsListInvariantStorage.sol"; import {RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol"; +/* ==== Interfaces === */ import {ISanctionsList} from "../interfaces/ISanctionsList.sol"; import {IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol"; +/* ==== CMTAT === */ import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; +/* ==== IRuleEngine === */ +import {IRule} from "RuleEngine/interfaces/IRule.sol"; contract RuleSanctionsList is - AccessControl, + AccessControlModuleStandalone, MetaTxModuleStandalone, RuleValidateTransfer, RuleSanctionsListInvariantStorage @@ -24,25 +29,14 @@ contract RuleSanctionsList is * @param forwarderIrrevocable Address of the forwarder, required for the gasless support */ constructor(address admin, address forwarderIrrevocable, ISanctionsList sanctionContractOracle_) - MetaTxModuleStandalone(forwarderIrrevocable) + MetaTxModuleStandalone(forwarderIrrevocable) AccessControlModuleStandalone(admin) { - if (admin == address(0)) { - revert RuleSanctionList_AdminWithAddressZeroNotAllowed(); - } if (address(sanctionContractOracle_) != address(0)) { _setSanctionListOracle(sanctionContractOracle_); } - _grantRole(DEFAULT_ADMIN_ROLE, admin); } - /** - * @notice Set the oracle contract - * @param sanctionContractOracle_ address of your oracle contract - * @dev zero address is authorized to authorize all transfers - */ - function setSanctionListOracle(ISanctionsList sanctionContractOracle_) public onlyRole(SANCTIONLIST_ROLE) { - _setSanctionListOracle(sanctionContractOracle_); - } + /* ============ View Functions ============ */ /** * @notice Check if an addres is in the SanctionsList or not @@ -67,18 +61,26 @@ contract RuleSanctionsList is return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } + /** + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ function detectTransferRestriction(address from, address to, uint256 /* tokenId */, uint256 value ) public view + virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) { return detectTransferRestriction(from, to, value); } + /** + * @inheritdoc IERC1404Extend + */ function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) public view + virtual override(IERC1404Extend) returns (uint8) { @@ -95,6 +97,7 @@ contract RuleSanctionsList is function detectTransferRestrictionFrom(address spender, address from, address to, uint256 /* tokenId */, uint256 value ) public view + virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) { @@ -103,58 +106,66 @@ contract RuleSanctionsList is /** * @notice To know if the restriction code is valid for this rule or not. - * @param _restrictionCode The target restriction code + * @param restrictionCode The target restriction code * @return true if the restriction code is known, false otherwise * */ - function canReturnTransferRestrictionCode(uint8 _restrictionCode) external pure override returns (bool) { - return _restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED || _restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED - || _restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED; + function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override(IRule) + returns (bool) { + return restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED || restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED + || restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED; } /** * @notice Return the corresponding message - * @param _restrictionCode The target restriction code + * @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) { + function messageForTransferRestriction(uint8 restrictionCode) public pure virtual override(IERC1404) + returns (string memory) { + if (restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED) { return TEXT_ADDRESS_FROM_IS_SANCTIONED; - } else if (_restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED) { + } else if (restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED) { return TEXT_ADDRESS_TO_IS_SANCTIONED; - } else if (_restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED) { + } else if (restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED) { return TEXT_ADDRESS_SPENDER_IS_SANCTIONED; } else { return TEXT_CODE_NOT_FOUND; } } - function transferred(address from, address to, uint256 value) public view override(IERC3643IComplianceContract){ + /* ============ State Functions ============ */ + /** + * @notice Set the oracle contract + * @param sanctionContractOracle_ address of your oracle contract + * @dev zero address is authorized to authorize all transfers + */ + function setSanctionListOracle(ISanctionsList sanctionContractOracle_) public onlyRole(SANCTIONLIST_ROLE) { + _setSanctionListOracle(sanctionContractOracle_); + } + + /** + * @inheritdoc IERC3643IComplianceContract + */ + function transferred(address from, address to, uint256 value) public view virtual override(IERC3643IComplianceContract){ uint8 code = this.detectTransferRestriction(from, to, value); require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code)); } - function transferred(address spender, address from, address to, uint256 value) public view override(IRuleEngine){ + /** + * @inheritdoc IRuleEngine + */ + function transferred(address spender, address from, address to, uint256 value) public view virtual override(IRuleEngine){ uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code)); } - function transferred(address spender, address from, address to, uint256 /* tokenId */, uint256 value) public view override(IERC7943NonFungibleComplianceExtend){ - transferred(spender, from, to, value); - } - - /* ============ ACCESS CONTROL ============ */ /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override(AccessControl) returns (bool) { - // The Default Admin has all roles - if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { - return true; - } else { - return AccessControl.hasRole(role, account); - } + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ + function transferred(address spender, address from, address to, uint256 /* tokenId */, uint256 value) public view virtual override(IERC7943NonFungibleComplianceExtend){ + transferred(spender, from, to, value); } /*////////////////////////////////////////////////////////////// diff --git a/src/rules/validation/RuleWhitelist.sol b/src/rules/validation/RuleWhitelist.sol index d97bc17..68acc33 100644 --- a/src/rules/validation/RuleWhitelist.sol +++ b/src/rules/validation/RuleWhitelist.sol @@ -1,9 +1,12 @@ // SPDX-License-Identifier: MPL-2.0 pragma solidity ^0.8.20; +/* ==== Abtract contracts === */ import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol"; import {RuleWhitelistCommon} from "./abstract/RuleWhitelistCommon.sol"; +/* ==== CMTAT === */ import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; +/* ==== Interfaces === */ import {IIdentityRegistryVerified} from "../interfaces/IIdentityRegistry.sol"; import {IERC7943NonFungibleCompliance, IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol"; @@ -24,10 +27,10 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry * @param admin Address of the contract (Access Control) * @param forwarderIrrevocable Address of the forwarder, required for the gasless support */ - constructor(address admin, address forwarderIrrevocable, bool checkSpender) + constructor(address admin, address forwarderIrrevocable, bool checkSpender_) RuleAddressSet(admin, forwarderIrrevocable) { - _checkSpender = checkSpender; + checkSpender = checkSpender_; } /*////////////////////////////////////////////////////////////// @@ -99,12 +102,15 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry override(IERC1404Extend) returns (uint8 code) { - if (_checkSpender && !isAddressListed(spender)) { + if (checkSpender && !isAddressListed(spender)) { return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; } return detectTransferRestriction(from, to, value); } + /** + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ function detectTransferRestrictionFrom(address spender, address from, address to, uint256 /* tokenId */, uint256 value ) public view diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol index fb94fb6..319de1d 100644 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -2,20 +2,26 @@ pragma solidity ^0.8.20; +/* ==== OpenZeppelin === */ import {AccessControl} from "OZ/access/AccessControl.sol"; +/* ==== Abtract contracts === */ +import {AccessControlModuleStandalone} from "../../modules/AccessControlModuleStandalone.sol"; import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../modules/MetaTxModuleStandalone.sol"; import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol"; import {RuleWhitelistCommon} from "./abstract/RuleWhitelistCommon.sol"; +/* ==== RuleEngine === */ import {RulesManagementModule} from "RuleEngine/modules/RulesManagementModule.sol"; import {RuleEngineInvariantStorage} from "RuleEngine/modules/library/RuleEngineInvariantStorage.sol"; import {IRule} from "RuleEngine/interfaces/IRule.sol"; +/* ==== CMTAT === */ +import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; +/* ==== Interfaces === */ import {IERC7943NonFungibleCompliance, IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol"; /** * @title Wrapper to call several different whitelist rules */ - -contract RuleWhitelistWrapper is RulesManagementModule, MetaTxModuleStandalone, RuleWhitelistCommon { +contract RuleWhitelistWrapper is RulesManagementModule, AccessControlModuleStandalone, MetaTxModuleStandalone, RuleWhitelistCommon { /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ @@ -23,14 +29,10 @@ contract RuleWhitelistWrapper is RulesManagementModule, MetaTxModuleStandalone, * @param admin Address of the contract (Access Control) * @param forwarderIrrevocable Address of the forwarder, required for the gasless support */ - constructor(address admin, address forwarderIrrevocable, bool checkSpender) - MetaTxModuleStandalone(forwarderIrrevocable) + constructor(address admin, address forwarderIrrevocable, bool checkSpender_) + MetaTxModuleStandalone(forwarderIrrevocable) AccessControlModuleStandalone(admin) { - if (admin == address(0)) { - revert RuleEngineInvariantStorage.RuleEngine_AdminWithAddressZeroNotAllowed(); - } - _checkSpender = checkSpender; - _grantRole(DEFAULT_ADMIN_ROLE, admin); + checkSpender = checkSpender_; } /** @@ -43,7 +45,7 @@ contract RuleWhitelistWrapper is RulesManagementModule, MetaTxModuleStandalone, function detectTransferRestriction(address from, address to, uint256 /*value*/ ) public view - override + override(IERC1404) returns (uint8) { address[] memory targetAddress = new address[](2); @@ -63,7 +65,7 @@ contract RuleWhitelistWrapper is RulesManagementModule, MetaTxModuleStandalone, function detectTransferRestriction(address from, address to, uint256 /* tokenId */, uint256 value ) public view - override + override(IERC7943NonFungibleComplianceExtend) returns (uint8) { return detectTransferRestriction(from, to, value); @@ -72,10 +74,10 @@ contract RuleWhitelistWrapper is RulesManagementModule, MetaTxModuleStandalone, function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) public view - override + override(IERC1404Extend) returns (uint8) { - if (!_checkSpender) { + if (!checkSpender) { return detectTransferRestriction(from, to, value); } @@ -97,6 +99,9 @@ contract RuleWhitelistWrapper is RulesManagementModule, MetaTxModuleStandalone, } } + /** + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ function detectTransferRestrictionFrom(address spender, address from, address to, uint256 /* tokenId */, uint256 value ) public view @@ -106,19 +111,23 @@ contract RuleWhitelistWrapper is RulesManagementModule, MetaTxModuleStandalone, return detectTransferRestrictionFrom(spender, from, to, value); } - /* ============ ACCESS CONTROL ============ */ - /** + + /* ============ Access control ============ */ + + /** * @dev Returns `true` if `account` has been granted `role`. */ - function hasRole(bytes32 role, address account) public view virtual override(AccessControl) returns (bool) { - // The Default Admin has all roles - if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { - return true; - } else { - return AccessControl.hasRole(role, account); - } + function hasRole( + bytes32 role, + address account + ) public view virtual override(AccessControl,AccessControlModuleStandalone ) returns (bool) { + return AccessControlModuleStandalone.hasRole(role, account); } + /*////////////////////////////////////////////////////////////// + INTERNAL/PRIVATE FUNCTIONS + //////////////////////////////////////////////////////////////*/ + function _detectTransferRestriction(address[] memory targetAddress) internal view returns (bool[] memory) { uint256 rulesLength = rulesCount(); bool[] memory result = new bool[](targetAddress.length); diff --git a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol index 66c34cf..42ea53d 100644 --- a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol +++ b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MPL-2.0 pragma solidity ^0.8.20; -import {AccessControl} from "OZ/access/AccessControl.sol"; -import {MetaTxModuleStandalone, ERC2771Context, Context} from "./../../../../modules/MetaTxModuleStandalone.sol"; +import {AccessControlModuleStandalone} from "../../../../modules/AccessControlModuleStandalone.sol"; +import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../../../modules/MetaTxModuleStandalone.sol"; import {RuleAddressSetInternal} from "./RuleAddressSetInternal.sol"; import {RuleAddressSetInvariantStorage} from "./invariantStorage/RuleAddressSetInvariantStorage.sol"; +/* ==== Interfaces === */ import {IIdentityRegistryContains} from "../../../interfaces/IIdentityRegistry.sol"; import {IAddressList} from "../../../interfaces/IAddressList.sol"; /** @@ -18,7 +19,7 @@ import {IAddressList} from "../../../interfaces/IAddressList.sol"; */ abstract contract RuleAddressSet is - AccessControl, + AccessControlModuleStandalone, MetaTxModuleStandalone, RuleAddressSetInternal, RuleAddressSetInvariantStorage, @@ -41,11 +42,9 @@ abstract contract RuleAddressSet is * @param forwarderIrrevocable Address of the ERC2771 forwarder (for meta-transactions). * @dev Reverts if the admin address is the zero address. */ - constructor(address admin, address forwarderIrrevocable) MetaTxModuleStandalone(forwarderIrrevocable) { - if (admin == address(0)) { - revert RuleAddressSet_AdminWithAddressZeroNotAllowed(); - } - _grantRole(DEFAULT_ADMIN_ROLE, admin); + constructor(address admin, address forwarderIrrevocable) + MetaTxModuleStandalone(forwarderIrrevocable) AccessControlModuleStandalone(admin){ + // nothing to do } /*////////////////////////////////////////////////////////////// @@ -143,25 +142,6 @@ abstract contract RuleAddressSet is results[i] = _isAddressListed(targetAddresses[i]); } } - - /*////////////////////////////////////////////////////////////// - ACCESS CONTROL - //////////////////////////////////////////////////////////////*/ - - /** - * @notice Returns `true` if `account` has been granted `role`. - * @dev - * The `DEFAULT_ADMIN_ROLE` implicitly grants all roles. - * @param role The role identifier. - * @param account The account address to check. - */ - function hasRole(bytes32 role, address account) public view virtual override(AccessControl) returns (bool) { - if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { - return true; - } - return AccessControl.hasRole(role, account); - } - /*////////////////////////////////////////////////////////////// ERC-2771 META TX //////////////////////////////////////////////////////////////*/ diff --git a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol index b4fb06b..fe77359 100644 --- a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol +++ b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 pragma solidity ^0.8.20; +/* ==== OpenZeppelin === */ import {EnumerableSet} from "OZ/utils/structs/EnumerableSet.sol"; /** diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol index 4230ef4..8458fd7 100644 --- a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; -import "../../RuleCommonInvariantStorage.sol"; +import {RuleCommonInvariantStorage} from "../../RuleCommonInvariantStorage.sol"; abstract contract RuleBlacklistInvariantStorage is RuleCommonInvariantStorage { error RuleBlacklist_InvalidTransfer(address rule, address from, address to, uint256 value, uint8 code); diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol index 92b8d11..7f12df5 100644 --- a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; -import "../../RuleCommonInvariantStorage.sol"; +import {RuleCommonInvariantStorage} from "../../RuleCommonInvariantStorage.sol"; abstract contract RuleWhitelistInvariantStorage is RuleCommonInvariantStorage { error RuleWhitelist_InvalidTransfer(address rule, address from, address to, uint256 value, uint8 code); diff --git a/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol index 439f920..b6665a4 100644 --- a/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol @@ -2,16 +2,15 @@ pragma solidity ^0.8.20; -import "./RuleCommonInvariantStorage.sol"; +import {RuleCommonInvariantStorage} from "./RuleCommonInvariantStorage.sol"; import {ISanctionsList} from "../../interfaces/ISanctionsList.sol"; abstract contract RuleSanctionsListInvariantStorage is RuleCommonInvariantStorage { - error RuleSanctionsList_InvalidTransfer(address rule, address from, address to, uint256 value, uint8 code); - /* ============ Event ============ */ + /* ============ Event ============ */ event SetSanctionListOracle(ISanctionsList newOracle); /* ============ Custom errors ============ */ - + error RuleSanctionsList_InvalidTransfer(address rule, address from, address to, uint256 value, uint8 code); error RuleSanctionList_AdminWithAddressZeroNotAllowed(); error RuleSanctionList_AddressAlreadyWhitelisted(); diff --git a/src/rules/validation/abstract/RuleValidateTransfer.sol b/src/rules/validation/abstract/RuleValidateTransfer.sol index 2f258ce..560793e 100644 --- a/src/rules/validation/abstract/RuleValidateTransfer.sol +++ b/src/rules/validation/abstract/RuleValidateTransfer.sol @@ -2,10 +2,12 @@ pragma solidity ^0.8.20; +/* ==== CMTAT === */ import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; import {IERC3643ComplianceRead} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol"; import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; +/* ==== RuleEngine === */ import {IRule} from "RuleEngine/interfaces/IRule.sol"; import {IERC7943NonFungibleCompliance, IERC7943NonFungibleComplianceExtend} from "../../interfaces/IERC7943NonFungibleCompliance.sol"; @@ -50,6 +52,9 @@ abstract contract RuleValidateTransfer is IERC7943NonFungibleComplianceExtend, I this.detectTransferRestriction(from, to, amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); } + /** + * @inheritdoc IERC7551Compliance + */ function canTransferFrom(address spender, address from, address to, uint256 value) public view @@ -61,6 +66,9 @@ abstract contract RuleValidateTransfer is IERC7943NonFungibleComplianceExtend, I == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); } + /** + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ function canTransferFrom(address spender, address from, address to, uint256 tokenId, uint256 value) public view diff --git a/src/rules/validation/abstract/RuleWhitelistCommon.sol b/src/rules/validation/abstract/RuleWhitelistCommon.sol index e54fa9c..0994bff 100644 --- a/src/rules/validation/abstract/RuleWhitelistCommon.sol +++ b/src/rules/validation/abstract/RuleWhitelistCommon.sol @@ -1,11 +1,15 @@ // SPDX-License-Identifier: MPL-2.0 pragma solidity ^0.8.20; +/* ==== CMTAT === */ +import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; +import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; +/* ==== Abstract contracts === */ import {RuleWhitelistInvariantStorage} from "./RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol"; import {RuleValidateTransfer} from "./RuleValidateTransfer.sol"; +/* ==== Interface === */ import {IERC7943NonFungibleCompliance, IERC7943NonFungibleComplianceExtend} from "../../interfaces/IERC7943NonFungibleCompliance.sol"; -import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; -import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; + /** * @title Rule Whitelist Common * @notice Provides common logic for validating whitelist-based transfer restrictions. @@ -15,11 +19,12 @@ import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; * - Inherits restriction code constants and messages from {RuleWhitelistInvariantStorage}. */ abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInvariantStorage { - bool internal _checkSpender; + /** + * Indicate if the spender is verified or not + */ + bool public checkSpender; - /*////////////////////////////////////////////////////////////// - RESTRICTION CODE LOGIC - //////////////////////////////////////////////////////////////*/ + /* ============ View Functions ============ */ /** * @notice Checks whether a restriction code is recognized by this rule. * @dev @@ -56,9 +61,7 @@ abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInva } } - /*////////////////////////////////////////////////////////////// - ERC-3643 HOOKS - //////////////////////////////////////////////////////////////*/ + /* ============ State Functions ============ */ /** * @notice ERC-3643 hook called when a transfer occurs. @@ -76,7 +79,7 @@ abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInva } /** - * @notice ERC-3643 hook called when a delegated transfer occurs (`transferFrom`). + * @notice hook called when a delegated transfer occurs (`transferFrom`). * @dev * - Validates that `spender`, `from`, and `to` are all whitelisted. * - Reverts if any restriction code other than `TRANSFER_OK` is returned. @@ -90,6 +93,9 @@ abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInva require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleWhitelist_InvalidTransfer(address(this), from, to, value, code)); } + /** + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ function transferred(address spender, address from, address to, uint256 /* tokenId */, uint256 value) public view override(IERC7943NonFungibleComplianceExtend){ transferred(spender, from, to, value); } From 152615fa00118e097e9102b0ec8de0b3bae88064 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Tue, 2 Dec 2025 17:11:21 +0100 Subject: [PATCH 12/25] Improve code comment + fix test --- src/modules/AccessControlModuleStandalone.sol | 18 ++-- .../IERC7943NonFungibleCompliance.sol | 99 ++++++++++++++++--- src/rules/validation/RuleBlacklist.sol | 6 +- src/rules/validation/RuleSanctionsList.sol | 3 + src/rules/validation/RuleWhitelist.sol | 4 +- src/rules/validation/RuleWhitelistWrapper.sol | 1 + .../RuleSanctionListDeploymentTest.t.sol | 3 +- .../CMTATIntegrationWhitelistWrapper.t.sol | 4 +- .../RuleWhitelistDeployment.t.sol | 4 +- 9 files changed, 115 insertions(+), 27 deletions(-) diff --git a/src/modules/AccessControlModuleStandalone.sol b/src/modules/AccessControlModuleStandalone.sol index 6cc6485..3d644ea 100644 --- a/src/modules/AccessControlModuleStandalone.sol +++ b/src/modules/AccessControlModuleStandalone.sol @@ -6,18 +6,22 @@ pragma solidity ^0.8.20; import {AccessControl} from "OZ/access/AccessControl.sol"; abstract contract AccessControlModuleStandalone is AccessControl { + error AccessControlModuleStandalone_AddressZeroNotAllowed(); /* ============ Constructor ============ */ /** - * @dev - * - * Revert if admin is the zero address - * Grant the admin with the admin role - * - */ + * @notice Assigns the provided address as the default admin. + * @dev + * - Reverts if `admin` is the zero address. + * - Grants `DEFAULT_ADMIN_ROLE` to `admin`. + * The return value of `_grantRole` is intentionally ignored, as it returns `false` + * only when the role was already granted. + * + * @param admin The address that will receive the `DEFAULT_ADMIN_ROLE`. + */ constructor(address admin) { if(admin == address(0)){ - //revert CMTAT_AccessControlModule_AddressZeroNotAllowed(); + revert AccessControlModuleStandalone_AddressZeroNotAllowed(); } // we don't check the return value // _grantRole attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. diff --git a/src/rules/interfaces/IERC7943NonFungibleCompliance.sol b/src/rules/interfaces/IERC7943NonFungibleCompliance.sol index 4f13da4..ad7e0f0 100644 --- a/src/rules/interfaces/IERC7943NonFungibleCompliance.sol +++ b/src/rules/interfaces/IERC7943NonFungibleCompliance.sol @@ -3,30 +3,107 @@ pragma solidity ^0.8.20; /** -* @dev for ERC-721 amount = 1 + * @title IERC7943NonFungibleCompliance + * @notice Compliance interface for ERC-721/1155–style non-fungible assets. + * @dev + * - For ERC-721 tokens, `amount` MUST be set to `1`. + * - This interface defines a read-only compliance check used to determine + * whether a transfer is permitted according to rule-based restrictions. */ interface IERC7943NonFungibleCompliance { - /// @notice Checks if a transfer is currently possible according to token rules. It enforces validations on the frozen tokens. - /// @dev This may involve checks like allowlists, blocklists, transfer limits and other policy-defined restrictions. - /// @param from The address sending tokens. - /// @param to The address receiving tokens. - /// @param tokenId The ID of the token being transferred. - /// @param amount The amount being transferred. - /// @return allowed True if the transfer is allowed, false otherwise. + /** + * @notice Verifies whether a transfer is permitted according to the token’s compliance rules. + * @dev + * This function must not modify state. + * It may enforce checks such as: + * - Allowlist / blocklist membership + * - Freezing rules + * - Transfer limitations + * - Jurisdictional, regulatory, or policy-driven restrictions + * If the transfer is not allowed, this function MUST return `false`. + * + * @param from The address currently holding the token. + * @param to The address intended to receive the token. + * @param tokenId The ERC-721/1155 token ID being transferred. + * @param amount The amount being transferred (always `1` for ERC-721). + * @return allowed `true` if the transfer is permitted, otherwise `false`. + */ function canTransfer(address from, address to, uint256 tokenId, uint256 amount) external view returns (bool allowed); } /** -* @dev for ERC-721 amount = 1 + * @title IERC7943NonFungibleComplianceExtend + * @notice Extended compliance interface for ERC-721/1155–style non-fungible assets. + * @dev + * Adds functionality for: + * - Returning standardized transfer-restriction codes + * - Compliance checks involving a spender (e.g., approvals and operators) + * - Writing compliance-related state upon successful transfers + * For ERC-721, `amount/value` MUST be set to `1`. */ -interface IERC7943NonFungibleComplianceExtend is IERC7943NonFungibleCompliance { + interface IERC7943NonFungibleComplianceExtend is IERC7943NonFungibleCompliance { + /** + * @notice Returns a transfer-restriction code describing why a transfer is blocked. + * @dev + * - MUST NOT modify state. + * - MUST return `0` when the transfer is allowed. + * - Non-zero codes SHOULD follow the ERC-1404 or RuleEngine restriction-code conventions. + * + * @param from The address currently holding the token. + * @param to The address intended to receive the token. + * @param tokenId The ERC-721/1155 token ID being checked. + * @param amount The amount being transferred (always `1` for ERC-721). + * @return code A restriction code: `0` for success, otherwise an implementation-defined error code. + */ function detectTransferRestriction(address from, address to, uint256 tokenId, uint256 amount ) external view returns(uint8 code); + + /** + * @notice Returns a transfer-restriction code for transfers triggered by a spender. + * @dev + * Similar to `detectTransferRestriction`, but includes the spender performing the transfer. + * - MUST NOT modify state. + * - MUST return `0` when transfer is allowed. + * + * @param spender The caller executing the transfer (owner, operator, or approved address). + * @param from The current owner of the token. + * @param to The intended recipient. + * @param tokenId The token ID being checked. + * @param value The amount being transferred (always `1` for ERC-721). + * @return code A restriction code: `0` for allowed, otherwise a non-zero restriction identifier. + */ function detectTransferRestrictionFrom(address spender, address from, address to, uint256 tokenId, uint256 value) external view returns (uint8 code); - function canTransferFrom(address spender, address from, address to, uint256 tokenId, uint256 value) external returns (bool); + /** + * @notice Determines whether a spender-initiated transfer is allowed. + * @dev + * - MUST NOT modify state. + * - Implementations SHOULD use `detectTransferRestrictionFrom` internally. + * + * @param spender The address performing the transfer (owner/operator). + * @param from The current token owner. + * @param to The recipient address. + * @param tokenId The token ID being transferred. + * @param value The transfer amount (always `1` for ERC-721). + * @return allowed `true` if the transfer is permitted, otherwise `false`. + */ + function canTransferFrom(address spender, address from, address to, uint256 tokenId, uint256 value) external returns (bool allowed); + + /** + * @notice Notifies the rule engine or compliance module that a transfer has been executed. + * @dev + * - MAY modify compliance-related state (e.g., consumption of approvals, updating limits). + * - MUST be called by the token contract after a successful transfer. + * - MUST revert if called by unauthorized contracts. + * + * @param spender The address executing the transfer. + * @param from The previous owner of the token. + * @param to The new owner of the token. + * @param tokenId The token ID that was transferred. + * @param value The transfer amount (always `1` for ERC-721). + */ function transferred(address spender, address from, address to, uint256 tokenId, uint256 value) external; } \ No newline at end of file diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol index f1943a8..9d4ab56 100644 --- a/src/rules/validation/RuleBlacklist.sol +++ b/src/rules/validation/RuleBlacklist.sol @@ -14,17 +14,21 @@ import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC364 import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; /* ==== IRuleEngine === */ import {IRule} from "RuleEngine/interfaces/IRule.sol"; + /** * @title a blacklist manager */ - contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInvariantStorage { + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ /** * @param admin Address of the contract (Access Control) * @param forwarderIrrevocable Address of the forwarder, required for the gasless support */ constructor(address admin, address forwarderIrrevocable) RuleAddressSet(admin, forwarderIrrevocable) {} + /* ============ View Functions ============ */ /** * @notice Check if an addres is in the whitelist or not * @param from the origin address diff --git a/src/rules/validation/RuleSanctionsList.sol b/src/rules/validation/RuleSanctionsList.sol index 1274c76..167d39a 100644 --- a/src/rules/validation/RuleSanctionsList.sol +++ b/src/rules/validation/RuleSanctionsList.sol @@ -24,6 +24,9 @@ contract RuleSanctionsList is { ISanctionsList public sanctionsList; + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ /** * @param admin Address of the contract (Access Control) * @param forwarderIrrevocable Address of the forwarder, required for the gasless support diff --git a/src/rules/validation/RuleWhitelist.sol b/src/rules/validation/RuleWhitelist.sol index 68acc33..85ec0ae 100644 --- a/src/rules/validation/RuleWhitelist.sol +++ b/src/rules/validation/RuleWhitelist.sol @@ -33,9 +33,7 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry checkSpender = checkSpender_; } - /*////////////////////////////////////////////////////////////// - TRANSFER RESTRICTION LOGIC - //////////////////////////////////////////////////////////////*/ + /* ============ View Functions ============ */ /** * @notice Detects whether a transfer between two addresses is allowed under the whitelist rule. diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol index 319de1d..53875d8 100644 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -35,6 +35,7 @@ contract RuleWhitelistWrapper is RulesManagementModule, AccessControlModuleStand checkSpender = checkSpender_; } + /* ============ View Functions ============ */ /** * @notice Go through all the whitelist rules to know if a restriction exists on the transfer * @param from the origin address diff --git a/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol b/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol index e54284f..7dfb2d2 100644 --- a/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol +++ b/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol @@ -6,6 +6,7 @@ import "../HelperContract.sol"; import "CMTAT/mocks/MinimalForwarderMock.sol"; import "../utils/SanctionListOracle.sol"; import {RuleSanctionsList, ISanctionsList} from "src/rules/validation/RuleSanctionsList.sol"; +import {AccessControlModuleStandalone} from "../../src/modules/AccessControlModuleStandalone.sol"; /** * @title General functions of the ruleSanctionList */ @@ -40,7 +41,7 @@ contract RuleSanctionListDeploymentTest is Test, HelperContract { vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); MinimalForwarderMock forwarder = new MinimalForwarderMock(); forwarder.initialize(ERC2771ForwarderDomain); - vm.expectRevert(RuleSanctionList_AdminWithAddressZeroNotAllowed.selector); + vm.expectRevert(AccessControlModuleStandalone.AccessControlModuleStandalone_AddressZeroNotAllowed.selector); vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); ruleSanctionList = new RuleSanctionsList(address(0), address(forwarder), ISanctionsList(ZERO_ADDRESS)); } diff --git a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol index 94d7e43..1d20f46 100644 --- a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol +++ b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "CMTAT/deployment/CMTATStandalone.sol"; import "../HelperContract.sol"; - +import {AccessControlModuleStandalone} from "../../src/modules/AccessControlModuleStandalone.sol"; /** * @title Integration test with the CMTAT */ @@ -55,7 +55,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { */ function testCannotDeployContractIfAdminAddressIsZero() public { vm.prank(WHITELIST_OPERATOR_ADDRESS); - vm.expectRevert(RuleEngine_AdminWithAddressZeroNotAllowed.selector); + vm.expectRevert(AccessControlModuleStandalone.AccessControlModuleStandalone_AddressZeroNotAllowed.selector); ruleWhitelistWrapper = new RuleWhitelistWrapper(ZERO_ADDRESS, ZERO_ADDRESS, true); } diff --git a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol index bca06ef..b109dc8 100644 --- a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol +++ b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../HelperContract.sol"; import "CMTAT/mocks/MinimalForwarderMock.sol"; - +import {AccessControlModuleStandalone} from "../../src/modules/AccessControlModuleStandalone.sol"; /** * @title General functions of the RuleWhitelist */ @@ -34,7 +34,7 @@ contract RuleWhitelistDeploymentTest is Test, HelperContract { vm.prank(WHITELIST_OPERATOR_ADDRESS); MinimalForwarderMock forwarder = new MinimalForwarderMock(); forwarder.initialize(ERC2771ForwarderDomain); - vm.expectRevert(RuleAddressSet_AdminWithAddressZeroNotAllowed.selector); + vm.expectRevert(AccessControlModuleStandalone.AccessControlModuleStandalone_AddressZeroNotAllowed.selector); vm.prank(WHITELIST_OPERATOR_ADDRESS); ruleWhitelist = new RuleWhitelist(address(0), address(forwarder), true); } From e7fd1693fe99e7ed35866e151ecb32d4da37a4da Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Tue, 2 Dec 2025 17:16:50 +0100 Subject: [PATCH 13/25] update readme and format code --- README.md | 642 +++++++++++++++++- doc/codelist.md | 20 - src/modules/AccessControlModuleStandalone.sol | 32 +- src/rules/interfaces/IAddressList.sol | 10 +- .../IERC7943NonFungibleCompliance.sol | 39 +- src/rules/validation/RuleBlacklist.sol | 69 +- src/rules/validation/RuleSanctionsList.sol | 83 ++- src/rules/validation/RuleWhitelist.sol | 31 +- src/rules/validation/RuleWhitelistWrapper.sol | 50 +- .../RuleAddressSet/RuleAddressSet.sol | 6 +- .../RuleSanctionsListInvariantStorage.sol | 2 +- .../abstract/RuleValidateTransfer.sol | 21 +- .../abstract/RuleWhitelistCommon.sol | 31 +- test/HelperContract.sol | 2 +- test/RuleBlacklist/CMTATIntegration.t.sol | 28 +- test/RuleBlacklist/RuleBlacklist.t.sol | 2 +- test/RuleWhitelist/CMTATIntegration.t.sol | 21 +- .../CMTATIntegrationWhitelistWrapper.t.sol | 22 +- test/RuleWhitelist/RuleWhitelistAdd.t.sol | 4 +- .../RuleWhitelistDeployment.t.sol | 1 + 20 files changed, 918 insertions(+), 198 deletions(-) delete mode 100644 doc/codelist.md diff --git a/README.md b/README.md index 1810d64..ff814e7 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,228 @@ # RuleEngine - Rules -> This repository includes the rules contract for the CMTAT [RuleEngine](https://github.com/CMTA/RuleEngine) -> -> This repository is currently under development +**Rules** is a collection of on-chain compliance and transfer-restriction rules designed for use with the + [CMTA RuleEngine](https://github.com/CMTA/RuleEngine) and the [CMTAT token standard](https://github.com/CMTA/CMTAT). -- The RuleEngine is an external contract used to apply transfer restrictions to another contract such as a CMTAT or ERC-3643 tokens. Acting as a controller, it can call different contract rules and apply these rules on each transfer. -- Rules: - - There are two types of rules in our RuleEngine implementation: validation and operation rules. - - Validation rules are read-only rules. These rules cannot update the state of the blockchain during a transfer call; they can only read information from the blockchain. - - The second type of rules, known as operation rules, can also modify the state of the blockchain (write) during a transfer call. +Each rule can be used **standalone**, directly plugged into a CMTAT token, **or** managed collectively via a RuleEngine. -## Rules details +**Status:** *Repository under active development* +[TOC] +## Overview -### Validation rule +The **RuleEngine** is an external smart contract that applies transfer restrictions to security tokens such as **CMTAT** or ERC-3643-compatible tokens. +Rules are modular validator contracts that the RuleEngine can call on every transfer to ensure regulatory and business-logic compliance. + +### Key Concepts + +- **Rules are controllers** that validate or modify token transfers. +- They can be applied: + - Directly on **CMTAT** (no RuleEngine required), **or** + - Through the **RuleEngine** (for multi-rule orchestration). +- Rules enforce conditions such as: + - Whitelisting / blacklisting + - Sanctions checks + - Multi-party operator-managed lists + - Conditional approvals + - Arbitrary compliance logic + +## Compatibility + +| Component | Compatible Versions | +| ---------------- | ----------------------------------------- | +| **Rules v0.1.0** | CMTAT ≥ v3.0.0
RuleEngine v3.0.0-rc0 | + +Each Rule implements the interface `IRuleEngine` defined in CMTAT. + +This interface declares the ERC-3643 functions `transferred`(read-write) and `canTransfer`(ready-only) with several other functions related to [ERC-1404](https://github.com/ethereum/eips/issues/1404), [ERC-7551](https://ethereum-magicians.org/t/erc-7551-crypto-security-token-smart-contract-interface-ewpg-reworked/25477) and [ERC-3643](https://eips.ethereum.org/EIPS/eip-3643). + +## Architecture + +### Rule - Code list + +> It is very important that each rule uses an unique code + +Here the list of codes used by the different rules + +| Contract | Constant name | Value | +| ----------------------- | ---------------------------------- | ----- | +| All | TRANSFER_OK (from CMTAT) | 0 | +| RuleWhitelist | CODE_ADDRESS_FROM_NOT_WHITELISTED | 21 | +| RuleWhitelist | CODE_ADDRESS_TO_NOT_WHITELISTED | 22 | +| RuleWhitelist | Free slot | 23-25 | +| RuleSanctionList | CODE_ADDRESS_FROM_IS_SANCTIONED | 26 | +| RuleSanctionList | CODE_ADDRESS_TO_IS_SANCTIONED | 27 | +| RuleSanctionList | Free slot | 28-30 | +| RuleBlacklist | CODE_ADDRESS_FROM_IS_BLACKLISTED | 31 | +| RuleBlacklist | CODE_ADDRESS_TO_IS_BLACKLISTED | 32 | +| RuleBlacklist | Free slot | 33-35 | +| RuleConditionalTransfer | CODE_TRANSFER_REQUEST_NOT_APPROVED | 36 | + + + +Warning: the CMTAT already uses the code 0-6 and the code 7-12 should be left free to allow further additions in the CMTAT. + +### Rules as Standalone Compliance Contracts + +Every rule implements the minimal interface expected by **CMTAT**, notably: + +```solidity +function transferred(address from, address to, uint256 value) +function transferred(address spender, address from, address to, uint256 value) +``` + +This makes rules directly pluggable into CMTAT without any intermediary RuleEngine. + +### Using Rules via RuleEngine + +When used through the RuleEngine, a rule must also implement: + +```solidity +interface IRule is IRuleEngine { + function canReturnTransferRestrictionCode(uint8 restrictionCode) + external + view + returns (bool); +} +``` + +The RuleEngine can then: + +- Aggregate multiple rules +- Execute them sequentially on each transfer +- Return restriction codes +- Mutate rule state (operation rules) + +#### CMTAT + +Each rule can be directly plugged to a CMTAT token similar to a RuleEngine. + +Indeed, each rules implements the required interface (`IRuleEngine`) with notably the following function as entrypoint. + +```solidity +function transferred(address from,address to,uint256 value) +function transferred(address spender,address from,address to,uint256 value) +``` + +```solidity +/* +* @title Minimum interface to define a RuleEngine +*/ +interface IRuleEngine is IERC1404Extend, IERC7551Compliance, IERC3643IComplianceContract { + /** + * @notice + * Function called whenever tokens are transferred from one wallet to another + * @dev + * Must revert if the transfer is invalid + * Same name as ERC-3643 but with one supplementary argument `spender` + * This function can be used to update state variables of the RuleEngine contract + * This function can be called ONLY by the token contract bound to the RuleEngine + * @param spender spender address (sender) + * @param from token holder address + * @param to receiver address + * @param value value of tokens involved in the transfer + */ + function transferred(address spender, address from, address to, uint256 value) external; +} +``` + + + +#### RuleEngine + +For a RuleEngine, each rule implements also the required entry point similar to CMTAT, and as well some specific interface for the RuleEngine through the implementation of `IRule`interface dfeined in the RuleEngine repository + +```solidity +interface IRule is IRuleEngine { + /** + * @dev Returns true if the restriction code exists, and false otherwise. + */ + function canReturnTransferRestrictionCode( + uint8 restrictionCode + ) external view returns (bool); +} + +``` + + + +## Types of Rules + +There are two categories of rules: validation rules (Read-only) and operation rules (read-write). + +### Validation Rules (Read-Only) + +- Cannot modify blockchain state during transfers. +- Used for simple eligibility checks. +- Examples: + - Whitelist + - Whitelist Wrapper + - Blacklist + - Sanction list (Chainalysis) + +### Operation Rules (Read-Write) + +- Can update state during transfer calls. +- Example: + - Conditional Transfer (approval-based) + +### Read-only (validation) rule Currently, there are four validation rules: whitelist, whitelistWrapper, blacklist, and sanctionlist. #### Whitelist -With a whitelist rule, only whitelisted addresses can hold the token. Thus, a transfer will fail if either the origin (current token holder) or the destination is not in the list. +Only whitelisted addresses may hold or receive tokens. + Transfers are rejected if: + +- `from` is not whitelisted +- `to` is not whitelisted + +The rule is read-only: it only checks stored state. + +**Example** During a transfer, this rule, called by the RuleEngine, will check if the address concerned is in the list, applying a read operation on the blockchain. #### Whitelist wrapper -This rule can be used to restrict transfers only from/to addresses inside a group of whitelist rules managed by different operators. Thus, each operator can manage independently their own whitelist. Here is an explanation schema: +Allows independent whitelist groups managed by different operators. + +- Each operator manages a dedicated whitelist. +- A transfer is allowed only if both addresses belong to *at least one* operator-managed list. +- Enables multi-party compliance #### Blacklist -The blacklist rule works similarly to the whitelist rule but in the opposite way. With this rule, the addresses must not be on the list to allow the transfer to succeed. +Opposite of whitelist: + +- Transfer fails if **either** address is blacklisted. #### Sanction list with Chainalysis -The purpose of this contract is to use the oracle contract from [Chainalysis](https://www.chainalysis.com/) to forbid transfers from/to an address included in a sanctions designation (US, EU, or UN). Documentation and the contracts addresses are available here: [Chainalysis oracle for sanctions screening](https://go.chainalysis.com/chainalysis-oracle-docs.html). +Uses the [Chainalysis](https://www.chainalysis.com/) Oracle to reject transfers involving sanctioned addresses. + +- Checks lists for: **US**, **EU**, and **UN** sanctions. +- Documentation: *Chainalysis Oracle for sanctions screening* +- If `from` or `to` is sanctioned, transfer is rejected. + +Documentation and the contracts addresses are available here: [Chainalysis oracle for sanctions screening](https://go.chainalysis.com/chainalysis-oracle-docs.html). + +**Example** During a transfer, if either address (from or to) is in the sanction list of the Oracle, the rule will return false, and the transfer will be rejected by the CMTAT. -### Operation rule +### Read-Write (Operation) rule For the moment, there is only one operation rule available: ConditionalTransfer. -Currently, we only have one operation rule: *ConditionalTransfer*. This rule requires that transfers must be approved before being executed by the token holders. During the transfer call, the rule will check if the transfer has been approved. If it has, the approval will be removed since the transfer has been processed, applying a write operation on the blockchain. - #### Conditional transfer +> This rule has been moved to a dedicated repository: [RuleConditionalTransfer](https://github.com/CMTA/RuleConditionalTransfer) + +This rule requires that transfers must be approved before being executed by the token holders. During the transfer call, the rule will check if the transfer has been approved. If it has, the approval will be removed since the transfer has been processed, applying a write operation on the blockchain. + This rule requires that transfers be approved by the token holders before being executed. Initially, this rule was designed to implement a specific requirement in Swiss law (Vinkulierung), but it has since been generalized to be more flexible. @@ -69,16 +246,435 @@ The toolchain includes the following components, where the versions are the late The RuleEngine is an external contract used to apply transfer restrictions to another contract, initially the CMTAT. Acting as a controller, it can call different contract rules and apply these rules on each transfer. -## Dependencies +## API -The toolchain includes the following components, where the versions are the latest ones that we tested: +### Address List Management -- Foundry [v1.9.4](https://github.com/foundry-rs/forge-std/releases/tag/v1.9.4) -- Solidity 0.8.30 (via solc-js) -- OpenZeppelin Contracts (submodule) [v5.3.0](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.3.0) -- CMTAT [v3.0.0](https://github.com/CMTA/CMTAT) +> This API is common to whitelist and blacklist rules + +#### addAddresses + +``` +function addAddresses(address[] calldata targetAddresses) + public + onlyRole(ADDRESS_LIST_ADD_ROLE) +``` + +##### Description + +Adds multiple addresses to the internal address set. + +##### Details + +- Does **not** revert if one or more addresses are already listed. +- Restricted to callers holding the `ADDRESS_LIST_ADD_ROLE`. +- Emits an `AddAddresses` event. + +##### Parameters + +| Name | Type | Description | +| ----------------- | ----------- | ------------------------------------------ | +| `targetAddresses` | `address[]` | Array of addresses to be added to the set. | + +------ + +#### removeAddresses + +``` +function removeAddresses(address[] calldata targetAddresses) + public + onlyRole(ADDRESS_LIST_REMOVE_ROLE) +``` + +##### Description + +Removes multiple addresses from the internal set. + +##### Details + +- Does **not** revert if an address is not currently listed. +- Restricted to callers holding the `ADDRESS_LIST_REMOVE_ROLE`. +- Emits a `RemoveAddresses` event. + +##### Parameters + +| Name | Type | Description | +| ----------------- | ----------- | --------------------------------- | +| `targetAddresses` | `address[]` | Array of addresses to be removed. | + +------ + +#### addAddress + +``` +function addAddress(address targetAddress) + public + onlyRole(ADDRESS_LIST_ADD_ROLE) +``` + +##### Description + +Adds a **single** address to the set. + +##### Details + +- **Reverts** if the address is already listed. +- Restricted to callers holding the `ADDRESS_LIST_ADD_ROLE`. +- Emits an `AddAddress` event. + +##### Parameters + +| Name | Type | Description | +| --------------- | --------- | --------------- | +| `targetAddress` | `address` | Address to add. | + +------ + +#### removeAddress + +``` +function removeAddress(address targetAddress) + public + onlyRole(ADDRESS_LIST_REMOVE_ROLE) +``` + +##### Description + +Removes a **single** address from the set. + +##### Details + +- **Reverts** if the address is not listed. +- Restricted to callers holding the `ADDRESS_LIST_REMOVE_ROLE`. +- Emits a `RemoveAddress` event. + +##### Parameters + +| Name | Type | Description | +| --------------- | --------- | ------------------ | +| `targetAddress` | `address` | Address to remove. | + +------ + +#### listedAddressCount + +``` +function listedAddressCount() public view returns (uint256 count) +``` + +##### Description + +Returns the total number of addresses currently listed in the internal set. + +##### Returns + +| Name | Type | Description | +| ------- | --------- | --------------------------------- | +| `count` | `uint256` | Total number of listed addresses. | + +------ + +##### contains + +``` +function contains(address targetAddress) + public + view + override(IIdentityRegistryContains) + returns (bool isListed) +``` + +##### Description + +Checks whether a specific address is listed. + Implements `IIdentityRegistryContains`. + +##### Parameters + +| Name | Type | Description | +| --------------- | --------- | ----------------- | +| `targetAddress` | `address` | Address to check. | + +##### Returns + +| Name | Type | Description | +| ---------- | ------ | --------------------------------------------------- | +| `isListed` | `bool` | `true` if the address is listed, otherwise `false`. | + +------ + +#### isAddressListed + +``` +function isAddressListed(address targetAddress) + public + view + returns (bool isListed) +``` + +##### Description + +Returns whether a given address is included in the internal set. + +##### Parameters + +| Name | Type | Description | +| --------------- | --------- | ----------------- | +| `targetAddress` | `address` | Address to check. | + +##### Returns + +| Name | Type | Description | +| ---------- | ------ | --------------- | +| `isListed` | `bool` | Listing status. | + +------ + +#### areAddressesListed + +``` +function areAddressesListed(address[] memory targetAddresses) + public + view + returns (bool[] memory results) +``` + +##### Description + +Checks the listing status of multiple addresses in a single call. + +##### Parameters + +| Name | Type | Description | +| ----------------- | ----------- | ---------------------------- | +| `targetAddresses` | `address[]` | Array of addresses to check. | + +##### Returns + +| Name | Type | Description | +| --------- | -------- | --------------------------------------------------- | +| `results` | `bool[]` | Array of boolean listing results, aligned by index. | + +### IERC7943NonFungibleCompliance + +Compliance interface for ERC-721 / ERC-1155–style non-fungible assets. + For ERC-721, `amount` must always be `1`. + +------ + +#### Functions + +| Name | Description | +| --------------- | ------------------------------------------------------------ | +| **canTransfer** | Verifies whether a transfer is permitted according to the token’s compliance rules. | + +------ + +#### canTransfer + +``` +function canTransfer( + address from, + address to, + uint256 tokenId, + uint256 amount +) external view returns (bool allowed) +``` + +##### Description + +Verifies whether a token transfer is permitted according to the rule-based compliance logic. + +##### Details + +- Must not modify state. +- May enforce checks such as allowlists, blocklists, freezing, transfer limits, regulatory rules. +- Must return `false` if the transfer is not permitted. + +##### Parameters + +| Name | Type | Description | +| --------- | --------- | ----------------------------------------- | +| `from` | `address` | Current token owner. | +| `to` | `address` | Receiving address. | +| `tokenId` | `uint256` | Token ID. | +| `amount` | `uint256` | Transfer amount (always `1` for ERC-721). | + +##### Returns + +| Name | Type | Description | +| --------- | ------ | ------------------------------------------------- | +| `allowed` | `bool` | `true` if transfer is allowed; otherwise `false`. | + +------ + +### IERC7943NonFungibleComplianceExtend + +Extended compliance interface for ERC-721 / ERC-1155 non-fungible assets. + Adds restriction-code reporting, spender-aware checks, and a post-transfer hook. + +For ERC-721, `amount` / `value` must always be `1`. + +------ + +#### Functions + +| Name | Description | +| --------------------------------- | ------------------------------------------------------------ | +| **detectTransferRestriction** | Returns a restriction code indicating why a transfer is blocked. | +| **detectTransferRestrictionFrom** | Returns a restriction code for a spender-initiated transfer. | +| **canTransferFrom** | Checks whether a spender-initiated transfer is allowed. | +| **transferred** | Notifies the compliance engine that a transfer has occurred. | + +------ + +#### detectTransferRestriction + +``` +function detectTransferRestriction( + address from, + address to, + uint256 tokenId, + uint256 amount +) external view returns (uint8 code) +``` + +##### Description + +Returns a restriction code describing whether and why a transfer is blocked. + +##### Details + +- Must not modify state. +- Must return `0` when the transfer is allowed. +- Non-zero codes should follow ERC-1404 or similar standards. + +##### Parameters + +| Name | Type | Description | +| --------- | --------- | ---------------------------------- | +| `from` | `address` | Current token holder. | +| `to` | `address` | Receiving address. | +| `tokenId` | `uint256` | Token ID. | +| `amount` | `uint256` | Transfer amount (`1` for ERC-721). | + +##### Returns + +| Name | Type | Description | +| ------ | ------- | --------------------------------------------- | +| `code` | `uint8` | `0` if allowed; otherwise a restriction code. | + +------ + +#### detectTransferRestrictionFrom + +``` +function detectTransferRestrictionFrom( + address spender, + address from, + address to, + uint256 tokenId, + uint256 value +) external view returns (uint8 code) +``` + +##### Description + +Returns a restriction code for a transfer initiated by a spender (approved operator or owner). + +##### Details + +- Must not modify state. +- Must return `0` when the transfer is permitted. + +##### Parameters + +| Name | Type | Description | +| --------- | --------- | ---------------------------------- | +| `spender` | `address` | Address performing the transfer. | +| `from` | `address` | Current owner. | +| `to` | `address` | Recipient address. | +| `tokenId` | `uint256` | Token ID being checked. | +| `value` | `uint256` | Transfer amount (`1` for ERC-721). | + +##### Returns + +| Name | Type | Description | +| ------ | ------- | ------------------------------------------- | +| `code` | `uint8` | `0` if allowed; otherwise restriction code. | + +------ + +#### canTransferFrom + +``` +function canTransferFrom( + address spender, + address from, + address to, + uint256 tokenId, + uint256 value +) external view returns (bool allowed) +``` + +##### Description + +Checks whether a spender-initiated transfer is allowed under the compliance rules. + +##### Details + +- Must not modify state. +- Should internally use `detectTransferRestrictionFrom`. + +##### Parameters + +| Name | Type | Description | +| --------- | --------- | ---------------------------------------- | +| `spender` | `address` | Address executing the transfer. | +| `from` | `address` | Current owner. | +| `to` | `address` | Recipient. | +| `tokenId` | `uint256` | Token ID. | +| `value` | `uint256` | Transfer amount (`1` for ERC-721 token). | + +##### Returns + +| Name | Type | Description | +| --------- | ------ | ------------------------------ | +| `allowed` | `bool` | `true` if transfer is allowed. | + +------ + +#### transferred + +``` +function transferred( + address spender, + address from, + address to, + uint256 tokenId, + uint256 value +) external +``` + +##### Description + +Signals to the compliance engine that a transfer has successfully occurred. + +##### Details + +- May modify compliance state. +- Must be called by the token contract after a successful transfer. +- Must revert if invoked by unauthorized callers. +##### Parameters +| Name | Type | Description | +| --------- | --------- | ---------------------------------------- | +| `spender` | `address` | Address executing the transfer. | +| `from` | `address` | Previous owner. | +| `to` | `address` | New owner. | +| `tokenId` | `uint256` | Token transferred. | +| `value` | `uint256` | Transfer amount (`1` for ERC-721 token). | ## Foundry diff --git a/doc/codelist.md b/doc/codelist.md deleted file mode 100644 index 2ad6da6..0000000 --- a/doc/codelist.md +++ /dev/null @@ -1,20 +0,0 @@ -# Rule - Code list - -> It is very important that each rule uses an unique code - -Here the list of codes used by the different rules - -| Contract | Constant name | Value | -| ----------------------- | ---------------------------------- | ----- | -| All | TRANSFER_OK (from CMTAT) | 0 | -| RuleWhitelist | CODE_ADDRESS_FROM_NOT_WHITELISTED | 21 | -| RuleWhitelist | CODE_ADDRESS_TO_NOT_WHITELISTED | 22 | -| RuleSanctionList | CODE_ADDRESS_FROM_IS_SANCTIONED | 31 | -| RuleSanctionList | CODE_ADDRESS_TO_IS_SANCTIONED | 32 | -| RuleBlacklist | CODE_ADDRESS_FROM_IS_BLACKLISTED | 41 | -| RuleBlacklist | CODE_ADDRESS_TO_IS_BLACKLISTED | 42 | -| RuleConditionalTransfer | CODE_TRANSFER_REQUEST_NOT_APPROVED | 51 | - - - -Warning: the CMTAT already uses the code 0-4 and the code 5-9 should be left free to allow further additions in the CMTAT diff --git a/src/modules/AccessControlModuleStandalone.sol b/src/modules/AccessControlModuleStandalone.sol index 3d644ea..58d72b0 100644 --- a/src/modules/AccessControlModuleStandalone.sol +++ b/src/modules/AccessControlModuleStandalone.sol @@ -9,18 +9,18 @@ abstract contract AccessControlModuleStandalone is AccessControl { error AccessControlModuleStandalone_AddressZeroNotAllowed(); /* ============ Constructor ============ */ /** - * @notice Assigns the provided address as the default admin. - * @dev - * - Reverts if `admin` is the zero address. - * - Grants `DEFAULT_ADMIN_ROLE` to `admin`. - * The return value of `_grantRole` is intentionally ignored, as it returns `false` - * only when the role was already granted. - * - * @param admin The address that will receive the `DEFAULT_ADMIN_ROLE`. - */ - constructor(address admin) - { - if(admin == address(0)){ + * @notice Assigns the provided address as the default admin. + * @dev + * - Reverts if `admin` is the zero address. + * - Grants `DEFAULT_ADMIN_ROLE` to `admin`. + * The return value of `_grantRole` is intentionally ignored, as it returns `false` + * only when the role was already granted. + * + * @param admin The address that will receive the `DEFAULT_ADMIN_ROLE`. + */ + + constructor(address admin) { + if (admin == address(0)) { revert AccessControlModuleStandalone_AddressZeroNotAllowed(); } // we don't check the return value @@ -29,17 +29,13 @@ abstract contract AccessControlModuleStandalone is AccessControl { _grantRole(DEFAULT_ADMIN_ROLE, admin); } - /*////////////////////////////////////////////////////////////// PUBLIC/EXTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ - /** + /** * @dev Returns `true` if `account` has been granted `role`. */ - function hasRole( - bytes32 role, - address account - ) public view virtual override(AccessControl) returns (bool) { + function hasRole(bytes32 role, address account) public view virtual override(AccessControl) returns (bool) { // The Default Admin has all roles if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { return true; diff --git a/src/rules/interfaces/IAddressList.sol b/src/rules/interfaces/IAddressList.sol index e55a596..7b2176f 100644 --- a/src/rules/interfaces/IAddressList.sol +++ b/src/rules/interfaces/IAddressList.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import {IIdentityRegistryContains} from "./IIdentityRegistry.sol"; + interface IAddressList is IIdentityRegistryContains { /* ============ Events ============ */ /// @notice Emitted when multiple addresses are added. @@ -20,7 +21,6 @@ interface IAddressList is IIdentityRegistryContains { /// @param targetAddress The removed address. event RemoveAddress(address targetAddress); - /* ============ Write ============ */ /** * @notice Adds multiple addresses to the set. @@ -50,7 +50,6 @@ interface IAddressList is IIdentityRegistryContains { */ function removeAddress(address targetAddress) external; - /* ============ Read ============ */ /** @@ -71,8 +70,5 @@ interface IAddressList is IIdentityRegistryContains { * @param targetAddresses Array of addresses to check. * @return results Boolean array aligned by index with listing results. */ - function areAddressesListed(address[] memory targetAddresses) - external - view - returns (bool[] memory results); -} \ No newline at end of file + function areAddressesListed(address[] memory targetAddresses) external view returns (bool[] memory results); +} diff --git a/src/rules/interfaces/IERC7943NonFungibleCompliance.sol b/src/rules/interfaces/IERC7943NonFungibleCompliance.sol index ad7e0f0..9fa9730 100644 --- a/src/rules/interfaces/IERC7943NonFungibleCompliance.sol +++ b/src/rules/interfaces/IERC7943NonFungibleCompliance.sol @@ -11,15 +11,15 @@ pragma solidity ^0.8.20; * whether a transfer is permitted according to rule-based restrictions. */ interface IERC7943NonFungibleCompliance { - /** + /** * @notice Verifies whether a transfer is permitted according to the token’s compliance rules. * @dev * This function must not modify state. * It may enforce checks such as: - * - Allowlist / blocklist membership - * - Freezing rules - * - Transfer limitations - * - Jurisdictional, regulatory, or policy-driven restrictions + * - Allowlist / blocklist membership + * - Freezing rules + * - Transfer limitations + * - Jurisdictional, regulatory, or policy-driven restrictions * If the transfer is not allowed, this function MUST return `false`. * * @param from The address currently holding the token. @@ -28,7 +28,10 @@ interface IERC7943NonFungibleCompliance { * @param amount The amount being transferred (always `1` for ERC-721). * @return allowed `true` if the transfer is permitted, otherwise `false`. */ - function canTransfer(address from, address to, uint256 tokenId, uint256 amount) external view returns (bool allowed); + function canTransfer(address from, address to, uint256 tokenId, uint256 amount) + external + view + returns (bool allowed); } /** @@ -36,17 +39,17 @@ interface IERC7943NonFungibleCompliance { * @notice Extended compliance interface for ERC-721/1155–style non-fungible assets. * @dev * Adds functionality for: - * - Returning standardized transfer-restriction codes - * - Compliance checks involving a spender (e.g., approvals and operators) - * - Writing compliance-related state upon successful transfers + * - Returning standardized transfer-restriction codes + * - Compliance checks involving a spender (e.g., approvals and operators) + * - Writing compliance-related state upon successful transfers * For ERC-721, `amount/value` MUST be set to `1`. */ - interface IERC7943NonFungibleComplianceExtend is IERC7943NonFungibleCompliance { +interface IERC7943NonFungibleComplianceExtend is IERC7943NonFungibleCompliance { /** * @notice Returns a transfer-restriction code describing why a transfer is blocked. * @dev - * - MUST NOT modify state. - * - MUST return `0` when the transfer is allowed. + * - MUST NOT modify state. + * - MUST return `0` when the transfer is allowed. * - Non-zero codes SHOULD follow the ERC-1404 or RuleEngine restriction-code conventions. * * @param from The address currently holding the token. @@ -55,8 +58,11 @@ interface IERC7943NonFungibleCompliance { * @param amount The amount being transferred (always `1` for ERC-721). * @return code A restriction code: `0` for success, otherwise an implementation-defined error code. */ - function detectTransferRestriction(address from, address to, uint256 tokenId, uint256 amount ) external view returns(uint8 code); - + function detectTransferRestriction(address from, address to, uint256 tokenId, uint256 amount) + external + view + returns (uint8 code); + /** * @notice Returns a transfer-restriction code for transfers triggered by a spender. * @dev @@ -89,7 +95,9 @@ interface IERC7943NonFungibleCompliance { * @param value The transfer amount (always `1` for ERC-721). * @return allowed `true` if the transfer is permitted, otherwise `false`. */ - function canTransferFrom(address spender, address from, address to, uint256 tokenId, uint256 value) external returns (bool allowed); + function canTransferFrom(address spender, address from, address to, uint256 tokenId, uint256 value) + external + returns (bool allowed); /** * @notice Notifies the rule engine or compliance module that a transfer has been executed. @@ -106,4 +114,3 @@ interface IERC7943NonFungibleCompliance { */ function transferred(address spender, address from, address to, uint256 tokenId, uint256 value) external; } - \ No newline at end of file diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol index 9d4ab56..4a3a657 100644 --- a/src/rules/validation/RuleBlacklist.sol +++ b/src/rules/validation/RuleBlacklist.sol @@ -3,7 +3,8 @@ pragma solidity ^0.8.20; /* ==== Abtract contracts === */ -import {RuleBlacklistInvariantStorage} from "./abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol"; +import {RuleBlacklistInvariantStorage} from + "./abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol"; import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol"; import {RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol"; /* ==== Interfaces === */ @@ -54,7 +55,7 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv /* * @inheritdoc IERC7943NonFungibleComplianceExtend */ - function detectTransferRestriction(address from, address to, uint256 /* tokenId */, uint256 value ) + function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value) public view override(IERC7943NonFungibleComplianceExtend) @@ -80,14 +81,15 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv } /** - * @inheritdoc IERC7943NonFungibleComplianceExtend - */ - function detectTransferRestrictionFrom(address spender, address from, address to, uint256 /* tokenId */, uint256 value ) - public - view - override(IERC7943NonFungibleComplianceExtend) - returns (uint8) - { + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ + function detectTransferRestrictionFrom( + address spender, + address from, + address to, + uint256, /* tokenId */ + uint256 value + ) public view override(IERC7943NonFungibleComplianceExtend) returns (uint8) { return detectTransferRestrictionFrom(spender, from, to, value); } @@ -97,7 +99,13 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv * @return true if the restriction code is known, false otherwise * */ - function canReturnTransferRestrictionCode(uint8 _restrictionCode) public pure virtual override(IRule) returns (bool) { + function canReturnTransferRestrictionCode(uint8 _restrictionCode) + public + pure + virtual + override(IRule) + returns (bool) + { return _restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED || _restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED || _restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED; } @@ -108,7 +116,13 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv * @return true if the transfer is valid, false otherwise * */ - function messageForTransferRestriction(uint8 _restrictionCode) public pure virtual override(IERC1404) returns (string memory) { + function messageForTransferRestriction(uint8 _restrictionCode) + public + pure + virtual + override(IERC1404) + returns (string memory) + { if (_restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED) { return TEXT_ADDRESS_FROM_IS_BLACKLISTED; } else if (_restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED) { @@ -122,17 +136,38 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv /* ============ State Functions ============ */ - function transferred(address from, address to, uint256 value) public view virtual override(IERC3643IComplianceContract) { + function transferred(address from, address to, uint256 value) + public + view + virtual + override(IERC3643IComplianceContract) + { uint8 code = this.detectTransferRestriction(from, to, value); - require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleBlacklist_InvalidTransfer(address(this), from, to, value, code)); + require( + code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + RuleBlacklist_InvalidTransfer(address(this), from, to, value, code) + ); } - function transferred(address spender, address from, address to, uint256 value) public view virtual override(IRuleEngine) { + function transferred(address spender, address from, address to, uint256 value) + public + view + virtual + override(IRuleEngine) + { uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); - require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleBlacklist_InvalidTransfer(address(this), from, to, value, code)); + require( + code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + RuleBlacklist_InvalidTransfer(address(this), from, to, value, code) + ); } - function transferred(address spender, address from, address to, uint256 /* tokenId */, uint256 value) public view virtual override(IERC7943NonFungibleComplianceExtend) { + function transferred(address spender, address from, address to, uint256, /* tokenId */ uint256 value) + public + view + virtual + override(IERC7943NonFungibleComplianceExtend) + { transferred(spender, from, to, value); } } diff --git a/src/rules/validation/RuleSanctionsList.sol b/src/rules/validation/RuleSanctionsList.sol index 167d39a..a94a5b4 100644 --- a/src/rules/validation/RuleSanctionsList.sol +++ b/src/rules/validation/RuleSanctionsList.sol @@ -16,6 +16,7 @@ import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC364 import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; /* ==== IRuleEngine === */ import {IRule} from "RuleEngine/interfaces/IRule.sol"; + contract RuleSanctionsList is AccessControlModuleStandalone, MetaTxModuleStandalone, @@ -32,7 +33,8 @@ contract RuleSanctionsList is * @param forwarderIrrevocable Address of the forwarder, required for the gasless support */ constructor(address admin, address forwarderIrrevocable, ISanctionsList sanctionContractOracle_) - MetaTxModuleStandalone(forwarderIrrevocable) AccessControlModuleStandalone(admin) + MetaTxModuleStandalone(forwarderIrrevocable) + AccessControlModuleStandalone(admin) { if (address(sanctionContractOracle_) != address(0)) { _setSanctionListOracle(sanctionContractOracle_); @@ -65,9 +67,9 @@ contract RuleSanctionsList is } /** - * @inheritdoc IERC7943NonFungibleComplianceExtend - */ - function detectTransferRestriction(address from, address to, uint256 /* tokenId */, uint256 value ) + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ + function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value) public view virtual @@ -78,8 +80,8 @@ contract RuleSanctionsList is } /** - * @inheritdoc IERC1404Extend - */ + * @inheritdoc IERC1404Extend + */ function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) public view @@ -97,13 +99,13 @@ contract RuleSanctionsList is return uint8(REJECTED_CODE_BASE.TRANSFER_OK); } - function detectTransferRestrictionFrom(address spender, address from, address to, uint256 /* tokenId */, uint256 value ) - public - view - virtual - override(IERC7943NonFungibleComplianceExtend) - returns (uint8) - { + function detectTransferRestrictionFrom( + address spender, + address from, + address to, + uint256, /* tokenId */ + uint256 value + ) public view virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) { return detectTransferRestrictionFrom(spender, from, to, value); } @@ -113,8 +115,7 @@ contract RuleSanctionsList is * @return true if the restriction code is known, false otherwise * */ - function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override(IRule) - returns (bool) { + function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override(IRule) returns (bool) { return restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED || restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED || restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED; } @@ -125,8 +126,13 @@ contract RuleSanctionsList is * @return true if the transfer is valid, false otherwise * */ - function messageForTransferRestriction(uint8 restrictionCode) public pure virtual override(IERC1404) - returns (string memory) { + function messageForTransferRestriction(uint8 restrictionCode) + public + pure + virtual + override(IERC1404) + returns (string memory) + { if (restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED) { return TEXT_ADDRESS_FROM_IS_SANCTIONED; } else if (restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED) { @@ -149,25 +155,46 @@ contract RuleSanctionsList is } /** - * @inheritdoc IERC3643IComplianceContract - */ - function transferred(address from, address to, uint256 value) public view virtual override(IERC3643IComplianceContract){ + * @inheritdoc IERC3643IComplianceContract + */ + function transferred(address from, address to, uint256 value) + public + view + virtual + override(IERC3643IComplianceContract) + { uint8 code = this.detectTransferRestriction(from, to, value); - require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code)); + require( + code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code) + ); } /** - * @inheritdoc IRuleEngine - */ - function transferred(address spender, address from, address to, uint256 value) public view virtual override(IRuleEngine){ + * @inheritdoc IRuleEngine + */ + function transferred(address spender, address from, address to, uint256 value) + public + view + virtual + override(IRuleEngine) + { uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); - require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code)); + require( + code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code) + ); } /** - * @inheritdoc IERC7943NonFungibleComplianceExtend - */ - function transferred(address spender, address from, address to, uint256 /* tokenId */, uint256 value) public view virtual override(IERC7943NonFungibleComplianceExtend){ + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ + function transferred(address spender, address from, address to, uint256, /* tokenId */ uint256 value) + public + view + virtual + override(IERC7943NonFungibleComplianceExtend) + { transferred(spender, from, to, value); } diff --git a/src/rules/validation/RuleWhitelist.sol b/src/rules/validation/RuleWhitelist.sol index 85ec0ae..897478b 100644 --- a/src/rules/validation/RuleWhitelist.sol +++ b/src/rules/validation/RuleWhitelist.sol @@ -8,7 +8,10 @@ import {RuleWhitelistCommon} from "./abstract/RuleWhitelistCommon.sol"; import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; /* ==== Interfaces === */ import {IIdentityRegistryVerified} from "../interfaces/IIdentityRegistry.sol"; -import {IERC7943NonFungibleCompliance, IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol"; +import { + IERC7943NonFungibleCompliance, + IERC7943NonFungibleComplianceExtend +} from "../interfaces/IERC7943NonFungibleCompliance.sol"; /** * @title Rule Whitelist @@ -18,7 +21,6 @@ import {IERC7943NonFungibleCompliance, IERC7943NonFungibleComplianceExtend} from * - Integrates restriction code logic from {RuleWhitelistCommon}. * - Implements {IERC1404} to return specific restriction codes for non-whitelisted transfers. */ - contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistryVerified { /*////////////////////////////////////////////////////////////// CONSTRUCTOR @@ -50,7 +52,7 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry * | `to` not whitelisted | `CODE_ADDRESS_TO_NOT_WHITELISTED` | * | Both whitelisted | `TRANSFER_OK` | */ - function detectTransferRestriction(address from, address to, uint256 /* value */) + function detectTransferRestriction(address from, address to, uint256 /* value */ ) public view override(IERC1404) @@ -66,9 +68,9 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry } /** - * @inheritdoc IERC7943NonFungibleComplianceExtend - */ - function detectTransferRestriction(address from, address to, uint256 /* tokenId */, uint256 value ) + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ + function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value) public view override(IERC7943NonFungibleComplianceExtend) @@ -107,14 +109,15 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry } /** - * @inheritdoc IERC7943NonFungibleComplianceExtend - */ - function detectTransferRestrictionFrom(address spender, address from, address to, uint256 /* tokenId */, uint256 value ) - public - view - override(IERC7943NonFungibleComplianceExtend) - returns (uint8) - { + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ + function detectTransferRestrictionFrom( + address spender, + address from, + address to, + uint256, /* tokenId */ + uint256 value + ) public view override(IERC7943NonFungibleComplianceExtend) returns (uint8) { return detectTransferRestrictionFrom(spender, from, to, value); } diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol index 53875d8..8aa66c2 100644 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -16,12 +16,20 @@ import {IRule} from "RuleEngine/interfaces/IRule.sol"; /* ==== CMTAT === */ import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; /* ==== Interfaces === */ -import {IERC7943NonFungibleCompliance, IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol"; +import { + IERC7943NonFungibleCompliance, + IERC7943NonFungibleComplianceExtend +} from "../interfaces/IERC7943NonFungibleCompliance.sol"; /** * @title Wrapper to call several different whitelist rules */ -contract RuleWhitelistWrapper is RulesManagementModule, AccessControlModuleStandalone, MetaTxModuleStandalone, RuleWhitelistCommon { +contract RuleWhitelistWrapper is + RulesManagementModule, + AccessControlModuleStandalone, + MetaTxModuleStandalone, + RuleWhitelistCommon +{ /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ @@ -30,7 +38,8 @@ contract RuleWhitelistWrapper is RulesManagementModule, AccessControlModuleStand * @param forwarderIrrevocable Address of the forwarder, required for the gasless support */ constructor(address admin, address forwarderIrrevocable, bool checkSpender_) - MetaTxModuleStandalone(forwarderIrrevocable) AccessControlModuleStandalone(admin) + MetaTxModuleStandalone(forwarderIrrevocable) + AccessControlModuleStandalone(admin) { checkSpender = checkSpender_; } @@ -63,7 +72,7 @@ contract RuleWhitelistWrapper is RulesManagementModule, AccessControlModuleStand } } - function detectTransferRestriction(address from, address to, uint256 /* tokenId */, uint256 value ) + function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value) public view override(IERC7943NonFungibleComplianceExtend) @@ -101,28 +110,31 @@ contract RuleWhitelistWrapper is RulesManagementModule, AccessControlModuleStand } /** - * @inheritdoc IERC7943NonFungibleComplianceExtend - */ - function detectTransferRestrictionFrom(address spender, address from, address to, uint256 /* tokenId */, uint256 value ) - public - view - override(IERC7943NonFungibleComplianceExtend) - returns (uint8) - { + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ + function detectTransferRestrictionFrom( + address spender, + address from, + address to, + uint256, /* tokenId */ + uint256 value + ) public view override(IERC7943NonFungibleComplianceExtend) returns (uint8) { return detectTransferRestrictionFrom(spender, from, to, value); } - /* ============ Access control ============ */ - /** + /** * @dev Returns `true` if `account` has been granted `role`. */ - function hasRole( - bytes32 role, - address account - ) public view virtual override(AccessControl,AccessControlModuleStandalone ) returns (bool) { - return AccessControlModuleStandalone.hasRole(role, account); + function hasRole(bytes32 role, address account) + public + view + virtual + override(AccessControl, AccessControlModuleStandalone) + returns (bool) + { + return AccessControlModuleStandalone.hasRole(role, account); } /*////////////////////////////////////////////////////////////// diff --git a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol index 42ea53d..8907f1c 100644 --- a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol +++ b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol @@ -42,8 +42,10 @@ abstract contract RuleAddressSet is * @param forwarderIrrevocable Address of the ERC2771 forwarder (for meta-transactions). * @dev Reverts if the admin address is the zero address. */ - constructor(address admin, address forwarderIrrevocable) - MetaTxModuleStandalone(forwarderIrrevocable) AccessControlModuleStandalone(admin){ + constructor(address admin, address forwarderIrrevocable) + MetaTxModuleStandalone(forwarderIrrevocable) + AccessControlModuleStandalone(admin) + { // nothing to do } diff --git a/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol index b6665a4..5a613d2 100644 --- a/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol @@ -6,10 +6,10 @@ import {RuleCommonInvariantStorage} from "./RuleCommonInvariantStorage.sol"; import {ISanctionsList} from "../../interfaces/ISanctionsList.sol"; abstract contract RuleSanctionsListInvariantStorage is RuleCommonInvariantStorage { - /* ============ Event ============ */ event SetSanctionListOracle(ISanctionsList newOracle); /* ============ Custom errors ============ */ + error RuleSanctionsList_InvalidTransfer(address rule, address from, address to, uint256 value, uint8 code); error RuleSanctionList_AdminWithAddressZeroNotAllowed(); error RuleSanctionList_AddressAlreadyWhitelisted(); diff --git a/src/rules/validation/abstract/RuleValidateTransfer.sol b/src/rules/validation/abstract/RuleValidateTransfer.sol index 560793e..7b5f256 100644 --- a/src/rules/validation/abstract/RuleValidateTransfer.sol +++ b/src/rules/validation/abstract/RuleValidateTransfer.sol @@ -9,7 +9,10 @@ import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.s import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; /* ==== RuleEngine === */ import {IRule} from "RuleEngine/interfaces/IRule.sol"; -import {IERC7943NonFungibleCompliance, IERC7943NonFungibleComplianceExtend} from "../../interfaces/IERC7943NonFungibleCompliance.sol"; +import { + IERC7943NonFungibleCompliance, + IERC7943NonFungibleComplianceExtend +} from "../../interfaces/IERC7943NonFungibleCompliance.sol"; abstract contract RuleValidateTransfer is IERC7943NonFungibleComplianceExtend, IRule { /** @@ -28,11 +31,10 @@ abstract contract RuleValidateTransfer is IERC7943NonFungibleComplianceExtend, I returns (bool isValid) { // does not work without `this` keyword => "Undeclared identifier" - return - this.detectTransferRestriction(from, to, tokenId, amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); + return this.detectTransferRestriction(from, to, tokenId, amount) + == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); } - /** * @notice Validate a transfer * @param from the origin address @@ -48,13 +50,12 @@ abstract contract RuleValidateTransfer is IERC7943NonFungibleComplianceExtend, I returns (bool isValid) { // does not work without `this` keyword => "Undeclared identifier" - return - this.detectTransferRestriction(from, to, amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); + return this.detectTransferRestriction(from, to, amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); } /** - * @inheritdoc IERC7551Compliance - */ + * @inheritdoc IERC7551Compliance + */ function canTransferFrom(address spender, address from, address to, uint256 value) public view @@ -67,8 +68,8 @@ abstract contract RuleValidateTransfer is IERC7943NonFungibleComplianceExtend, I } /** - * @inheritdoc IERC7943NonFungibleComplianceExtend - */ + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ function canTransferFrom(address spender, address from, address to, uint256 tokenId, uint256 value) public view diff --git a/src/rules/validation/abstract/RuleWhitelistCommon.sol b/src/rules/validation/abstract/RuleWhitelistCommon.sol index 0994bff..245750c 100644 --- a/src/rules/validation/abstract/RuleWhitelistCommon.sol +++ b/src/rules/validation/abstract/RuleWhitelistCommon.sol @@ -8,7 +8,10 @@ import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; import {RuleWhitelistInvariantStorage} from "./RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol"; import {RuleValidateTransfer} from "./RuleValidateTransfer.sol"; /* ==== Interface === */ -import {IERC7943NonFungibleCompliance, IERC7943NonFungibleComplianceExtend} from "../../interfaces/IERC7943NonFungibleCompliance.sol"; +import { + IERC7943NonFungibleCompliance, + IERC7943NonFungibleComplianceExtend +} from "../../interfaces/IERC7943NonFungibleCompliance.sol"; /** * @title Rule Whitelist Common @@ -20,8 +23,8 @@ import {IERC7943NonFungibleCompliance, IERC7943NonFungibleComplianceExtend} from */ abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInvariantStorage { /** - * Indicate if the spender is verified or not - */ + * Indicate if the spender is verified or not + */ bool public checkSpender; /* ============ View Functions ============ */ @@ -73,9 +76,12 @@ abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInva * @param to The address receiving tokens. * @param value The token amount being transferred. */ - function transferred(address from, address to, uint256 value) public view override(IERC3643IComplianceContract){ + function transferred(address from, address to, uint256 value) public view override(IERC3643IComplianceContract) { uint8 code = this.detectTransferRestriction(from, to, value); - require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleWhitelist_InvalidTransfer(address(this), from, to, value, code)); + require( + code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + RuleWhitelist_InvalidTransfer(address(this), from, to, value, code) + ); } /** @@ -90,13 +96,20 @@ abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInva */ function transferred(address spender, address from, address to, uint256 value) public view override(IRuleEngine) { uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); - require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleWhitelist_InvalidTransfer(address(this), from, to, value, code)); + require( + code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + RuleWhitelist_InvalidTransfer(address(this), from, to, value, code) + ); } /** - * @inheritdoc IERC7943NonFungibleComplianceExtend - */ - function transferred(address spender, address from, address to, uint256 /* tokenId */, uint256 value) public view override(IERC7943NonFungibleComplianceExtend){ + * @inheritdoc IERC7943NonFungibleComplianceExtend + */ + function transferred(address spender, address from, address to, uint256, /* tokenId */ uint256 value) + public + view + override(IERC7943NonFungibleComplianceExtend) + { transferred(spender, from, to, value); } } diff --git a/test/HelperContract.sol b/test/HelperContract.sol index df84c59..f2b5340 100644 --- a/test/HelperContract.sol +++ b/test/HelperContract.sol @@ -25,7 +25,7 @@ import {RuleAddressSetInvariantStorage} from import {RuleSanctionsListInvariantStorage} from "src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol"; // Rule interface -import {IAddressList} from "src/rules/interfaces/IAddressList.sol"; +import {IAddressList} from "src/rules/interfaces/IAddressList.sol"; // utils import "RuleEngine/../test/utils/CMTATDeployment.sol"; diff --git a/test/RuleBlacklist/CMTATIntegration.t.sol b/test/RuleBlacklist/CMTATIntegration.t.sol index de872f8..fbae761 100644 --- a/test/RuleBlacklist/CMTATIntegration.t.sol +++ b/test/RuleBlacklist/CMTATIntegration.t.sol @@ -59,7 +59,12 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleBlacklist_InvalidTransfer.selector, address(ruleBlacklist), ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_TO_IS_BLACKLISTED + RuleBlacklist_InvalidTransfer.selector, + address(ruleBlacklist), + ADDRESS1, + ADDRESS2, + amount, + CODE_ADDRESS_TO_IS_BLACKLISTED ) ); // Act @@ -75,7 +80,12 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleBlacklist_InvalidTransfer.selector, address(ruleBlacklist), ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_IS_BLACKLISTED + RuleBlacklist_InvalidTransfer.selector, + address(ruleBlacklist), + ADDRESS1, + ADDRESS2, + amount, + CODE_ADDRESS_FROM_IS_BLACKLISTED ) ); // Act @@ -96,7 +106,12 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleBlacklist_InvalidTransfer.selector, address(ruleBlacklist), ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_IS_BLACKLISTED + RuleBlacklist_InvalidTransfer.selector, + address(ruleBlacklist), + ADDRESS1, + ADDRESS2, + amount, + CODE_ADDRESS_FROM_IS_BLACKLISTED ) ); CMTAT_CONTRACT.transfer(ADDRESS2, amount); @@ -190,7 +205,12 @@ contract CMTATIntegration is Test, HelperContract { // Act vm.expectRevert( abi.encodeWithSelector( - RuleBlacklist_InvalidTransfer.selector, address(ruleBlacklist), ZERO_ADDRESS, ADDRESS1, amount, CODE_ADDRESS_TO_IS_BLACKLISTED + RuleBlacklist_InvalidTransfer.selector, + address(ruleBlacklist), + ZERO_ADDRESS, + ADDRESS1, + amount, + CODE_ADDRESS_TO_IS_BLACKLISTED ) ); vm.prank(DEFAULT_ADMIN_ADDRESS); diff --git a/test/RuleBlacklist/RuleBlacklist.t.sol b/test/RuleBlacklist/RuleBlacklist.t.sol index f206ed2..b0fbf4b 100644 --- a/test/RuleBlacklist/RuleBlacklist.t.sol +++ b/test/RuleBlacklist/RuleBlacklist.t.sol @@ -81,7 +81,7 @@ contract RuleBlacklistTest is Test, HelperContract { // Act resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); - // With tokenId + // With tokenId resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resUint8, CODE_ADDRESS_TO_IS_BLACKLISTED); diff --git a/test/RuleWhitelist/CMTATIntegration.t.sol b/test/RuleWhitelist/CMTATIntegration.t.sol index c8ec3a4..4e7720d 100644 --- a/test/RuleWhitelist/CMTATIntegration.t.sol +++ b/test/RuleWhitelist/CMTATIntegration.t.sol @@ -47,7 +47,12 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, address(ruleWhitelist), ADDRESS1, ADDRESS2, 21, CODE_ADDRESS_FROM_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, + address(ruleWhitelist), + ADDRESS1, + ADDRESS2, + 21, + CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -63,7 +68,12 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, address(ruleWhitelist),ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, + address(ruleWhitelist), + ADDRESS1, + ADDRESS2, + amount, + CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -79,7 +89,12 @@ contract CMTATIntegration is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, address(ruleWhitelist), ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_TO_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, + address(ruleWhitelist), + ADDRESS1, + ADDRESS2, + amount, + CODE_ADDRESS_TO_NOT_WHITELISTED ) ); // Act diff --git a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol index 1d20f46..d2b450c 100644 --- a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol +++ b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol @@ -8,6 +8,7 @@ import {AccessControlModuleStandalone} from "../../src/modules/AccessControlModu /** * @title Integration test with the CMTAT */ + contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { uint256 ADDRESS1_BALANCE_INIT = 31; uint256 ADDRESS2_BALANCE_INIT = 32; @@ -67,7 +68,12 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, address(ruleWhitelistWrapper), ADDRESS1, ADDRESS2, 21, CODE_ADDRESS_FROM_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, + address(ruleWhitelistWrapper), + ADDRESS1, + ADDRESS2, + 21, + CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -83,7 +89,12 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, address(ruleWhitelistWrapper), ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_FROM_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, + address(ruleWhitelistWrapper), + ADDRESS1, + ADDRESS2, + amount, + CODE_ADDRESS_FROM_NOT_WHITELISTED ) ); // Act @@ -99,7 +110,12 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { vm.prank(ADDRESS1); vm.expectRevert( abi.encodeWithSelector( - RuleWhitelist_InvalidTransfer.selector, address(ruleWhitelistWrapper), ADDRESS1, ADDRESS2, amount, CODE_ADDRESS_TO_NOT_WHITELISTED + RuleWhitelist_InvalidTransfer.selector, + address(ruleWhitelistWrapper), + ADDRESS1, + ADDRESS2, + amount, + CODE_ADDRESS_TO_NOT_WHITELISTED ) ); // Act diff --git a/test/RuleWhitelist/RuleWhitelistAdd.t.sol b/test/RuleWhitelist/RuleWhitelistAdd.t.sol index 034d8d0..94fe2e3 100644 --- a/test/RuleWhitelist/RuleWhitelistAdd.t.sol +++ b/test/RuleWhitelist/RuleWhitelistAdd.t.sol @@ -75,7 +75,7 @@ contract RuleWhitelistAddTest is Test, HelperContract { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit IAddressList.AddAddress(address(0x0)); + emit IAddressList.AddAddress(address(0x0)); ruleWhitelist.addAddress(address(0x0)); // Assert @@ -95,7 +95,7 @@ contract RuleWhitelistAddTest is Test, HelperContract { // Act vm.prank(WHITELIST_OPERATOR_ADDRESS); - emit IAddressList.AddAddresses(whitelist); + emit IAddressList.AddAddresses(whitelist); (resCallBool,) = address(ruleWhitelist).call(abi.encodeWithSignature("addAddresses(address[])", whitelist)); // Assert - Main diff --git a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol index b109dc8..add51c3 100644 --- a/test/RuleWhitelist/RuleWhitelistDeployment.t.sol +++ b/test/RuleWhitelist/RuleWhitelistDeployment.t.sol @@ -8,6 +8,7 @@ import {AccessControlModuleStandalone} from "../../src/modules/AccessControlModu /** * @title General functions of the RuleWhitelist */ + contract RuleWhitelistDeploymentTest is Test, HelperContract { // Arrange function setUp() public {} From c56189a8702d69fa232467423936bd34cc224899 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Tue, 2 Dec 2025 17:23:54 +0100 Subject: [PATCH 14/25] update CLI workflow --- .github/workflows/test.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 34a4a52..de33fae 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,12 +16,15 @@ jobs: name: Foundry project runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2 with: submodules: recursive - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 + #v1.5.0 + uses: foundry-rs/foundry-toolchain@50d5a8956f2e319df19e6b57539d7e2acb9f8c1e + with: + version: nightly - name: Show Forge version run: | From 94a8c86be0f749c4ff47131ddb22263bb09b8dc3 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Tue, 2 Dec 2025 17:26:14 +0100 Subject: [PATCH 15/25] Remove fmt check from github workflow --- .github/workflows/test.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index de33fae..ce8ea5c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,11 +30,6 @@ jobs: run: | forge --version - - name: Run Forge fmt - run: | - forge fmt --check - id: fmt - - name: Run Forge build run: | forge build --sizes From b372b1b1463040826f797840bd29c3abbe4247e6 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Tue, 2 Dec 2025 17:28:48 +0100 Subject: [PATCH 16/25] Install NPM package in github workflow --- .github/workflows/test.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ce8ea5c..f6a89cf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,6 +20,16 @@ jobs: with: submodules: recursive + + - name: Setup NodeJS 20.5.0 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 #v4.4.0 + with: + node-version: 20.5.0 + + - name: Install nodes modules inside CMTAT lib + run: npm install + working-directory: ./lib/CMTAT + - name: Install Foundry #v1.5.0 uses: foundry-rs/foundry-toolchain@50d5a8956f2e319df19e6b57539d7e2acb9f8c1e From 20e20a73c50486eb0000bc36b1f703521de2be29 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Tue, 2 Dec 2025 17:41:58 +0100 Subject: [PATCH 17/25] update config and remove docgen module for package.json --- .gitignore | 3 + CONTRIBUTING.md | 6 +- doc/TOOLCHAIN.md | 18 +----- foundry.toml | 10 +++- hardhat.config.js | 5 +- package-lock.json | 148 +--------------------------------------------- package.json | 1 - 7 files changed, 21 insertions(+), 170 deletions(-) diff --git a/.gitignore b/.gitignore index 85198aa..ecd40ca 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ docs/ # Dotenv file .env +# node_modules +node_modules/ + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ba78c6..08fa470 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,10 @@ # Contributing Guidelines -There are many ways to contribute to RuleEngine Contracts. +There are many ways to contribute to Rules Contracts. + +## Development branch + +If you want to propose some improvement to the codebase, use the current development branch `dev` to perform the modification. ## Opening an issue diff --git a/doc/TOOLCHAIN.md b/doc/TOOLCHAIN.md index f5d9cc1..de83611 100644 --- a/doc/TOOLCHAIN.md +++ b/doc/TOOLCHAIN.md @@ -131,21 +131,9 @@ slither . --checklist --filter-paths "openzeppelin-contracts|test|CMTAT|forge-s ## Code style guidelines -We use the following tools to ensure consistent coding style: +We use `Foundry` to perform code style guidelines -[Prettier](https://github.com/prettier-solidity/prettier-plugin-solidity) - -``` -npm run-script lint:sol:prettier -``` - -[Ethlint / Solium](https://github.com/duaraghav8/Ethlint) - -``` -npm run-script lint:sol -npm run-script lint:sol:fix -npm run-script lint:sol:test -npm run-script lint:sol:test:fix +```bash +forge fmt ``` -The related components can be installed with `npm install` (see [package.json](./package.json)). diff --git a/foundry.toml b/foundry.toml index 25b918f..388d129 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,6 +1,10 @@ [profile.default] -src = "src" -out = "out" -libs = ["lib"] +solc = "0.8.30" +src = 'src' +out = 'out' +libs = ['lib'] +optimizer = true +optimizer_runs = 200 +evm_version = 'prague' # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/hardhat.config.js b/hardhat.config.js index 83d9e54..8ebcba7 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -1,13 +1,12 @@ /** @type import('hardhat/config').HardhatUserConfig */ require("@nomicfoundation/hardhat-foundry"); -require('solidity-docgen'); module.exports = { - solidity: "0.8.27", + solidity: "0.8.30", settings: { optimizer: { enabled: true, runs: 200 }, - evmVersion:"cancun" + evmVersion:"prague" } }; diff --git a/package-lock.json b/package-lock.json index 755c254..27c66e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "RuleEngine", + "name": "Rules", "lockfileVersion": 2, "requires": true, "packages": { @@ -9,7 +9,6 @@ "ethlint": "^1.2.5", "prettier-plugin-solidity": "^1.0.0-rc.1", "sol2uml": "^2.5.20", - "solidity-docgen": "^0.6.0-beta.35", "surya": "^0.4.6" } }, @@ -3969,45 +3968,6 @@ "node": ">=4.x" } }, - "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/handlebars/node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/hardhat": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.14.0.tgz", @@ -6184,12 +6144,6 @@ "dev": true, "peer": true }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, "node_modules/next-tick": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", @@ -8010,31 +7964,12 @@ "node": ">=0.6.0" } }, - "node_modules/solidity-ast": { - "version": "0.4.49", - "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.49.tgz", - "integrity": "sha512-Pr5sCAj1SFqzwFZw1HPKSq0PehlQNdM8GwKyAVYh2DOn7/cCK8LUKD1HeHnKtTgBW7hi9h4nnnan7hpAg5RhWQ==", - "dev": true - }, "node_modules/solidity-comments-extractor": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz", "integrity": "sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==", "dev": true }, - "node_modules/solidity-docgen": { - "version": "0.6.0-beta.35", - "resolved": "https://registry.npmjs.org/solidity-docgen/-/solidity-docgen-0.6.0-beta.35.tgz", - "integrity": "sha512-9QdwK1THk/MWIdq1PEW/6dvtND0pUqpFTsbKwwU9YQIMYuRhH1lek9SsgnsGGYtdJ0VTrXXcVT30q20a8Y610A==", - "dev": true, - "dependencies": { - "handlebars": "^4.7.7", - "solidity-ast": "^0.4.38" - }, - "peerDependencies": { - "hardhat": "^2.8.0" - } - }, "node_modules/solium": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/solium/-/solium-1.2.5.tgz", @@ -8779,19 +8714,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "dev": true, - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/unbzip2-stream": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", @@ -8973,12 +8895,6 @@ "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", "dev": true }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true - }, "node_modules/workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", @@ -12271,33 +12187,6 @@ "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", "dev": true }, - "handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dev": true, - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, "hardhat": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.14.0.tgz", @@ -13965,12 +13854,6 @@ "dev": true, "peer": true }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, "next-tick": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", @@ -15401,28 +15284,12 @@ } } }, - "solidity-ast": { - "version": "0.4.49", - "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.49.tgz", - "integrity": "sha512-Pr5sCAj1SFqzwFZw1HPKSq0PehlQNdM8GwKyAVYh2DOn7/cCK8LUKD1HeHnKtTgBW7hi9h4nnnan7hpAg5RhWQ==", - "dev": true - }, "solidity-comments-extractor": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz", "integrity": "sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==", "dev": true }, - "solidity-docgen": { - "version": "0.6.0-beta.35", - "resolved": "https://registry.npmjs.org/solidity-docgen/-/solidity-docgen-0.6.0-beta.35.tgz", - "integrity": "sha512-9QdwK1THk/MWIdq1PEW/6dvtND0pUqpFTsbKwwU9YQIMYuRhH1lek9SsgnsGGYtdJ0VTrXXcVT30q20a8Y610A==", - "dev": true, - "requires": { - "handlebars": "^4.7.7", - "solidity-ast": "^0.4.38" - } - }, "solium": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/solium/-/solium-1.2.5.tgz", @@ -16026,13 +15893,6 @@ "dev": true, "peer": true }, - "uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "dev": true, - "optional": true - }, "unbzip2-stream": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", @@ -16181,12 +16041,6 @@ "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", "dev": true }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true - }, "workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", diff --git a/package.json b/package.json index b76074f..6239783 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,6 @@ "ethlint": "^1.2.5", "prettier-plugin-solidity": "^1.0.0-rc.1", "sol2uml": "^2.5.20", - "solidity-docgen": "^0.6.0-beta.35", "surya": "^0.4.6" } } From 1ebed5388bc77ac6f98dac9fce44e122282471fe Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Wed, 3 Dec 2025 13:11:22 +0100 Subject: [PATCH 18/25] Update library, doc and error code --- README.md | 392 +++++++++++++++++- doc/technical/RuleBlacklist.md | 32 -- doc/technical/RuleEngine.md | 58 --- doc/technical/RuleSanctionList.md | 6 +- doc/technical/RuleWhitelist.md | 2 +- doc/technical/RuleWhitelistWrapper.md | 4 +- lib/forge-std | 2 +- lib/openzeppelin-contracts | 2 +- src/rules/validation/RuleSanctionsList.sol | 21 +- src/rules/validation/RuleWhitelist.sol | 4 + src/rules/validation/RuleWhitelistWrapper.sol | 5 +- .../RuleAddressSet/RuleAddressSetInternal.sol | 2 +- .../RuleAddressSetInvariantStorage.sol | 2 - .../RuleBlacklistInvariantStorage.sol | 6 +- .../abstract/RuleCommonInvariantStorage.sol | 2 +- .../RuleSanctionsListInvariantStorage.sol | 6 +- 16 files changed, 413 insertions(+), 133 deletions(-) delete mode 100644 doc/technical/RuleEngine.md diff --git a/README.md b/README.md index ff814e7..3c3f153 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Each rule can be used **standalone**, directly plugged into a CMTAT token, **or* ## Overview The **RuleEngine** is an external smart contract that applies transfer restrictions to security tokens such as **CMTAT** or ERC-3643-compatible tokens. -Rules are modular validator contracts that the RuleEngine can call on every transfer to ensure regulatory and business-logic compliance. +Rules are modular validator contracts that the `RuleEngine` or `CMTAT` compatible token can call on every transfer to ensure regulatory and business-logic compliance. ### Key Concepts @@ -37,6 +37,19 @@ Each Rule implements the interface `IRuleEngine` defined in CMTAT. This interface declares the ERC-3643 functions `transferred`(read-write) and `canTransfer`(ready-only) with several other functions related to [ERC-1404](https://github.com/ethereum/eips/issues/1404), [ERC-7551](https://ethereum-magicians.org/t/erc-7551-crypto-security-token-smart-contract-interface-ewpg-reworked/25477) and [ERC-3643](https://eips.ethereum.org/EIPS/eip-3643). +### ERC-3643 + +Each rule implements the following functions from the ERC-3643 `ICompliance`interface + +```solidity +function canTransfer(address _from, address _to, uint256 _amount) external view returns (bool); +function transferred(address _from, address _to, uint256 _amount) external; +``` + +However, contrary to the RuleEngine, the whole interface is currently not implemented (e.g. `created`and `destroyed`) and as a result, the rule can not directly supported ERC-3643 token. + +The alternative to use a Rule with an ERC-3643 token is trough the RuleEngine, which implements the whole `ICompliance`interface. + ## Architecture ### Rule - Code list @@ -45,23 +58,28 @@ This interface declares the ERC-3643 functions `transferred`(read-write) and `ca Here the list of codes used by the different rules -| Contract | Constant name | Value | -| ----------------------- | ---------------------------------- | ----- | -| All | TRANSFER_OK (from CMTAT) | 0 | -| RuleWhitelist | CODE_ADDRESS_FROM_NOT_WHITELISTED | 21 | -| RuleWhitelist | CODE_ADDRESS_TO_NOT_WHITELISTED | 22 | -| RuleWhitelist | Free slot | 23-25 | -| RuleSanctionList | CODE_ADDRESS_FROM_IS_SANCTIONED | 26 | -| RuleSanctionList | CODE_ADDRESS_TO_IS_SANCTIONED | 27 | -| RuleSanctionList | Free slot | 28-30 | -| RuleBlacklist | CODE_ADDRESS_FROM_IS_BLACKLISTED | 31 | -| RuleBlacklist | CODE_ADDRESS_TO_IS_BLACKLISTED | 32 | -| RuleBlacklist | Free slot | 33-35 | -| RuleConditionalTransfer | CODE_TRANSFER_REQUEST_NOT_APPROVED | 36 | - - - -Warning: the CMTAT already uses the code 0-6 and the code 7-12 should be left free to allow further additions in the CMTAT. +| Contract | Constant name | Value | +| ----------------------- | ------------------------------------ | ----- | +| All | TRANSFER_OK (from CMTAT) | 0 | +| RuleWhitelist | CODE_ADDRESS_FROM_NOT_WHITELISTED | 21 | +| | CODE_ADDRESS_TO_NOT_WHITELISTED | 22 | +| | CODE_ADDRESS_SPENDER_NOT_WHITELISTED | 23 | +| | Free slot | 24-29 | +| RuleSanctionList | CODE_ADDRESS_FROM_IS_SANCTIONED | 30 | +| | CODE_ADDRESS_TO_IS_SANCTIONED | 31 | +| | CODE_ADDRESS_SPENDER_IS_SANCTIONED | 32 | +| | Free slot | 33-35 | +| RuleBlacklist | CODE_ADDRESS_FROM_IS_BLACKLISTED | 36 | +| | CODE_ADDRESS_TO_IS_BLACKLISTED | 37 | +| | CODE_ADDRESS_SPENDER_IS_BLACKLISTED | 38 | +| | Free slot | 39-44 | +| RuleConditionalTransfer | CODE_TRANSFER_REQUEST_NOT_APPROVED | 45 | +| | Free slot | 46-50 | + +Note: + +- The CMTAT already uses the code 0-6 and the code 7-12 should be left free to allow further additions in the CMTAT. +- If you decide to create your own rules, we encourage you to use code > 100 to leave free the other restriction codes for future rules added in this project. ### Rules as Standalone Compliance Contracts @@ -167,6 +185,8 @@ There are two categories of rules: validation rules (Read-only) and operation ru - Example: - Conditional Transfer (approval-based) +## Rules details + ### Read-only (validation) rule Currently, there are four validation rules: whitelist, whitelistWrapper, blacklist, and sanctionlist. @@ -185,6 +205,8 @@ The rule is read-only: it only checks stored state. During a transfer, this rule, called by the RuleEngine, will check if the address concerned is in the list, applying a read operation on the blockchain. +![surya_inheritance_RuleWhitelist.sol](./doc/surya/surya_inheritance/surya_inheritance_RuleWhitelist.sol.png) + #### Whitelist wrapper Allows independent whitelist groups managed by different operators. @@ -193,12 +215,26 @@ Allows independent whitelist groups managed by different operators. - A transfer is allowed only if both addresses belong to *at least one* operator-managed list. - Enables multi-party compliance + + +##### Architecture + +This rule inherits from `RuleEngineValidationCommon`. Thus the whitelist rules are managed with the same architecture and code than for the ruleEngine. For example, rules are added with the functions `setRules` or `addRule`. + + + +![surya_inheritance_RuleWhitelistWrapper.sol](./doc/surya/surya_inheritance/surya_inheritance_RuleWhitelistWrapper.sol.png) + + + #### Blacklist Opposite of whitelist: - Transfer fails if **either** address is blacklisted. +![surya_inheritance_RuleWhitelistWrapper.sol](./doc/surya/surya_inheritance/surya_inheritance_RuleBlacklist.sol.png) + #### Sanction list with Chainalysis Uses the [Chainalysis](https://www.chainalysis.com/) Oracle to reject transfers involving sanctioned addresses. @@ -213,6 +249,10 @@ Documentation and the contracts addresses are available here: [Chainalysis oracl During a transfer, if either address (from or to) is in the sanction list of the Oracle, the rule will return false, and the transfer will be rejected by the CMTAT. + + +![surya_inheritance_RuleWhitelistWrapper.sol](./doc/surya/surya_inheritance/surya_inheritance_RuleSanctionList.sol.png) + ### Read-Write (Operation) rule For the moment, there is only one operation rule available: ConditionalTransfer. @@ -233,21 +273,262 @@ We have added another option, not required by Swiss law, to automatically perfor Reference: [Taurus - Token Transfer Management: How to Apply Restrictions with CMTAT and ERC-1404](https://www.taurushq.com/blog/token-transfer-management-how-to-apply-restrictions-with-cmtat-and-erc-1404/) + + +## Access Control + +The modules `AccessControlModuleStandalone` allows to implement RBAC access control by inheriting from the contract `AccessControl`from OpenZeppelin. + +This module overrides the OpenZeppelin function `hasRole`to give by default all the roles to the `admin`. + +Each rule implements its own access control by inheriting from the module `AccessControlModuleStandalone`. + +For all rules, the default admin is the address put in argument(`admin`) inside the constructor and set when the contract is deployed. + +See also [docs.openzeppelin.com - AccessControl](https://docs.openzeppelin.com/contracts/5.x/api/access#AccessControl) + +### Address List + +Common access control between `blacklistRule`and `WhitelistRule` + +Here a schema of the Access Control. +![alt text](./doc/security/accessControl/access-control-RuleWhitelist.png) + + + +### RuleSanctionList + +![alt text](./doc/security/accessControl/access-control-RuleSanctionList.drawio.png) + + + ## Dependencies The toolchain includes the following components, where the versions are the latest ones that we tested: -- Foundry [v1.9.4](https://github.com/foundry-rs/forge-std/releases/tag/v1.9.4) +- Foundry [v1.5.0](https://github.com/foundry-rs/foundry) +- Forge std [v1.12.0](https://github.com/foundry-rs/forge-std/releases/tag/v1.12.0 ) - Solidity 0.8.30 (via solc-js) -- OpenZeppelin Contracts (submodule) [v5.3.0](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.3.0) +- OpenZeppelin Contracts (submodule) [v5.5.0](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.5.0) - CMTAT [v3.0.0](https://github.com/CMTA/CMTAT) - - This repository includes the RuleEngine contract for the [CMTAT](https://github.com/CMTA/CMTAT) token. +- RuleEngine The RuleEngine is an external contract used to apply transfer restrictions to another contract, initially the CMTAT. Acting as a controller, it can call different contract rules and apply these rules on each transfer. ## API +### IRuleEngine + +> Each rule implements the IRuleEngine interface + +#### transferred + +``` +function transferred(address spender, address from, address to, uint256 value) + external; +``` + +Called during an ERC-20 token transfer + Used by rules to update internal state or enforce operation-based restrictions. + +##### Parameters + +| Name | Type | Description | +| --------- | --------- | ------------------------------------------------------------ | +| `spender` | `address` | Address executing the transfer (owner, operator, or approved). | +| `from` | `address` | Current token holder. | +| `to` | `address` | Recipient address. | +| `value` | `uint256` | Amount transferred. | + +------ + +### IERC1404 + +#### detectTransferRestriction + +``` +function detectTransferRestriction(address from, address to, uint256 value) + external + view + returns (uint8); +``` + +Returns a restriction code describing why a transfer is blocked. + +##### Parameters + +| Name | Type | Description | +| ------- | --------- | ------------------------- | +| `from` | `address` | Sender address. | +| `to` | `address` | Recipient address. | +| `value` | `uint256` | Amount being transferred. | + +##### Returns + +| Name | Type | Description | +| ----- | ------- | ---------------------------------------- | +| `0` | `uint8` | Transfer allowed. | +| other | `uint8` | Implementation-defined restriction code. | + +------ + +#### messageForTransferRestriction + +``` +function messageForTransferRestriction(uint8 restrictionCode) + external + view + returns (string memory); +``` + +Returns a human-readable message associated with a restriction code. + +##### Parameters + +| Name | Type | Description | +| ----------------- | ------- | --------------------------------------------------------- | +| `restrictionCode` | `uint8` | Restriction code returned by `detectTransferRestriction`. | + +##### Returns + +| Name | Type | Description | +| --------- | -------- | ------------------------------------- | +| `message` | `string` | Explanation for the restriction code. | + +------ + +### IERC1404Extend + +#### REJECTED_CODE_BASE + +``` +enum REJECTED_CODE_BASE { + TRANSFER_OK, + TRANSFER_REJECTED_DEACTIVATED, + TRANSFER_REJECTED_PAUSED, + TRANSFER_REJECTED_FROM_FROZEN, + TRANSFER_REJECTED_TO_FROZEN, + TRANSFER_REJECTED_SPENDER_FROZEN, + TRANSFER_REJECTED_FROM_INSUFFICIENT_ACTIVE_BALANCE +} +``` + +Base transfer restriction codes used by ERC-1404 extensions. + +------ + +#### detectTransferRestrictionFrom + +``` +function detectTransferRestrictionFrom( + address spender, + address from, + address to, + uint256 value +) + external + view + returns (uint8); +``` + +Restriction code for transfers performed by a spender (approved operator). + +##### Parameters + +| Name | Type | Description | +| --------- | --------- | -------------------------------- | +| `spender` | `address` | Address performing the transfer. | +| `from` | `address` | Current token owner. | +| `to` | `address` | Recipient address. | +| `value` | `uint256` | Transfer amount. | + +##### Returns + +| Name | Type | Description | +| ------ | ------- | ---------------------------------------------------- | +| `code` | `uint8` | 0 if transfer allowed, otherwise a restriction code. | + +------ + +### IERC7551Compliance + +#### canTransferFrom + +``` +function canTransferFrom(address spender, address from, address to, uint256 value) + external + view + returns (bool); +``` + +Determines if a spender-initiated transfer is permitted. + +##### Parameters + +| Name | Type | Description | +| --------- | --------- | -------------------------- | +| `spender` | `address` | Caller executing transfer. | +| `from` | `address` | Token owner. | +| `to` | `address` | Recipient. | +| `value` | `uint256` | Amount. | + +##### Returns + +| Name | Type | Description | +| --------- | ------ | ----------------------------- | +| `allowed` | `bool` | `true` if transfer permitted. | + +------ + +### IERC3643ComplianceRead + +#### canTransfer + +``` +function canTransfer(address from, address to, uint256 value) + external + view + returns (bool isValid); +``` + +Returns whether a transfer is compliant. + +##### Parameters + +| Name | Type | Description | +| ------- | --------- | ---------------- | +| `from` | `address` | Sender. | +| `to` | `address` | Receiver. | +| `value` | `uint256` | Transfer amount. | + +##### Returns + +| Name | Type | Description | +| --------- | ------ | -------------------- | +| `isValid` | `bool` | `true` if compliant. | + +------ + +### IERC3643IComplianceContract + +#### transferred + +``` +function transferred(address from, address to, uint256 value) + external; +``` + +Hook invoked during an ERC-20 token transfer. + +##### Parameters + +| Name | Type | Description | +| ------- | --------- | ------------------- | +| `from` | `address` | Previous owner. | +| `to` | `address` | New owner. | +| `value` | `uint256` | Amount transferred. | + ### Address List Management > This API is common to whitelist and blacklist rules @@ -455,6 +736,28 @@ Checks the listing status of multiple addresses in a single call. | --------- | -------- | --------------------------------------------------- | | `results` | `bool[]` | Array of boolean listing results, aligned by index. | +#### Details + +##### Null address + +It is possible to add the null address (0x0) to the blacklist. If it is the case, it will not be possible to mint and burn tokens. + +##### Duplicate address + +**addAddress** +If the address already exists, the transaction is reverted to save gas. +**addAddresses** +If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert). + +##### NonExistent Address + +**removeAddress** +If the address does not exist in the whitelist, the transaction is reverted to save gas. +**removeAddresses** +If the address does not exist in the whitelist, there is no change for this address. The transaction remains valid (no revert). + + + ### IERC7943NonFungibleCompliance Compliance interface for ERC-721 / ERC-1155–style non-fungible assets. @@ -676,6 +979,53 @@ Signals to the compliance engine that a transfer has successfully occurred. | `tokenId` | `uint256` | Token transferred. | | `value` | `uint256` | Transfer amount (`1` for ERC-721 token). | +### RuleSanctionsList + +Compliance rule enforcing sanctions-screening for token transfers. + Integrates a sanctions-oracle (e.g., Chainalysis) to block transfers when the sender, recipient, or spender is sanctioned. + +------ + +#### Constructor + +```solidity +constructor(address admin, address forwarderIrrevocable, ISanctionsList sanctionContractOracle_) +``` + +Initializes access control, meta-transaction forwarder, and optionally the sanctions oracle. + +#### setSanctionListOracle + +```solidity +function setSanctionListOracle(ISanctionsList sanctionContractOracle_) + public + virtual + onlyRole(SANCTIONLIST_ROLE) +``` + +Set the sanctions-oracle contract used for transfer-restriction checks. + +##### Parameters + +| Name | Type | Description | +| ------------------------- | ---------------- | ------------------------------------------------------------ | +| `sanctionContractOracle_` | `ISanctionsList` | Address of the sanctions-oracle. Passing the zero address disables sanctions checks. | + +##### Description + +Updates the sanctions-oracle contract reference. + This function may only be called by accounts granted the `SANCTIONLIST_ROLE`. + +Setting the oracle to the zero address is permitted and effectively disables all sanctions-based transfer restrictions. + +##### Emits + +| Event | Description | +| -------------------------------- | ----------------------------------------------------- | +| `SetSanctionListOracle(address)` | Emitted when the sanctions-oracle address is updated. | + + + ## Foundry **Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** diff --git a/doc/technical/RuleBlacklist.md b/doc/technical/RuleBlacklist.md index 59ebb3c..1186217 100644 --- a/doc/technical/RuleBlacklist.md +++ b/doc/technical/RuleBlacklist.md @@ -15,35 +15,3 @@ A part of the code is shared with Rule Whitelist ![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleBlacklist.sol.png) -## Access Control - -### Admin - -The default admin is the address put in argument(`admin`) inside the constructor. It is set in the constructor when the contract is deployed. - -### Schema - -Here a schema of the Access Control. -![alt text](../security/accessControl/access-control-RuleWhitelist.png) - - - - - -## Methods - -### Null address -It is possible to add the null address (0x0) to the blacklist. If it is the case, it will not be possible to mint and burn tokens. - -### Duplicate address - -**addAddress** -If the address already exists, the transaction is reverted to save gas. -**addAddresses** -If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert). - -### NonExistent Address -**removeAddress** -If the address does not exist in the whitelist, the transaction is reverted to save gas. -**removeAddresses** -If the address does not exist in the whitelist, there is no change for this address. The transaction remains valid (no revert). diff --git a/doc/technical/RuleEngine.md b/doc/technical/RuleEngine.md deleted file mode 100644 index 159cf07..0000000 --- a/doc/technical/RuleEngine.md +++ /dev/null @@ -1,58 +0,0 @@ -# RuleEngine - -[TOC] - -The RuleEngine is an external contract used to apply transfer restriction to the CMTAT. - -This contract acts as a controller and can call different contract rule to apply rule on each transfer. - -A possible rule is a whitelist rule where only the address inside the whitelist can perform a transfer - -## Schema - -![RuleEngine](../schema/RuleEngine.png) - -### Graph - - - -![surya_graph_RuleEngine](../surya/surya_graph/surya_graph_RuleEngine.sol.png) - - - -## Access Control - -### Admin - -The default admin is the address put in argument(`admin`) inside the constructor. It is set in the constructor when the contract is deployed. - -### Schema - -Here a schema of the Access Control. -![alt text](../security/accessControl/access-control-RuleEngine.png) - -By default, the `DEFAULT_ADMIN_ROLE` has the role `RULE_ENGINE_ROLE`. - - - -## Methods - -### Duplicate rules - -**setRules** - -If one rule is already present, the function is reverted - -**addRule** - -If one rule is already present, the function is reverted - -### Null address - -**setRules** - -The function is reverted if one rule is the zero address - -**addRule** - -The function is reverted if one rule is the zero address diff --git a/doc/technical/RuleSanctionList.md b/doc/technical/RuleSanctionList.md index 3ce697e..f9bf55a 100644 --- a/doc/technical/RuleSanctionList.md +++ b/doc/technical/RuleSanctionList.md @@ -20,7 +20,7 @@ The documentation and the contracts addresses are available here: [Chainalysis o ### Inheritance -![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleSanctionList.sol.png) + ## Access Control @@ -32,7 +32,3 @@ The default admin is the address put in argument(`admin`) inside the constructor Here a schema of the Access Control. -**RuleSanctionList** - -![alt text](../security/accessControl/access-control-RuleSanctionList.drawio.png) - diff --git a/doc/technical/RuleWhitelist.md b/doc/technical/RuleWhitelist.md index d74b8aa..d72c098 100644 --- a/doc/technical/RuleWhitelist.md +++ b/doc/technical/RuleWhitelist.md @@ -12,7 +12,7 @@ This rule can be used to restrict transfers from/to only addresses inside a whit ### Inheritance -![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleWhitelist.sol.png) + ## Access Control diff --git a/doc/technical/RuleWhitelistWrapper.md b/doc/technical/RuleWhitelistWrapper.md index 4895bf1..e8a0047 100644 --- a/doc/technical/RuleWhitelistWrapper.md +++ b/doc/technical/RuleWhitelistWrapper.md @@ -19,13 +19,13 @@ If this is the case, the rule return 0 (transfer valid) or an error otherwise. ### Inheritance -![surya_inheritance_RuleWhitelistWrapper.sol](../surya/surya_inheritance/surya_inheritance_RuleWhitelistWrapper.sol.png) + ## Details ### Architecture -This rule inherits from `RuleEngineValidationCommon`. Thus the whitelist rules are managed with the same architecture and code than for the ruleEngine. For example, rules are added with the functions `setRulesValidation` or `addRuleValidation`. + ### Admin diff --git a/lib/forge-std b/lib/forge-std index c7be2a3..7117c90 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit c7be2a3481f9e51230880bb0949072c7e3a4da82 +Subproject commit 7117c90c8cf6c68e5acce4f09a6b24715cea4de6 diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts index c64a1ed..fcbae53 160000 --- a/lib/openzeppelin-contracts +++ b/lib/openzeppelin-contracts @@ -1 +1 @@ -Subproject commit c64a1edb67b6e3f4a15cca8909c9482ad33a02b0 +Subproject commit fcbae5394ae8ad52d8e580a3477db99814b9d565 diff --git a/src/rules/validation/RuleSanctionsList.sol b/src/rules/validation/RuleSanctionsList.sol index a94a5b4..12ddb7f 100644 --- a/src/rules/validation/RuleSanctionsList.sol +++ b/src/rules/validation/RuleSanctionsList.sol @@ -17,6 +17,25 @@ import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; /* ==== IRuleEngine === */ import {IRule} from "RuleEngine/interfaces/IRule.sol"; + +/** + * @title RuleSanctionsList + * @notice Compliance rule enforcing sanctions-screening for token transfers. + * @dev + * This rule integrates a sanctions-oracle (e.g., Chainalysis) and blocks + * transfers when: + * - the sender is sanctioned, + * - the recipient is sanctioned, + * - or the spender/operator is sanctioned. + * + * Features: + * - Supports ERC-1404, ERC-3643 (transferred) and ERC-7943 non-fungible compliance flows. + * - Oracle address can be updated by accounts holding `SANCTIONLIST_ROLE`. + * - Zero oracle address disables sanctions checks (all transfers allowed). + * + * The rule is designed for RuleEngine or for direct integration with + * CMTAT / ERC-3643 compliant tokens. + */ contract RuleSanctionsList is AccessControlModuleStandalone, MetaTxModuleStandalone, @@ -150,7 +169,7 @@ contract RuleSanctionsList is * @param sanctionContractOracle_ address of your oracle contract * @dev zero address is authorized to authorize all transfers */ - function setSanctionListOracle(ISanctionsList sanctionContractOracle_) public onlyRole(SANCTIONLIST_ROLE) { + function setSanctionListOracle(ISanctionsList sanctionContractOracle_) public virtual onlyRole(SANCTIONLIST_ROLE) { _setSanctionListOracle(sanctionContractOracle_); } diff --git a/src/rules/validation/RuleWhitelist.sol b/src/rules/validation/RuleWhitelist.sol index 897478b..5ce5b70 100644 --- a/src/rules/validation/RuleWhitelist.sol +++ b/src/rules/validation/RuleWhitelist.sol @@ -55,6 +55,7 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry function detectTransferRestriction(address from, address to, uint256 /* value */ ) public view + virtual override(IERC1404) returns (uint8 code) { @@ -73,6 +74,7 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value) public view + virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) { @@ -99,6 +101,7 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) public view + virtual override(IERC1404Extend) returns (uint8 code) { @@ -129,6 +132,7 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry function isVerified(address targetAddress) public view + virtual override(IIdentityRegistryVerified) returns (bool isListed) { diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol index 8aa66c2..6bc6d49 100644 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -55,6 +55,7 @@ contract RuleWhitelistWrapper is function detectTransferRestriction(address from, address to, uint256 /*value*/ ) public view + virtual override(IERC1404) returns (uint8) { @@ -75,6 +76,7 @@ contract RuleWhitelistWrapper is function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value) public view + virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) { @@ -84,6 +86,7 @@ contract RuleWhitelistWrapper is function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) public view + virtual override(IERC1404Extend) returns (uint8) { @@ -118,7 +121,7 @@ contract RuleWhitelistWrapper is address to, uint256, /* tokenId */ uint256 value - ) public view override(IERC7943NonFungibleComplianceExtend) returns (uint8) { + ) public view virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) { return detectTransferRestrictionFrom(spender, from, to, value); } diff --git a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol index fe77359..270c4b6 100644 --- a/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol +++ b/src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol @@ -23,7 +23,7 @@ abstract contract RuleAddressSetInternal { EnumerableSet.AddressSet private _listedAddresses; /*////////////////////////////////////////////////////////////// - CORE LOGIC + INTERNAL //////////////////////////////////////////////////////////////*/ /** diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol index 730f5c5..5d1a8a9 100644 --- a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol @@ -4,8 +4,6 @@ pragma solidity ^0.8.20; abstract contract RuleAddressSetInvariantStorage { /* ============ Custom errors ============ */ - error RuleAddressSet_AdminWithAddressZeroNotAllowed(); - /// @notice Thrown when trying to add an address that is already listed. error RuleAddressSet_AddressAlreadyListed(); diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol index 8458fd7..16e74ce 100644 --- a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol @@ -14,7 +14,7 @@ abstract contract RuleBlacklistInvariantStorage is RuleCommonInvariantStorage { /* ============ Code ============ */ // It is very important that each rule uses an unique code - uint8 public constant CODE_ADDRESS_FROM_IS_BLACKLISTED = 41; - uint8 public constant CODE_ADDRESS_TO_IS_BLACKLISTED = 42; - uint8 public constant CODE_ADDRESS_SPENDER_IS_BLACKLISTED = 43; + uint8 public constant CODE_ADDRESS_FROM_IS_BLACKLISTED = 36; + uint8 public constant CODE_ADDRESS_TO_IS_BLACKLISTED = 37; + uint8 public constant CODE_ADDRESS_SPENDER_IS_BLACKLISTED = 38; } diff --git a/src/rules/validation/abstract/RuleCommonInvariantStorage.sol b/src/rules/validation/abstract/RuleCommonInvariantStorage.sol index 855e72f..e4cd505 100644 --- a/src/rules/validation/abstract/RuleCommonInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleCommonInvariantStorage.sol @@ -2,6 +2,6 @@ pragma solidity ^0.8.20; abstract contract RuleCommonInvariantStorage { - // Text + /* ============ String message ============ */ string constant TEXT_CODE_NOT_FOUND = "Unknown restriction code"; } diff --git a/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol index 5a613d2..b9f96fd 100644 --- a/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol @@ -24,7 +24,7 @@ abstract contract RuleSanctionsListInvariantStorage is RuleCommonInvariantStorag /* ============ Code ============ */ // It is very important that each rule uses an unique code - uint8 public constant CODE_ADDRESS_FROM_IS_SANCTIONED = 31; - uint8 public constant CODE_ADDRESS_TO_IS_SANCTIONED = 32; - uint8 public constant CODE_ADDRESS_SPENDER_IS_SANCTIONED = 33; + uint8 public constant CODE_ADDRESS_FROM_IS_SANCTIONED = 30; + uint8 public constant CODE_ADDRESS_TO_IS_SANCTIONED = 31; + uint8 public constant CODE_ADDRESS_SPENDER_IS_SANCTIONED = 32; } From a2d039d9e6c34003e3be4f13c6ea4a606bb21c3f Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Wed, 3 Dec 2025 13:26:26 +0100 Subject: [PATCH 19/25] Add new tests --- test/RuleBlacklist/RuleBlacklist.t.sol | 93 +++++++++++++++++++ .../RuleSanctionListTest.t.sol | 53 +++++++++++ test/RuleWhitelist/RuleWhitelist.t.sol | 25 +++++ 3 files changed, 171 insertions(+) diff --git a/test/RuleBlacklist/RuleBlacklist.t.sol b/test/RuleBlacklist/RuleBlacklist.t.sol index b0fbf4b..0a7651d 100644 --- a/test/RuleBlacklist/RuleBlacklist.t.sol +++ b/test/RuleBlacklist/RuleBlacklist.t.sol @@ -80,6 +80,7 @@ contract RuleBlacklistTest is Test, HelperContract { ruleBlacklist.addAddress(ADDRESS2); // Act resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); + assertEq(resUint8, CODE_ADDRESS_TO_IS_BLACKLISTED); // With tokenId resUint8 = ruleBlacklist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); @@ -96,4 +97,96 @@ contract RuleBlacklistTest is Test, HelperContract { // Assert assertFalse(resBool); } + + function testDetectTransferRestrictionSpender() public { + // Arrange + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleBlacklist.addAddress(ADDRESS3); + // Act + resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + assertEq(resUint8, CODE_ADDRESS_SPENDER_IS_BLACKLISTED); + + // With tokenId + resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_SPENDER_IS_BLACKLISTED); + + // Act + resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + // Assert + assertFalse(resBool); + + // Act + resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertFalse(resBool); + } + + function testDetectTransferRestrictionSpenderTo() public { + // Arrange + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleBlacklist.addAddress(ADDRESS2); + // Act + resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + + // With tokenId + resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_TO_IS_BLACKLISTED); + + // Act + resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + // Assert + assertFalse(resBool); + + // Act + resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertFalse(resBool); + } + + function testDetectTransferRestrictionSpenderFrom() public { + // Arrange + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleBlacklist.addAddress(ADDRESS1); + // Act + resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + assertEq(resUint8, CODE_ADDRESS_FROM_IS_BLACKLISTED); + // With tokenId + resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_FROM_IS_BLACKLISTED); + + // Act + resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + // Assert + assertFalse(resBool); + + // Act + resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertFalse(resBool); + } + + function testDetectTransferRestrictionSpenderOk() public { + // Act + resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + assertEq(resUint8, NO_ERROR); + + // With tokenId + resUint8 = ruleBlacklist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, NO_ERROR); + + // Act + resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resBool, true); + + // Act + resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resBool, true); + } + } diff --git a/test/RuleSanctionList/RuleSanctionListTest.t.sol b/test/RuleSanctionList/RuleSanctionListTest.t.sol index 925cf60..65ec3ef 100644 --- a/test/RuleSanctionList/RuleSanctionListTest.t.sol +++ b/test/RuleSanctionList/RuleSanctionListTest.t.sol @@ -126,4 +126,57 @@ contract RuleSanctionlistTest is Test, HelperContract { // Assert assertEq(resUint8, NO_ERROR); } + + function testDetectTransferRestrictionWitSpenderOk() public { + // Act + resUint8 = ruleSanctionList.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resUint8, NO_ERROR); + + // Act + resUint8 = ruleSanctionList.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, NO_ERROR); + + + resBool = ruleSanctionList.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + assertEq(resBool, true); + + resBool = ruleSanctionList.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + assertEq(resBool, true); + } + + function testDetectTransferRestrictionWitSpender() public { + // Act + resUint8 = ruleSanctionList.detectTransferRestrictionFrom(ATTACKER, ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_SPENDER_IS_SANCTIONED); + + // Act + resUint8 = ruleSanctionList.detectTransferRestrictionFrom(ATTACKER, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_SPENDER_IS_SANCTIONED); + } + + function testDetectTransferRestrictionWitSpenderTo() public { + // Act + resUint8 = ruleSanctionList.detectTransferRestrictionFrom(ADDRESS2, ADDRESS1, ATTACKER, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_TO_IS_SANCTIONED); + + // Act + resUint8 = ruleSanctionList.detectTransferRestrictionFrom(ADDRESS2, ADDRESS1, ATTACKER, 0, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_TO_IS_SANCTIONED); + + // Act + resBool = ruleSanctionList.canTransferFrom(ADDRESS2, ADDRESS1, ATTACKER, 20); + // Assert + assertFalse(resBool); + + // Act + resBool = ruleSanctionList.canTransferFrom(ADDRESS2, ADDRESS1, ATTACKER, 0, 20); + // Assert + assertFalse(resBool); + } } diff --git a/test/RuleWhitelist/RuleWhitelist.t.sol b/test/RuleWhitelist/RuleWhitelist.t.sol index bec226e..2910742 100644 --- a/test/RuleWhitelist/RuleWhitelist.t.sol +++ b/test/RuleWhitelist/RuleWhitelist.t.sol @@ -132,6 +132,11 @@ contract RuleWhitelistTest is Test, HelperContract { resBool = ruleWhitelist.canTransfer(ADDRESS1, ADDRESS2, 20); // Assert assertFalse(resBool); + + // Act + resBool = ruleWhitelist.canTransfer(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertFalse(resBool); } function testlistedAddressCount() public { @@ -196,10 +201,20 @@ contract RuleWhitelistTest is Test, HelperContract { // Assert assertEq(resUint8, CODE_ADDRESS_SPENDER_NOT_WHITELISTED); + // Act + resBool = ruleWhitelist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resBool, false); + // With tokenId resUint8 = ruleWhitelist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resUint8, CODE_ADDRESS_SPENDER_NOT_WHITELISTED); + + // Act + resBool = ruleWhitelist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resBool, false); } function testDetectTransferRestrictionOk() public { @@ -237,6 +252,16 @@ contract RuleWhitelistTest is Test, HelperContract { // Assert assertEq(resUint8, NO_ERROR); + // Act + resBool = ruleWhitelist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resBool, true); + + // Act + resBool = ruleWhitelist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resBool, true); + // With tokenId resUint8 = ruleWhitelist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); // Assert From 12ff6ea76170da51396f5335ed21fc8869674307 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Wed, 3 Dec 2025 13:34:17 +0100 Subject: [PATCH 20/25] Add ERC-165 support for rule --- src/rules/validation/RuleBlacklist.sol | 7 ++++++- src/rules/validation/RuleSanctionsList.sol | 7 ++++++- src/rules/validation/RuleWhitelist.sol | 7 ++++++- src/rules/validation/RuleWhitelistWrapper.sol | 6 +++++- src/rules/validation/abstract/RuleValidateTransfer.sol | 5 +++++ 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol index 4a3a657..a71ee65 100644 --- a/src/rules/validation/RuleBlacklist.sol +++ b/src/rules/validation/RuleBlacklist.sol @@ -2,11 +2,12 @@ pragma solidity ^0.8.20; +import {AccessControl} from "OZ/access/AccessControl.sol"; /* ==== Abtract contracts === */ import {RuleBlacklistInvariantStorage} from "./abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol"; import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol"; -import {RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol"; +import {RuleValidateTransfer, RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol"; /* ==== Interfaces === */ import {IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol"; /* ==== CMTAT === */ @@ -134,6 +135,10 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv } } + function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) { + return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId); + } + /* ============ State Functions ============ */ function transferred(address from, address to, uint256 value) diff --git a/src/rules/validation/RuleSanctionsList.sol b/src/rules/validation/RuleSanctionsList.sol index 12ddb7f..8a91605 100644 --- a/src/rules/validation/RuleSanctionsList.sol +++ b/src/rules/validation/RuleSanctionsList.sol @@ -2,11 +2,12 @@ pragma solidity ^0.8.20; +import {AccessControl} from "OZ/access/AccessControl.sol"; /* ==== Abtract contracts === */ import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../modules/MetaTxModuleStandalone.sol"; import {AccessControlModuleStandalone} from "../../modules/AccessControlModuleStandalone.sol"; import {RuleSanctionsListInvariantStorage} from "./abstract/RuleSanctionsListInvariantStorage.sol"; -import {RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol"; +import {RuleValidateTransfer, RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol"; /* ==== Interfaces === */ import {ISanctionsList} from "../interfaces/ISanctionsList.sol"; import {IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol"; @@ -163,6 +164,10 @@ contract RuleSanctionsList is } } + function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) { + return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId); + } + /* ============ State Functions ============ */ /** * @notice Set the oracle contract diff --git a/src/rules/validation/RuleWhitelist.sol b/src/rules/validation/RuleWhitelist.sol index 5ce5b70..07e1dca 100644 --- a/src/rules/validation/RuleWhitelist.sol +++ b/src/rules/validation/RuleWhitelist.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MPL-2.0 pragma solidity ^0.8.20; +import {AccessControl} from "OZ/access/AccessControl.sol"; /* ==== Abtract contracts === */ import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol"; -import {RuleWhitelistCommon} from "./abstract/RuleWhitelistCommon.sol"; +import {RuleWhitelistCommon, RuleValidateTransfer} from "./abstract/RuleWhitelistCommon.sol"; /* ==== CMTAT === */ import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; /* ==== Interfaces === */ @@ -138,4 +139,8 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry { isListed = _isAddressListed(targetAddress); } + + function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) { + return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId); + } } diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol index 6bc6d49..dc3824f 100644 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -8,7 +8,7 @@ import {AccessControl} from "OZ/access/AccessControl.sol"; import {AccessControlModuleStandalone} from "../../modules/AccessControlModuleStandalone.sol"; import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../modules/MetaTxModuleStandalone.sol"; import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol"; -import {RuleWhitelistCommon} from "./abstract/RuleWhitelistCommon.sol"; +import {RuleWhitelistCommon, RuleValidateTransfer} from "./abstract/RuleWhitelistCommon.sol"; /* ==== RuleEngine === */ import {RulesManagementModule} from "RuleEngine/modules/RulesManagementModule.sol"; import {RuleEngineInvariantStorage} from "RuleEngine/modules/library/RuleEngineInvariantStorage.sol"; @@ -171,6 +171,10 @@ contract RuleWhitelistWrapper is return result; } + function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) { + return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId); + } + /*////////////////////////////////////////////////////////////// ERC-2771 //////////////////////////////////////////////////////////////*/ diff --git a/src/rules/validation/abstract/RuleValidateTransfer.sol b/src/rules/validation/abstract/RuleValidateTransfer.sol index 7b5f256..10d3a0e 100644 --- a/src/rules/validation/abstract/RuleValidateTransfer.sol +++ b/src/rules/validation/abstract/RuleValidateTransfer.sol @@ -79,4 +79,9 @@ abstract contract RuleValidateTransfer is IERC7943NonFungibleComplianceExtend, I { return canTransferFrom(spender, from, to, value); } + + + function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { + return interfaceId == type(IRule).interfaceId; + } } From 0c9b8544c015b770d866b5b48b314e0738d4b310 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Wed, 3 Dec 2025 13:50:51 +0100 Subject: [PATCH 21/25] Update documentation --- CHANGELOG.md | 4 + README.md | 260 +++++++++++++++++++++++++++++++++-------------- doc/TOOLCHAIN.md | 8 -- 3 files changed, 186 insertions(+), 86 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dbdc5d6..0290e02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,3 +16,7 @@ Please follow [https://changelog.md/](https://changelog.md/) conventions. - Perform an audit with several audit tools (Mythril and Slither), update the report in the corresponding directory [./doc/security/audits/tools](./doc/security/audits/tools) - Update surya doc by running the 3 scripts in [./doc/script](./doc/script) - Update changelog + +## v0.1.0 + +First release ! diff --git a/README.md b/README.md index 3c3f153..484ef6f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # RuleEngine - Rules -**Rules** is a collection of on-chain compliance and transfer-restriction rules designed for use with the - [CMTA RuleEngine](https://github.com/CMTA/RuleEngine) and the [CMTAT token standard](https://github.com/CMTA/CMTAT). +**Rules** is a collection of on-chain compliance and transfer-restriction rules designed for use with the [CMTA RuleEngine](https://github.com/CMTA/RuleEngine) and the [CMTAT token standard](https://github.com/CMTA/CMTAT). Each rule can be used **standalone**, directly plugged into a CMTAT token, **or** managed collectively via a RuleEngine. @@ -11,7 +10,7 @@ Each rule can be used **standalone**, directly plugged into a CMTAT token, **or* ## Overview -The **RuleEngine** is an external smart contract that applies transfer restrictions to security tokens such as **CMTAT** or ERC-3643-compatible tokens. +The **RuleEngine** is an external smart contract that applies transfer restrictions to security tokens such as **CMTAT** or ERC-3643-compatible tokens through a RuleEngine. Rules are modular validator contracts that the `RuleEngine` or `CMTAT` compatible token can call on every transfer to ensure regulatory and business-logic compliance. ### Key Concepts @@ -48,7 +47,7 @@ function transferred(address _from, address _to, uint256 _amount) external; However, contrary to the RuleEngine, the whole interface is currently not implemented (e.g. `created`and `destroyed`) and as a result, the rule can not directly supported ERC-3643 token. -The alternative to use a Rule with an ERC-3643 token is trough the RuleEngine, which implements the whole `ICompliance`interface. +The alternative to use a Rule with an ERC-3643 token is trough the RuleEngine, which implements the whole `ICompliance` interface. ## Architecture @@ -302,19 +301,187 @@ Here a schema of the Access Control. -## Dependencies +## Toolchains and Usage -The toolchain includes the following components, where the versions are the latest ones that we tested: +*Explain how it works.* -- Foundry [v1.5.0](https://github.com/foundry-rs/foundry) -- Forge std [v1.12.0](https://github.com/foundry-rs/forge-std/releases/tag/v1.12.0 ) -- Solidity 0.8.30 (via solc-js) -- OpenZeppelin Contracts (submodule) [v5.5.0](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.5.0) -- CMTAT [v3.0.0](https://github.com/CMTA/CMTAT) -- RuleEngine +### Configuration + +Here are the settings for [Hardhat](https://hardhat.org) and [Foundry](https://getfoundry.sh). + +- `hardhat.config.js` + + - Solidity [v0.8.30](https://docs.soliditylang.org/en/v0.8.30/) + - EVM version: Prague (Pectra upgrade) + - Optimizer: true, 200 runs + +- `foundry.toml` + + - Solidity [v0.8.30](https://docs.soliditylang.org/en/v0.8.30/) + - EVM version: Prague (Pectra upgrade) + - Optimizer: true, 200 runs + +- Library + + - Foundry [v1.5.0](https://github.com/foundry-rs/foundry) + + - Forge std [v1.12.0](https://github.com/foundry-rs/forge-std/releases/tag/v1.12.0 ) + + - OpenZeppelin Contracts (submodule) [v5.5.0](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.5.0) + + - CMTAT [v3.0.0](https://github.com/CMTA/CMTAT) + + - RuleEngine [v3.0.0-rc0](https://github.com/CMTA/RuleEngine/releases/tag/v3.0.0-rc0) + +### Toolchain installation + +The contracts are developed and tested with [Foundry](https://book.getfoundry.sh), a smart contract development toolchain. + +To install the Foundry suite, please refer to the official instructions in the [Foundry book](https://book.getfoundry.sh/getting-started/installation). + +### Initialization + +You must first initialize the submodules, with + +``` +forge install +``` + +See also the command's [documentation](https://book.getfoundry.sh/reference/forge/forge-install). + +Later you can update all the submodules with: + +``` +forge update +``` + +See also the command's [documentation](https://book.getfoundry.sh/reference/forge/forge-update). + +#### CMTAT + +You also have to install OpenZeppelin inside CMTAT repository (submodule) + +```bash +cd CMTAT +npm install +``` + + + +### Compilation + +The official documentation is available in the Foundry [website](https://book.getfoundry.sh/reference/forge/build-commands) + +``` + forge build +``` + +### Contract size + +```bash + forge compile --sizes +``` + +### Testing + +You can run the tests with + +```bash +forge test +``` + +To run a specific test, use + +```bash +forge test --match-contract --match-test +``` + +Generate gas report + +```bash +forge test --gas-report +``` + +See also the test framework's [official documentation](https://book.getfoundry.sh/forge/tests), and that of the [test commands](https://book.getfoundry.sh/reference/forge/test-commands). + +### Coverage + +A code coverage is available in [index.html](./doc/coverage/coverage/index.html). + +* Perform a code coverage + +``` +forge coverage +``` + +* Generate LCOV report + +``` +forge coverage --report lcov +``` + +- Generate `index.html` + +```bash +forge coverage --no-match-coverage "(script|mocks|test)" --report lcov && genhtml lcov.info --branch-coverage --output-dir coverage +``` + +See [Solidity Coverage in VS Code with Foundry](https://mirror.xyz/devanon.eth/RrDvKPnlD-pmpuW7hQeR5wWdVjklrpOgPCOA-PJkWFU) & [Foundry forge coverage]( + +### Other + +Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.* + +Foundry consists of: + +- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). +- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. +- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. +- **Chisel**: Fast, utilitarian, and verbose solidity REPL. + +#### Documentation + +https://book.getfoundry.sh/ + +#### Format + +```shell +$ forge fmt +``` + +#### Gas Snapshots + +```shell +$ forge snapshot +``` + +#### Anvil + +```shell +$ anvil +``` + +#### Deploy + +```shell +$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key +``` + +#### Cast + +```shell +$ cast +``` + +#### Help + +```shell +$ forge --help +$ anvil --help +$ cast --help +``` -The RuleEngine is an external contract used to apply transfer restrictions to another contract, initially the CMTAT. Acting as a controller, it can call different contract rules and apply these rules on each transfer. ## API @@ -1026,69 +1193,6 @@ Setting the oracle to the zero address is permitted and effectively disables all -## Foundry - -**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** - -Foundry consists of: - -- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). -- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. -- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. -- **Chisel**: Fast, utilitarian, and verbose solidity REPL. - -## Documentation - -https://book.getfoundry.sh/ - -## Usage - -### Build - -```shell -$ forge build -``` - -### Test - -```shell -$ forge test -``` - -### Format - -```shell -$ forge fmt -``` - -### Gas Snapshots - -```shell -$ forge snapshot -``` - -### Anvil +## Intellectual property -```shell -$ anvil -``` - -### Deploy - -```shell -$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key -``` - -### Cast - -```shell -$ cast -``` - -### Help - -```shell -$ forge --help -$ anvil --help -$ cast --help -``` +The code is copyright (c) Capital Market and Technology Association, 2022-2025, and is released under [Mozilla Public License 2.0](https://github.com/CMTA/CMTAT/blob/master/LICENSE.md). diff --git a/doc/TOOLCHAIN.md b/doc/TOOLCHAIN.md index de83611..64b6246 100644 --- a/doc/TOOLCHAIN.md +++ b/doc/TOOLCHAIN.md @@ -53,14 +53,6 @@ Warning: ## Generate documentation -### [docgen](https://github.com/OpenZeppelin/solidity-docgen) - ->Solidity-docgen is a program that extracts documentation for a Solidity project. - -``` -npx hardhat docgen -``` - ### [sol2uml](https://github.com/naddison36/sol2uml) >Generate UML for smart contracts From 1a1474034c232498fa9d0126ddf81ff97c2a8810 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Wed, 3 Dec 2025 14:13:58 +0100 Subject: [PATCH 22/25] Code coverage and improve tests --- ...trolModuleStandalone.sol.func-sort-c.html} | 32 +- ...cessControlModuleStandalone.sol.func.html} | 32 +- ...cessControlModuleStandalone.sol.gcov.html} | 99 +- .../dev/Rules/src/modules}/index-sort-b.html | 46 +- .../dev/Rules/src/modules}/index-sort-f.html | 46 +- .../dev/Rules/src/modules}/index-sort-l.html | 46 +- .../dev/Rules/src/modules}/index.html | 46 +- doc/coverage/coverage/index-sort-b.html | 144 +- doc/coverage/coverage/index-sort-f.html | 142 +- doc/coverage/coverage/index-sort-l.html | 144 +- doc/coverage/coverage/index.html | 146 +- ...ithRuleEngineScript.s.sol.func-sort-c.html | 85 - .../CMTATWithRuleEngineScript.s.sol.func.html | 85 - .../CMTATWithRuleEngineScript.s.sol.gcov.html | 128 -- .../RuleEngineScript.s.sol.func-sort-c.html | 85 - .../script/RuleEngineScript.s.sol.func.html | 85 - .../script/RuleEngineScript.s.sol.gcov.html | 121 -- .../coverage/script/index-sort-b.html | 119 -- .../coverage/script/index-sort-f.html | 119 -- .../coverage/script/index-sort-l.html | 119 -- doc/coverage/coverage/script/index.html | 119 -- .../RuleEngineOperation.sol.func-sort-c.html | 125 -- .../modules/RuleEngineOperation.sol.func.html | 125 -- .../modules/RuleEngineOperation.sol.gcov.html | 255 --- .../RuleEngineValidation.sol.func-sort-c.html | 89 - .../RuleEngineValidation.sol.func.html | 89 - .../RuleEngineValidation.sol.gcov.html | 147 -- ...ngineValidationCommon.sol.func-sort-c.html | 121 -- .../RuleEngineValidationCommon.sol.func.html | 121 -- .../coverage/src/modules/index-sort-b.html | 143 -- .../coverage/src/modules/index-sort-f.html | 143 -- .../coverage/src/modules/index-sort-l.html | 143 -- doc/coverage/coverage/src/modules/index.html | 143 -- ...leConditionalTransfer.sol.func-sort-c.html | 153 -- .../RuleConditionalTransfer.sol.func.html | 153 -- .../RuleConditionalTransfer.sol.gcov.html | 486 ------ ...ionalTransferOperator.sol.func-sort-c.html | 161 -- ...eConditionalTransferOperator.sol.func.html | 161 -- ...eConditionalTransferOperator.sol.gcov.html | 558 ------ .../src/rules/operation/index-sort-b.html | 107 -- .../src/rules/operation/index-sort-f.html | 107 -- .../src/rules/operation/index-sort-l.html | 107 -- .../coverage/src/rules/operation/index.html | 107 -- .../RuleBlacklist.sol.func-sort-c.html | 97 - .../validation/RuleBlacklist.sol.func.html | 97 - .../validation/RuleSanctionList.sol.gcov.html | 250 --- .../RuleWhitelist.sol.func-sort-c.html | 89 - .../validation/RuleWhitelist.sol.func.html | 89 - .../validation/RuleWhitelist.sol.gcov.html | 125 -- .../RuleWhitelistWrapper.sol.func-sort-c.html | 105 -- .../RuleWhitelistWrapper.sol.func.html | 105 -- .../RuleWhitelistWrapper.sol.gcov.html | 215 --- .../RuleAddressList.sol.func-sort-c.html | 129 -- .../RuleAddressList.sol.func.html | 129 -- ...leAddressListInternal.sol.func-sort-c.html | 105 -- .../RuleAddressListInternal.sol.func.html | 105 -- .../RuleAddressListInternal.sol.gcov.html | 186 -- .../RuleAddressList/index-sort-b.html | 119 -- .../RuleAddressList/index-sort-f.html | 119 -- .../RuleAddressList/index-sort-l.html | 119 -- .../abstract/RuleAddressList/index.html | 119 -- .../RuleValidateTransfer.sol.func-sort-c.html | 85 - .../RuleValidateTransfer.sol.func.html | 85 - .../RuleValidateTransfer.sol.gcov.html | 110 -- .../validation/abstract/index-sort-b.html | 119 -- .../validation/abstract/index-sort-f.html | 119 -- .../validation/abstract/index-sort-l.html | 119 -- .../src/rules/validation/abstract/index.html | 119 -- .../src/rules/validation/index-sort-b.html | 143 -- .../src/rules/validation/index-sort-f.html | 143 -- .../src/rules/validation/index-sort-l.html | 143 -- .../coverage/src/rules/validation/index.html | 143 -- .../utils/RuleCTDeployment.sol.gcov.html | 142 -- .../CMTATDeployment.sol.func-sort-c.html | 85 - .../test/utils/CMTATDeployment.sol.func.html | 85 - .../test/utils/CMTATDeployment.sol.gcov.html | 129 -- .../utils/SanctionListOracle.sol.gcov.html | 109 -- .../RuleBlacklist.sol.func-sort-c.html | 121 ++ .../validation/RuleBlacklist.sol.func.html | 121 ++ .../validation/RuleBlacklist.sol.gcov.html | 263 +++ .../RuleSanctionsList.sol.func-sort-c.html | 145 ++ .../RuleSanctionsList.sol.func.html | 145 ++ .../RuleSanctionsList.sol.gcov.html | 343 ++++ .../RuleWhitelist.sol.func-sort-c.html} | 58 +- .../RuleWhitelist.sol.func.html} | 60 +- .../RuleWhitelist.sol.gcov.html} | 328 ++-- .../RuleWhitelistWrapper.sol.func-sort-c.html | 125 ++ .../RuleWhitelistWrapper.sol.func.html | 125 ++ .../RuleWhitelistWrapper.sol.gcov.html} | 408 ++--- .../RuleAddressSet.sol.func-sort-c.html} | 60 +- .../RuleAddressSet.sol.func.html} | 62 +- .../RuleAddressSet.sol.gcov.html} | 363 ++-- ...leAddressSetInternal.sol.func-sort-c.html} | 40 +- .../RuleAddressSetInternal.sol.func.html} | 40 +- .../RuleAddressSetInternal.sol.gcov.html} | 181 +- .../RuleAddressSet}/index-sort-b.html | 42 +- .../RuleAddressSet}/index-sort-f.html | 42 +- .../RuleAddressSet}/index-sort-l.html | 42 +- .../abstract/RuleAddressSet}/index.html | 42 +- ...RuleValidateTransfer.sol.func-sort-c.html} | 34 +- .../RuleValidateTransfer.sol.func.html} | 34 +- .../RuleValidateTransfer.sol.gcov.html} | 196 +-- .../RuleWhitelistCommon.sol.func-sort-c.html} | 44 +- .../RuleWhitelistCommon.sol.func.html} | 44 +- .../RuleWhitelistCommon.sol.gcov.html | 200 +++ .../abstract}/index-sort-b.html | 52 +- .../abstract}/index-sort-f.html | 52 +- .../abstract}/index-sort-l.html | 52 +- .../utils => validation/abstract}/index.html | 52 +- .../{src => validation}/index-sort-b.html | 74 +- .../{src => validation}/index-sort-f.html | 74 +- .../{src => validation}/index-sort-l.html | 74 +- .../coverage/{src => validation}/index.html | 74 +- doc/coverage/lcov.info | 1555 ++++++----------- src/rules/validation/RuleWhitelistWrapper.sol | 2 +- test/RuleBlacklist/RuleBlacklist.t.sol | 22 + .../RuleSanctionListDeploymentTest.t.sol | 29 + .../RuleSanctionListTest.t.sol | 8 + test/RuleWhitelist/RuleWhitelist.t.sol | 17 + test/RuleWhitelist/WhitelistWrapper.t.sol | 179 ++ 120 files changed, 4090 insertions(+), 11846 deletions(-) rename doc/coverage/coverage/{src/rules/validation/abstract/RuleWhitelistCommon.sol.func.html => home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func-sort-c.html} (58%) rename doc/coverage/coverage/{src/rules/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html => home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func.html} (56%) rename doc/coverage/coverage/{src/rules/validation/abstract/RuleWhitelistCommon.sol.gcov.html => home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.gcov.html} (52%) rename doc/coverage/coverage/{src/rules/operation/abstract => home/ryan/Pictures/dev/Rules/src/modules}/index-sort-b.html (57%) rename doc/coverage/coverage/{src/rules/operation/abstract => home/ryan/Pictures/dev/Rules/src/modules}/index-sort-f.html (57%) rename doc/coverage/coverage/{src/rules/operation/abstract => home/ryan/Pictures/dev/Rules/src/modules}/index-sort-l.html (56%) rename doc/coverage/coverage/{src/rules/operation/abstract => home/ryan/Pictures/dev/Rules/src/modules}/index.html (57%) delete mode 100644 doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html delete mode 100644 doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html delete mode 100644 doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html delete mode 100644 doc/coverage/coverage/script/RuleEngineScript.s.sol.func-sort-c.html delete mode 100644 doc/coverage/coverage/script/RuleEngineScript.s.sol.func.html delete mode 100644 doc/coverage/coverage/script/RuleEngineScript.s.sol.gcov.html delete mode 100644 doc/coverage/coverage/script/index-sort-b.html delete mode 100644 doc/coverage/coverage/script/index-sort-f.html delete mode 100644 doc/coverage/coverage/script/index-sort-l.html delete mode 100644 doc/coverage/coverage/script/index.html delete mode 100644 doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html delete mode 100644 doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func.html delete mode 100644 doc/coverage/coverage/src/modules/RuleEngineOperation.sol.gcov.html delete mode 100644 doc/coverage/coverage/src/modules/RuleEngineValidation.sol.func-sort-c.html delete mode 100644 doc/coverage/coverage/src/modules/RuleEngineValidation.sol.func.html delete mode 100644 doc/coverage/coverage/src/modules/RuleEngineValidation.sol.gcov.html delete mode 100644 doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.func-sort-c.html delete mode 100644 doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.func.html delete mode 100644 doc/coverage/coverage/src/modules/index-sort-b.html delete mode 100644 doc/coverage/coverage/src/modules/index-sort-f.html delete mode 100644 doc/coverage/coverage/src/modules/index-sort-l.html delete mode 100644 doc/coverage/coverage/src/modules/index.html delete mode 100644 doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.func-sort-c.html delete mode 100644 doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.func.html delete mode 100644 doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.gcov.html delete mode 100644 doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func-sort-c.html delete mode 100644 doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func.html delete mode 100644 doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.gcov.html delete mode 100644 doc/coverage/coverage/src/rules/operation/index-sort-b.html delete mode 100644 doc/coverage/coverage/src/rules/operation/index-sort-f.html delete mode 100644 doc/coverage/coverage/src/rules/operation/index-sort-l.html delete mode 100644 doc/coverage/coverage/src/rules/operation/index.html delete mode 100644 doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.func-sort-c.html delete mode 100644 doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.func.html delete mode 100644 doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.gcov.html delete mode 100644 doc/coverage/coverage/src/rules/validation/RuleWhitelist.sol.func-sort-c.html delete mode 100644 doc/coverage/coverage/src/rules/validation/RuleWhitelist.sol.func.html delete mode 100644 doc/coverage/coverage/src/rules/validation/RuleWhitelist.sol.gcov.html delete mode 100644 doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func-sort-c.html delete mode 100644 doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func.html delete mode 100644 doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.gcov.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func-sort-c.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func-sort-c.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.gcov.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-b.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-f.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-l.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.gcov.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/index-sort-b.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/index-sort-f.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/index-sort-l.html delete mode 100644 doc/coverage/coverage/src/rules/validation/abstract/index.html delete mode 100644 doc/coverage/coverage/src/rules/validation/index-sort-b.html delete mode 100644 doc/coverage/coverage/src/rules/validation/index-sort-f.html delete mode 100644 doc/coverage/coverage/src/rules/validation/index-sort-l.html delete mode 100644 doc/coverage/coverage/src/rules/validation/index.html delete mode 100644 doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.gcov.html delete mode 100644 doc/coverage/coverage/test/utils/CMTATDeployment.sol.func-sort-c.html delete mode 100644 doc/coverage/coverage/test/utils/CMTATDeployment.sol.func.html delete mode 100644 doc/coverage/coverage/test/utils/CMTATDeployment.sol.gcov.html delete mode 100644 doc/coverage/coverage/test/utils/SanctionListOracle.sol.gcov.html create mode 100644 doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/validation/RuleBlacklist.sol.func.html create mode 100644 doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html create mode 100644 doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/validation/RuleSanctionsList.sol.func.html create mode 100644 doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html rename doc/coverage/coverage/{src/RuleEngine.sol.func-sort-c.html => validation/RuleWhitelist.sol.func-sort-c.html} (54%) rename doc/coverage/coverage/{src/RuleEngine.sol.func.html => validation/RuleWhitelist.sol.func.html} (54%) rename doc/coverage/coverage/{src/modules/RuleEngineValidationCommon.sol.gcov.html => validation/RuleWhitelist.sol.gcov.html} (54%) create mode 100644 doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html rename doc/coverage/coverage/{src/RuleEngine.sol.gcov.html => validation/RuleWhitelistWrapper.sol.gcov.html} (55%) rename doc/coverage/coverage/{src/rules/validation/RuleSanctionList.sol.func-sort-c.html => validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html} (54%) rename doc/coverage/coverage/{src/rules/validation/RuleSanctionList.sol.func.html => validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html} (54%) rename doc/coverage/coverage/{src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html => validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html} (58%) rename doc/coverage/coverage/{test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func-sort-c.html => validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html} (57%) rename doc/coverage/coverage/{test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func.html => validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html} (57%) rename doc/coverage/coverage/{src/rules/validation/RuleBlacklist.sol.gcov.html => validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html} (54%) rename doc/coverage/coverage/{test/RuleConditionalTransfer/utils => validation/abstract/RuleAddressSet}/index-sort-b.html (71%) rename doc/coverage/coverage/{test/RuleConditionalTransfer/utils => validation/abstract/RuleAddressSet}/index-sort-f.html (71%) rename doc/coverage/coverage/{test/RuleConditionalTransfer/utils => validation/abstract/RuleAddressSet}/index-sort-l.html (71%) rename doc/coverage/coverage/{test/RuleConditionalTransfer/utils => validation/abstract/RuleAddressSet}/index.html (71%) rename doc/coverage/coverage/{test/utils/SanctionListOracle.sol.func-sort-c.html => validation/abstract/RuleValidateTransfer.sol.func-sort-c.html} (63%) rename doc/coverage/coverage/{test/utils/SanctionListOracle.sol.func.html => validation/abstract/RuleValidateTransfer.sol.func.html} (63%) rename doc/coverage/coverage/{src/modules/RuleInternal.sol.gcov.html => validation/abstract/RuleValidateTransfer.sol.gcov.html} (50%) rename doc/coverage/coverage/{src/modules/RuleInternal.sol.func-sort-c.html => validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html} (57%) rename doc/coverage/coverage/{src/modules/RuleInternal.sol.func.html => validation/abstract/RuleWhitelistCommon.sol.func.html} (57%) create mode 100644 doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html rename doc/coverage/coverage/{test/utils => validation/abstract}/index-sort-b.html (71%) rename doc/coverage/coverage/{test/utils => validation/abstract}/index-sort-f.html (71%) rename doc/coverage/coverage/{test/utils => validation/abstract}/index-sort-l.html (71%) rename doc/coverage/coverage/{test/utils => validation/abstract}/index.html (71%) rename doc/coverage/coverage/{src => validation}/index-sort-b.html (52%) rename doc/coverage/coverage/{src => validation}/index-sort-f.html (52%) rename doc/coverage/coverage/{src => validation}/index-sort-l.html (52%) rename doc/coverage/coverage/{src => validation}/index.html (52%) create mode 100644 test/RuleWhitelist/WhitelistWrapper.t.sol diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func-sort-c.html similarity index 58% rename from doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func.html rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func-sort-c.html index b899bc1..d863117 100644 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func-sort-c.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - src/rules/validation/abstract/RuleWhitelistCommon.sol - functions - + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol - functions + - + - +
LCOV - code coverage report
- + @@ -37,7 +37,7 @@ - + @@ -49,38 +49,38 @@ - - + + - +
Current view:top level - src/rules/validation/abstract - RuleWhitelistCommon.sol (source / functions)top level - home/ryan/Pictures/dev/Rules/src/modules - AccessControlModuleStandalone.sol (source / functions) Hit
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions: 2 Branches:4433 100.0 %
- - + + - - + + - - + +

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

- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func.html similarity index 56% rename from doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func.html index d40fb06..6d00c42 100644 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - src/rules/validation/abstract/RuleWhitelistCommon.sol - functions - + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol - functions + - + - +
LCOV - code coverage report
- + @@ -37,7 +37,7 @@ - + @@ -49,38 +49,38 @@ - - + + - +
Current view:top level - src/rules/validation/abstract - RuleWhitelistCommon.sol (source / functions)top level - home/ryan/Pictures/dev/Rules/src/modules - AccessControlModuleStandalone.sol (source / functions) Hit
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions: 2 Branches:4433 100.0 %
- - + + - - + + - - + +

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

- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.gcov.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.gcov.html similarity index 52% rename from doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.gcov.html rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.gcov.html index 20b596c..cd3a87d 100644 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleWhitelistCommon.sol.gcov.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.gcov.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - src/rules/validation/abstract/RuleWhitelistCommon.sol - + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol + - + - +
LCOV - code coverage report
- + @@ -37,7 +37,7 @@ - + @@ -49,16 +49,16 @@ - - + + - +
Current view:top level - src/rules/validation/abstract - RuleWhitelistCommon.sol (source / functions)top level - home/ryan/Pictures/dev/Rules/src/modules - AccessControlModuleStandalone.sol (source / functions) Hit
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions: 2 Branches:4433 100.0 %
@@ -69,47 +69,52 @@ @@ -117,7 +122,7 @@
           Branch data     Line data    Source code
-       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       1                 :            : //SPDX-License-Identifier: MPL-2.0
        2                 :            : 
        3                 :            : pragma solidity ^0.8.20;
        4                 :            : 
-       5                 :            : import "./RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol";
-       6                 :            : import "./RuleValidateTransfer.sol";
+       5                 :            : /* ==== OpenZeppelin === */
+       6                 :            : import {AccessControl} from "OZ/access/AccessControl.sol";
        7                 :            : 
-       8                 :            : abstract contract RuleWhitelistCommon is
-       9                 :            :     RuleValidateTransfer,
-      10                 :            :     RuleWhitelistInvariantStorage
-      11                 :            : {
-      12                 :            :     /**
-      13                 :            :      * @notice To know if the restriction code is valid for this rule or not
-      14                 :            :      * @param _restrictionCode The target restriction code
-      15                 :            :      * @return true if the restriction code is known, false otherwise
-      16                 :            :      **/
-      17                 :            :     function canReturnTransferRestrictionCode(
-      18                 :            :         uint8 _restrictionCode
-      19                 :            :     ) external pure override returns (bool) {
-      20                 :         12 :         return
-      21                 :         12 :             _restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED ||
-      22                 :          6 :             _restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED;
-      23                 :            :     }
-      24                 :            : 
-      25                 :            :     /**
-      26                 :            :      * @notice Return the corresponding message
-      27                 :            :      * @param _restrictionCode The target restriction code
-      28                 :            :      * @return true if the transfer is valid, false otherwise
-      29                 :            :      **/
-      30                 :            :     function messageForTransferRestriction(
-      31                 :            :         uint8 _restrictionCode
-      32                 :            :     ) external pure override returns (string memory) {
-      33         [ +  + ]:         10 :         if (_restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) {
-      34                 :          6 :             return TEXT_ADDRESS_FROM_NOT_WHITELISTED;
-      35         [ +  + ]:          4 :         } else if (_restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) {
-      36                 :          3 :             return TEXT_ADDRESS_TO_NOT_WHITELISTED;
-      37                 :            :         } else {
-      38                 :          1 :             return TEXT_CODE_NOT_FOUND;
-      39                 :            :         }
-      40                 :            :     }
-      41                 :            : }
+       8                 :            : abstract contract AccessControlModuleStandalone is AccessControl {
+       9                 :            :     error AccessControlModuleStandalone_AddressZeroNotAllowed();
+      10                 :            :     /* ============ Constructor ============ */
+      11                 :            :     /**
+      12                 :            :      * @notice Assigns the provided address as the default admin.
+      13                 :            :      * @dev
+      14                 :            :      *  - Reverts if `admin` is the zero address.
+      15                 :            :      *  - Grants `DEFAULT_ADMIN_ROLE` to `admin`.
+      16                 :            :      *    The return value of `_grantRole` is intentionally ignored, as it returns `false`
+      17                 :            :      *    only when the role was already granted.
+      18                 :            :      *
+      19                 :            :      * @param admin The address that will receive the `DEFAULT_ADMIN_ROLE`.
+      20                 :            :      */
+      21                 :            : 
+      22                 :        161 :     constructor(address admin) {
+      23            [ + ]:        161 :         if (admin == address(0)) {
+      24                 :          4 :             revert AccessControlModuleStandalone_AddressZeroNotAllowed();
+      25                 :            :         }
+      26                 :            :         // we don't check the return value
+      27                 :            :         // _grantRole attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
+      28                 :            :         // return false only if the admin has already the role
+      29                 :        157 :         _grantRole(DEFAULT_ADMIN_ROLE, admin);
+      30                 :            :     }
+      31                 :            : 
+      32                 :            :     /*//////////////////////////////////////////////////////////////
+      33                 :            :                             PUBLIC/EXTERNAL FUNCTIONS
+      34                 :            :     //////////////////////////////////////////////////////////////*/
+      35                 :            :     /**
+      36                 :            :      * @dev Returns `true` if `account` has been granted `role`.
+      37                 :            :      */
+      38                 :        228 :     function hasRole(bytes32 role, address account) public view virtual override(AccessControl) returns (bool) {
+      39                 :            :         // The Default Admin has all roles
+      40         [ +  + ]:        328 :         if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
+      41                 :        152 :             return true;
+      42                 :            :         } else {
+      43                 :        176 :             return AccessControl.hasRole(role, account);
+      44                 :            :         }
+      45                 :            :     }
+      46                 :            : }
 
- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-b.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-b.html similarity index 57% rename from doc/coverage/coverage/src/rules/operation/abstract/index-sort-b.html rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-b.html index e47a898..dd04fd8 100644 --- a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-b.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-b.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - src/rules/operation/abstract - + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules + - + - +
LCOV - code coverage report
- + @@ -31,17 +31,17 @@ - - + + - + - - + + @@ -49,16 +49,16 @@ - - + + - +
Current view:top level - src/rules/operation/abstracttop level - /home/ryan/Pictures/dev/Rules/src/modules Hitlcov.info Lines:11311388 100.0 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:202022 100.0 %
Branches:313133 100.0 %
@@ -76,29 +76,29 @@ - Filename Sort by name - Line Coverage Sort by line coverage - Functions Sort by function coverage - Branches Sort by branch coverage + Filename Sort by name + Line Coverage Sort by line coverage + Functions Sort by function coverage + Branches Sort by branch coverage - RuleConditionalTransferOperator.sol + AccessControlModuleStandalone.sol -
100.0%
+
100.0%
100.0 % - 113 / 113 + 8 / 8 100.0 % - 20 / 20 + 2 / 2 100.0 % - 31 / 31 + 3 / 3

- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-f.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-f.html similarity index 57% rename from doc/coverage/coverage/src/rules/operation/abstract/index-sort-f.html rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-f.html index aaae3fc..a1ecac1 100644 --- a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-f.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-f.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - src/rules/operation/abstract - + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules + - + - +
LCOV - code coverage report
- + @@ -31,17 +31,17 @@ - - + + - + - - + + @@ -49,16 +49,16 @@ - - + + - +
Current view:top level - src/rules/operation/abstracttop level - /home/ryan/Pictures/dev/Rules/src/modules Hitlcov.info Lines:11311388 100.0 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:202022 100.0 %
Branches:313133 100.0 %
@@ -76,29 +76,29 @@ - Filename Sort by name - Line Coverage Sort by line coverage - Functions Sort by function coverage - Branches Sort by branch coverage + Filename Sort by name + Line Coverage Sort by line coverage + Functions Sort by function coverage + Branches Sort by branch coverage - RuleConditionalTransferOperator.sol + AccessControlModuleStandalone.sol -
100.0%
+
100.0%
100.0 % - 113 / 113 + 8 / 8 100.0 % - 20 / 20 + 2 / 2 100.0 % - 31 / 31 + 3 / 3

- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-l.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-l.html similarity index 56% rename from doc/coverage/coverage/src/rules/operation/abstract/index-sort-l.html rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-l.html index 2ec5b2c..f87dc66 100644 --- a/doc/coverage/coverage/src/rules/operation/abstract/index-sort-l.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-l.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - src/rules/operation/abstract - + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules + - + - +
LCOV - code coverage report
- + @@ -31,17 +31,17 @@ - - + + - + - - + + @@ -49,16 +49,16 @@ - - + + - +
Current view:top level - src/rules/operation/abstracttop level - /home/ryan/Pictures/dev/Rules/src/modules Hitlcov.info Lines:11311388 100.0 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:202022 100.0 %
Branches:313133 100.0 %
@@ -76,29 +76,29 @@ - Filename Sort by name - Line Coverage Sort by line coverage - Functions Sort by function coverage - Branches Sort by branch coverage + Filename Sort by name + Line Coverage Sort by line coverage + Functions Sort by function coverage + Branches Sort by branch coverage - RuleConditionalTransferOperator.sol + AccessControlModuleStandalone.sol -
100.0%
+
100.0%
100.0 % - 113 / 113 + 8 / 8 100.0 % - 20 / 20 + 2 / 2 100.0 % - 31 / 31 + 3 / 3

- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/src/rules/operation/abstract/index.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index.html similarity index 57% rename from doc/coverage/coverage/src/rules/operation/abstract/index.html rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index.html index 1428f56..47daaf2 100644 --- a/doc/coverage/coverage/src/rules/operation/abstract/index.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - src/rules/operation/abstract - + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules + - + - +
LCOV - code coverage report
- + @@ -31,17 +31,17 @@ - - + + - + - - + + @@ -49,16 +49,16 @@ - - + + - +
Current view:top level - src/rules/operation/abstracttop level - /home/ryan/Pictures/dev/Rules/src/modules Hitlcov.info Lines:11311388 100.0 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:202022 100.0 %
Branches:313133 100.0 %
@@ -76,29 +76,29 @@ - Filename Sort by name - Line Coverage Sort by line coverage - Functions Sort by function coverage - Branches Sort by branch coverage + Filename Sort by name + Line Coverage Sort by line coverage + Functions Sort by function coverage + Branches Sort by branch coverage - RuleConditionalTransferOperator.sol + AccessControlModuleStandalone.sol -
100.0%
+
100.0%
100.0 % - 113 / 113 + 8 / 8 100.0 % - 20 / 20 + 2 / 2 100.0 % - 31 / 31 + 3 / 3

- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/index-sort-b.html b/doc/coverage/coverage/index-sort-b.html index 79c22e9..abdd86e 100644 --- a/doc/coverage/coverage/index-sort-b.html +++ b/doc/coverage/coverage/index-sort-b.html @@ -31,27 +31,27 @@ lcov.info Lines: - 479 - 511 - 93.7 % + 206 + 247 + 83.4 % Date: - 2024-12-20 10:41:14 + 2025-12-03 14:12:50 Functions: - 117 - 125 - 93.6 % + 56 + 73 + 76.7 % Branches: - 126 - 128 - 98.4 % + 57 + 68 + 83.8 % @@ -82,124 +82,52 @@ Branches Sort by branch coverage - script + validation/abstract -
0.0%
+
75.9%75.9%
- 0.0 % - 0 / 26 - 0.0 % - 0 / 2 - 0.0 % - 0 / 2 - - - test/RuleConditionalTransfer/utils - -
100.0%
- - 100.0 % - 10 / 10 - 100.0 % - 1 / 1 - - - 0 / 0 - - - test/utils - -
85.7%85.7%
- - 85.7 % - 6 / 7 + 75.9 % + 22 / 29 + 70.0 % + 7 / 10 80.0 % - 4 / 5 - - - 0 / 0 - - - src/rules/validation/abstract - -
100.0%
- - 100.0 % - 10 / 10 - 100.0 % - 3 / 3 - 100.0 % - 4 / 4 - - - src/rules/validation/abstract/RuleAddressList - -
97.8%97.8%
- - 97.8 % - 44 / 45 - 94.4 % - 17 / 18 - 100.0 % - 6 / 6 + 8 / 10 - src + validation -
97.4%97.4%
+
81.7%81.7%
- 97.4 % - 38 / 39 - 88.9 % - 8 / 9 - 100.0 % - 8 / 8 + 81.7 % + 134 / 164 + 72.7 % + 32 / 44 + 83.0 % + 44 / 53 - src/modules + validation/abstract/RuleAddressSet -
100.0%
+
91.3%91.3%
+ 91.3 % + 42 / 46 + 88.2 % + 15 / 17 100.0 % - 81 / 81 - 100.0 % - 27 / 27 - 100.0 % - 12 / 12 + 2 / 2 - src/rules/operation/abstract + /home/ryan/Pictures/dev/Rules/src/modules
100.0%
100.0 % - 113 / 113 - 100.0 % - 20 / 20 - 100.0 % - 31 / 31 - - - src/rules/validation - -
97.3%97.3%
- - 97.3 % - 72 / 74 - 90.9 % - 20 / 22 + 8 / 8 100.0 % - 32 / 32 - - - src/rules/operation - -
99.1%99.1%
- - 99.1 % - 105 / 106 - 94.4 % - 17 / 18 + 2 / 2 100.0 % - 33 / 33 + 3 / 3 diff --git a/doc/coverage/coverage/index-sort-f.html b/doc/coverage/coverage/index-sort-f.html index 4c104bd..ab33f1e 100644 --- a/doc/coverage/coverage/index-sort-f.html +++ b/doc/coverage/coverage/index-sort-f.html @@ -31,27 +31,27 @@ lcov.info Lines: - 479 - 511 - 93.7 % + 206 + 247 + 83.4 % Date: - 2024-12-20 10:41:14 + 2025-12-03 14:12:50 Functions: - 117 - 125 - 93.6 % + 56 + 73 + 76.7 % Branches: - 126 - 128 - 98.4 % + 57 + 68 + 83.8 % @@ -82,124 +82,52 @@ Branches Sort by branch coverage - script + validation/abstract -
0.0%
+
75.9%75.9%
- 0.0 % - 0 / 26 - 0.0 % - 0 / 2 - 0.0 % - 0 / 2 - - - test/utils - -
85.7%85.7%
- - 85.7 % - 6 / 7 + 75.9 % + 22 / 29 + 70.0 % + 7 / 10 80.0 % - 4 / 5 - - - 0 / 0 - - - src - -
97.4%97.4%
- - 97.4 % - 38 / 39 - 88.9 % - 8 / 9 - 100.0 % - 8 / 8 + 8 / 10 - src/rules/validation + validation -
97.3%97.3%
+
81.7%81.7%
- 97.3 % - 72 / 74 - 90.9 % - 20 / 22 - 100.0 % - 32 / 32 - - - src/rules/validation/abstract/RuleAddressList - -
97.8%97.8%
- - 97.8 % - 44 / 45 - 94.4 % - 17 / 18 - 100.0 % - 6 / 6 + 81.7 % + 134 / 164 + 72.7 % + 32 / 44 + 83.0 % + 44 / 53 - src/rules/operation + validation/abstract/RuleAddressSet -
99.1%99.1%
+
91.3%91.3%
- 99.1 % - 105 / 106 - 94.4 % - 17 / 18 + 91.3 % + 42 / 46 + 88.2 % + 15 / 17 100.0 % - 33 / 33 + 2 / 2 - test/RuleConditionalTransfer/utils + /home/ryan/Pictures/dev/Rules/src/modules
100.0%
100.0 % - 10 / 10 - 100.0 % - 1 / 1 - - - 0 / 0 - - - src/rules/validation/abstract - -
100.0%
- + 8 / 8 100.0 % - 10 / 10 + 2 / 2 100.0 % 3 / 3 - 100.0 % - 4 / 4 - - - src/rules/operation/abstract - -
100.0%
- - 100.0 % - 113 / 113 - 100.0 % - 20 / 20 - 100.0 % - 31 / 31 - - - src/modules - -
100.0%
- - 100.0 % - 81 / 81 - 100.0 % - 27 / 27 - 100.0 % - 12 / 12 diff --git a/doc/coverage/coverage/index-sort-l.html b/doc/coverage/coverage/index-sort-l.html index f352c82..fc88c8b 100644 --- a/doc/coverage/coverage/index-sort-l.html +++ b/doc/coverage/coverage/index-sort-l.html @@ -31,27 +31,27 @@ lcov.info Lines: - 479 - 511 - 93.7 % + 206 + 247 + 83.4 % Date: - 2024-12-20 10:41:14 + 2025-12-03 14:12:50 Functions: - 117 - 125 - 93.6 % + 56 + 73 + 76.7 % Branches: - 126 - 128 - 98.4 % + 57 + 68 + 83.8 % @@ -82,124 +82,52 @@ Branches Sort by branch coverage - script + validation/abstract -
0.0%
+
75.9%75.9%
- 0.0 % - 0 / 26 - 0.0 % - 0 / 2 - 0.0 % - 0 / 2 - - - test/utils - -
85.7%85.7%
- - 85.7 % - 6 / 7 + 75.9 % + 22 / 29 + 70.0 % + 7 / 10 80.0 % - 4 / 5 - - - 0 / 0 - - - src/rules/validation - -
97.3%97.3%
- - 97.3 % - 72 / 74 - 90.9 % - 20 / 22 - 100.0 % - 32 / 32 - - - src - -
97.4%97.4%
- - 97.4 % - 38 / 39 - 88.9 % - 8 / 9 - 100.0 % - 8 / 8 - - - src/rules/validation/abstract/RuleAddressList - -
97.8%97.8%
- - 97.8 % - 44 / 45 - 94.4 % - 17 / 18 - 100.0 % - 6 / 6 - - - src/rules/operation - -
99.1%99.1%
- - 99.1 % - 105 / 106 - 94.4 % - 17 / 18 - 100.0 % - 33 / 33 + 8 / 10 - src/rules/validation/abstract + validation -
100.0%
+
81.7%81.7%
- 100.0 % - 10 / 10 - 100.0 % - 3 / 3 - 100.0 % - 4 / 4 + 81.7 % + 134 / 164 + 72.7 % + 32 / 44 + 83.0 % + 44 / 53 - test/RuleConditionalTransfer/utils + validation/abstract/RuleAddressSet -
100.0%
+
91.3%91.3%
+ 91.3 % + 42 / 46 + 88.2 % + 15 / 17 100.0 % - 10 / 10 - 100.0 % - 1 / 1 - - - 0 / 0 + 2 / 2 - src/modules + /home/ryan/Pictures/dev/Rules/src/modules
100.0%
100.0 % - 81 / 81 - 100.0 % - 27 / 27 - 100.0 % - 12 / 12 - - - src/rules/operation/abstract - -
100.0%
- - 100.0 % - 113 / 113 + 8 / 8 100.0 % - 20 / 20 + 2 / 2 100.0 % - 31 / 31 + 3 / 3 diff --git a/doc/coverage/coverage/index.html b/doc/coverage/coverage/index.html index 92f429f..38a03fc 100644 --- a/doc/coverage/coverage/index.html +++ b/doc/coverage/coverage/index.html @@ -31,27 +31,27 @@ lcov.info Lines: - 479 - 511 - 93.7 % + 206 + 247 + 83.4 % Date: - 2024-12-20 10:41:14 + 2025-12-03 14:12:50 Functions: - 117 - 125 - 93.6 % + 56 + 73 + 76.7 % Branches: - 126 - 128 - 98.4 % + 57 + 68 + 83.8 % @@ -82,124 +82,52 @@ Branches Sort by branch coverage - script - -
0.0%
- - 0.0 % - 0 / 26 - 0.0 % - 0 / 2 - 0.0 % - 0 / 2 - - - src - -
97.4%97.4%
- - 97.4 % - 38 / 39 - 88.9 % - 8 / 9 - 100.0 % - 8 / 8 - - - src/modules - -
100.0%
- - 100.0 % - 81 / 81 - 100.0 % - 27 / 27 - 100.0 % - 12 / 12 - - - src/rules/operation - -
99.1%99.1%
- - 99.1 % - 105 / 106 - 94.4 % - 17 / 18 - 100.0 % - 33 / 33 - - - src/rules/operation/abstract + /home/ryan/Pictures/dev/Rules/src/modules
100.0%
100.0 % - 113 / 113 - 100.0 % - 20 / 20 - 100.0 % - 31 / 31 - - - src/rules/validation - -
97.3%97.3%
- - 97.3 % - 72 / 74 - 90.9 % - 20 / 22 - 100.0 % - 32 / 32 - - - src/rules/validation/abstract - -
100.0%
- + 8 / 8 100.0 % - 10 / 10 + 2 / 2 100.0 % 3 / 3 - 100.0 % - 4 / 4 - src/rules/validation/abstract/RuleAddressList + validation -
97.8%97.8%
+
81.7%81.7%
- 97.8 % - 44 / 45 - 94.4 % - 17 / 18 - 100.0 % - 6 / 6 + 81.7 % + 134 / 164 + 72.7 % + 32 / 44 + 83.0 % + 44 / 53 - test/RuleConditionalTransfer/utils + validation/abstract -
100.0%
+
75.9%75.9%
- 100.0 % - 10 / 10 - 100.0 % - 1 / 1 - - - 0 / 0 + 75.9 % + 22 / 29 + 70.0 % + 7 / 10 + 80.0 % + 8 / 10 - test/utils + validation/abstract/RuleAddressSet -
85.7%85.7%
+
91.3%91.3%
- 85.7 % - 6 / 7 - 80.0 % - 4 / 5 - - - 0 / 0 + 91.3 % + 42 / 46 + 88.2 % + 15 / 17 + 100.0 % + 2 / 2 diff --git a/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html b/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html deleted file mode 100644 index 9ab57f2..0000000 --- a/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - script/CMTATWithRuleEngineScript.s.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - script - CMTATWithRuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0140.0 %
Date:2024-12-20 10:41:14Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
CMTATWithRuleEngineScript.run0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html b/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html deleted file mode 100644 index 6dcfe5d..0000000 --- a/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - script/CMTATWithRuleEngineScript.s.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - script - CMTATWithRuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0140.0 %
Date:2024-12-20 10:41:14Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
CMTATWithRuleEngineScript.run0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html b/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html deleted file mode 100644 index 0600472..0000000 --- a/doc/coverage/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - - LCOV - lcov.info - script/CMTATWithRuleEngineScript.s.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - script - CMTATWithRuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0140.0 %
Date:2024-12-20 10:41:14Functions:010.0 %
Branches:00-
-
- - - - - - - - -

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

Function Name Sort by function nameHit count Sort by hit count
RuleEngineScript.run0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/script/RuleEngineScript.s.sol.func.html b/doc/coverage/coverage/script/RuleEngineScript.s.sol.func.html deleted file mode 100644 index 29ef250..0000000 --- a/doc/coverage/coverage/script/RuleEngineScript.s.sol.func.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - script/RuleEngineScript.s.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - script - RuleEngineScript.s.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2024-12-20 10:41:14Functions:010.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - -

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

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

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 10.0 %0 / 2
CMTATWithRuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 140.0 %0 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/script/index-sort-f.html b/doc/coverage/coverage/script/index-sort-f.html deleted file mode 100644 index 89cfad4..0000000 --- a/doc/coverage/coverage/script/index-sort-f.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - LCOV - lcov.info - script - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - scriptHitTotalCoverage
Test:lcov.infoLines:0260.0 %
Date:2024-12-20 10:41:14Functions:020.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
CMTATWithRuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 140.0 %0 / 1-0 / 0
RuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 10.0 %0 / 2
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/script/index-sort-l.html b/doc/coverage/coverage/script/index-sort-l.html deleted file mode 100644 index 0303269..0000000 --- a/doc/coverage/coverage/script/index-sort-l.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - LCOV - lcov.info - script - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - scriptHitTotalCoverage
Test:lcov.infoLines:0260.0 %
Date:2024-12-20 10:41:14Functions:020.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 10.0 %0 / 2
CMTATWithRuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 140.0 %0 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/script/index.html b/doc/coverage/coverage/script/index.html deleted file mode 100644 index 11ddb92..0000000 --- a/doc/coverage/coverage/script/index.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - LCOV - lcov.info - script - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - scriptHitTotalCoverage
Test:lcov.infoLines:0260.0 %
Date:2024-12-20 10:41:14Functions:020.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
CMTATWithRuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 140.0 %0 / 1-0 / 0
RuleEngineScript.s.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 10.0 %0 / 2
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html b/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html deleted file mode 100644 index 260f236..0000000 --- a/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - LCOV - lcov.info - src/modules/RuleEngineOperation.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modules - RuleEngineOperation.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2525100.0 %
Date:2024-12-20 10:41:14Functions:1111100.0 %
Branches:22100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleEngineOperation.ruleOperation1
RuleEngineOperation.getRuleIndexOperation3
RuleEngineOperation.clearRulesOperation4
RuleEngineOperation.removeRuleOperation5
RuleEngineOperation.rulesOperation5
RuleEngineOperation.setRulesOperation11
RuleEngineOperation._clearRulesOperation14
RuleEngineOperation._removeRuleOperation22
RuleEngineOperation.rulesCountOperation41
RuleEngineOperation._operateOnTransfer58
RuleEngineOperation.addRuleOperation85
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func.html b/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func.html deleted file mode 100644 index 323d585..0000000 --- a/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.func.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - LCOV - lcov.info - src/modules/RuleEngineOperation.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modules - RuleEngineOperation.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2525100.0 %
Date:2024-12-20 10:41:14Functions:1111100.0 %
Branches:22100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleEngineOperation._clearRulesOperation14
RuleEngineOperation._operateOnTransfer58
RuleEngineOperation._removeRuleOperation22
RuleEngineOperation.addRuleOperation85
RuleEngineOperation.clearRulesOperation4
RuleEngineOperation.getRuleIndexOperation3
RuleEngineOperation.removeRuleOperation5
RuleEngineOperation.ruleOperation1
RuleEngineOperation.rulesCountOperation41
RuleEngineOperation.rulesOperation5
RuleEngineOperation.setRulesOperation11
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.gcov.html b/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.gcov.html deleted file mode 100644 index 75768bd..0000000 --- a/doc/coverage/coverage/src/modules/RuleEngineOperation.sol.gcov.html +++ /dev/null @@ -1,255 +0,0 @@ - - - - - - - LCOV - lcov.info - src/modules/RuleEngineOperation.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modules - RuleEngineOperation.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2525100.0 %
Date:2024-12-20 10:41:14Functions:1111100.0 %
Branches:22100.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.20;
-       4                 :            : 
-       5                 :            : import "./RuleInternal.sol";
-       6                 :            : import "../interfaces/IRuleEngineOperation.sol";
-       7                 :            : import "../interfaces/IRuleOperation.sol";
-       8                 :            : import "OZ/access/AccessControl.sol";
-       9                 :            : 
-      10                 :            : /**
-      11                 :            :  * @title Implementation of a ruleEngine defined by the CMTAT
-      12                 :            :  */
-      13                 :            : abstract contract RuleEngineOperation is
-      14                 :            :     AccessControl,
-      15                 :            :     RuleInternal,
-      16                 :            :     IRuleEngineOperation
-      17                 :            : {
-      18                 :            :     /// @dev Array of rules
-      19                 :            :     address[] internal _rulesOperation;
-      20                 :            : 
-      21                 :            :     /**
-      22                 :            :      * @notice Set all the rules, will overwrite all the previous rules. \n
-      23                 :            :      * Revert if one rule is a zero address or if the rule is already present
-      24                 :            :      *
-      25                 :            :      */
-      26                 :            :     function setRulesOperation(
-      27                 :            :         address[] calldata rules_
-      28                 :            :     ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
-      29            [ + ]:         11 :         if (_rulesOperation.length > 0) {
-      30                 :         10 :             _clearRulesOperation();
-      31                 :            :         }
-      32                 :         11 :         _setRules(rules_);
-      33                 :          8 :         _rulesOperation = rules_;
-      34                 :            :     }
-      35                 :            : 
-      36                 :            :     /**
-      37                 :            :      * @notice Clear all the rules of the array of rules
-      38                 :            :      *
-      39                 :            :      */
-      40                 :            :     function clearRulesOperation() public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
-      41                 :          4 :         _clearRulesOperation();
-      42                 :            :     }
-      43                 :            : 
-      44                 :            :     /**
-      45                 :            :      * @notice Clear all the rules of the array of rules
-      46                 :            :      *
-      47                 :            :      */
-      48                 :            :     function _clearRulesOperation() internal {
-      49                 :         14 :         uint256 index;
-      50                 :            :         // we remove the last element first since it is more optimized.
-      51                 :         14 :         for (uint256 i = _rulesOperation.length; i > 0; --i) {
-      52                 :            :             unchecked {
-      53                 :            :                 // don't underflow since i > 0
-      54                 :         17 :                 index = i - 1;
-      55                 :            :             }
-      56                 :         17 :             _removeRuleOperation(_rulesOperation[index], index);
-      57                 :            :         }
-      58                 :         14 :         emit ClearRules(_rulesOperation);
-      59                 :            :     }
-      60                 :            : 
-      61                 :            :     /**
-      62                 :            :      * @notice Add a rule to the array of rules
-      63                 :            :      * Revert if one rule is a zero address or if the rule is already present
-      64                 :            :      *
-      65                 :            :      */
-      66                 :            :     function addRuleOperation(
-      67                 :            :         IRuleOperation rule_
-      68                 :            :     ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
-      69                 :         85 :         RuleInternal._addRule(_rulesOperation, address(rule_));
-      70                 :         83 :         emit AddRule(address(rule_));
-      71                 :            :     }
-      72                 :            : 
-      73                 :            :     /**
-      74                 :            :      * @notice Remove a rule from the array of rules
-      75                 :            :      * Revert if the rule found at the specified index does not match the rule in argument
-      76                 :            :      * @param rule_ address of the target rule
-      77                 :            :      * @param index the position inside the array of rule
-      78                 :            :      * @dev To reduce the array size, the last rule is moved to the location occupied
-      79                 :            :      * by the rule to remove
-      80                 :            :      *
-      81                 :            :      *
-      82                 :            :      */
-      83                 :            :     function removeRuleOperation(
-      84                 :            :         IRuleOperation rule_,
-      85                 :            :         uint256 index
-      86                 :            :     ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
-      87                 :          5 :         _removeRuleOperation(address(rule_), index);
-      88                 :            :     }
-      89                 :            : 
-      90                 :            :     /**
-      91                 :            :      * @notice Remove a rule from the array of rules
-      92                 :            :      * Revert if the rule found at the specified index does not match the rule in argument
-      93                 :            :      * @param rule_ address of the target rule
-      94                 :            :      * @param index the position inside the array of rule
-      95                 :            :      * @dev To reduce the array size, the last rule is moved to the location occupied
-      96                 :            :      * by the rule to remove
-      97                 :            :      *
-      98                 :            :      *
-      99                 :            :      */
-     100                 :            :     function _removeRuleOperation(address rule_, uint256 index) internal {
-     101                 :         22 :         RuleInternal._removeRule(_rulesOperation, rule_, index);
-     102                 :         21 :         emit RemoveRule(address(rule_));
-     103                 :            :     }
-     104                 :            : 
-     105                 :            :     /**
-     106                 :            :      * @return The number of rules inside the array
-     107                 :            :      */
-     108                 :            :     function rulesCountOperation() external view override returns (uint256) {
-     109                 :         41 :         return _rulesOperation.length;
-     110                 :            :     }
-     111                 :            : 
-     112                 :            :     /**
-     113                 :            :      * @notice Get the index of a rule inside the list
-     114                 :            :      * @return index if the rule is found, _rulesOperation.length otherwise
-     115                 :            :      */
-     116                 :            :     function getRuleIndexOperation(
-     117                 :            :         IRuleOperation rule_
-     118                 :            :     ) external view returns (uint256 index) {
-     119                 :          3 :         return RuleInternal._getRuleIndex(_rulesOperation, address(rule_));
-     120                 :            :     }
-     121                 :            : 
-     122                 :            :     /**
-     123                 :            :      * @notice Get the rule at the position specified by ruleId
-     124                 :            :      * @param ruleId index of the rule
-     125                 :            :      * @return a rule address
-     126                 :            :      */
-     127                 :            :     function ruleOperation(
-     128                 :            :         uint256 ruleId
-     129                 :            :     ) external view override returns (address) {
-     130                 :          1 :         return _rulesOperation[ruleId];
-     131                 :            :     }
-     132                 :            : 
-     133                 :            :     /**
-     134                 :            :      * @notice Get all the rules
-     135                 :            :      * @return An array of rules
-     136                 :            :      */
-     137                 :            :     function rulesOperation()
-     138                 :            :         external
-     139                 :            :         view
-     140                 :            :         override
-     141                 :            :         returns (address[] memory)
-     142                 :            :     {
-     143                 :          5 :         return _rulesOperation;
-     144                 :            :     }
-     145                 :            : 
-     146                 :            :     /**
-     147                 :            :      * @notice Go through all the rule to know if a restriction exists on the transfer
-     148                 :            :      * @param _from the origin address
-     149                 :            :      * @param _to the destination address
-     150                 :            :      * @param _amount to transfer
-     151                 :            :      **/
-     152                 :            :     function _operateOnTransfer(
-     153                 :            :         address _from,
-     154                 :            :         address _to,
-     155                 :            :         uint256 _amount
-     156                 :            :     ) internal returns (bool isValid) {
-     157                 :         58 :         uint256 rulesLength = _rulesOperation.length;
-     158                 :         58 :         for (uint256 i = 0; i < rulesLength; ++i) {
-     159                 :         50 :             bool result = IRuleOperation(_rulesOperation[i]).operateOnTransfer(
-     160                 :            :                 _from,
-     161                 :            :                 _to,
-     162                 :            :                 _amount
-     163                 :            :             );
-     164            [ + ]:         50 :             if (!result) {
-     165                 :         24 :                 return false;
-     166                 :            :             }
-     167                 :            :         }
-     168                 :         34 :         return true;
-     169                 :            :     }
-     170                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/modules/RuleEngineValidation.sol.func-sort-c.html b/doc/coverage/coverage/src/modules/RuleEngineValidation.sol.func-sort-c.html deleted file mode 100644 index 3f2eb78..0000000 --- a/doc/coverage/coverage/src/modules/RuleEngineValidation.sol.func-sort-c.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - src/modules/RuleEngineValidation.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modules - RuleEngineValidation.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:88100.0 %
Date:2024-12-20 10:41:14Functions:22100.0 %
Branches:11100.0 %
-
- -
- - - - - - - - - - - - - - -

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

Function Name Sort by function nameHit count Sort by hit count
RuleEngineValidation.detectTransferRestrictionValidation3
RuleEngineValidation.validateTransferValidation2
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/modules/RuleEngineValidation.sol.gcov.html b/doc/coverage/coverage/src/modules/RuleEngineValidation.sol.gcov.html deleted file mode 100644 index 92443af..0000000 --- a/doc/coverage/coverage/src/modules/RuleEngineValidation.sol.gcov.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - LCOV - lcov.info - src/modules/RuleEngineValidation.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modules - RuleEngineValidation.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:88100.0 %
Date:2024-12-20 10:41:14Functions:22100.0 %
Branches:11100.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.20;
-       4                 :            : 
-       5                 :            : import "OZ/access/AccessControl.sol";
-       6                 :            : import "./RuleInternal.sol";
-       7                 :            : import "./RuleEngineValidationCommon.sol";
-       8                 :            : import "../interfaces/IRuleEngineValidation.sol";
-       9                 :            : import "../interfaces/IRuleValidation.sol";
-      10                 :            : import "CMTAT/interfaces/draft-IERC1404/draft-IERC1404EnumCode.sol";
-      11                 :            : 
-      12                 :            : /**
-      13                 :            :  * @title Implementation of a ruleEngine defined by the CMTAT
-      14                 :            :  */
-      15                 :            : abstract contract RuleEngineValidation is
-      16                 :            :     AccessControl,
-      17                 :            :     RuleInternal,
-      18                 :            :     RuleEngineValidationCommon,
-      19                 :            :     IRuleEngineValidation,
-      20                 :            :     IERC1404EnumCode
-      21                 :            : {
-      22                 :            :     /**
-      23                 :            :      * @notice Go through all the rule to know if a restriction exists on the transfer
-      24                 :            :      * @param _from the origin address
-      25                 :            :      * @param _to the destination address
-      26                 :            :      * @param _amount to transfer
-      27                 :            :      * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
-      28                 :            :      **/
-      29                 :            :     function detectTransferRestrictionValidation(
-      30                 :            :         address _from,
-      31                 :            :         address _to,
-      32                 :            :         uint256 _amount
-      33                 :            :     ) public view override returns (uint8) {
-      34                 :        105 :         uint256 rulesLength = _rulesValidation.length;
-      35                 :        105 :         for (uint256 i = 0; i < rulesLength; ++i) {
-      36                 :         43 :             uint8 restriction = IRuleValidation(_rulesValidation[i])
-      37                 :            :                 .detectTransferRestriction(_from, _to, _amount);
-      38            [ + ]:         43 :             if (restriction > 0) {
-      39                 :         28 :                 return restriction;
-      40                 :            :             }
-      41                 :            :         }
-      42                 :            : 
-      43                 :         77 :         return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
-      44                 :            :     }
-      45                 :            : 
-      46                 :            :     /**
-      47                 :            :      * @notice Validate a transfer
-      48                 :            :      * @param _from the origin address
-      49                 :            :      * @param _to the destination address
-      50                 :            :      * @param _amount to transfer
-      51                 :            :      * @return True if the transfer is valid, false otherwise
-      52                 :            :      **/
-      53                 :            :     function validateTransferValidation(
-      54                 :            :         address _from,
-      55                 :            :         address _to,
-      56                 :            :         uint256 _amount
-      57                 :            :     ) public view override returns (bool) {
-      58                 :         70 :         return
-      59                 :         70 :             detectTransferRestrictionValidation(_from, _to, _amount) ==
-      60                 :            :             uint8(REJECTED_CODE_BASE.TRANSFER_OK);
-      61                 :            :     }
-      62                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.func-sort-c.html b/doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.func-sort-c.html deleted file mode 100644 index 31de5ea..0000000 --- a/doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.func-sort-c.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - LCOV - lcov.info - src/modules/RuleEngineValidationCommon.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modules - RuleEngineValidationCommon.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1919100.0 %
Date:2024-12-20 10:41:14Functions:1010100.0 %
Branches:11100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

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

Function Name Sort by function nameHit count Sort by hit count
RuleEngineValidationCommon._clearRulesValidation25
RuleEngineValidationCommon._removeRuleValidation33
RuleEngineValidationCommon.addRuleValidation119
RuleEngineValidationCommon.clearRulesValidation6
RuleEngineValidationCommon.getRuleIndexValidation3
RuleEngineValidationCommon.removeRuleValidation6
RuleEngineValidationCommon.ruleValidation1
RuleEngineValidationCommon.rulesCountValidation69
RuleEngineValidationCommon.rulesValidation5
RuleEngineValidationCommon.setRulesValidation22
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/modules/index-sort-b.html b/doc/coverage/coverage/src/modules/index-sort-b.html deleted file mode 100644 index 1356192..0000000 --- a/doc/coverage/coverage/src/modules/index-sort-b.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - LCOV - lcov.info - src/modules - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modulesHitTotalCoverage
Test:lcov.infoLines:8181100.0 %
Date:2024-12-20 10:41:14Functions:2727100.0 %
Branches:1212100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngineValidationCommon.sol -
100.0%
-
100.0 %19 / 19100.0 %10 / 10100.0 %1 / 1
RuleEngineValidation.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %1 / 1
RuleEngineOperation.sol -
100.0%
-
100.0 %25 / 25100.0 %11 / 11100.0 %2 / 2
RuleInternal.sol -
100.0%
-
100.0 %29 / 29100.0 %4 / 4100.0 %8 / 8
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/modules/index-sort-f.html b/doc/coverage/coverage/src/modules/index-sort-f.html deleted file mode 100644 index f0cc112..0000000 --- a/doc/coverage/coverage/src/modules/index-sort-f.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - LCOV - lcov.info - src/modules - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modulesHitTotalCoverage
Test:lcov.infoLines:8181100.0 %
Date:2024-12-20 10:41:14Functions:2727100.0 %
Branches:1212100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngineValidation.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %1 / 1
RuleInternal.sol -
100.0%
-
100.0 %29 / 29100.0 %4 / 4100.0 %8 / 8
RuleEngineValidationCommon.sol -
100.0%
-
100.0 %19 / 19100.0 %10 / 10100.0 %1 / 1
RuleEngineOperation.sol -
100.0%
-
100.0 %25 / 25100.0 %11 / 11100.0 %2 / 2
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/modules/index-sort-l.html b/doc/coverage/coverage/src/modules/index-sort-l.html deleted file mode 100644 index 7d113ca..0000000 --- a/doc/coverage/coverage/src/modules/index-sort-l.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - LCOV - lcov.info - src/modules - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modulesHitTotalCoverage
Test:lcov.infoLines:8181100.0 %
Date:2024-12-20 10:41:14Functions:2727100.0 %
Branches:1212100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngineValidation.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %1 / 1
RuleEngineValidationCommon.sol -
100.0%
-
100.0 %19 / 19100.0 %10 / 10100.0 %1 / 1
RuleEngineOperation.sol -
100.0%
-
100.0 %25 / 25100.0 %11 / 11100.0 %2 / 2
RuleInternal.sol -
100.0%
-
100.0 %29 / 29100.0 %4 / 4100.0 %8 / 8
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/modules/index.html b/doc/coverage/coverage/src/modules/index.html deleted file mode 100644 index 60ae93b..0000000 --- a/doc/coverage/coverage/src/modules/index.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - LCOV - lcov.info - src/modules - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/modulesHitTotalCoverage
Test:lcov.infoLines:8181100.0 %
Date:2024-12-20 10:41:14Functions:2727100.0 %
Branches:1212100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleEngineOperation.sol -
100.0%
-
100.0 %25 / 25100.0 %11 / 11100.0 %2 / 2
RuleEngineValidation.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %1 / 1
RuleEngineValidationCommon.sol -
100.0%
-
100.0 %19 / 19100.0 %10 / 10100.0 %1 / 1
RuleInternal.sol -
100.0%
-
100.0 %29 / 29100.0 %4 / 4100.0 %8 / 8
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.func-sort-c.html deleted file mode 100644 index 7f4ab01..0000000 --- a/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.func-sort-c.html +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/operation/RuleConditionalTransfer.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation - RuleConditionalTransfer.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:10510699.1 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:3333100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleConditionalTransfer._msgData0
RuleConditionalTransfer.canReturnTransferRestrictionCode2
RuleConditionalTransfer.cancelTransferRequestBatch3
RuleConditionalTransfer.createTransferRequestBatch3
RuleConditionalTransfer.messageForTransferRestriction3
RuleConditionalTransfer.cancelTransferRequest6
RuleConditionalTransfer._cancelTransferRequest9
RuleConditionalTransfer.getRequestByStatus35
RuleConditionalTransfer.operateOnTransfer50
RuleConditionalTransfer.detectTransferRestriction56
RuleConditionalTransfer.getRequestTrade57
RuleConditionalTransfer._validateApproval97
RuleConditionalTransfer._validateBurnMint103
RuleConditionalTransfer._validateTransfer106
RuleConditionalTransfer.createTransferRequest114
RuleConditionalTransfer.158
RuleConditionalTransfer._contextSuffixLength829
RuleConditionalTransfer._msgSender829
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.func.html b/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.func.html deleted file mode 100644 index fba2e82..0000000 --- a/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.func.html +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/operation/RuleConditionalTransfer.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation - RuleConditionalTransfer.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:10510699.1 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:3333100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleConditionalTransfer.158
RuleConditionalTransfer._cancelTransferRequest9
RuleConditionalTransfer._contextSuffixLength829
RuleConditionalTransfer._msgData0
RuleConditionalTransfer._msgSender829
RuleConditionalTransfer._validateApproval97
RuleConditionalTransfer._validateBurnMint103
RuleConditionalTransfer._validateTransfer106
RuleConditionalTransfer.canReturnTransferRestrictionCode2
RuleConditionalTransfer.cancelTransferRequest6
RuleConditionalTransfer.cancelTransferRequestBatch3
RuleConditionalTransfer.createTransferRequest114
RuleConditionalTransfer.createTransferRequestBatch3
RuleConditionalTransfer.detectTransferRestriction56
RuleConditionalTransfer.getRequestByStatus35
RuleConditionalTransfer.getRequestTrade57
RuleConditionalTransfer.messageForTransferRestriction3
RuleConditionalTransfer.operateOnTransfer50
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.gcov.html b/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.gcov.html deleted file mode 100644 index 476c0ca..0000000 --- a/doc/coverage/coverage/src/rules/operation/RuleConditionalTransfer.sol.gcov.html +++ /dev/null @@ -1,486 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/operation/RuleConditionalTransfer.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation - RuleConditionalTransfer.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:10510699.1 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:3333100.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.20;
-       4                 :            : 
-       5                 :            : import "OZ/access/AccessControl.sol";
-       6                 :            : import "../../interfaces/IRuleOperation.sol";
-       7                 :            : import "./../../modules/MetaTxModuleStandalone.sol";
-       8                 :            : import "./abstract/RuleConditionalTransferInvariantStorage.sol";
-       9                 :            : import "./abstract/RuleConditionalTransferOperator.sol";
-      10                 :            : import "../validation/abstract/RuleValidateTransfer.sol";
-      11                 :            : import "CMTAT/interfaces/engine/IRuleEngine.sol";
-      12                 :            : 
-      13                 :            : /**
-      14                 :            :  * @title RuleConditionalTransfer
-      15                 :            :  */
-      16                 :            : 
-      17                 :            : contract RuleConditionalTransfer is
-      18                 :            :     RuleValidateTransfer,
-      19                 :            :     IRuleOperation,
-      20                 :            :     RuleConditionalTransferOperator,
-      21                 :            :     MetaTxModuleStandalone
-      22                 :            : {
-      23                 :            :     /**
-      24                 :            :      * @param admin Address of the contract (Access Control)
-      25                 :            :      * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
-      26                 :            :      */
-      27                 :            :     constructor(
-      28                 :            :         address admin,
-      29                 :            :         address forwarderIrrevocable,
-      30                 :            :         IRuleEngine ruleEngineContract,
-      31                 :            :         OPTION memory options_
-      32                 :            :     ) MetaTxModuleStandalone(forwarderIrrevocable) {
-      33            [ + ]:        158 :         if (admin == address(0)) {
-      34                 :          1 :             revert RuleConditionalTransfer_AdminWithAddressZeroNotAllowed();
-      35                 :            :         }
-      36                 :        157 :         _grantRole(DEFAULT_ADMIN_ROLE, admin);
-      37            [ + ]:        157 :         if (address(ruleEngineContract) != address(0x0)) {
-      38                 :        153 :             _grantRole(RULE_ENGINE_CONTRACT_ROLE, address(ruleEngineContract));
-      39                 :            :         }
-      40                 :        157 :         options = options_;
-      41                 :            :     }
-      42                 :            : 
-      43                 :            :     /*//////////////////////////////////////////////////////////////
-      44                 :            :                             PUBLIC/EXTERNAL FUNCTIONS
-      45                 :            :     //////////////////////////////////////////////////////////////*/
-      46                 :            :     /**
-      47                 :            :      * @notice function called by the RuleEngine
-      48                 :            :      * @dev Returns true if the transfer is valid, and false otherwise.
-      49                 :            :      * Add access control with the RuleEngine
-      50                 :            :      */
-      51                 :            :     function operateOnTransfer(
-      52                 :            :         address _from,
-      53                 :            :         address _to,
-      54                 :            :         uint256 _amount
-      55                 :            :     )
-      56                 :            :         public
-      57                 :            :         override
-      58                 :            :         onlyRole(RULE_ENGINE_CONTRACT_ROLE)
-      59                 :            :         returns (bool isValid)
-      60                 :            :     {
-      61         [ +  + ]:         50 :         if (_validateTransfer(_from, _to)) {
-      62                 :          8 :             return true;
-      63                 :            :         } else {
-      64                 :         42 :             bytes32 key = keccak256(abi.encode(_from, _to, _amount));
-      65         [ +  + ]:         42 :             if (_validateApproval(key)) {
-      66                 :         18 :                 _updateProcessedTransfer(key);
-      67                 :         18 :                 return true;
-      68                 :            :             } else {
-      69                 :         24 :                 return false;
-      70                 :            :             }
-      71                 :            :         }
-      72                 :            :     }
-      73                 :            : 
-      74                 :            :     /**
-      75                 :            :      * @notice Create a request of transfer for yourselves
-      76                 :            :      * @param to recipient of tokens
-      77                 :            :      * @param value amount of tokens to transfer
-      78                 :            :      */
-      79                 :            :     function createTransferRequest(address to, uint256 value) public {
-      80                 :            :         // WAIT => Will set a new delay to approve
-      81                 :            :         // APPROVED => will overwrite previous status
-      82                 :            :         // DENIED => reject
-      83                 :        117 :         address from = _msgSender();
-      84                 :        117 :         bytes32 key = keccak256(abi.encode(from, to, value));
-      85            [ + ]:        117 :         if (transferRequests[key].status == STATUS.DENIED) {
-      86                 :          1 :             revert RuleConditionalTransfer_TransferDenied();
-      87                 :            :         }
-      88         [ +  + ]:        116 :         if (_checkRequestStatus(key)) {
-      89                 :        113 :             uint256 requestIdLocal = requestId;
-      90                 :        113 :             TransferRequest memory newTransferApproval = TransferRequest({
-      91                 :            :                 key: key,
-      92                 :            :                 id: requestIdLocal,
-      93                 :            :                 keyElement: TransferRequestKeyElement({
-      94                 :            :                     from: from,
-      95                 :            :                     to: to,
-      96                 :            :                     value: value
-      97                 :            :                 }),
-      98                 :            :                 askTime: block.timestamp,
-      99                 :            :                 maxTime: 0,
-     100                 :            :                 status: STATUS.WAIT
-     101                 :            :             });
-     102                 :        113 :             transferRequests[key] = newTransferApproval;
-     103                 :        113 :             IdToKey[requestIdLocal] = key;
-     104                 :        113 :             emit transferWaiting(key, from, to, value, requestId);
-     105                 :        113 :             ++requestId;
-     106                 :            :         } else {
-     107                 :            :             // Overwrite previous approval
-     108                 :          3 :             transferRequests[key].askTime = block.timestamp;
-     109                 :          3 :             transferRequests[key].status = STATUS.WAIT;
-     110                 :          3 :             emit transferWaiting(
-     111                 :            :                 key,
-     112                 :            :                 from,
-     113                 :            :                 to,
-     114                 :            :                 value,
-     115                 :            :                 transferRequests[key].id
-     116                 :            :             );
-     117                 :            :         }
-     118                 :            :     }
-     119                 :            : 
-     120                 :            :     /**
-     121                 :            :      * @notice Batch version of {createTransferRequest}
-     122                 :            :      */
-     123                 :            :     function createTransferRequestBatch(
-     124                 :            :         address[] memory tos,
-     125                 :            :         uint256[] memory values
-     126                 :            :     ) public {
-     127            [ + ]:          3 :         if (tos.length == 0) {
-     128                 :          1 :             revert RuleConditionalTransfer_EmptyArray();
-     129                 :            :         }
-     130            [ + ]:          2 :         if (tos.length != values.length) {
-     131                 :          1 :             revert RuleConditionalTransfer_InvalidLengthArray();
-     132                 :            :         }
-     133                 :          1 :         for (uint256 i = 0; i < tos.length; ++i) {
-     134                 :          3 :             createTransferRequest(tos[i], values[i]);
-     135                 :            :         }
-     136                 :            :     }
-     137                 :            : 
-     138                 :            :     /**
-     139                 :            :      * @notice allow a token holder to cancel/reset his own request
-     140                 :            :      */
-     141                 :            :     function cancelTransferRequest(uint256 requestId_) public {
-     142                 :          6 :         _cancelTransferRequest(requestId_);
-     143                 :            :     }
-     144                 :            : 
-     145                 :            :     /**
-     146                 :            :      * @notice allow a token holder to cancel/reset his own request
-     147                 :            :      */
-     148                 :            :     function cancelTransferRequestBatch(uint256[] memory requestIds) public {
-     149            [ + ]:          3 :         if (requestIds.length == 0) {
-     150                 :          1 :             revert RuleConditionalTransfer_EmptyArray();
-     151                 :            :         }
-     152                 :            :         // Check id validity before performing actions
-     153                 :          2 :         for (uint256 i = 0; i < requestIds.length; ++i) {
-     154            [ + ]:          5 :             if (requestIds[i] + 1 > requestId) {
-     155                 :          1 :                 revert RuleConditionalTransfer_InvalidId();
-     156                 :            :             }
-     157                 :            :         }
-     158                 :          1 :         for (uint256 i = 0; i < requestIds.length; ++i) {
-     159                 :          3 :             _cancelTransferRequest(requestIds[i]);
-     160                 :            :         }
-     161                 :            :     }
-     162                 :            : 
-     163                 :            :     function getRequestTrade(
-     164                 :            :         address from,
-     165                 :            :         address to,
-     166                 :            :         uint256 value
-     167                 :            :     ) public view returns (TransferRequest memory) {
-     168                 :         57 :         bytes32 key = keccak256(abi.encode(from, to, value));
-     169                 :         57 :         return transferRequests[key];
-     170                 :            :     }
-     171                 :            : 
-     172                 :            :     /**
-     173                 :            :      * @notice get Trade by status
-     174                 :            :      * @param  _targetStatus The status of the transactions you want to retrieve
-     175                 :            :      * @return array with corresponding transactions
-     176                 :            :      */
-     177                 :            :     function getRequestByStatus(
-     178                 :            :         STATUS _targetStatus
-     179                 :            :     ) public view returns (TransferRequest[] memory) {
-     180                 :         35 :         uint totalRequestCount = requestId;
-     181                 :         35 :         uint requestCount = 0;
-     182                 :         35 :         uint currentIndex = 0;
-     183                 :            : 
-     184                 :            :         // We count the number of requests matching the criteria
-     185                 :         35 :         for (uint i = 0; i < totalRequestCount; ++i) {
-     186            [ + ]:         38 :             if (transferRequests[IdToKey[i]].status == _targetStatus) {
-     187                 :         36 :                 requestCount += 1;
-     188                 :            :             }
-     189                 :            :         }
-     190                 :            : 
-     191                 :            :         // We reserve the memory to store the trade
-     192                 :         35 :         TransferRequest[] memory requests = new TransferRequest[](requestCount);
-     193                 :            : 
-     194                 :            :         // We create an array with the list of trade
-     195                 :         35 :         for (uint i = 0; i < totalRequestCount; ++i) {
-     196            [ + ]:         38 :             if (transferRequests[IdToKey[i]].status == _targetStatus) {
-     197                 :            :                 //uint currentId = i + 1;
-     198                 :         36 :                 TransferRequest memory currentRequest = transferRequests[
-     199                 :            :                     IdToKey[i]
-     200                 :            :                 ];
-     201                 :         36 :                 requests[currentIndex] = currentRequest;
-     202                 :         36 :                 currentIndex += 1;
-     203                 :            :             }
-     204                 :            :         }
-     205                 :         35 :         return requests;
-     206                 :            :     }
-     207                 :            : 
-     208                 :            :     /**
-     209                 :            :      * @notice Check if the transfer is valid
-     210                 :            :      * @param _from the origin address
-     211                 :            :      * @param _to the destination address
-     212                 :            :      * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
-     213                 :            :      **/
-     214                 :            :     function detectTransferRestriction(
-     215                 :            :         address _from,
-     216                 :            :         address _to,
-     217                 :            :         uint256 _amount
-     218                 :            :     ) public view override returns (uint8) {
-     219                 :            :         // No need of approval if from and to are in the whitelist
-     220            [ + ]:         56 :         if (_validateTransfer(_from, _to)) {
-     221                 :          1 :             return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
-     222                 :            :         }
-     223                 :         55 :         bytes32 key = keccak256(abi.encode(_from, _to, _amount));
-     224         [ +  + ]:         55 :         if (_validateApproval(key)) {
-     225                 :          8 :             return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
-     226                 :            :         } else {
-     227                 :         47 :             return CODE_TRANSFER_REQUEST_NOT_APPROVED;
-     228                 :            :         }
-     229                 :            :     }
-     230                 :            : 
-     231                 :            :     /**
-     232                 :            :      * @notice To know if the restriction code is valid for this rule or not.
-     233                 :            :      * @param _restrictionCode The target restriction code
-     234                 :            :      * @return true if the restriction code is known, false otherwise
-     235                 :            :      **/
-     236                 :            :     function canReturnTransferRestrictionCode(
-     237                 :            :         uint8 _restrictionCode
-     238                 :            :     ) external pure override returns (bool) {
-     239                 :          2 :         return _restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED;
-     240                 :            :     }
-     241                 :            : 
-     242                 :            :     /**
-     243                 :            :      * @notice Return the corresponding message
-     244                 :            :      * @param _restrictionCode The target restriction code
-     245                 :            :      * @return true if the transfer is valid, false otherwise
-     246                 :            :      **/
-     247                 :            :     function messageForTransferRestriction(
-     248                 :            :         uint8 _restrictionCode
-     249                 :            :     ) external pure override returns (string memory) {
-     250         [ +  + ]:          3 :         if (_restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED) {
-     251                 :          2 :             return TEXT_TRANSFER_REQUEST_NOT_APPROVED;
-     252                 :            :         } else {
-     253                 :          1 :             return TEXT_CODE_NOT_FOUND;
-     254                 :            :         }
-     255                 :            :     }
-     256                 :            : 
-     257                 :            :     /*//////////////////////////////////////////////////////////////
-     258                 :            :                             INTERNAL FUNCTIONS
-     259                 :            :     //////////////////////////////////////////////////////////////*/
-     260                 :            :     function _validateTransfer(
-     261                 :            :         address _from,
-     262                 :            :         address _to
-     263                 :            :     ) internal view returns (bool) {
-     264                 :            :         // No need of approval if from and to are in the whitelist
-     265            [ + ]:        106 :         if (address(whitelistConditionalTransfer) != address(0)) {
-     266                 :            :             if (
-     267                 :         36 :                 whitelistConditionalTransfer.addressIsListed(_from) &&
-     268                 :          5 :                 whitelistConditionalTransfer.addressIsListed(_to)
-     269            [ + ]:          3 :             ) {
-     270                 :          3 :                 return true;
-     271                 :            :             }
-     272                 :            :         }
-     273                 :            : 
-     274                 :            :         // Mint & Burn
-     275            [ + ]:        103 :         if (_validateBurnMint(_from, _to)) {
-     276                 :          6 :             return true;
-     277                 :            :         }
-     278                 :         97 :         return false;
-     279                 :            :     }
-     280                 :            : 
-     281                 :            :     function _cancelTransferRequest(uint256 requestId_) internal {
-     282            [ + ]:          9 :         if (requestId_ + 1 > requestId) {
-     283                 :          1 :             revert RuleConditionalTransfer_InvalidId();
-     284                 :            :         }
-     285                 :          8 :         bytes32 key = IdToKey[requestId_];
-     286                 :            :         // Check Sender
-     287            [ + ]:          8 :         if (transferRequests[key].keyElement.from != _msgSender()) {
-     288                 :          1 :             revert RuleConditionalTransfer_InvalidSender();
-     289                 :            :         }
-     290                 :            :         // Check status
-     291                 :            :         if (
-     292                 :          7 :             transferRequests[key].status != STATUS.WAIT &&
-     293                 :          2 :             transferRequests[key].status != STATUS.APPROVED
-     294            [ + ]:          1 :         ) {
-     295                 :          1 :             revert RuleConditionalTransfer_Wrong_Status();
-     296                 :            :         }
-     297                 :          6 :         _resetRequestStatus(key);
-     298                 :            :     }
-     299                 :            : 
-     300                 :            :     /**
-     301                 :            :      *
-     302                 :            :      * @dev
-     303                 :            :      * Test burn and mint condition
-     304                 :            :      * Returns true if the transfer is valid, and false otherwise.
-     305                 :            :      *
-     306                 :            :      */
-     307                 :            :     function _validateBurnMint(
-     308                 :            :         address _from,
-     309                 :            :         address _to
-     310                 :            :     ) internal view returns (bool isValid) {
-     311                 :            :         // Mint & Burn
-     312                 :            :         if (
-     313                 :        103 :             (_from == address(0) &&
-     314                 :            :                 options.issuance.authorizedMintWithoutApproval) ||
-     315                 :            :             (_to == address(0) &&
-     316                 :            :                 options.issuance.authorizedBurnWithoutApproval)
-     317            [ + ]:          6 :         ) {
-     318                 :          6 :             return true;
-     319                 :            :         }
-     320                 :         97 :         return false;
-     321                 :            :     }
-     322                 :            : 
-     323                 :            :     /**
-     324                 :            :      *
-     325                 :            :      * @dev
-     326                 :            :      * Test transfer approval condition
-     327                 :            :      * Returns true if the transfer is valid, and false otherwise.
-     328                 :            :      */
-     329                 :            :     function _validateApproval(
-     330                 :            :         bytes32 key
-     331                 :            :     ) internal view returns (bool isValid) {
-     332                 :            :         // If automatic approval is activate and time to approve the request has passed
-     333                 :         97 :         if(transferRequests[key].status == STATUS.NONE
-     334                 :            :         ||
-     335                 :         50 :         transferRequests[key].status == STATUS.DENIED
-     336                 :            :         || 
-     337                 :         47 :         transferRequests[key].status == STATUS.EXECUTED)
-     338            [ + ]:         50 :         {
-     339                 :         50 :             return false;
-     340                 :            :         }
-     341                 :         47 :         bool isTransferApproved;
-     342                 :         47 :         bool automaticApprovalCondition;
-     343            [ + ]:         47 :         if(transferRequests[key].status ==
-     344            [ + ]:         20 :             STATUS.APPROVED){
-     345                 :         20 :                  isTransferApproved = (transferRequests[key].maxTime >= block.timestamp);
-     346                 :            :         } else if(options
-     347                 :            :             .automaticApproval
-     348            [ + ]:         27 :             .isActivate){
-     349                 :            :         // Warning: overflow possible if timeLimitBeforeAutomaticApproval == max(uint256)
-     350                 :         27 :                  automaticApprovalCondition= block.timestamp >=
-     351                 :            :             (transferRequests[key].askTime +
-     352                 :            :                 options.automaticApproval.timeLimitBeforeAutomaticApproval);
-     353                 :            :         }
-     354                 :            :         // If the transfer is approved and delay to perform the transfer is respected
-     355         [ +  + ]:         47 :         if (automaticApprovalCondition || isTransferApproved) {
-     356                 :         26 :             return true;
-     357                 :            :         } else {
-     358                 :         21 :             return false;
-     359                 :            :         }
-     360                 :            :     }
-     361                 :            : 
-     362                 :            :     /*//////////////////////////////////////////////////////////////
-     363                 :            :                            ERC-2771
-     364                 :            :     //////////////////////////////////////////////////////////////*/
-     365                 :            : 
-     366                 :            :     /**
-     367                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
-     368                 :            :      */
-     369                 :            :     function _msgSender()
-     370                 :            :         internal
-     371                 :            :         view
-     372                 :            :         override(ERC2771Context, Context)
-     373                 :            :         returns (address sender)
-     374                 :            :     {
-     375                 :        829 :         return ERC2771Context._msgSender();
-     376                 :            :     }
-     377                 :            : 
-     378                 :            :     /**
-     379                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
-     380                 :            :      */
-     381                 :            :     function _msgData()
-     382                 :            :         internal
-     383                 :            :         view
-     384                 :            :         override(ERC2771Context, Context)
-     385                 :            :         returns (bytes calldata)
-     386                 :            :     {
-     387                 :          0 :         return ERC2771Context._msgData();
-     388                 :            :     }
-     389                 :            : 
-     390                 :            :     /**
-     391                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
-     392                 :            :      */
-     393                 :            :     function _contextSuffixLength()
-     394                 :            :         internal
-     395                 :            :         view
-     396                 :            :         override(ERC2771Context, Context)
-     397                 :            :         returns (uint256)
-     398                 :            :     {
-     399                 :        829 :         return ERC2771Context._contextSuffixLength();
-     400                 :            :     }
-     401                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func-sort-c.html deleted file mode 100644 index acebdd7..0000000 --- a/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func-sort-c.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/operation/abstract/RuleConditionalTransferOperator.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation/abstract - RuleConditionalTransferOperator.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:113113100.0 %
Date:2024-12-20 10:41:14Functions:2020100.0 %
Branches:3131100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch3
RuleConditionalTransferOperator.resetRequestStatus3
RuleConditionalTransferOperator.resetRequestStatusBatch3
RuleConditionalTransferOperator.setAutomaticTransfer4
RuleConditionalTransferOperator.approveTransferRequestWithId5
RuleConditionalTransferOperator.setTimeLimit5
RuleConditionalTransferOperator.createTransferRequestWithApproval6
RuleConditionalTransferOperator.approveTransferRequestBatch7
RuleConditionalTransferOperator.approveTransferRequestBatchWithId7
RuleConditionalTransferOperator.setIssuanceOptions7
RuleConditionalTransferOperator._resetRequestStatus10
RuleConditionalTransferOperator.setAutomaticApproval10
RuleConditionalTransferOperator._createTransferRequestWithApproval17
RuleConditionalTransferOperator._updateProcessedTransfer18
RuleConditionalTransferOperator.setConditionalWhitelist26
RuleConditionalTransferOperator.approveTransferRequest40
RuleConditionalTransferOperator._approveTransferRequestKeyElement48
RuleConditionalTransferOperator._approveRequest53
RuleConditionalTransferOperator._checkRequestStatus133
RuleConditionalTransferOperator.hasRole310
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func.html b/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func.html deleted file mode 100644 index bbcca68..0000000 --- a/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/operation/abstract/RuleConditionalTransferOperator.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation/abstract - RuleConditionalTransferOperator.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:113113100.0 %
Date:2024-12-20 10:41:14Functions:2020100.0 %
Branches:3131100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleConditionalTransferOperator._approveRequest53
RuleConditionalTransferOperator._approveTransferRequestKeyElement48
RuleConditionalTransferOperator._checkRequestStatus133
RuleConditionalTransferOperator._createTransferRequestWithApproval17
RuleConditionalTransferOperator._resetRequestStatus10
RuleConditionalTransferOperator._updateProcessedTransfer18
RuleConditionalTransferOperator.approveTransferRequest40
RuleConditionalTransferOperator.approveTransferRequestBatch7
RuleConditionalTransferOperator.approveTransferRequestBatchWithId7
RuleConditionalTransferOperator.approveTransferRequestWithId5
RuleConditionalTransferOperator.createTransferRequestWithApproval6
RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch3
RuleConditionalTransferOperator.hasRole310
RuleConditionalTransferOperator.resetRequestStatus3
RuleConditionalTransferOperator.resetRequestStatusBatch3
RuleConditionalTransferOperator.setAutomaticApproval10
RuleConditionalTransferOperator.setAutomaticTransfer4
RuleConditionalTransferOperator.setConditionalWhitelist26
RuleConditionalTransferOperator.setIssuanceOptions7
RuleConditionalTransferOperator.setTimeLimit5
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.gcov.html b/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.gcov.html deleted file mode 100644 index 8a6d8ca..0000000 --- a/doc/coverage/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.gcov.html +++ /dev/null @@ -1,558 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/operation/abstract/RuleConditionalTransferOperator.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operation/abstract - RuleConditionalTransferOperator.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:113113100.0 %
Date:2024-12-20 10:41:14Functions:2020100.0 %
Branches:3131100.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.20;
-       4                 :            : 
-       5                 :            : import "OZ/access/AccessControl.sol";
-       6                 :            : import "./RuleConditionalTransferInvariantStorage.sol";
-       7                 :            : import "OZ/token/ERC20/utils/SafeERC20.sol";
-       8                 :            : 
-       9                 :            : /**
-      10                 :            :  * @title Restricted functions
-      11                 :            :  */
-      12                 :            : abstract contract RuleConditionalTransferOperator is
-      13                 :            :     AccessControl,
-      14                 :            :     RuleConditionalTransferInvariantStorage
-      15                 :            : {
-      16                 :            :     // Security
-      17                 :            :     using SafeERC20 for IERC20;
-      18                 :            :     /* ============ State Variables ============ */
-      19                 :            :     OPTION public options;
-      20                 :            :     uint256 public requestId;
-      21                 :            :     mapping(uint256 => bytes32) public IdToKey;
-      22                 :            :     mapping(bytes32 => TransferRequest) public transferRequests;
-      23                 :            :     RuleWhitelist public whitelistConditionalTransfer;
-      24                 :            : 
-      25                 :            :     /*//////////////////////////////////////////////////////////////
-      26                 :            :                             PUBLIC/EXTERNAL FUNCTIONS
-      27                 :            :     //////////////////////////////////////////////////////////////*/
-      28                 :            : 
-      29                 :            :     /**
-      30                 :            :      * @notice set a whitelist. A transfer does not need of an approved request if from and to are in the whitelist
-      31                 :            :      */
-      32                 :            :     function setConditionalWhitelist(
-      33                 :            :         RuleWhitelist newWhitelistConditionalTransfer
-      34                 :            :     ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
-      35                 :         26 :         whitelistConditionalTransfer = newWhitelistConditionalTransfer;
-      36                 :         26 :         emit WhitelistConditionalTransfer(newWhitelistConditionalTransfer);
-      37                 :            :     }
-      38                 :            : 
-      39                 :            :     /**
-      40                 :            :      * @notice set/unset the issuance options (mint & burn)
-      41                 :            :      */
-      42                 :            :     function setIssuanceOptions(
-      43                 :            :         ISSUANCE calldata issuance_
-      44                 :            :     ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
-      45                 :            :         if (
-      46                 :          6 :             options.issuance.authorizedMintWithoutApproval !=
-      47                 :            :             issuance_.authorizedMintWithoutApproval
-      48            [ + ]:          3 :         ) {
-      49                 :          3 :             options.issuance.authorizedMintWithoutApproval = issuance_
-      50                 :            :                 .authorizedMintWithoutApproval;
-      51                 :            :         }
-      52                 :            :         if (
-      53                 :          6 :             options.issuance.authorizedBurnWithoutApproval !=
-      54                 :            :             issuance_.authorizedBurnWithoutApproval
-      55            [ + ]:          3 :         ) {
-      56                 :          3 :             options.issuance.authorizedBurnWithoutApproval = issuance_
-      57                 :            :                 .authorizedBurnWithoutApproval;
-      58                 :            :         }
-      59                 :            :     }
-      60                 :            : 
-      61                 :            :     /**
-      62                 :            :      * @notice set/unset the option to perform the transfer if the request is approved by the rule operator.
-      63                 :            :      * To perform the transfer, the token holder has to approve the rule to spend tokens on his behalf (standard ERC-20 approval).
-      64                 :            :      * If the allowance is not sufficient, the request will be approved, but without performing the transfer.
-      65                 :            :      */
-      66                 :            :     function setAutomaticTransfer(
-      67                 :            :         AUTOMATIC_TRANSFER calldata automaticTransfer_
-      68                 :            :     ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
-      69                 :            :         if (
-      70                 :          3 :             automaticTransfer_.isActivate !=
-      71                 :            :             options.automaticTransfer.isActivate
-      72            [ + ]:          2 :         ) {
-      73                 :          2 :             options.automaticTransfer.isActivate = automaticTransfer_
-      74                 :            :                 .isActivate;
-      75                 :            :         }
-      76                 :            :         // No need to put the cmtat to zero to deactivate automaticTransfer
-      77                 :            :         if (
-      78                 :          3 :             address(automaticTransfer_.cmtat) !=
-      79                 :            :             address(options.automaticTransfer.cmtat)
-      80            [ + ]:          2 :         ) {
-      81                 :          2 :             options.automaticTransfer.cmtat = automaticTransfer_.cmtat;
-      82                 :            :         }
-      83                 :            :     }
-      84                 :            : 
-      85                 :            :     /**
-      86                 :            :      * @notice set time limit for new requests (Approval and transfer)
-      87                 :            :      * timeLimitToApprove: time limit for an operator to approve a request
-      88                 :            :      * timeLimitToTransfer: once a request is approved, time limit for the token holder to perform the transfer
-      89                 :            :      */
-      90                 :            :     function setTimeLimit(
-      91                 :            :         TIME_LIMIT memory timeLimit_
-      92                 :            :     ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
-      93                 :            :         if (
-      94                 :          4 :             options.timeLimit.timeLimitToApprove !=
-      95                 :            :             timeLimit_.timeLimitToApprove
-      96            [ + ]:          4 :         ) {
-      97                 :          4 :             options.timeLimit.timeLimitToApprove = timeLimit_
-      98                 :            :                 .timeLimitToApprove;
-      99                 :            :         }
-     100                 :            :         if (
-     101                 :          4 :             options.timeLimit.timeLimitToTransfer !=
-     102                 :            :             timeLimit_.timeLimitToTransfer
-     103            [ + ]:          4 :         ) {
-     104                 :          4 :             options.timeLimit.timeLimitToTransfer = timeLimit_
-     105                 :            :                 .timeLimitToTransfer;
-     106                 :            :         }
-     107                 :            :     }
-     108                 :            : 
-     109                 :            :     /**
-     110                 :            :      * @notice  If the transfer is not approved or denied within {timeLimitBeforeAutomaticApproval},
-     111                 :            :      * the request is considered as approved during a transfer.
-     112                 :            :      *
-     113                 :            :      */
-     114                 :            :     function setAutomaticApproval(
-     115                 :            :         AUTOMATIC_APPROVAL memory automaticApproval_
-     116                 :            :     ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
-     117                 :            :         if (
-     118                 :          9 :             options.automaticApproval.isActivate !=
-     119                 :            :             automaticApproval_.isActivate
-     120            [ + ]:          6 :         ) {
-     121                 :          6 :             options.automaticApproval.isActivate = automaticApproval_
-     122                 :            :                 .isActivate;
-     123                 :            :         }
-     124                 :            :         if (
-     125                 :          9 :             options.automaticApproval.timeLimitBeforeAutomaticApproval !=
-     126                 :            :             automaticApproval_.timeLimitBeforeAutomaticApproval
-     127            [ + ]:          9 :         ) {
-     128                 :          9 :             options
-     129                 :            :                 .automaticApproval
-     130                 :            :                 .timeLimitBeforeAutomaticApproval = automaticApproval_
-     131                 :            :                 .timeLimitBeforeAutomaticApproval;
-     132                 :            :         }
-     133                 :            :     }
-     134                 :            : 
-     135                 :            :     /**
-     136                 :            :      * @notice create a transfer request directly approved
-     137                 :            :      */
-     138                 :            :     function createTransferRequestWithApproval(
-     139                 :            :         TransferRequestKeyElement calldata keyElement
-     140                 :            :     ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
-     141                 :          5 :         _createTransferRequestWithApproval(keyElement);
-     142                 :            :     }
-     143                 :            : 
-     144                 :            :     /**
-     145                 :            :      * @notice approve a transferRequest
-     146                 :            :      * @param keyElement contains from, to, value
-     147                 :            :      * @param partialValue amount approved. Put 0 if all the amount specified by value is approved.
-     148                 :            :      * @param isApproved approved (true) or refused (false). Put true if you use partialApproval
-     149                 :            :      */
-     150                 :            :     function approveTransferRequest(
-     151                 :            :         TransferRequestKeyElement calldata keyElement,
-     152                 :            :         uint256 partialValue,
-     153                 :            :         bool isApproved
-     154                 :            :     ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
-     155                 :         39 :         _approveTransferRequestKeyElement(keyElement, partialValue, isApproved);
-     156                 :            :     }
-     157                 :            : 
-     158                 :            :     /**
-     159                 :            :      * @notice approve a transferRequestby using its id
-     160                 :            :      */
-     161                 :            :     function approveTransferRequestWithId(
-     162                 :            :         uint256 requestId_,
-     163                 :            :         bool isApproved
-     164                 :            :     ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
-     165            [ + ]:          4 :         if (requestId_ + 1 > requestId) {
-     166                 :          2 :             revert RuleConditionalTransfer_InvalidId();
-     167                 :            :         }
-     168                 :          2 :         TransferRequest memory transferRequest = transferRequests[
-     169                 :            :             IdToKey[requestId_]
-     170                 :            :         ];
-     171                 :          2 :         _approveRequest(transferRequest, isApproved);
-     172                 :            :     }
-     173                 :            : 
-     174                 :            :     /**
-     175                 :            :      * @notice reset to None the status of a request
-     176                 :            :      */
-     177                 :            :     function resetRequestStatus(
-     178                 :            :         uint256 requestId_
-     179                 :            :     ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
-     180            [ + ]:          2 :         if (requestId_ + 1 > requestId) {
-     181                 :          1 :             revert RuleConditionalTransfer_InvalidId();
-     182                 :            :         }
-     183                 :          1 :         bytes32 key = IdToKey[requestId_];
-     184                 :          1 :         _resetRequestStatus(key);
-     185                 :            :     }
-     186                 :            : 
-     187                 :            :     /* ============ Batch function ============ */
-     188                 :            :     /**
-     189                 :            :      * @notice Batch version of {approveTransferRequestWithId}
-     190                 :            :      */
-     191                 :            :     function approveTransferRequestBatchWithId(
-     192                 :            :         uint256[] calldata requestId_,
-     193                 :            :         bool[] calldata isApproved
-     194                 :            :     ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
-     195            [ + ]:          5 :         if (requestId_.length == 0) {
-     196                 :          1 :             revert RuleConditionalTransfer_EmptyArray();
-     197                 :            :         }
-     198            [ + ]:          4 :         if (requestId_.length != isApproved.length) {
-     199                 :          1 :             revert RuleConditionalTransfer_InvalidLengthArray();
-     200                 :            :         }
-     201                 :            :         // Check id validity before performing actions
-     202                 :          3 :         for (uint256 i = 0; i < requestId_.length; ++i) {
-     203            [ + ]:         11 :             if (requestId_[i] + 1 > requestId) {
-     204                 :          1 :                 revert RuleConditionalTransfer_InvalidId();
-     205                 :            :             }
-     206                 :            :         }
-     207                 :          2 :         for (uint256 i = 0; i < requestId_.length; ++i) {
-     208                 :          5 :             TransferRequest memory transferRequest = transferRequests[
-     209                 :            :                 IdToKey[requestId_[i]]
-     210                 :            :             ];
-     211                 :          5 :             _approveRequest(transferRequest, isApproved[i]);
-     212                 :            :         }
-     213                 :            :     }
-     214                 :            : 
-     215                 :            :     /**
-     216                 :            :      * @notice Batch version of {approveTransferRequest}
-     217                 :            :      */
-     218                 :            :     function approveTransferRequestBatch(
-     219                 :            :         TransferRequestKeyElement[] calldata keyElements,
-     220                 :            :         uint256[] calldata partialValues,
-     221                 :            :         bool[] calldata isApproved
-     222                 :            :     ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
-     223            [ + ]:          6 :         if (keyElements.length == 0) {
-     224                 :          1 :             revert RuleConditionalTransfer_EmptyArray();
-     225                 :            :         }
-     226                 :            :         if (
-     227                 :          5 :             (keyElements.length != partialValues.length) ||
-     228                 :            :             (partialValues.length != isApproved.length)
-     229            [ + ]:          3 :         ) {
-     230                 :          3 :             revert RuleConditionalTransfer_InvalidLengthArray();
-     231                 :            :         }
-     232                 :          2 :         for (uint256 i = 0; i < keyElements.length; ++i) {
-     233                 :          9 :             _approveTransferRequestKeyElement(
-     234                 :            :                 keyElements[i],
-     235                 :            :                 partialValues[i],
-     236                 :            :                 isApproved[i]
-     237                 :            :             );
-     238                 :            :         }
-     239                 :            :     }
-     240                 :            : 
-     241                 :            :     /**
-     242                 :            :      * @notice Batch version of {createTransferRequestWithApproval}
-     243                 :            :      */
-     244                 :            :     function createTransferRequestWithApprovalBatch(
-     245                 :            :         TransferRequestKeyElement[] calldata keyElements
-     246                 :            :     ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
-     247            [ + ]:          2 :         if (keyElements.length == 0) {
-     248                 :          1 :             revert RuleConditionalTransfer_EmptyArray();
-     249                 :            :         }
-     250                 :          1 :         for (uint256 i = 0; i < keyElements.length; ++i) {
-     251                 :          4 :             _createTransferRequestWithApproval(keyElements[i]);
-     252                 :            :         }
-     253                 :            :     }
-     254                 :            : 
-     255                 :            :     /**
-     256                 :            :      * @notice Batch version of {resetRequestStatus}
-     257                 :            :      */
-     258                 :            :     function resetRequestStatusBatch(
-     259                 :            :         uint256[] memory requestIds
-     260                 :            :     ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
-     261            [ + ]:          3 :         if (requestIds.length == 0) {
-     262                 :          1 :             revert RuleConditionalTransfer_EmptyArray();
-     263                 :            :         }
-     264                 :            :         // Check id validity before performing actions
-     265                 :          2 :         for (uint256 i = 0; i < requestIds.length; ++i) {
-     266            [ + ]:          4 :             if (requestIds[i] + 1 > requestId) {
-     267                 :          1 :                 revert RuleConditionalTransfer_InvalidId();
-     268                 :            :             }
-     269                 :            :         }
-     270                 :          1 :         for (uint256 i = 0; i < requestIds.length; ++i) {
-     271                 :          3 :             bytes32 key = IdToKey[requestIds[i]];
-     272                 :          3 :             _resetRequestStatus(key);
-     273                 :            :         }
-     274                 :            :     }
-     275                 :            : 
-     276                 :            :     /* ============ ACCESS CONTROL ============ */
-     277                 :            :     /**
-     278                 :            :      * @dev Returns `true` if `account` has been granted `role`.
-     279                 :            :      */
-     280                 :            :     function hasRole(
-     281                 :            :         bytes32 role,
-     282                 :            :         address account
-     283                 :            :     ) public view virtual override(AccessControl) returns (bool) {
-     284                 :            :         // The Default Admin has all roles
-     285            [ + ]:        704 :         if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
-     286                 :        137 :             return true;
-     287                 :            :         }
-     288                 :        567 :         return AccessControl.hasRole(role, account);
-     289                 :            :     }
-     290                 :            : 
-     291                 :            :     /*//////////////////////////////////////////////////////////////
-     292                 :            :                             INTERNAL FUNCTIONS
-     293                 :            :     //////////////////////////////////////////////////////////////*/
-     294                 :            :     function _approveTransferRequestKeyElement(
-     295                 :            :         TransferRequestKeyElement calldata keyElement,
-     296                 :            :         uint256 partialValue,
-     297                 :            :         bool isApproved
-     298                 :            :     ) internal {
-     299            [ + ]:         48 :         if (partialValue > keyElement.value) {
-     300                 :          1 :             revert RuleConditionalTransfer_InvalidValueApproved();
-     301                 :            :         }
-     302                 :         47 :         bytes32 key = keccak256(
-     303                 :            :             abi.encode(keyElement.from, keyElement.to, keyElement.value)
-     304                 :            :         );
-     305                 :         47 :         TransferRequest memory transferRequest = transferRequests[key];
-     306         [ +  + ]:         47 :         if (partialValue > 0) {
-     307            [ + ]:          9 :             if (!isApproved) {
-     308                 :          1 :                 revert RuleConditionalTransfer_CannotDeniedPartially();
-     309                 :            :             }
-     310                 :            :             // Denied the first request
-     311                 :          8 :             _approveRequest(transferRequest, false);
-     312                 :            :             // Create new request
-     313                 :          8 :             _createTransferRequestWithApproval(
-     314                 :            :                 TransferRequestKeyElement({
-     315                 :            :                     from: keyElement.from,
-     316                 :            :                     to: keyElement.to,
-     317                 :            :                     value: partialValue
-     318                 :            :                 })
-     319                 :            :             );
-     320                 :            :         } else {
-     321                 :         38 :             _approveRequest(transferRequest, isApproved);
-     322                 :            :         }
-     323                 :            :     }
-     324                 :            : 
-     325                 :            :     function _createTransferRequestWithApproval(
-     326                 :            :         TransferRequestKeyElement memory keyElement_
-     327                 :            :     ) internal {
-     328                 :            :         // WAIT => Will overwrite
-     329                 :            :         // APPROVED => will overwrite previous status with a new delay
-     330                 :            :         // DENIED => will overwrite
-     331                 :         17 :         bytes32 key = keccak256(
-     332                 :            :             abi.encode(keyElement_.from, keyElement_.to, keyElement_.value)
-     333                 :            :         );
-     334         [ +  + ]:         17 :         if (_checkRequestStatus(key)) {
-     335                 :            :             // Only if it is a new request
-     336                 :         16 :             TransferRequest memory newTransferApproval = TransferRequest({
-     337                 :            :                 key: key,
-     338                 :            :                 id: requestId,
-     339                 :            :                 keyElement: keyElement_,
-     340                 :            :                 askTime: 0,
-     341                 :            :                 // Warning: overflow possible if timeLimitToTransfer == max(uint256)
-     342                 :            :                 maxTime: block.timestamp +
-     343                 :            :                     options.timeLimit.timeLimitToTransfer,
-     344                 :            :                 status: STATUS.APPROVED
-     345                 :            :             });
-     346                 :         16 :             transferRequests[key] = newTransferApproval;
-     347                 :         16 :             IdToKey[requestId] = key;
-     348                 :         16 :             emit transferApproved(
-     349                 :            :                 key,
-     350                 :            :                 keyElement_.from,
-     351                 :            :                 keyElement_.to,
-     352                 :            :                 keyElement_.value,
-     353                 :            :                 requestId
-     354                 :            :             );
-     355                 :         16 :             ++requestId;
-     356                 :            :         } else {
-     357                 :            :             // Overwrite previous approval
-     358                 :            :             // Warning: overflow possible if timeLimitToTransfer == max(uint256)
-     359                 :          1 :             transferRequests[key].maxTime =
-     360                 :            :                 block.timestamp +
-     361                 :            :                 options.timeLimit.timeLimitToTransfer;
-     362                 :          1 :             transferRequests[key].status = STATUS.APPROVED;
-     363                 :          1 :             emit transferApproved(
-     364                 :            :                 key,
-     365                 :            :                 keyElement_.from,
-     366                 :            :                 keyElement_.to,
-     367                 :            :                 keyElement_.value,
-     368                 :            :                 transferRequests[key].id
-     369                 :            :             );
-     370                 :            :         }
-     371                 :            :     }
-     372                 :            : 
-     373                 :            :     function _resetRequestStatus(bytes32 key) internal {
-     374                 :         10 :         transferRequests[key].status = STATUS.NONE;
-     375                 :         10 :         emit transferReset(
-     376                 :            :             key,
-     377                 :            :             transferRequests[key].keyElement.from,
-     378                 :            :             transferRequests[key].keyElement.to,
-     379                 :            :             transferRequests[key].keyElement.value,
-     380                 :            :             transferRequests[key].id
-     381                 :            :         );
-     382                 :            :     }
-     383                 :            : 
-     384                 :            :     /**
-     385                 :            :     * @dev check if it is a new request or not
-     386                 :            :     */
-     387                 :            :     function _checkRequestStatus(bytes32 key) internal view returns (bool) {
-     388                 :            :         // Status NONE not enough because reset is possible
-     389                 :        133 :         return
-     390                 :        133 :             (transferRequests[key].status == STATUS.NONE) &&
-     391                 :            :             (transferRequests[key].key == 0x0);
-     392                 :            :     }
-     393                 :            : 
-     394                 :            :     function _approveRequest(
-     395                 :            :         TransferRequest memory transferRequest,
-     396                 :            :         bool isApproved
-     397                 :            :     ) internal {
-     398                 :            :         // status
-     399            [ + ]:         53 :         if (transferRequest.status != STATUS.WAIT) {
-     400                 :          1 :             revert RuleConditionalTransfer_Wrong_Status();
-     401                 :            :         }
-     402         [ +  + ]:         32 :         if (isApproved) {
-     403                 :            :             // Time
-     404                 :            :             if (
-     405                 :         32 :                 block.timestamp >
-     406                 :            :                 (transferRequest.askTime + options.timeLimit.timeLimitToApprove)
-     407            [ + ]:          3 :             ) {
-     408                 :          3 :                 revert RuleConditionalTransfer_timeExceeded();
-     409                 :            :             }
-     410                 :            :             // Set status
-     411                 :         29 :             transferRequests[transferRequest.key].status = STATUS.APPROVED;
-     412                 :            :             // Set max time
-     413                 :         29 :             transferRequests[transferRequest.key].maxTime =
-     414                 :            :                 block.timestamp +
-     415                 :            :                 options.timeLimit.timeLimitToTransfer;
-     416                 :         29 :             emit transferApproved(
-     417                 :            :                 transferRequest.key,
-     418                 :            :                 transferRequest.keyElement.from,
-     419                 :            :                 transferRequest.keyElement.to,
-     420                 :            :                 transferRequest.keyElement.value,
-     421                 :            :                 transferRequests[transferRequest.key].id
-     422                 :            :             );
-     423                 :            :             if (
-     424                 :         29 :                 options.automaticTransfer.isActivate &&
-     425                 :          7 :                 address(options.automaticTransfer.cmtat) != address(0)
-     426            [ + ]:          7 :             ) {
-     427                 :            :                 // Transfer with approval
-     428                 :            :                 // External call
-     429                 :            :                 if (
-     430                 :          7 :                     options.automaticTransfer.cmtat.allowance(
-     431                 :            :                         transferRequest.keyElement.from,
-     432                 :            :                         address(this)
-     433                 :            :                     ) >= transferRequest.keyElement.value
-     434            [ + ]:          3 :                 ) {
-     435                 :            :                     // Will call the ruleEngine and the rule again...
-     436                 :          3 :                     options.automaticTransfer.cmtat.safeTransferFrom(
-     437                 :            :                         transferRequest.keyElement.from,
-     438                 :            :                         transferRequest.keyElement.to,
-     439                 :            :                         transferRequest.keyElement.value
-     440                 :            :                     );
-     441                 :            :                 }
-     442                 :            :             }
-     443                 :            :         } else {
-     444                 :         20 :             transferRequests[transferRequest.key].status = STATUS.DENIED;
-     445                 :         20 :             emit transferDenied(
-     446                 :            :                 transferRequest.key,
-     447                 :            :                 transferRequest.keyElement.from,
-     448                 :            :                 transferRequest.keyElement.to,
-     449                 :            :                 transferRequest.keyElement.value,
-     450                 :            :                 transferRequests[transferRequest.key].id
-     451                 :            :             );
-     452                 :            :         }
-     453                 :            :     }
-     454                 :            : 
-     455                 :            :     /**
-     456                 :            :      * @notice update the request during a transfer
-     457                 :            :      */
-     458                 :            :     function _updateProcessedTransfer(bytes32 key) internal {
-     459                 :            :         // Reset to zero
-     460                 :         18 :         transferRequests[key].maxTime = 0;
-     461                 :         18 :         transferRequests[key].askTime = 0;
-     462                 :            :         // Change status
-     463                 :         18 :         transferRequests[key].status = STATUS.EXECUTED;
-     464                 :            :         // Emit event
-     465                 :         18 :         emit transferProcessed(
-     466                 :            :             key,
-     467                 :            :             transferRequests[key].keyElement.from,
-     468                 :            :             transferRequests[key].keyElement.to,
-     469                 :            :             transferRequests[key].keyElement.value,
-     470                 :            :             transferRequests[key].id
-     471                 :            :         );
-     472                 :            :     }
-     473                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/operation/index-sort-b.html b/doc/coverage/coverage/src/rules/operation/index-sort-b.html deleted file mode 100644 index d14d712..0000000 --- a/doc/coverage/coverage/src/rules/operation/index-sort-b.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/operation - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operationHitTotalCoverage
Test:lcov.infoLines:10510699.1 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:3333100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransfer.sol -
99.1%99.1%
-
99.1 %105 / 10694.4 %17 / 18100.0 %33 / 33
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/operation/index-sort-f.html b/doc/coverage/coverage/src/rules/operation/index-sort-f.html deleted file mode 100644 index d28f603..0000000 --- a/doc/coverage/coverage/src/rules/operation/index-sort-f.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/operation - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operationHitTotalCoverage
Test:lcov.infoLines:10510699.1 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:3333100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransfer.sol -
99.1%99.1%
-
99.1 %105 / 10694.4 %17 / 18100.0 %33 / 33
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/operation/index-sort-l.html b/doc/coverage/coverage/src/rules/operation/index-sort-l.html deleted file mode 100644 index ece5b0b..0000000 --- a/doc/coverage/coverage/src/rules/operation/index-sort-l.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/operation - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operationHitTotalCoverage
Test:lcov.infoLines:10510699.1 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:3333100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransfer.sol -
99.1%99.1%
-
99.1 %105 / 10694.4 %17 / 18100.0 %33 / 33
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/operation/index.html b/doc/coverage/coverage/src/rules/operation/index.html deleted file mode 100644 index 260d74e..0000000 --- a/doc/coverage/coverage/src/rules/operation/index.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/operation - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/operationHitTotalCoverage
Test:lcov.infoLines:10510699.1 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:3333100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransfer.sol -
99.1%99.1%
-
99.1 %105 / 10694.4 %17 / 18100.0 %33 / 33
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.func-sort-c.html deleted file mode 100644 index a23344e..0000000 --- a/doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.func-sort-c.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/RuleBlacklist.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation - RuleBlacklist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1313100.0 %
Date:2024-12-20 10:41:14Functions:44100.0 %
Branches:88100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

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

Function Name Sort by function nameHit count Sort by hit count
RuleBlacklist.12
RuleBlacklist.canReturnTransferRestrictionCode4
RuleBlacklist.detectTransferRestriction10
RuleBlacklist.messageForTransferRestriction4
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.gcov.html b/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.gcov.html deleted file mode 100644 index 299cb3a..0000000 --- a/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.gcov.html +++ /dev/null @@ -1,250 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/RuleSanctionList.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation - RuleSanctionList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:272896.4 %
Date:2024-12-20 10:41:14Functions:91090.0 %
Branches:1111100.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.20;
-       4                 :            : 
-       5                 :            : import "OZ/access/AccessControl.sol";
-       6                 :            : import "../../modules/MetaTxModuleStandalone.sol";
-       7                 :            : import "./abstract/RuleSanctionListInvariantStorage.sol";
-       8                 :            : import "./abstract/RuleValidateTransfer.sol";
-       9                 :            : 
-      10                 :            : interface SanctionsList {
-      11                 :            :     function isSanctioned(address addr) external view returns (bool);
-      12                 :            : }
-      13                 :            : 
-      14                 :            : contract RuleSanctionList is
-      15                 :            :     AccessControl,
-      16                 :            :     MetaTxModuleStandalone,
-      17                 :            :     RuleValidateTransfer,
-      18                 :            :     RuleSanctionlistInvariantStorage
-      19                 :            : {
-      20                 :            :     SanctionsList public sanctionsList;
-      21                 :            : 
-      22                 :            :     /**
-      23                 :            :      * @param admin Address of the contract (Access Control)
-      24                 :            :      * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
-      25                 :            :      */
-      26                 :            :     constructor(
-      27                 :            :         address admin,
-      28                 :            :         address forwarderIrrevocable,
-      29                 :            :         address sanctionContractOracle_
-      30                 :            :     ) MetaTxModuleStandalone(forwarderIrrevocable) {
-      31            [ + ]:         13 :         if (admin == address(0)) {
-      32                 :          1 :             revert RuleSanctionList_AdminWithAddressZeroNotAllowed();
-      33                 :            :         }
-      34            [ + ]:         12 :         if (sanctionContractOracle_ != address(0)) {
-      35                 :          1 :             _setSanctionListOracle(sanctionContractOracle_);
-      36                 :            :         }
-      37                 :         12 :         _grantRole(DEFAULT_ADMIN_ROLE, admin);
-      38                 :            :     }
-      39                 :            : 
-      40                 :            :     /**
-      41                 :            :      * @notice Set the oracle contract
-      42                 :            :      * @param sanctionContractOracle_ address of your oracle contract
-      43                 :            :      * @dev zero address is authorized to authorize all transfers
-      44                 :            :      */
-      45                 :            :     function setSanctionListOracle(
-      46                 :            :         address sanctionContractOracle_
-      47                 :            :     ) public onlyRole(SANCTIONLIST_ROLE) {
-      48                 :         10 :         _setSanctionListOracle(sanctionContractOracle_);
-      49                 :            :     }
-      50                 :            : 
-      51                 :            :     /**
-      52                 :            :      * @notice Check if an addres is in the whitelist or not
-      53                 :            :      * @param _from the origin address
-      54                 :            :      * @param _to the destination address
-      55                 :            :      * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
-      56                 :            :      **/
-      57                 :            :     function detectTransferRestriction(
-      58                 :            :         address _from,
-      59                 :            :         address _to,
-      60                 :            :         uint256 /*_amount */
-      61                 :            :     ) public view override returns (uint8) {
-      62            [ + ]:          7 :         if (address(sanctionsList) != address(0)) {
-      63         [ +  + ]:          7 :             if (sanctionsList.isSanctioned(_from)) {
-      64                 :          2 :                 return CODE_ADDRESS_FROM_IS_SANCTIONED;
-      65            [ + ]:          5 :             } else if (sanctionsList.isSanctioned(_to)) {
-      66                 :          2 :                 return CODE_ADDRESS_TO_IS_SANCTIONED;
-      67                 :            :             }
-      68                 :            :         }
-      69                 :          3 :         return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
-      70                 :            :     }
-      71                 :            : 
-      72                 :            :     /**
-      73                 :            :      * @notice To know if the restriction code is valid for this rule or not.
-      74                 :            :      * @param _restrictionCode The target restriction code
-      75                 :            :      * @return true if the restriction code is known, false otherwise
-      76                 :            :      **/
-      77                 :            :     function canReturnTransferRestrictionCode(
-      78                 :            :         uint8 _restrictionCode
-      79                 :            :     ) external pure override returns (bool) {
-      80                 :          3 :         return
-      81                 :          3 :             _restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED ||
-      82                 :          2 :             _restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED;
-      83                 :            :     }
-      84                 :            : 
-      85                 :            :     /**
-      86                 :            :      * @notice Return the corresponding message
-      87                 :            :      * @param _restrictionCode The target restriction code
-      88                 :            :      * @return true if the transfer is valid, false otherwise
-      89                 :            :      **/
-      90                 :            :     function messageForTransferRestriction(
-      91                 :            :         uint8 _restrictionCode
-      92                 :            :     ) external pure override returns (string memory) {
-      93         [ +  + ]:          3 :         if (_restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED) {
-      94                 :          1 :             return TEXT_ADDRESS_FROM_IS_SANCTIONED;
-      95         [ +  + ]:          2 :         } else if (_restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED) {
-      96                 :          1 :             return TEXT_ADDRESS_TO_IS_SANCTIONED;
-      97                 :            :         } else {
-      98                 :          1 :             return TEXT_CODE_NOT_FOUND;
-      99                 :            :         }
-     100                 :            :     }
-     101                 :            : 
-     102                 :            :     /* ============ ACCESS CONTROL ============ */
-     103                 :            :     /**
-     104                 :            :      * @dev Returns `true` if `account` has been granted `role`.
-     105                 :            :      */
-     106                 :            :     function hasRole(
-     107                 :            :         bytes32 role,
-     108                 :            :         address account
-     109                 :            :     ) public view virtual override(AccessControl) returns (bool) {
-     110                 :            :         // The Default Admin has all roles
-     111            [ + ]:         24 :         if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
-     112                 :         11 :             return true;
-     113                 :            :         }
-     114                 :         13 :         return AccessControl.hasRole(role, account);
-     115                 :            :     }
-     116                 :            : 
-     117                 :            :     /*//////////////////////////////////////////////////////////////
-     118                 :            :                             INTERNAL FUNCTIONS
-     119                 :            :     //////////////////////////////////////////////////////////////*/
-     120                 :            : 
-     121                 :            :     function _setSanctionListOracle(address sanctionContractOracle_) internal {
-     122                 :         11 :         sanctionsList = SanctionsList(sanctionContractOracle_);
-     123                 :         11 :         emit SetSanctionListOracle(address(sanctionContractOracle_));
-     124                 :            :     }
-     125                 :            : 
-     126                 :            :     /*//////////////////////////////////////////////////////////////
-     127                 :            :                            ERC-2771
-     128                 :            :     //////////////////////////////////////////////////////////////*/
-     129                 :            : 
-     130                 :            :     /**
-     131                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
-     132                 :            :      */
-     133                 :            :     function _msgSender()
-     134                 :            :         internal
-     135                 :            :         view
-     136                 :            :         override(ERC2771Context, Context)
-     137                 :            :         returns (address sender)
-     138                 :            :     {
-     139                 :         23 :         return ERC2771Context._msgSender();
-     140                 :            :     }
-     141                 :            : 
-     142                 :            :     /**
-     143                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
-     144                 :            :      */
-     145                 :            :     function _msgData()
-     146                 :            :         internal
-     147                 :            :         view
-     148                 :            :         override(ERC2771Context, Context)
-     149                 :            :         returns (bytes calldata)
-     150                 :            :     {
-     151                 :          0 :         return ERC2771Context._msgData();
-     152                 :            :     }
-     153                 :            : 
-     154                 :            :     /**
-     155                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
-     156                 :            :      */
-     157                 :            :     function _contextSuffixLength()
-     158                 :            :         internal
-     159                 :            :         view
-     160                 :            :         override(ERC2771Context, Context)
-     161                 :            :         returns (uint256)
-     162                 :            :     {
-     163                 :         23 :         return ERC2771Context._contextSuffixLength();
-     164                 :            :     }
-     165                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/RuleWhitelist.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/validation/RuleWhitelist.sol.func-sort-c.html deleted file mode 100644 index 3983775..0000000 --- a/doc/coverage/coverage/src/rules/validation/RuleWhitelist.sol.func-sort-c.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/RuleWhitelist.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation - RuleWhitelist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:55100.0 %
Date:2024-12-20 10:41:14Functions:22100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - -

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

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

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.20;
-       4                 :            : 
-       5                 :            : import "./abstract/RuleAddressList/RuleAddressList.sol";
-       6                 :            : import "./abstract/RuleWhitelistCommon.sol";
-       7                 :            : 
-       8                 :            : /**
-       9                 :            :  * @title a whitelist manager
-      10                 :            :  */
-      11                 :            : contract RuleWhitelist is RuleAddressList, RuleWhitelistCommon {
-      12                 :            :     /**
-      13                 :            :      * @param admin Address of the contract (Access Control)
-      14                 :            :      * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
-      15                 :            :      */
-      16                 :            :     constructor(
-      17                 :            :         address admin,
-      18                 :            :         address forwarderIrrevocable
-      19                 :            :     ) RuleAddressList(admin, forwarderIrrevocable) {}
-      20                 :            : 
-      21                 :            :     /**
-      22                 :            :      * @notice Check if an addres is in the whitelist or not
-      23                 :            :      * @param _from the origin address
-      24                 :            :      * @param _to the destination address
-      25                 :            :      * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
-      26                 :            :      **/
-      27                 :            :     function detectTransferRestriction(
-      28                 :            :         address _from,
-      29                 :            :         address _to,
-      30                 :            :         uint256 /*_amount */
-      31                 :            :     ) public view override returns (uint8) {
-      32         [ +  + ]:         28 :         if (!addressIsListed(_from)) {
-      33                 :         13 :             return CODE_ADDRESS_FROM_NOT_WHITELISTED;
-      34         [ +  + ]:         15 :         } else if (!addressIsListed(_to)) {
-      35                 :          5 :             return CODE_ADDRESS_TO_NOT_WHITELISTED;
-      36                 :            :         } else {
-      37                 :         10 :             return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
-      38                 :            :         }
-      39                 :            :     }
-      40                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func-sort-c.html deleted file mode 100644 index 50d42d4..0000000 --- a/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func-sort-c.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/RuleWhitelistWrapper.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation - RuleWhitelistWrapper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:272896.4 %
Date:2024-12-20 10:41:14Functions:5683.3 %
Branches:99100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistWrapper._msgData0
RuleWhitelistWrapper.detectTransferRestriction11
RuleWhitelistWrapper.hasRole13
RuleWhitelistWrapper.14
RuleWhitelistWrapper._contextSuffixLength52
RuleWhitelistWrapper._msgSender52
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func.html b/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func.html deleted file mode 100644 index 87ddb39..0000000 --- a/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.func.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/RuleWhitelistWrapper.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation - RuleWhitelistWrapper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:272896.4 %
Date:2024-12-20 10:41:14Functions:5683.3 %
Branches:99100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistWrapper.14
RuleWhitelistWrapper._contextSuffixLength52
RuleWhitelistWrapper._msgData0
RuleWhitelistWrapper._msgSender52
RuleWhitelistWrapper.detectTransferRestriction11
RuleWhitelistWrapper.hasRole13
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.gcov.html b/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.gcov.html deleted file mode 100644 index 497bf06..0000000 --- a/doc/coverage/coverage/src/rules/validation/RuleWhitelistWrapper.sol.gcov.html +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/RuleWhitelistWrapper.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation - RuleWhitelistWrapper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:272896.4 %
Date:2024-12-20 10:41:14Functions:5683.3 %
Branches:99100.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.20;
-       4                 :            : 
-       5                 :            : import "OZ/access/AccessControl.sol";
-       6                 :            : import "../../modules/RuleEngineValidationCommon.sol";
-       7                 :            : import "../../modules/MetaTxModuleStandalone.sol";
-       8                 :            : import "./abstract/RuleAddressList/RuleAddressList.sol";
-       9                 :            : import "./abstract/RuleWhitelistCommon.sol";
-      10                 :            : 
-      11                 :            : /**
-      12                 :            :  * @title Wrapper to call several different whitelist rules
-      13                 :            :  */
-      14                 :            : contract RuleWhitelistWrapper is
-      15                 :            :     RuleEngineValidationCommon,
-      16                 :            :     MetaTxModuleStandalone,
-      17                 :            :     RuleWhitelistCommon
-      18                 :            : {
-      19                 :            :     /**
-      20                 :            :      * @param admin Address of the contract (Access Control)
-      21                 :            :      * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
-      22                 :            :      */
-      23                 :            :     constructor(
-      24                 :            :         address admin,
-      25                 :            :         address forwarderIrrevocable
-      26                 :            :     ) MetaTxModuleStandalone(forwarderIrrevocable) {
-      27            [ + ]:         14 :         if (admin == address(0)) {
-      28                 :          1 :             revert RuleEngine_AdminWithAddressZeroNotAllowed();
-      29                 :            :         }
-      30                 :         13 :         _grantRole(DEFAULT_ADMIN_ROLE, admin);
-      31                 :            :     }
-      32                 :            : 
-      33                 :            :     /**
-      34                 :            :      * @notice Go through all the whitelist rules to know if a restriction exists on the transfer
-      35                 :            :      * @param _from the origin address
-      36                 :            :      * @param _to the destination address
-      37                 :            :      * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
-      38                 :            :      **/
-      39                 :            :     function detectTransferRestriction(
-      40                 :            :         address _from,
-      41                 :            :         address _to,
-      42                 :            :         uint256 /*_amount*/
-      43                 :            :     ) public view override returns (uint8) {
-      44                 :         11 :         address[] memory targetAddress = new address[](2);
-      45                 :         11 :         bool[] memory isListed = new bool[](2);
-      46                 :         11 :         bool[] memory result = new bool[](2);
-      47                 :         11 :         targetAddress[0] = _from;
-      48                 :         11 :         targetAddress[1] = _to;
-      49                 :         11 :         uint256 rulesLength = _rulesValidation.length;
-      50                 :            :         // For each whitelist rule, we ask if from or to are in the whitelist
-      51                 :         11 :         for (uint256 i = 0; i < rulesLength; ++i) {
-      52                 :            :             // External call
-      53                 :         25 :             isListed = RuleAddressList(_rulesValidation[i])
-      54                 :            :                 .addressIsListedBatch(targetAddress);
-      55            [ + ]:         25 :             if (isListed[0] && !result[0]) {
-      56                 :            :                 // Update if from is in the list
-      57                 :          7 :                 result[0] = true;
-      58                 :            :             }
-      59            [ + ]:         25 :             if (isListed[1] && !result[1]) {
-      60                 :            :                 // Update if to is in the list
-      61                 :          7 :                 result[1] = true;
-      62                 :            :             }
-      63            [ + ]:         25 :             if (result[0] && result[1]) {
-      64                 :         25 :                 break;
-      65                 :            :             }
-      66                 :            :         }
-      67         [ +  + ]:         11 :         if (!result[0]) {
-      68                 :          4 :             return CODE_ADDRESS_FROM_NOT_WHITELISTED;
-      69         [ +  + ]:          7 :         } else if (!result[1]) {
-      70                 :          2 :             return CODE_ADDRESS_TO_NOT_WHITELISTED;
-      71                 :            :         } else {
-      72                 :          5 :             return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
-      73                 :            :         }
-      74                 :            :     }
-      75                 :            : 
-      76                 :            :     /* ============ ACCESS CONTROL ============ */
-      77                 :            :     /**
-      78                 :            :      * @dev Returns `true` if `account` has been granted `role`.
-      79                 :            :      */
-      80                 :            :     function hasRole(
-      81                 :            :         bytes32 role,
-      82                 :            :         address account
-      83                 :            :     ) public view virtual override(AccessControl) returns (bool) {
-      84                 :            :         // The Default Admin has all roles
-      85            [ + ]:         52 :         if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
-      86                 :         39 :             return true;
-      87                 :            :         }
-      88                 :         13 :         return AccessControl.hasRole(role, account);
-      89                 :            :     }
-      90                 :            : 
-      91                 :            :     /*//////////////////////////////////////////////////////////////
-      92                 :            :                            ERC-2771
-      93                 :            :     //////////////////////////////////////////////////////////////*/
-      94                 :            : 
-      95                 :            :     /**
-      96                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
-      97                 :            :      */
-      98                 :            :     function _msgSender()
-      99                 :            :         internal
-     100                 :            :         view
-     101                 :            :         override(ERC2771Context, Context)
-     102                 :            :         returns (address sender)
-     103                 :            :     {
-     104                 :         52 :         return ERC2771Context._msgSender();
-     105                 :            :     }
-     106                 :            : 
-     107                 :            :     /**
-     108                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
-     109                 :            :      */
-     110                 :            :     function _msgData()
-     111                 :            :         internal
-     112                 :            :         view
-     113                 :            :         override(ERC2771Context, Context)
-     114                 :            :         returns (bytes calldata)
-     115                 :            :     {
-     116                 :          0 :         return ERC2771Context._msgData();
-     117                 :            :     }
-     118                 :            : 
-     119                 :            :     /**
-     120                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
-     121                 :            :      */
-     122                 :            :     function _contextSuffixLength()
-     123                 :            :         internal
-     124                 :            :         view
-     125                 :            :         override(ERC2771Context, Context)
-     126                 :            :         returns (uint256)
-     127                 :            :     {
-     128                 :         52 :         return ERC2771Context._contextSuffixLength();
-     129                 :            :     }
-     130                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func-sort-c.html deleted file mode 100644 index 98ee305..0000000 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func-sort-c.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressList - RuleAddressList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:222395.7 %
Date:2024-12-20 10:41:14Functions:111291.7 %
Branches:22100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleAddressList._msgData0
RuleAddressList.removeAddressFromTheList3
RuleAddressList.removeAddressesFromTheList4
RuleAddressList.addAddressesToTheList17
RuleAddressList.numberListedAddress24
RuleAddressList.addressIsListedBatch28
RuleAddressList.addAddressToTheList52
RuleAddressList.addressIsListed101
RuleAddressList.185
RuleAddressList.hasRole194
RuleAddressList._contextSuffixLength270
RuleAddressList._msgSender270
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func.html deleted file mode 100644 index ed5ebcb..0000000 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressList - RuleAddressList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:222395.7 %
Date:2024-12-20 10:41:14Functions:111291.7 %
Branches:22100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleAddressList.185
RuleAddressList._contextSuffixLength270
RuleAddressList._msgData0
RuleAddressList._msgSender270
RuleAddressList.addAddressToTheList52
RuleAddressList.addAddressesToTheList17
RuleAddressList.addressIsListed101
RuleAddressList.addressIsListedBatch28
RuleAddressList.hasRole194
RuleAddressList.numberListedAddress24
RuleAddressList.removeAddressFromTheList3
RuleAddressList.removeAddressesFromTheList4
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func-sort-c.html deleted file mode 100644 index 5b3956f..0000000 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func-sort-c.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressList - RuleAddressListInternal.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2222100.0 %
Date:2024-12-20 10:41:14Functions:66100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleAddressListInternal._removeAddressFromThelist2
RuleAddressListInternal._removeAddressesFromThelist3
RuleAddressListInternal._addAddressesToThelist16
RuleAddressListInternal._numberListedAddress24
RuleAddressListInternal._addAddressToThelist51
RuleAddressListInternal._addressIsListed214
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func.html deleted file mode 100644 index d5e1465..0000000 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressList - RuleAddressListInternal.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2222100.0 %
Date:2024-12-20 10:41:14Functions:66100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleAddressListInternal._addAddressToThelist51
RuleAddressListInternal._addAddressesToThelist16
RuleAddressListInternal._addressIsListed214
RuleAddressListInternal._numberListedAddress24
RuleAddressListInternal._removeAddressFromThelist2
RuleAddressListInternal._removeAddressesFromThelist3
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.gcov.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.gcov.html deleted file mode 100644 index f91cf24..0000000 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.gcov.html +++ /dev/null @@ -1,186 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressList - RuleAddressListInternal.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2222100.0 %
Date:2024-12-20 10:41:14Functions:66100.0 %
Branches:44100.0 %
-
- - - - - - - - -

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

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleAddressList.sol -
95.7%95.7%
-
95.7 %22 / 2391.7 %11 / 12100.0 %2 / 2
RuleAddressListInternal.sol -
100.0%
-
100.0 %22 / 22100.0 %6 / 6100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-f.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-f.html deleted file mode 100644 index d55918c..0000000 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-f.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressListHitTotalCoverage
Test:lcov.infoLines:444597.8 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:66100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleAddressList.sol -
95.7%95.7%
-
95.7 %22 / 2391.7 %11 / 12100.0 %2 / 2
RuleAddressListInternal.sol -
100.0%
-
100.0 %22 / 22100.0 %6 / 6100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-l.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-l.html deleted file mode 100644 index 94dea7d..0000000 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-l.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressListHitTotalCoverage
Test:lcov.infoLines:444597.8 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:66100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleAddressList.sol -
95.7%95.7%
-
95.7 %22 / 2391.7 %11 / 12100.0 %2 / 2
RuleAddressListInternal.sol -
100.0%
-
100.0 %22 / 22100.0 %6 / 6100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index.html deleted file mode 100644 index b24b451..0000000 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/index.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract/RuleAddressListHitTotalCoverage
Test:lcov.infoLines:444597.8 %
Date:2024-12-20 10:41:14Functions:171894.4 %
Branches:66100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleAddressList.sol -
95.7%95.7%
-
95.7 %22 / 2391.7 %11 / 12100.0 %2 / 2
RuleAddressListInternal.sol -
100.0%
-
100.0 %22 / 22100.0 %6 / 6100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html b/doc/coverage/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html deleted file mode 100644 index 9025b1d..0000000 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/abstract/RuleValidateTransfer.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstract - RuleValidateTransfer.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - -

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

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

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

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleValidateTransfer.sol -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
RuleWhitelistCommon.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/abstract/index-sort-f.html b/doc/coverage/coverage/src/rules/validation/abstract/index-sort-f.html deleted file mode 100644 index 37e913e..0000000 --- a/doc/coverage/coverage/src/rules/validation/abstract/index-sort-f.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/abstract - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstractHitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2024-12-20 10:41:14Functions:33100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleValidateTransfer.sol -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
RuleWhitelistCommon.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/abstract/index-sort-l.html b/doc/coverage/coverage/src/rules/validation/abstract/index-sort-l.html deleted file mode 100644 index 51f2975..0000000 --- a/doc/coverage/coverage/src/rules/validation/abstract/index-sort-l.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/abstract - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstractHitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2024-12-20 10:41:14Functions:33100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleValidateTransfer.sol -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
RuleWhitelistCommon.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/abstract/index.html b/doc/coverage/coverage/src/rules/validation/abstract/index.html deleted file mode 100644 index 74cd455..0000000 --- a/doc/coverage/coverage/src/rules/validation/abstract/index.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation/abstract - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validation/abstractHitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2024-12-20 10:41:14Functions:33100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleValidateTransfer.sol -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
RuleWhitelistCommon.sol -
100.0%
-
100.0 %8 / 8100.0 %2 / 2100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/index-sort-b.html b/doc/coverage/coverage/src/rules/validation/index-sort-b.html deleted file mode 100644 index d627eb6..0000000 --- a/doc/coverage/coverage/src/rules/validation/index-sort-b.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validationHitTotalCoverage
Test:lcov.infoLines:727497.3 %
Date:2024-12-20 10:41:14Functions:202290.9 %
Branches:3232100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleWhitelist.sol -
100.0%
-
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
RuleBlacklist.sol -
100.0%
-
100.0 %13 / 13100.0 %4 / 4100.0 %8 / 8
RuleWhitelistWrapper.sol -
96.4%96.4%
-
96.4 %27 / 2883.3 %5 / 6100.0 %9 / 9
RuleSanctionList.sol -
96.4%96.4%
-
96.4 %27 / 2890.0 %9 / 10100.0 %11 / 11
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/index-sort-f.html b/doc/coverage/coverage/src/rules/validation/index-sort-f.html deleted file mode 100644 index 7939279..0000000 --- a/doc/coverage/coverage/src/rules/validation/index-sort-f.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validationHitTotalCoverage
Test:lcov.infoLines:727497.3 %
Date:2024-12-20 10:41:14Functions:202290.9 %
Branches:3232100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleWhitelistWrapper.sol -
96.4%96.4%
-
96.4 %27 / 2883.3 %5 / 6100.0 %9 / 9
RuleSanctionList.sol -
96.4%96.4%
-
96.4 %27 / 2890.0 %9 / 10100.0 %11 / 11
RuleWhitelist.sol -
100.0%
-
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
RuleBlacklist.sol -
100.0%
-
100.0 %13 / 13100.0 %4 / 4100.0 %8 / 8
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/index-sort-l.html b/doc/coverage/coverage/src/rules/validation/index-sort-l.html deleted file mode 100644 index e147ebd..0000000 --- a/doc/coverage/coverage/src/rules/validation/index-sort-l.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validationHitTotalCoverage
Test:lcov.infoLines:727497.3 %
Date:2024-12-20 10:41:14Functions:202290.9 %
Branches:3232100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleSanctionList.sol -
96.4%96.4%
-
96.4 %27 / 2890.0 %9 / 10100.0 %11 / 11
RuleWhitelistWrapper.sol -
96.4%96.4%
-
96.4 %27 / 2883.3 %5 / 6100.0 %9 / 9
RuleWhitelist.sol -
100.0%
-
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
RuleBlacklist.sol -
100.0%
-
100.0 %13 / 13100.0 %4 / 4100.0 %8 / 8
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/src/rules/validation/index.html b/doc/coverage/coverage/src/rules/validation/index.html deleted file mode 100644 index 3d1ec09..0000000 --- a/doc/coverage/coverage/src/rules/validation/index.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - LCOV - lcov.info - src/rules/validation - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - src/rules/validationHitTotalCoverage
Test:lcov.infoLines:727497.3 %
Date:2024-12-20 10:41:14Functions:202290.9 %
Branches:3232100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleBlacklist.sol -
100.0%
-
100.0 %13 / 13100.0 %4 / 4100.0 %8 / 8
RuleSanctionList.sol -
96.4%96.4%
-
96.4 %27 / 2890.0 %9 / 10100.0 %11 / 11
RuleWhitelist.sol -
100.0%
-
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
RuleWhitelistWrapper.sol -
96.4%96.4%
-
96.4 %27 / 2883.3 %5 / 6100.0 %9 / 9
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.gcov.html b/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.gcov.html deleted file mode 100644 index 471014d..0000000 --- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.gcov.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - - LCOV - lcov.info - test/RuleConditionalTransfer/utils/RuleCTDeployment.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/RuleConditionalTransfer/utils - RuleCTDeployment.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : pragma solidity ^0.8.20;
-       3                 :            : 
-       4                 :            : import "forge-std/Test.sol";
-       5                 :            : import "../../HelperContract.sol";
-       6                 :            : import "src/RuleEngine.sol";
-       7                 :            : 
-       8                 :            : /**
-       9                 :            :  * @title Tests on the Access Control
-      10                 :            :  */
-      11                 :            : contract RuleCTDeployment is Test, HelperContract {
-      12                 :            :     // Arrange
-      13                 :            :     constructor() {
-      14                 :         13 :         TIME_LIMIT memory timeLimit_ = TIME_LIMIT({
-      15                 :            :             timeLimitToApprove: 7 days,
-      16                 :            :             timeLimitToTransfer: 30 days
-      17                 :            :         });
-      18                 :            : 
-      19                 :         13 :         AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
-      20                 :            :             isActivate: false,
-      21                 :            :             timeLimitBeforeAutomaticApproval: 0
-      22                 :            :         });
-      23                 :            : 
-      24                 :         13 :         ISSUANCE memory issuanceOption_ = ISSUANCE({
-      25                 :            :             authorizedMintWithoutApproval: false,
-      26                 :            :             authorizedBurnWithoutApproval: false
-      27                 :            :         });
-      28                 :         13 :         AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({
-      29                 :            :             isActivate: false,
-      30                 :            :             cmtat: IERC20(address(0))
-      31                 :            :         });
-      32                 :            : 
-      33                 :         13 :         OPTION memory options = OPTION({
-      34                 :            :             issuance: issuanceOption_,
-      35                 :            :             timeLimit: timeLimit_,
-      36                 :            :             automaticApproval: automaticApproval_,
-      37                 :            :             automaticTransfer: automaticTransfer_
-      38                 :            :         });
-      39                 :         13 :         ruleEngineMock = new RuleEngine(
-      40                 :            :             RULE_ENGINE_OPERATOR_ADDRESS,
-      41                 :            :             ZERO_ADDRESS,
-      42                 :            :             ZERO_ADDRESS
-      43                 :            :         );
-      44                 :         13 :         vm.prank(DEFAULT_ADMIN_ADDRESS);
-      45                 :         13 :         ruleConditionalTransfer = new RuleConditionalTransfer(
-      46                 :            :             DEFAULT_ADMIN_ADDRESS,
-      47                 :            :             ZERO_ADDRESS,
-      48                 :            :             ruleEngineMock,
-      49                 :            :             options
-      50                 :            :         );
-      51                 :         13 :         vm.prank(DEFAULT_ADMIN_ADDRESS);
-      52                 :         13 :         ruleConditionalTransfer.grantRole(
-      53                 :            :             RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE,
-      54                 :            :             CONDITIONAL_TRANSFER_OPERATOR_ADDRESS
-      55                 :            :         );
-      56                 :            :     }
-      57                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func-sort-c.html b/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func-sort-c.html deleted file mode 100644 index a8ae820..0000000 --- a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func-sort-c.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils/CMTATDeployment.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utils - CMTATDeployment.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:44100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
CMTATDeployment.86
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func.html b/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func.html deleted file mode 100644 index a912669..0000000 --- a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.func.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils/CMTATDeployment.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utils - CMTATDeployment.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:44100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
CMTATDeployment.86
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.gcov.html b/doc/coverage/coverage/test/utils/CMTATDeployment.sol.gcov.html deleted file mode 100644 index a0b1546..0000000 --- a/doc/coverage/coverage/test/utils/CMTATDeployment.sol.gcov.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils/CMTATDeployment.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utils - CMTATDeployment.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:44100.0 %
Date:2024-12-20 10:41:14Functions:11100.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : //SPDX-License-Identifier: MPL-2.0
-       2                 :            : pragma solidity ^0.8.20;
-       3                 :            : 
-       4                 :            : import "forge-std/Test.sol";
-       5                 :            : import "OZ/access/AccessControl.sol";
-       6                 :            : import "CMTAT/CMTAT_STANDALONE.sol";
-       7                 :            : 
-       8                 :            : contract CMTATDeployment {
-       9                 :            :     // Share with helper contract
-      10                 :            :     address constant ZERO_ADDRESS = address(0);
-      11                 :            :     address constant DEFAULT_ADMIN_ADDRESS = address(1);
-      12                 :            : 
-      13                 :            :     CMTAT_STANDALONE public cmtat;
-      14                 :            : 
-      15                 :            :     constructor() {
-      16                 :            :         // CMTAT
-      17                 :         86 :         ICMTATConstructor.ERC20Attributes
-      18                 :            :             memory erc20Attributes = ICMTATConstructor.ERC20Attributes(
-      19                 :            :                 "CMTA Token",
-      20                 :            :                 "CMTAT",
-      21                 :            :                 0
-      22                 :            :             );
-      23                 :         86 :         ICMTATConstructor.BaseModuleAttributes
-      24                 :            :             memory baseModuleAttributes = ICMTATConstructor
-      25                 :            :                 .BaseModuleAttributes(
-      26                 :            :                     "CMTAT_ISIN",
-      27                 :            :                     "https://cmta.ch",
-      28                 :            :                     "CMTAT_info"
-      29                 :            :                 );
-      30                 :         86 :         ICMTATConstructor.Engine memory engines = ICMTATConstructor.Engine(
-      31                 :            :             IRuleEngine(ZERO_ADDRESS),
-      32                 :            :             IDebtEngine(ZERO_ADDRESS),
-      33                 :            :             IAuthorizationEngine(ZERO_ADDRESS),
-      34                 :            :             IERC1643(ZERO_ADDRESS)
-      35                 :            :         );
-      36                 :         86 :         cmtat = new CMTAT_STANDALONE(
-      37                 :            :             ZERO_ADDRESS,
-      38                 :            :             DEFAULT_ADMIN_ADDRESS,
-      39                 :            :             erc20Attributes,
-      40                 :            :             baseModuleAttributes,
-      41                 :            :             engines
-      42                 :            :         );
-      43                 :            :     }
-      44                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.gcov.html b/doc/coverage/coverage/test/utils/SanctionListOracle.sol.gcov.html deleted file mode 100644 index 6a45b5a..0000000 --- a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.gcov.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - LCOV - lcov.info - test/utils/SanctionListOracle.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test/utils - SanctionListOracle.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2366.7 %
Date:2024-12-20 10:41:14Functions:3475.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : pragma solidity ^0.8.20;
-       3                 :            : 
-       4                 :            : /**
-       5                 :            :  * @notice Test contract from
-       6                 :            :  * https://etherscan.io/address/0x40c57923924b5c5c5455c48d93317139addac8fb#code
-       7                 :            :  */
-       8                 :            : contract SanctionListOracle {
-       9                 :            :     constructor() {}
-      10                 :            : 
-      11                 :            :     mapping(address => bool) private sanctionedAddresses;
-      12                 :            : 
-      13                 :            :     function addToSanctionsList(address newSanction) public {
-      14                 :         10 :         sanctionedAddresses[newSanction] = true;
-      15                 :            :     }
-      16                 :            : 
-      17                 :            :     function removeFromSanctionsList(address removeSanction) public {
-      18                 :          0 :         sanctionedAddresses[removeSanction] = true;
-      19                 :            :     }
-      20                 :            : 
-      21                 :            :     function isSanctioned(address addr) public view returns (bool) {
-      22                 :         12 :         return sanctionedAddresses[addr] == true;
-      23                 :            :     }
-      24                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html b/doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html new file mode 100644 index 0000000..aed9162 --- /dev/null +++ b/doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html @@ -0,0 +1,121 @@ + + + + + + + LCOV - lcov.info - validation/RuleBlacklist.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleBlacklist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:283580.0 %
Date:2025-12-03 14:12:50Functions:71070.0 %
Branches:141687.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleBlacklist.supportsInterface0
RuleBlacklist.transferred.10
RuleBlacklist.transferred.20
RuleBlacklist.canReturnTransferRestrictionCode4
RuleBlacklist.detectTransferRestrictionFrom.14
RuleBlacklist.transferred.06
RuleBlacklist.detectTransferRestriction.17
RuleBlacklist.messageForTransferRestriction8
RuleBlacklist.detectTransferRestrictionFrom.012
RuleBlacklist.detectTransferRestriction.016
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/validation/RuleBlacklist.sol.func.html b/doc/coverage/coverage/validation/RuleBlacklist.sol.func.html new file mode 100644 index 0000000..d35253a --- /dev/null +++ b/doc/coverage/coverage/validation/RuleBlacklist.sol.func.html @@ -0,0 +1,121 @@ + + + + + + + LCOV - lcov.info - validation/RuleBlacklist.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleBlacklist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:283580.0 %
Date:2025-12-03 14:12:50Functions:71070.0 %
Branches:141687.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleBlacklist.canReturnTransferRestrictionCode4
RuleBlacklist.detectTransferRestriction.016
RuleBlacklist.detectTransferRestriction.17
RuleBlacklist.detectTransferRestrictionFrom.012
RuleBlacklist.detectTransferRestrictionFrom.14
RuleBlacklist.messageForTransferRestriction8
RuleBlacklist.supportsInterface0
RuleBlacklist.transferred.06
RuleBlacklist.transferred.10
RuleBlacklist.transferred.20
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html b/doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html new file mode 100644 index 0000000..7c7d78e --- /dev/null +++ b/doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html @@ -0,0 +1,263 @@ + + + + + + + LCOV - lcov.info - validation/RuleBlacklist.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleBlacklist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:283580.0 %
Date:2025-12-03 14:12:50Functions:71070.0 %
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 {AccessControl} from "OZ/access/AccessControl.sol";
+       6                 :            : /* ==== Abtract contracts === */
+       7                 :            : import {RuleBlacklistInvariantStorage} from
+       8                 :            :     "./abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol";
+       9                 :            : import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol";
+      10                 :            : import {RuleValidateTransfer, RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol";
+      11                 :            : /* ==== Interfaces === */
+      12                 :            : import {IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol";
+      13                 :            : /* ==== CMTAT === */
+      14                 :            : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+      15                 :            : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+      16                 :            : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+      17                 :            : /* ==== IRuleEngine === */
+      18                 :            : import {IRule} from "RuleEngine/interfaces/IRule.sol";
+      19                 :            : 
+      20                 :            : /**
+      21                 :            :  * @title a blacklist manager
+      22                 :            :  */
+      23                 :            : contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInvariantStorage {
+      24                 :            :     /*//////////////////////////////////////////////////////////////
+      25                 :            :                               CONSTRUCTOR
+      26                 :            :     //////////////////////////////////////////////////////////////*/
+      27                 :            :     /**
+      28                 :            :      * @param admin Address of the contract (Access Control)
+      29                 :            :      * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
+      30                 :            :      */
+      31                 :            :     constructor(address admin, address forwarderIrrevocable) RuleAddressSet(admin, forwarderIrrevocable) {}
+      32                 :            : 
+      33                 :            :     /* ============  View Functions ============ */
+      34                 :            :     /**
+      35                 :            :      * @notice Check if an addres is in the whitelist or not
+      36                 :            :      * @param from the origin address
+      37                 :            :      * @param to the destination address
+      38                 :            :      * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
+      39                 :            :      *
+      40                 :            :      */
+      41                 :         16 :     function detectTransferRestriction(address from, address to, uint256 /* value */ )
+      42                 :            :         public
+      43                 :            :         view
+      44                 :            :         override(IERC1404)
+      45                 :            :         returns (uint8)
+      46                 :            :     {
+      47         [ +  + ]:         35 :         if (isAddressListed(from)) {
+      48                 :         12 :             return CODE_ADDRESS_FROM_IS_BLACKLISTED;
+      49         [ +  + ]:         23 :         } else if (isAddressListed(to)) {
+      50                 :         11 :             return CODE_ADDRESS_TO_IS_BLACKLISTED;
+      51                 :            :         } else {
+      52                 :         12 :             return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+      53                 :            :         }
+      54                 :            :     }
+      55                 :            : 
+      56                 :            :     /*
+      57                 :            :     * @inheritdoc IERC7943NonFungibleComplianceExtend
+      58                 :            :     */
+      59                 :          7 :     function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value)
+      60                 :            :         public
+      61                 :            :         view
+      62                 :            :         override(IERC7943NonFungibleComplianceExtend)
+      63                 :            :         returns (uint8)
+      64                 :            :     {
+      65                 :          7 :         return detectTransferRestriction(from, to, value);
+      66                 :            :     }
+      67                 :            : 
+      68                 :            :     /*
+      69                 :            :     * @inheritdoc IERC1404Extend
+      70                 :            :     */
+      71                 :         12 :     function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+      72                 :            :         public
+      73                 :            :         view
+      74                 :            :         override(IERC1404Extend)
+      75                 :            :         returns (uint8)
+      76                 :            :     {
+      77         [ +  + ]:         16 :         if (isAddressListed(spender)) {
+      78                 :          4 :             return CODE_ADDRESS_SPENDER_IS_BLACKLISTED;
+      79                 :            :         } else {
+      80                 :         12 :             return detectTransferRestriction(from, to, value);
+      81                 :            :         }
+      82                 :            :     }
+      83                 :            : 
+      84                 :            :     /**
+      85                 :            :      * @inheritdoc IERC7943NonFungibleComplianceExtend
+      86                 :            :      */
+      87                 :          4 :     function detectTransferRestrictionFrom(
+      88                 :            :         address spender,
+      89                 :            :         address from,
+      90                 :            :         address to,
+      91                 :            :         uint256, /* tokenId */
+      92                 :            :         uint256 value
+      93                 :            :     ) public view override(IERC7943NonFungibleComplianceExtend) returns (uint8) {
+      94                 :          4 :         return detectTransferRestrictionFrom(spender, from, to, value);
+      95                 :            :     }
+      96                 :            : 
+      97                 :            :     /**
+      98                 :            :      * @notice To know if the restriction code is valid for this rule or not.
+      99                 :            :      * @param _restrictionCode The target restriction code
+     100                 :            :      * @return true if the restriction code is known, false otherwise
+     101                 :            :      *
+     102                 :            :      */
+     103                 :          4 :     function canReturnTransferRestrictionCode(uint8 _restrictionCode)
+     104                 :            :         public
+     105                 :            :         pure
+     106                 :            :         virtual
+     107                 :            :         override(IRule)
+     108                 :            :         returns (bool)
+     109                 :            :     {
+     110                 :          4 :         return _restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED
+     111                 :          2 :             || _restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED || _restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED;
+     112                 :            :     }
+     113                 :            : 
+     114                 :            :     /**
+     115                 :            :      * @notice Return the corresponding message
+     116                 :            :      * @param _restrictionCode The target restriction code
+     117                 :            :      * @return true if the transfer is valid, false otherwise
+     118                 :            :      *
+     119                 :            :      */
+     120                 :          8 :     function messageForTransferRestriction(uint8 _restrictionCode)
+     121                 :            :         public
+     122                 :            :         pure
+     123                 :            :         virtual
+     124                 :            :         override(IERC1404)
+     125                 :            :         returns (string memory)
+     126                 :            :     {
+     127         [ +  + ]:          8 :         if (_restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED) {
+     128                 :          3 :             return TEXT_ADDRESS_FROM_IS_BLACKLISTED;
+     129         [ +  + ]:          5 :         } else if (_restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED) {
+     130                 :          2 :             return TEXT_ADDRESS_TO_IS_BLACKLISTED;
+     131         [ +  + ]:          3 :         } else if (_restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED) {
+     132                 :          1 :             return TEXT_ADDRESS_SPENDER_IS_BLACKLISTED;
+     133                 :            :         } else {
+     134                 :          2 :             return TEXT_CODE_NOT_FOUND;
+     135                 :            :         }
+     136                 :            :     }
+     137                 :            : 
+     138                 :          0 :     function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) {
+     139                 :          0 :         return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId);
+     140                 :            :     }
+     141                 :            : 
+     142                 :            :     /* ============  State Functions ============ */
+     143                 :            : 
+     144                 :          6 :     function transferred(address from, address to, uint256 value)
+     145                 :            :         public
+     146                 :            :         view
+     147                 :            :         virtual
+     148                 :            :         override(IERC3643IComplianceContract)
+     149                 :            :     {
+     150                 :          6 :         uint8 code = this.detectTransferRestriction(from, to, value);
+     151         [ +  + ]:          6 :         require(
+     152                 :            :             code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+     153                 :            :             RuleBlacklist_InvalidTransfer(address(this), from, to, value, code)
+     154                 :            :         );
+     155                 :            :     }
+     156                 :            : 
+     157                 :          0 :     function transferred(address spender, address from, address to, uint256 value)
+     158                 :            :         public
+     159                 :            :         view
+     160                 :            :         virtual
+     161                 :            :         override(IRuleEngine)
+     162                 :            :     {
+     163                 :          0 :         uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value);
+     164         [ #  # ]:          0 :         require(
+     165                 :            :             code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+     166                 :            :             RuleBlacklist_InvalidTransfer(address(this), from, to, value, code)
+     167                 :            :         );
+     168                 :            :     }
+     169                 :            : 
+     170                 :          0 :     function transferred(address spender, address from, address to, uint256, /* tokenId */ uint256 value)
+     171                 :            :         public
+     172                 :            :         view
+     173                 :            :         virtual
+     174                 :            :         override(IERC7943NonFungibleComplianceExtend)
+     175                 :            :     {
+     176                 :          0 :         transferred(spender, from, to, value);
+     177                 :            :     }
+     178                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html b/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html new file mode 100644 index 0000000..0565295 --- /dev/null +++ b/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html @@ -0,0 +1,145 @@ + + + + + + + LCOV - lcov.info - validation/RuleSanctionsList.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleSanctionsList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:405276.9 %
Date:2025-12-03 14:12:50Functions:111668.8 %
Branches:141877.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleSanctionsList._msgData0
RuleSanctionsList.supportsInterface0
RuleSanctionsList.transferred.00
RuleSanctionsList.transferred.10
RuleSanctionsList.transferred.20
RuleSanctionsList.canReturnTransferRestrictionCode3
RuleSanctionsList.detectTransferRestrictionFrom.13
RuleSanctionsList.messageForTransferRestriction4
RuleSanctionsList.detectTransferRestrictionFrom.08
RuleSanctionsList.detectTransferRestriction.19
RuleSanctionsList.detectTransferRestriction.010
RuleSanctionsList._setSanctionListOracle14
RuleSanctionsList.setSanctionListOracle14
RuleSanctionsList.constructor17
RuleSanctionsList._contextSuffixLength30
RuleSanctionsList._msgSender30
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/validation/RuleSanctionsList.sol.func.html b/doc/coverage/coverage/validation/RuleSanctionsList.sol.func.html new file mode 100644 index 0000000..73e3403 --- /dev/null +++ b/doc/coverage/coverage/validation/RuleSanctionsList.sol.func.html @@ -0,0 +1,145 @@ + + + + + + + LCOV - lcov.info - validation/RuleSanctionsList.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleSanctionsList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:405276.9 %
Date:2025-12-03 14:12:50Functions:111668.8 %
Branches:141877.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleSanctionsList._contextSuffixLength30
RuleSanctionsList._msgData0
RuleSanctionsList._msgSender30
RuleSanctionsList._setSanctionListOracle14
RuleSanctionsList.canReturnTransferRestrictionCode3
RuleSanctionsList.constructor17
RuleSanctionsList.detectTransferRestriction.010
RuleSanctionsList.detectTransferRestriction.19
RuleSanctionsList.detectTransferRestrictionFrom.08
RuleSanctionsList.detectTransferRestrictionFrom.13
RuleSanctionsList.messageForTransferRestriction4
RuleSanctionsList.setSanctionListOracle14
RuleSanctionsList.supportsInterface0
RuleSanctionsList.transferred.00
RuleSanctionsList.transferred.10
RuleSanctionsList.transferred.20
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html b/doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html new file mode 100644 index 0000000..f308e1e --- /dev/null +++ b/doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html @@ -0,0 +1,343 @@ + + + + + + + LCOV - lcov.info - validation/RuleSanctionsList.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleSanctionsList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:405276.9 %
Date:2025-12-03 14:12:50Functions:111668.8 %
Branches:141877.8 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : 
+       3                 :            : pragma solidity ^0.8.20;
+       4                 :            : 
+       5                 :            : import {AccessControl} from "OZ/access/AccessControl.sol";
+       6                 :            : /* ==== Abtract contracts === */
+       7                 :            : import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../modules/MetaTxModuleStandalone.sol";
+       8                 :            : import {AccessControlModuleStandalone} from "../../modules/AccessControlModuleStandalone.sol";
+       9                 :            : import {RuleSanctionsListInvariantStorage} from "./abstract/RuleSanctionsListInvariantStorage.sol";
+      10                 :            : import {RuleValidateTransfer, RuleValidateTransfer} from "./abstract/RuleValidateTransfer.sol";
+      11                 :            : /* ==== Interfaces === */
+      12                 :            : import {ISanctionsList} from "../interfaces/ISanctionsList.sol";
+      13                 :            : import {IERC7943NonFungibleComplianceExtend} from "../interfaces/IERC7943NonFungibleCompliance.sol";
+      14                 :            : /* ==== CMTAT === */
+      15                 :            : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+      16                 :            : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+      17                 :            : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+      18                 :            : /* ==== IRuleEngine === */
+      19                 :            : import {IRule} from "RuleEngine/interfaces/IRule.sol";
+      20                 :            : 
+      21                 :            : 
+      22                 :            : /**
+      23                 :            :  * @title RuleSanctionsList
+      24                 :            :  * @notice Compliance rule enforcing sanctions-screening for token transfers.
+      25                 :            :  * @dev
+      26                 :            :  *  This rule integrates a sanctions-oracle (e.g., Chainalysis) and blocks
+      27                 :            :  *  transfers when:
+      28                 :            :  *    - the sender is sanctioned,
+      29                 :            :  *    - the recipient is sanctioned,
+      30                 :            :  *    - or the spender/operator is sanctioned.
+      31                 :            :  *
+      32                 :            :  *  Features:
+      33                 :            :  *    - Supports ERC-1404, ERC-3643 (transferred) and ERC-7943 non-fungible compliance flows.
+      34                 :            :  *    - Oracle address can be updated by accounts holding `SANCTIONLIST_ROLE`.
+      35                 :            :  *    - Zero oracle address disables sanctions checks (all transfers allowed).
+      36                 :            :  *
+      37                 :            :  *  The rule is designed for RuleEngine or for direct integration with
+      38                 :            :  *  CMTAT / ERC-3643 compliant tokens.
+      39                 :            :  */
+      40                 :            : contract RuleSanctionsList is
+      41                 :            :     AccessControlModuleStandalone,
+      42                 :            :     MetaTxModuleStandalone,
+      43                 :            :     RuleValidateTransfer,
+      44                 :            :     RuleSanctionsListInvariantStorage
+      45                 :            : {
+      46                 :            :     ISanctionsList public sanctionsList;
+      47                 :            : 
+      48                 :            :     /*//////////////////////////////////////////////////////////////
+      49                 :            :                               CONSTRUCTOR
+      50                 :            :     //////////////////////////////////////////////////////////////*/
+      51                 :            :     /**
+      52                 :            :      * @param admin Address of the contract (Access Control)
+      53                 :            :      * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
+      54                 :            :      */
+      55                 :         17 :     constructor(address admin, address forwarderIrrevocable, ISanctionsList sanctionContractOracle_)
+      56                 :            :         MetaTxModuleStandalone(forwarderIrrevocable)
+      57                 :            :         AccessControlModuleStandalone(admin)
+      58                 :            :     {
+      59            [ + ]:         16 :         if (address(sanctionContractOracle_) != address(0)) {
+      60                 :          1 :             _setSanctionListOracle(sanctionContractOracle_);
+      61                 :            :         }
+      62                 :            :     }
+      63                 :            : 
+      64                 :            :     /* ============  View Functions ============ */
+      65                 :            : 
+      66                 :            :     /**
+      67                 :            :      * @notice Check if an addres is in the SanctionsList or not
+      68                 :            :      * @param from the origin address
+      69                 :            :      * @param to the destination address
+      70                 :            :      * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
+      71                 :            :      *
+      72                 :            :      */
+      73                 :         10 :     function detectTransferRestriction(address from, address to, uint256 /*value */ )
+      74                 :            :         public
+      75                 :            :         view
+      76                 :            :         override(IERC1404)
+      77                 :            :         returns (uint8)
+      78                 :            :     {
+      79            [ + ]:         27 :         if (address(sanctionsList) != address(0)) {
+      80         [ +  + ]:         22 :             if (sanctionsList.isSanctioned(from)) {
+      81                 :          4 :                 return CODE_ADDRESS_FROM_IS_SANCTIONED;
+      82            [ + ]:         18 :             } else if (sanctionsList.isSanctioned(to)) {
+      83                 :          8 :                 return CODE_ADDRESS_TO_IS_SANCTIONED;
+      84                 :            :             }
+      85                 :            :         }
+      86                 :         15 :         return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+      87                 :            :     }
+      88                 :            : 
+      89                 :            :     /**
+      90                 :            :      * @inheritdoc IERC7943NonFungibleComplianceExtend
+      91                 :            :      */
+      92                 :          9 :     function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value)
+      93                 :            :         public
+      94                 :            :         view
+      95                 :            :         virtual
+      96                 :            :         override(IERC7943NonFungibleComplianceExtend)
+      97                 :            :         returns (uint8)
+      98                 :            :     {
+      99                 :          9 :         return detectTransferRestriction(from, to, value);
+     100                 :            :     }
+     101                 :            : 
+     102                 :            :     /**
+     103                 :            :      * @inheritdoc IERC1404Extend
+     104                 :            :      */
+     105                 :          8 :     function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+     106                 :            :         public
+     107                 :            :         view
+     108                 :            :         virtual
+     109                 :            :         override(IERC1404Extend)
+     110                 :            :         returns (uint8)
+     111                 :            :     {
+     112            [ + ]:         11 :         if (address(sanctionsList) != address(0)) {
+     113         [ +  + ]:         10 :             if (sanctionsList.isSanctioned(spender)) {
+     114                 :          2 :                 return CODE_ADDRESS_SPENDER_IS_SANCTIONED;
+     115                 :            :             } else {
+     116                 :          8 :                 return detectTransferRestriction(from, to, value);
+     117                 :            :             }
+     118                 :            :         }
+     119                 :          1 :         return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+     120                 :            :     }
+     121                 :            : 
+     122                 :          3 :     function detectTransferRestrictionFrom(
+     123                 :            :         address spender,
+     124                 :            :         address from,
+     125                 :            :         address to,
+     126                 :            :         uint256, /* tokenId */
+     127                 :            :         uint256 value
+     128                 :            :     ) public view virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) {
+     129                 :          3 :         return detectTransferRestrictionFrom(spender, from, to, value);
+     130                 :            :     }
+     131                 :            : 
+     132                 :            :     /**
+     133                 :            :      * @notice To know if the restriction code is valid for this rule or not.
+     134                 :            :      * @param restrictionCode The target restriction code
+     135                 :            :      * @return true if the restriction code is known, false otherwise
+     136                 :            :      *
+     137                 :            :      */
+     138                 :          3 :     function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override(IRule) returns (bool) {
+     139                 :          3 :         return restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED || restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED
+     140                 :          1 :             || restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED;
+     141                 :            :     }
+     142                 :            : 
+     143                 :            :     /**
+     144                 :            :      * @notice Return the corresponding message
+     145                 :            :      * @param restrictionCode The target restriction code
+     146                 :            :      * @return true if the transfer is valid, false otherwise
+     147                 :            :      *
+     148                 :            :      */
+     149                 :          4 :     function messageForTransferRestriction(uint8 restrictionCode)
+     150                 :            :         public
+     151                 :            :         pure
+     152                 :            :         virtual
+     153                 :            :         override(IERC1404)
+     154                 :            :         returns (string memory)
+     155                 :            :     {
+     156         [ +  + ]:          4 :         if (restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED) {
+     157                 :          1 :             return TEXT_ADDRESS_FROM_IS_SANCTIONED;
+     158         [ +  + ]:          3 :         } else if (restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED) {
+     159                 :          1 :             return TEXT_ADDRESS_TO_IS_SANCTIONED;
+     160         [ +  + ]:          2 :         } else if (restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED) {
+     161                 :          1 :             return TEXT_ADDRESS_SPENDER_IS_SANCTIONED;
+     162                 :            :         } else {
+     163                 :          1 :             return TEXT_CODE_NOT_FOUND;
+     164                 :            :         }
+     165                 :            :     }
+     166                 :            : 
+     167                 :          0 :     function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) {
+     168                 :          0 :         return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId);
+     169                 :            :     }
+     170                 :            : 
+     171                 :            :     /* ============  State Functions ============ */
+     172                 :            :     /**
+     173                 :            :      * @notice Set the oracle contract
+     174                 :            :      * @param sanctionContractOracle_ address of your oracle contract
+     175                 :            :      * @dev zero address is authorized to authorize all transfers
+     176                 :            :      */
+     177                 :         14 :     function setSanctionListOracle(ISanctionsList sanctionContractOracle_) public virtual onlyRole(SANCTIONLIST_ROLE) {
+     178                 :         13 :         _setSanctionListOracle(sanctionContractOracle_);
+     179                 :            :     }
+     180                 :            : 
+     181                 :            :     /**
+     182                 :            :      * @inheritdoc IERC3643IComplianceContract
+     183                 :            :      */
+     184                 :          0 :     function transferred(address from, address to, uint256 value)
+     185                 :            :         public
+     186                 :            :         view
+     187                 :            :         virtual
+     188                 :            :         override(IERC3643IComplianceContract)
+     189                 :            :     {
+     190                 :          0 :         uint8 code = this.detectTransferRestriction(from, to, value);
+     191         [ #  # ]:          0 :         require(
+     192                 :            :             code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+     193                 :            :             RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code)
+     194                 :            :         );
+     195                 :            :     }
+     196                 :            : 
+     197                 :            :     /**
+     198                 :            :      * @inheritdoc IRuleEngine
+     199                 :            :      */
+     200                 :          0 :     function transferred(address spender, address from, address to, uint256 value)
+     201                 :            :         public
+     202                 :            :         view
+     203                 :            :         virtual
+     204                 :            :         override(IRuleEngine)
+     205                 :            :     {
+     206                 :          0 :         uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value);
+     207         [ #  # ]:          0 :         require(
+     208                 :            :             code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+     209                 :            :             RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code)
+     210                 :            :         );
+     211                 :            :     }
+     212                 :            : 
+     213                 :            :     /**
+     214                 :            :      * @inheritdoc IERC7943NonFungibleComplianceExtend
+     215                 :            :      */
+     216                 :          0 :     function transferred(address spender, address from, address to, uint256, /* tokenId */ uint256 value)
+     217                 :            :         public
+     218                 :            :         view
+     219                 :            :         virtual
+     220                 :            :         override(IERC7943NonFungibleComplianceExtend)
+     221                 :            :     {
+     222                 :          0 :         transferred(spender, from, to, value);
+     223                 :            :     }
+     224                 :            : 
+     225                 :            :     /*//////////////////////////////////////////////////////////////
+     226                 :            :                             INTERNAL FUNCTIONS
+     227                 :            :     //////////////////////////////////////////////////////////////*/
+     228                 :            : 
+     229                 :         14 :     function _setSanctionListOracle(ISanctionsList sanctionContractOracle_) internal {
+     230                 :         14 :         sanctionsList = sanctionContractOracle_;
+     231                 :         14 :         emit SetSanctionListOracle(sanctionContractOracle_);
+     232                 :            :     }
+     233                 :            : 
+     234                 :            :     /*//////////////////////////////////////////////////////////////
+     235                 :            :                            ERC-2771
+     236                 :            :     //////////////////////////////////////////////////////////////*/
+     237                 :            : 
+     238                 :            :     /**
+     239                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
+     240                 :            :      */
+     241                 :         30 :     function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
+     242                 :         30 :         return ERC2771Context._msgSender();
+     243                 :            :     }
+     244                 :            : 
+     245                 :            :     /**
+     246                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
+     247                 :            :      */
+     248                 :          0 :     function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) {
+     249                 :          0 :         return ERC2771Context._msgData();
+     250                 :            :     }
+     251                 :            : 
+     252                 :            :     /**
+     253                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
+     254                 :            :      */
+     255                 :         30 :     function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
+     256                 :         30 :         return ERC2771Context._contextSuffixLength();
+     257                 :            :     }
+     258                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/src/RuleEngine.sol.func-sort-c.html b/doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html similarity index 54% rename from doc/coverage/coverage/src/RuleEngine.sol.func-sort-c.html rename to doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html index eabf2d9..587528e 100644 --- a/doc/coverage/coverage/src/RuleEngine.sol.func-sort-c.html +++ b/doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src/RuleEngine.sol - functions + LCOV - lcov.info - validation/RuleWhitelist.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,26 +31,26 @@ - - - + + + - + - - - + + + - - + + @@ -65,44 +65,36 @@
Current view:top level - src - RuleEngine.sol (source / functions)top level - validation - RuleWhitelist.sol (source / functions) Hitlcov.info Lines:383997.4 %162080.0 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:8988.9 %5771.4 %
Branches:8855 100.0 %
- + - + - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + +

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

diff --git a/doc/coverage/coverage/src/RuleEngine.sol.func.html b/doc/coverage/coverage/validation/RuleWhitelist.sol.func.html similarity index 54% rename from doc/coverage/coverage/src/RuleEngine.sol.func.html rename to doc/coverage/coverage/validation/RuleWhitelist.sol.func.html index f12d35b..a8ca06b 100644 --- a/doc/coverage/coverage/src/RuleEngine.sol.func.html +++ b/doc/coverage/coverage/validation/RuleWhitelist.sol.func.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src/RuleEngine.sol - functions + LCOV - lcov.info - validation/RuleWhitelist.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,26 +31,26 @@ - - - + + + - + - - - + + + - - + + @@ -66,43 +66,35 @@ - + - - + + - - + + - - - - - - + + - - + + - - + + - - - - - - + + - - + +
Current view:top level - src - RuleEngine.sol (source / functions)top level - validation - RuleWhitelist.sol (source / functions) Hitlcov.info Lines:383997.4 %162080.0 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:8988.9 %5771.4 %
Branches:8855 100.0 %

Function Name Sort by function nameHit count Sort by hit countHit count Sort by hit count
RuleEngine.205RuleWhitelist.constructor102
RuleEngine._contextSuffixLength588RuleWhitelist.detectTransferRestriction.016
RuleEngine._msgData0
RuleEngine._msgSender588RuleWhitelist.detectTransferRestriction.17
RuleEngine.detectTransferRestriction20RuleWhitelist.detectTransferRestrictionFrom.06
RuleEngine.hasRole299RuleWhitelist.detectTransferRestrictionFrom.12
RuleEngine.messageForTransferRestriction18
RuleEngine.operateOnTransfer69RuleWhitelist.isVerified0
RuleEngine.validateTransfer12RuleWhitelist.supportsInterface0

diff --git a/doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.gcov.html b/doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html similarity index 54% rename from doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.gcov.html rename to doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html index 1c29fc2..b427104 100644 --- a/doc/coverage/coverage/src/modules/RuleEngineValidationCommon.sol.gcov.html +++ b/doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - src/modules/RuleEngineValidationCommon.sol - + LCOV - lcov.info - validation/RuleWhitelist.sol + - + - +
LCOV - code coverage report
- + @@ -31,34 +31,34 @@ - - - + + + - + - - - + + + - - + + - +
Current view:top level - src/modules - RuleEngineValidationCommon.sol (source / functions)top level - validation - RuleWhitelist.sol (source / functions) Hitlcov.info Lines:1919100.0 %162080.0 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:1010100.0 %5771.4 %
Branches:1155 100.0 %
@@ -70,157 +70,151 @@
           Branch data     Line data    Source code
        1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.20;
-       4                 :            : 
-       5                 :            : import "OZ/access/AccessControl.sol";
-       6                 :            : import "./RuleInternal.sol";
-       7                 :            : import "../interfaces/IRuleEngineValidation.sol";
-       8                 :            : import "../interfaces/IRuleValidation.sol";
-       9                 :            : 
-      10                 :            : /**
-      11                 :            :  * @title Implementation of a ruleEngine defined by the CMTAT
-      12                 :            :  */
-      13                 :            : abstract contract RuleEngineValidationCommon is
-      14                 :            :     AccessControl,
-      15                 :            :     RuleInternal,
-      16                 :            :     IRuleEngineValidationCommon
-      17                 :            : {
-      18                 :            :     /// @dev Array of rules
-      19                 :            :     address[] internal _rulesValidation;
-      20                 :            : 
-      21                 :            :     /*//////////////////////////////////////////////////////////////
-      22                 :            :                            PUBLIC/EXTERNAL FUNCTIONS
-      23                 :            :     //////////////////////////////////////////////////////////////*/
-      24                 :            :     /**
-      25                 :            :      * @notice Set all the rules, will overwrite all the previous rules. \n
-      26                 :            :      * Revert if one rule is a zero address or if the rule is already present
-      27                 :            :      * @dev take address[] instead of IRuleEngineValidation[] since it is not possible to cast IRuleEngineValidation[] -> address[]
-      28                 :            :      *
-      29                 :            :      */
-      30                 :            :     function setRulesValidation(
-      31                 :            :         address[] calldata rules_
-      32                 :            :     ) public override onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
-      33            [ + ]:         21 :         if (_rulesValidation.length > 0) {
-      34                 :         20 :             _clearRulesValidation();
-      35                 :            :         }
-      36                 :         21 :         _setRules(rules_);
-      37                 :         18 :         _rulesValidation = rules_;
-      38                 :            :     }
-      39                 :            : 
-      40                 :            :     /**
-      41                 :            :      * @notice Clear all the rules of the array of rules
-      42                 :            :      *
-      43                 :            :      */
-      44                 :            :     function clearRulesValidation() public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
-      45                 :          5 :         _clearRulesValidation();
-      46                 :            :     }
-      47                 :            : 
-      48                 :            :     /**
-      49                 :            :      * @notice Add a rule to the array of rules
-      50                 :            :      * Revert if one rule is a zero address or if the rule is already present
-      51                 :            :      *
-      52                 :            :      */
-      53                 :            :     function addRuleValidation(
-      54                 :            :         IRuleValidation rule_
-      55                 :            :     ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
-      56                 :        118 :         RuleInternal._addRule(_rulesValidation, address(rule_));
-      57                 :        116 :         emit AddRule(address(rule_));
-      58                 :            :     }
-      59                 :            : 
-      60                 :            :     /**
-      61                 :            :      * @notice Remove a rule from the array of rules
-      62                 :            :      * Revert if the rule found at the specified index does not match the rule in argument
-      63                 :            :      * @param rule_ address of the target rule
-      64                 :            :      * @param index the position inside the array of rule
-      65                 :            :      * @dev To reduce the array size, the last rule is moved to the location occupied
-      66                 :            :      * by the rule to remove
-      67                 :            :      *
-      68                 :            :      *
-      69                 :            :      */
-      70                 :            :     function removeRuleValidation(
-      71                 :            :         IRuleValidation rule_,
-      72                 :            :         uint256 index
-      73                 :            :     ) public onlyRole(RULE_ENGINE_OPERATOR_ROLE) {
-      74                 :          5 :         _removeRuleValidation(address(rule_), index);
-      75                 :            :     }
-      76                 :            : 
-      77                 :            :     /**
-      78                 :            :      * @return The number of rules inside the array
-      79                 :            :      */
-      80                 :            :     function rulesCountValidation() external view override returns (uint256) {
-      81                 :         69 :         return _rulesValidation.length;
-      82                 :            :     }
-      83                 :            : 
-      84                 :            :     /**
-      85                 :            :      * @notice Get the index of a rule inside the list
-      86                 :            :      * @return index if the rule is found, _rulesValidation.length otherwise
-      87                 :            :      */
-      88                 :            :     function getRuleIndexValidation(
-      89                 :            :         IRuleValidation rule_
-      90                 :            :     ) external view returns (uint256 index) {
-      91                 :          3 :         return RuleInternal._getRuleIndex(_rulesValidation, address(rule_));
-      92                 :            :     }
-      93                 :            : 
-      94                 :            :     /**
-      95                 :            :      * @notice Get the rule at the position specified by ruleId
-      96                 :            :      * @param ruleId index of the rule
-      97                 :            :      * @return a rule address
-      98                 :            :      */
-      99                 :            :     function ruleValidation(
-     100                 :            :         uint256 ruleId
-     101                 :            :     ) external view override returns (address) {
-     102                 :          1 :         return _rulesValidation[ruleId];
-     103                 :            :     }
-     104                 :            : 
-     105                 :            :     /**
-     106                 :            :      * @notice Get all the rules
-     107                 :            :      * @return An array of rules
-     108                 :            :      */
-     109                 :            :     function rulesValidation()
-     110                 :            :         external
-     111                 :            :         view
-     112                 :            :         override
-     113                 :            :         returns (address[] memory)
-     114                 :            :     {
-     115                 :          5 :         return _rulesValidation;
-     116                 :            :     }
-     117                 :            : 
-     118                 :            :     /*//////////////////////////////////////////////////////////////
-     119                 :            :                            INTERNAL FUNCTIONS
-     120                 :            :     //////////////////////////////////////////////////////////////*/
-     121                 :            :     /**
-     122                 :            :      * @notice Clear all the rules of the array of rules
-     123                 :            :      *
-     124                 :            :      */
-     125                 :            :     function _clearRulesValidation() internal {
-     126                 :         25 :         uint256 index;
-     127                 :            :         // we remove the last element first since it is more optimized.
-     128                 :         25 :         for (uint256 i = _rulesValidation.length; i > 0; --i) {
-     129                 :            :             unchecked {
-     130                 :            :                 // don't underflow since i > 0
-     131                 :         28 :                 index = i - 1;
-     132                 :            :             }
-     133                 :         28 :             _removeRuleValidation(_rulesValidation[index], index);
-     134                 :            :         }
-     135                 :         25 :         emit ClearRules(_rulesValidation);
-     136                 :            :     }
-     137                 :            : 
-     138                 :            :     /**
-     139                 :            :      * @notice Remove a rule from the array of rules
-     140                 :            :      * Revert if the rule found at the specified index does not match the rule in argument
-     141                 :            :      * @param rule_ address of the target rule
-     142                 :            :      * @param index the position inside the array of rule
-     143                 :            :      * @dev To reduce the array size, the last rule is moved to the location occupied
-     144                 :            :      * by the rule to remove
-     145                 :            :      *
-     146                 :            :      *
-     147                 :            :      */
-     148                 :            :     function _removeRuleValidation(address rule_, uint256 index) internal {
-     149                 :         33 :         RuleInternal._removeRule(_rulesValidation, rule_, index);
-     150                 :         32 :         emit RemoveRule(address(rule_));
-     151                 :            :     }
-     152                 :            : }
+       2                 :            : pragma solidity ^0.8.20;
+       3                 :            : 
+       4                 :            : import {AccessControl} from "OZ/access/AccessControl.sol";
+       5                 :            : /* ==== Abtract contracts === */
+       6                 :            : import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol";
+       7                 :            : import {RuleWhitelistCommon, RuleValidateTransfer} from "./abstract/RuleWhitelistCommon.sol";
+       8                 :            : /* ==== CMTAT === */
+       9                 :            : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+      10                 :            : /* ==== Interfaces === */
+      11                 :            : import {IIdentityRegistryVerified} from "../interfaces/IIdentityRegistry.sol";
+      12                 :            : import {
+      13                 :            :     IERC7943NonFungibleCompliance,
+      14                 :            :     IERC7943NonFungibleComplianceExtend
+      15                 :            : } from "../interfaces/IERC7943NonFungibleCompliance.sol";
+      16                 :            : 
+      17                 :            : /**
+      18                 :            :  * @title Rule Whitelist
+      19                 :            :  * @notice Manages a whitelist of authorized addresses and enforces whitelist-based transfer restrictions.
+      20                 :            :  * @dev
+      21                 :            :  * - Inherits core address management logic from {RuleAddressSet}.
+      22                 :            :  * - Integrates restriction code logic from {RuleWhitelistCommon}.
+      23                 :            :  * - Implements {IERC1404} to return specific restriction codes for non-whitelisted transfers.
+      24                 :            :  */
+      25                 :            : contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistryVerified {
+      26                 :            :     /*//////////////////////////////////////////////////////////////
+      27                 :            :                               CONSTRUCTOR
+      28                 :            :     //////////////////////////////////////////////////////////////*/
+      29                 :            :     /**
+      30                 :            :      * @param admin Address of the contract (Access Control)
+      31                 :            :      * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
+      32                 :            :      */
+      33                 :        102 :     constructor(address admin, address forwarderIrrevocable, bool checkSpender_)
+      34                 :            :         RuleAddressSet(admin, forwarderIrrevocable)
+      35                 :            :     {
+      36                 :        101 :         checkSpender = checkSpender_;
+      37                 :            :     }
+      38                 :            : 
+      39                 :            :     /* ============  View Functions ============ */
+      40                 :            : 
+      41                 :            :     /**
+      42                 :            :      * @notice Detects whether a transfer between two addresses is allowed under the whitelist rule.
+      43                 :            :      * @dev
+      44                 :            :      * - Returns a restriction code indicating why a transfer is blocked.
+      45                 :            :      * - Implements the `IERC1404.detectTransferRestriction` interface.
+      46                 :            :      * @param from The address sending tokens.
+      47                 :            :      * @param to The address receiving tokens.
+      48                 :            :      * @return code Restriction code (e.g., `TRANSFER_OK` or specific whitelist rejection).
+      49                 :            :      *
+      50                 :            :      * | Condition | Returned Code |
+      51                 :            :      * |------------|---------------|
+      52                 :            :      * | `from` not whitelisted | `CODE_ADDRESS_FROM_NOT_WHITELISTED` |
+      53                 :            :      * | `to` not whitelisted | `CODE_ADDRESS_TO_NOT_WHITELISTED` |
+      54                 :            :      * | Both whitelisted | `TRANSFER_OK` |
+      55                 :            :      */
+      56                 :         16 :     function detectTransferRestriction(address from, address to, uint256 /* value */ )
+      57                 :            :         public
+      58                 :            :         view
+      59                 :            :         virtual
+      60                 :            :         override(IERC1404)
+      61                 :            :         returns (uint8 code)
+      62                 :            :     {
+      63         [ +  + ]:         27 :         if (!isAddressListed(from)) {
+      64                 :          9 :             return CODE_ADDRESS_FROM_NOT_WHITELISTED;
+      65         [ +  + ]:         18 :         } else if (!isAddressListed(to)) {
+      66                 :          4 :             return CODE_ADDRESS_TO_NOT_WHITELISTED;
+      67                 :            :         } else {
+      68                 :         14 :             return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+      69                 :            :         }
+      70                 :            :     }
+      71                 :            : 
+      72                 :            :     /**
+      73                 :            :      * @inheritdoc IERC7943NonFungibleComplianceExtend
+      74                 :            :      */
+      75                 :          7 :     function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value)
+      76                 :            :         public
+      77                 :            :         view
+      78                 :            :         virtual
+      79                 :            :         override(IERC7943NonFungibleComplianceExtend)
+      80                 :            :         returns (uint8)
+      81                 :            :     {
+      82                 :          7 :         return detectTransferRestriction(from, to, value);
+      83                 :            :     }
+      84                 :            : 
+      85                 :            :     /**
+      86                 :            :      * @notice Detects transfer restriction for delegated transfers (`transferFrom`).
+      87                 :            :      * @dev
+      88                 :            :      * - Checks the `spender`, `from`, and `to` addresses for whitelist compliance.
+      89                 :            :      * - Implements `IERC1404Extend.detectTransferRestrictionFrom`.
+      90                 :            :      * @param spender The address initiating the transfer on behalf of another.
+      91                 :            :      * @param from The address from which tokens are transferred.
+      92                 :            :      * @param to The address receiving the tokens.
+      93                 :            :      * @param value The amount being transferred (unused in this check).
+      94                 :            :      * @return code Restriction code, or `TRANSFER_OK` if all parties are whitelisted.
+      95                 :            :      *
+      96                 :            :      * | Condition | Returned Code |
+      97                 :            :      * |------------|---------------|
+      98                 :            :      * | `spender` not whitelisted | `CODE_ADDRESS_SPENDER_NOT_WHITELISTED` |
+      99                 :            :      * | `from` or `to` not whitelisted | respective restriction code from `detectTransferRestriction` |
+     100                 :            :      * | All whitelisted | `TRANSFER_OK` |
+     101                 :            :      */
+     102                 :          6 :     function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+     103                 :            :         public
+     104                 :            :         view
+     105                 :            :         virtual
+     106                 :            :         override(IERC1404Extend)
+     107                 :            :         returns (uint8 code)
+     108                 :            :     {
+     109            [ + ]:          8 :         if (checkSpender && !isAddressListed(spender)) {
+     110                 :          4 :             return CODE_ADDRESS_SPENDER_NOT_WHITELISTED;
+     111                 :            :         }
+     112                 :          4 :         return detectTransferRestriction(from, to, value);
+     113                 :            :     }
+     114                 :            : 
+     115                 :            :     /**
+     116                 :            :      * @inheritdoc IERC7943NonFungibleComplianceExtend
+     117                 :            :      */
+     118                 :          2 :     function detectTransferRestrictionFrom(
+     119                 :            :         address spender,
+     120                 :            :         address from,
+     121                 :            :         address to,
+     122                 :            :         uint256, /* tokenId */
+     123                 :            :         uint256 value
+     124                 :            :     ) public view override(IERC7943NonFungibleComplianceExtend) returns (uint8) {
+     125                 :          2 :         return detectTransferRestrictionFrom(spender, from, to, value);
+     126                 :            :     }
+     127                 :            : 
+     128                 :            :     /**
+     129                 :            :      * @notice Checks whether a specific address is currently listed.
+     130                 :            :      * @param targetAddress The address to check.
+     131                 :            :      * @return isListed True if listed, false otherwise.
+     132                 :            :      */
+     133                 :          0 :     function isVerified(address targetAddress)
+     134                 :            :         public
+     135                 :            :         view
+     136                 :            :         virtual
+     137                 :            :         override(IIdentityRegistryVerified)
+     138                 :            :         returns (bool isListed)
+     139                 :            :     {
+     140                 :          0 :         isListed = _isAddressListed(targetAddress);
+     141                 :            :     }
+     142                 :            : 
+     143                 :          0 :     function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) {
+     144                 :          0 :         return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId);
+     145                 :            :     }
+     146                 :            : }
 
@@ -228,7 +222,7 @@
- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html new file mode 100644 index 0000000..7fa22b2 --- /dev/null +++ b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html @@ -0,0 +1,125 @@ + + + + + + + LCOV - lcov.info - validation/RuleWhitelistWrapper.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleWhitelistWrapper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:505787.7 %
Date:2025-12-03 14:12:50Functions:91181.8 %
Branches:111478.6 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistWrapper._msgData0
RuleWhitelistWrapper.supportsInterface0
RuleWhitelistWrapper.detectTransferRestrictionFrom.12
RuleWhitelistWrapper.detectTransferRestriction.14
RuleWhitelistWrapper.detectTransferRestrictionFrom.06
RuleWhitelistWrapper.detectTransferRestriction.015
RuleWhitelistWrapper.hasRole20
RuleWhitelistWrapper.constructor22
RuleWhitelistWrapper._detectTransferRestriction27
RuleWhitelistWrapper._contextSuffixLength80
RuleWhitelistWrapper._msgSender80
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html new file mode 100644 index 0000000..249ce1b --- /dev/null +++ b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html @@ -0,0 +1,125 @@ + + + + + + + LCOV - lcov.info - validation/RuleWhitelistWrapper.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation - RuleWhitelistWrapper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:505787.7 %
Date:2025-12-03 14:12:50Functions:91181.8 %
Branches:111478.6 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistWrapper._contextSuffixLength80
RuleWhitelistWrapper._detectTransferRestriction27
RuleWhitelistWrapper._msgData0
RuleWhitelistWrapper._msgSender80
RuleWhitelistWrapper.constructor22
RuleWhitelistWrapper.detectTransferRestriction.015
RuleWhitelistWrapper.detectTransferRestriction.14
RuleWhitelistWrapper.detectTransferRestrictionFrom.06
RuleWhitelistWrapper.detectTransferRestrictionFrom.12
RuleWhitelistWrapper.hasRole20
RuleWhitelistWrapper.supportsInterface0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/src/RuleEngine.sol.gcov.html b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html similarity index 55% rename from doc/coverage/coverage/src/RuleEngine.sol.gcov.html rename to doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html index b32d492..a064c2b 100644 --- a/doc/coverage/coverage/src/RuleEngine.sol.gcov.html +++ b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src/RuleEngine.sol + LCOV - lcov.info - validation/RuleWhitelistWrapper.sol @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - + + - - - + + +
Current view:top level - src - RuleEngine.sol (source / functions)top level - validation - RuleWhitelistWrapper.sol (source / functions) Hitlcov.info Lines:383997.4 %505787.7 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:8 988.9 %1181.8 %
Branches:88100.0 %111478.6 %
@@ -73,202 +73,202 @@ 2 : : 3 : : pragma solidity ^0.8.20; 4 : : - 5 : : import "CMTAT/interfaces/engine/IRuleEngine.sol"; - 6 : : import "./modules/MetaTxModuleStandalone.sol"; - 7 : : import "./modules/RuleEngineOperation.sol"; - 8 : : import "./modules/RuleEngineValidation.sol"; - 9 : : - 10 : : /** - 11 : : * @title Implementation of a ruleEngine as defined by the CMTAT - 12 : : */ - 13 : : contract RuleEngine is - 14 : : IRuleEngine, - 15 : : RuleEngineOperation, - 16 : : RuleEngineValidation, - 17 : : MetaTxModuleStandalone - 18 : : { - 19 : : /** - 20 : : * @notice - 21 : : * Get the current version of the smart contract - 22 : : */ - 23 : : string public constant VERSION = "2.0.4"; - 24 : : - 25 : : /** - 26 : : * @param admin Address of the contract (Access Control) - 27 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - 28 : : */ - 29 : : constructor( - 30 : : address admin, - 31 : : address forwarderIrrevocable, - 32 : : address tokenContract - 33 : : ) MetaTxModuleStandalone(forwarderIrrevocable) { - 34 [ + ]: 205 : if (admin == address(0)) { - 35 : 1 : revert RuleEngine_AdminWithAddressZeroNotAllowed(); - 36 : : } - 37 [ + ]: 204 : if (tokenContract != address(0)) { - 38 : 86 : _grantRole(TOKEN_CONTRACT_ROLE, tokenContract); - 39 : : } - 40 : 204 : _grantRole(DEFAULT_ADMIN_ROLE, admin); - 41 : : } - 42 : : - 43 : : /** - 44 : : * @notice Go through all the rule to know if a restriction exists on the transfer - 45 : : * @param _from the origin address - 46 : : * @param _to the destination address - 47 : : * @param _amount to transfer - 48 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - 49 : : **/ - 50 : : function detectTransferRestriction( - 51 : : address _from, - 52 : : address _to, - 53 : : uint256 _amount - 54 : : ) public view override returns (uint8) { - 55 : : // Validation - 56 : 32 : uint8 code = RuleEngineValidation.detectTransferRestrictionValidation( - 57 : : _from, - 58 : : _to, - 59 : : _amount - 60 : : ); - 61 [ + ]: 32 : if (code != uint8(REJECTED_CODE_BASE.TRANSFER_OK)) { - 62 : 15 : return code; - 63 : : } - 64 : : - 65 : : // Operation - 66 : 17 : uint256 rulesLength = _rulesOperation.length; - 67 : 17 : for (uint256 i = 0; i < rulesLength; ++i) { - 68 : 12 : uint8 restriction = IRuleValidation(_rulesOperation[i]) - 69 : : .detectTransferRestriction(_from, _to, _amount); - 70 [ + ]: 12 : if (restriction > 0) { - 71 : 11 : return restriction; - 72 : : } + 5 : : /* ==== OpenZeppelin === */ + 6 : : import {AccessControl} from "OZ/access/AccessControl.sol"; + 7 : : /* ==== Abtract contracts === */ + 8 : : import {AccessControlModuleStandalone} from "../../modules/AccessControlModuleStandalone.sol"; + 9 : : import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../modules/MetaTxModuleStandalone.sol"; + 10 : : import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol"; + 11 : : import {RuleWhitelistCommon, RuleValidateTransfer} from "./abstract/RuleWhitelistCommon.sol"; + 12 : : /* ==== RuleEngine === */ + 13 : : import {RulesManagementModule} from "RuleEngine/modules/RulesManagementModule.sol"; + 14 : : import {RuleEngineInvariantStorage} from "RuleEngine/modules/library/RuleEngineInvariantStorage.sol"; + 15 : : import {IRule} from "RuleEngine/interfaces/IRule.sol"; + 16 : : /* ==== CMTAT === */ + 17 : : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; + 18 : : /* ==== Interfaces === */ + 19 : : import { + 20 : : IERC7943NonFungibleCompliance, + 21 : : IERC7943NonFungibleComplianceExtend + 22 : : } from "../interfaces/IERC7943NonFungibleCompliance.sol"; + 23 : : + 24 : : /** + 25 : : * @title Wrapper to call several different whitelist rules + 26 : : */ + 27 : : contract RuleWhitelistWrapper is + 28 : : RulesManagementModule, + 29 : : AccessControlModuleStandalone, + 30 : : MetaTxModuleStandalone, + 31 : : RuleWhitelistCommon + 32 : : { + 33 : : /*////////////////////////////////////////////////////////////// + 34 : : CONSTRUCTOR + 35 : : //////////////////////////////////////////////////////////////*/ + 36 : : /** + 37 : : * @param admin Address of the contract (Access Control) + 38 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + 39 : : */ + 40 : 22 : constructor(address admin, address forwarderIrrevocable, bool checkSpender_) + 41 : : MetaTxModuleStandalone(forwarderIrrevocable) + 42 : : AccessControlModuleStandalone(admin) + 43 : : { + 44 : 20 : checkSpender = checkSpender_; + 45 : : } + 46 : : + 47 : : /* ============ View Functions ============ */ + 48 : : /** + 49 : : * @notice Go through all the whitelist rules to know if a restriction exists on the transfer + 50 : : * @param from the origin address + 51 : : * @param to the destination address + 52 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + 53 : : * + 54 : : */ + 55 : 15 : function detectTransferRestriction(address from, address to, uint256 /*value*/ ) + 56 : : public + 57 : : view + 58 : : virtual + 59 : : override(IERC1404) + 60 : : returns (uint8) + 61 : : { + 62 : 19 : address[] memory targetAddress = new address[](2); + 63 : 19 : targetAddress[0] = from; + 64 : 19 : targetAddress[1] = to; + 65 : : + 66 : 19 : bool[] memory result = _detectTransferRestriction(targetAddress); + 67 [ + + ]: 19 : if (!result[0]) { + 68 : 7 : return CODE_ADDRESS_FROM_NOT_WHITELISTED; + 69 [ + + ]: 12 : } else if (!result[1]) { + 70 : 4 : return CODE_ADDRESS_TO_NOT_WHITELISTED; + 71 : : } else { + 72 : 8 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); 73 : : } - 74 : : - 75 : 6 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 76 : : } - 77 : : - 78 : : /** - 79 : : * @notice Validate a transfer - 80 : : * @param _from the origin address - 81 : : * @param _to the destination address - 82 : : * @param _amount to transfer - 83 : : * @return True if the transfer is valid, false otherwise - 84 : : **/ - 85 : : function validateTransfer( - 86 : : address _from, - 87 : : address _to, - 88 : : uint256 _amount - 89 : : ) public view override returns (bool) { - 90 : 12 : return - 91 : 12 : detectTransferRestriction(_from, _to, _amount) == - 92 : : uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 93 : : } - 94 : : - 95 : : /** - 96 : : * @notice Return the message corresponding to the code - 97 : : * @param _restrictionCode The target restriction code - 98 : : * @return True if the transfer is valid, false otherwise - 99 : : **/ - 100 : : function messageForTransferRestriction( - 101 : : uint8 _restrictionCode - 102 : : ) external view override returns (string memory) { - 103 : : // Validation - 104 : 18 : uint256 rulesLength = _rulesValidation.length; - 105 : 18 : for (uint256 i = 0; i < rulesLength; ++i) { - 106 : : if ( - 107 : 13 : IRuleValidation(_rulesValidation[i]) - 108 : : .canReturnTransferRestrictionCode(_restrictionCode) - 109 [ + ]: 10 : ) { - 110 : 10 : return - 111 : 10 : IRuleValidation(_rulesValidation[i]) - 112 : : .messageForTransferRestriction(_restrictionCode); - 113 : : } - 114 : : } - 115 : : // operation - 116 : 8 : rulesLength = _rulesOperation.length; - 117 : 8 : for (uint256 i = 0; i < rulesLength; ++i) { - 118 : : if ( - 119 : 2 : IRuleValidation(_rulesOperation[i]) - 120 : : .canReturnTransferRestrictionCode(_restrictionCode) - 121 [ + ]: 1 : ) { - 122 : 1 : return - 123 : 1 : IRuleValidation(_rulesOperation[i]) - 124 : : .messageForTransferRestriction(_restrictionCode); - 125 : : } - 126 : : } - 127 : 7 : return "Unknown restriction code"; - 128 : : } + 74 : : } + 75 : : + 76 : 4 : function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value) + 77 : : public + 78 : : view + 79 : : virtual + 80 : : override(IERC7943NonFungibleComplianceExtend) + 81 : : returns (uint8) + 82 : : { + 83 : 4 : return detectTransferRestriction(from, to, value); + 84 : : } + 85 : : + 86 : 6 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) + 87 : : public + 88 : : view + 89 : : virtual + 90 : : override(IERC1404Extend) + 91 : : returns (uint8) + 92 : : { + 93 [ # ]: 8 : if (!checkSpender) { + 94 : 0 : return detectTransferRestriction(from, to, value); + 95 : : } + 96 : : + 97 : 8 : address[] memory targetAddress = new address[](3); + 98 : 8 : targetAddress[0] = from; + 99 : 8 : targetAddress[1] = to; + 100 : 8 : targetAddress[2] = spender; + 101 : : + 102 : 8 : bool[] memory result = _detectTransferRestriction(targetAddress); + 103 : : + 104 [ # + ]: 8 : if (!result[0]) { + 105 : 0 : return CODE_ADDRESS_FROM_NOT_WHITELISTED; + 106 [ # + ]: 8 : } else if (!result[1]) { + 107 : 0 : return CODE_ADDRESS_TO_NOT_WHITELISTED; + 108 [ + + ]: 8 : } else if (!result[2]) { + 109 : 4 : return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; + 110 : : } else { + 111 : 4 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 112 : : } + 113 : : } + 114 : : + 115 : : /** + 116 : : * @inheritdoc IERC7943NonFungibleComplianceExtend + 117 : : */ + 118 : 2 : function detectTransferRestrictionFrom( + 119 : : address spender, + 120 : : address from, + 121 : : address to, + 122 : : uint256, /* tokenId */ + 123 : : uint256 value + 124 : : ) public view virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) { + 125 : 2 : return detectTransferRestrictionFrom(spender, from, to, value); + 126 : : } + 127 : : + 128 : : /* ============ Access control ============ */ 129 : : - 130 : : /* - 131 : : * @notice function protected by access control + 130 : : /** + 131 : : * @dev Returns `true` if `account` has been granted `role`. 132 : : */ - 133 : : function operateOnTransfer( - 134 : : address from, - 135 : : address to, - 136 : : uint256 amount - 137 : : ) external override onlyRole(TOKEN_CONTRACT_ROLE) returns (bool isValid) { - 138 : : // Validate the transfer - 139 : : if ( - 140 : 68 : !RuleEngineValidation.validateTransferValidation(from, to, amount) - 141 [ + ]: 10 : ) { - 142 : 10 : return false; - 143 : : } - 144 : : // Apply operation on RuleEngine - 145 : 58 : return RuleEngineOperation._operateOnTransfer(from, to, amount); - 146 : : } - 147 : : - 148 : : /* ============ ACCESS CONTROL ============ */ - 149 : : /** - 150 : : * @dev Returns `true` if `account` has been granted `role`. - 151 : : */ - 152 : : function hasRole( - 153 : : bytes32 role, - 154 : : address account - 155 : : ) public view virtual override(AccessControl) returns (bool) { - 156 : : // The Default Admin has all roles - 157 [ + ]: 597 : if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { - 158 : 220 : return true; - 159 : : } - 160 : 377 : return AccessControl.hasRole(role, account); - 161 : : } - 162 : : - 163 : : /*////////////////////////////////////////////////////////////// - 164 : : ERC-2771 - 165 : : //////////////////////////////////////////////////////////////*/ - 166 : : - 167 : : /** - 168 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 169 : : */ - 170 : : function _msgSender() - 171 : : internal - 172 : : view - 173 : : override(ERC2771Context, Context) - 174 : : returns (address sender) - 175 : : { - 176 : 588 : return ERC2771Context._msgSender(); - 177 : : } - 178 : : - 179 : : /** - 180 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 181 : : */ - 182 : : function _msgData() - 183 : : internal - 184 : : view - 185 : : override(ERC2771Context, Context) - 186 : : returns (bytes calldata) - 187 : : { - 188 : 0 : return ERC2771Context._msgData(); - 189 : : } - 190 : : - 191 : : /** - 192 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 193 : : */ - 194 : : function _contextSuffixLength() - 195 : : internal - 196 : : view - 197 : : override(ERC2771Context, Context) - 198 : : returns (uint256) - 199 : : { - 200 : 588 : return ERC2771Context._contextSuffixLength(); + 133 : 20 : function hasRole(bytes32 role, address account) + 134 : : public + 135 : : view + 136 : : virtual + 137 : : override(AccessControl, AccessControlModuleStandalone) + 138 : : returns (bool) + 139 : : { + 140 : 80 : return AccessControlModuleStandalone.hasRole(role, account); + 141 : : } + 142 : : + 143 : : /*////////////////////////////////////////////////////////////// + 144 : : INTERNAL/PRIVATE FUNCTIONS + 145 : : //////////////////////////////////////////////////////////////*/ + 146 : : + 147 : 27 : function _detectTransferRestriction(address[] memory targetAddress) internal view returns (bool[] memory) { + 148 : 27 : uint256 rulesLength = rulesCount(); + 149 : 27 : bool[] memory result = new bool[](targetAddress.length); + 150 : 27 : for (uint256 i = 0; i < rulesLength; ++i) { + 151 : : // Call the whitelist rules + 152 : 59 : bool[] memory isListed = RuleAddressSet(rule(i)).areAddressesListed(targetAddress); + 153 : 59 : for (uint256 j = 0; j < targetAddress.length; ++j) { + 154 [ + ]: 42 : if (isListed[j]) { + 155 : 42 : result[j] = true; + 156 : : } + 157 : : } + 158 : : + 159 : : // Break early if all listed + 160 : 59 : bool allListed = true; + 161 : 59 : for (uint256 k = 0; k < result.length; ++k) { + 162 [ + ]: 113 : if (!result[k]) { + 163 : 47 : allListed = false; + 164 : 47 : break; + 165 : : } + 166 : : } + 167 [ + ]: 12 : if (allListed) { + 168 : 12 : break; + 169 : : } + 170 : : } + 171 : 27 : return result; + 172 : : } + 173 : : + 174 : 0 : function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) { + 175 : 0 : return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId); + 176 : : } + 177 : : + 178 : : /*////////////////////////////////////////////////////////////// + 179 : : ERC-2771 + 180 : : //////////////////////////////////////////////////////////////*/ + 181 : : + 182 : : /** + 183 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 184 : : */ + 185 : 80 : function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) { + 186 : 80 : return ERC2771Context._msgSender(); + 187 : : } + 188 : : + 189 : : /** + 190 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 191 : : */ + 192 : 0 : function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) { + 193 : 0 : return ERC2771Context._msgData(); + 194 : : } + 195 : : + 196 : : /** + 197 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 198 : : */ + 199 : 80 : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { + 200 : 80 : return ERC2771Context._contextSuffixLength(); 201 : : } 202 : : } diff --git a/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html similarity index 54% rename from doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html index 76ad884..282132f 100644 --- a/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src/rules/validation/RuleSanctionList.sol - functions + LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSet.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,26 +31,26 @@ - - + + - + - - + + - - + + @@ -65,48 +65,52 @@
Current view:top level - src/rules/validation - RuleSanctionList.sol (source / functions)top level - validation/abstract/RuleAddressSet - RuleAddressSet.sol (source / functions) Hitlcov.info Lines:27 2896.4 %3287.5 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions: 91090.0 %1181.8 %
Branches:111122 100.0 %
- + - + - - + + - + - - + + + + + + - - + + - - + + - - + + - - + + - - + + - - + +

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

diff --git a/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html similarity index 54% rename from doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func.html rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html index f3eefa0..5c09f24 100644 --- a/doc/coverage/coverage/src/rules/validation/RuleSanctionList.sol.func.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src/rules/validation/RuleSanctionList.sol - functions + LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSet.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,26 +31,26 @@ - - + + - + - - + + - - + + @@ -66,47 +66,51 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + + + + + - - + + - - + + - + - - + +
Current view:top level - src/rules/validation - RuleSanctionList.sol (source / functions)top level - validation/abstract/RuleAddressSet - RuleAddressSet.sol (source / functions) Hitlcov.info Lines:27 2896.4 %3287.5 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions: 91090.0 %1181.8 %
Branches:111122 100.0 %

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

diff --git a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html similarity index 58% rename from doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html index 2cd242c..92f804f 100644 --- a/doc/coverage/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol - + LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSet.sol + - + - +
LCOV - code coverage report
- + @@ -31,18 +31,18 @@ - - - + + + - + + - - + @@ -53,12 +53,12 @@ - +
Current view:top level - src/rules/validation/abstract/RuleAddressList - RuleAddressList.sol (source / functions)top level - validation/abstract/RuleAddressSet - RuleAddressSet.sol (source / functions) Hitlcov.info Lines:222395.7 %283287.5 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:9 111291.7 %81.8 %
2 100.0 %
@@ -70,181 +70,170 @@
           Branch data     Line data    Source code
        1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.20;
-       4                 :            : 
-       5                 :            : import "OZ/access/AccessControl.sol";
-       6                 :            : import "./../../../../modules/MetaTxModuleStandalone.sol";
-       7                 :            : import "./RuleAddressListInternal.sol";
-       8                 :            : import "./invariantStorage/RuleAddressListInvariantStorage.sol";
-       9                 :            : 
-      10                 :            : /**
-      11                 :            : @title an addresses list manager
-      12                 :            : */
-      13                 :            : 
-      14                 :            : abstract contract RuleAddressList is
-      15                 :            :     AccessControl,
-      16                 :            :     MetaTxModuleStandalone,
-      17                 :            :     RuleAddressListInternal,
-      18                 :            :     RuleAddressListInvariantStorage
-      19                 :            : {
-      20                 :            :     // Number of addresses in the list at the moment
-      21                 :            :     uint256 private numAddressesWhitelisted;
-      22                 :            : 
-      23                 :            :     /**
-      24                 :            :      * @param admin Address of the contract (Access Control)
-      25                 :            :      * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
-      26                 :            :      */
-      27                 :            :     constructor(
-      28                 :            :         address admin,
-      29                 :            :         address forwarderIrrevocable
-      30                 :            :     ) MetaTxModuleStandalone(forwarderIrrevocable) {
-      31            [ + ]:        185 :         if (admin == address(0)) {
-      32                 :          1 :             revert RuleAddressList_AdminWithAddressZeroNotAllowed();
-      33                 :            :         }
-      34                 :        184 :         _grantRole(DEFAULT_ADMIN_ROLE, admin);
-      35                 :            :     }
-      36                 :            : 
-      37                 :            :     /**
-      38                 :            :      * @notice Add addresses to the list
-      39                 :            :      * If one of addresses already exist, there is no change for this address. The transaction remains valid (no revert).
-      40                 :            :      * @param listTargetAddresses an array with the addresses to list
-      41                 :            :      */
-      42                 :            :     function addAddressesToTheList(
-      43                 :            :         address[] calldata listTargetAddresses
-      44                 :            :     ) public onlyRole(ADDRESS_LIST_ADD_ROLE) {
-      45                 :         16 :         _addAddressesToThelist(listTargetAddresses);
-      46                 :         16 :         emit AddAddressesToTheList(listTargetAddresses);
-      47                 :            :     }
-      48                 :            : 
-      49                 :            :     /**
-      50                 :            :      * @notice Remove addresses from the list
-      51                 :            :      * If the address does not exist in the list, there is no change for this address.
-      52                 :            :      * The transaction remains valid (no revert).
-      53                 :            :      * @param listTargetAddresses an array with the addresses to remove
-      54                 :            :      */
-      55                 :            :     function removeAddressesFromTheList(
-      56                 :            :         address[] calldata listTargetAddresses
-      57                 :            :     ) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) {
-      58                 :          3 :         _removeAddressesFromThelist(listTargetAddresses);
-      59                 :          3 :         emit RemoveAddressesFromTheList(listTargetAddresses);
-      60                 :            :     }
-      61                 :            : 
-      62                 :            :     /**
-      63                 :            :      * @notice Add one address to the list
-      64                 :            :      * If the address already exists, the transaction is reverted to save gas.
-      65                 :            :      * @param targetAddress The address to list
-      66                 :            :      */
-      67                 :            :     function addAddressToTheList(
-      68                 :            :         address targetAddress
-      69                 :            :     ) public onlyRole(ADDRESS_LIST_ADD_ROLE) {
-      70                 :         51 :         _addAddressToThelist(targetAddress);
-      71                 :         50 :         emit AddAddressToTheList(targetAddress);
-      72                 :            :     }
-      73                 :            : 
-      74                 :            :     /**
-      75                 :            :      * @notice Remove one address from the list
-      76                 :            :      * If the address does not exist in the list, the transaction is reverted to save gas.
-      77                 :            :      * @param targetAddress The address to remove
-      78                 :            :      *
-      79                 :            :      */
-      80                 :            :     function removeAddressFromTheList(
-      81                 :            :         address targetAddress
-      82                 :            :     ) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) {
-      83                 :          2 :         _removeAddressFromThelist(targetAddress);
-      84                 :          1 :         emit RemoveAddressFromTheList(targetAddress);
-      85                 :            :     }
-      86                 :            : 
-      87                 :            :     /**
-      88                 :            :      * @notice Get the number of listed addresses
-      89                 :            :      * @return Number of listed addresses
-      90                 :            :      *
-      91                 :            :      */
-      92                 :            :     function numberListedAddress() public view returns (uint256) {
-      93                 :         24 :         return _numberListedAddress();
-      94                 :            :     }
-      95                 :            : 
-      96                 :            :     /**
-      97                 :            :      * @notice Know if an address is listed or not
-      98                 :            :      * @param _targetAddress The concerned address
-      99                 :            :      * @return True if the address is listed, false otherwise
-     100                 :            :      *
+       2                 :            : pragma solidity ^0.8.20;
+       3                 :            : 
+       4                 :            : import {AccessControlModuleStandalone} from "../../../../modules/AccessControlModuleStandalone.sol";
+       5                 :            : import {MetaTxModuleStandalone, ERC2771Context, Context} from "../../../../modules/MetaTxModuleStandalone.sol";
+       6                 :            : import {RuleAddressSetInternal} from "./RuleAddressSetInternal.sol";
+       7                 :            : import {RuleAddressSetInvariantStorage} from "./invariantStorage/RuleAddressSetInvariantStorage.sol";
+       8                 :            : /* ==== Interfaces === */
+       9                 :            : import {IIdentityRegistryContains} from "../../../interfaces/IIdentityRegistry.sol";
+      10                 :            : import {IAddressList} from "../../../interfaces/IAddressList.sol";
+      11                 :            : /**
+      12                 :            :  * @title Rule Address Set
+      13                 :            :  * @notice Manages a permissioned set of addresses related to rule logic.
+      14                 :            :  * @dev
+      15                 :            :  * - Provides controlled functions for adding and removing addresses.
+      16                 :            :  * - Integrates `AccessControl` for role-based access.
+      17                 :            :  * - Supports gasless transactions via ERC-2771 meta-transactions.
+      18                 :            :  * - Extends internal logic defined in {RuleAddressSetInternal}.
+      19                 :            :  */
+      20                 :            : 
+      21                 :            : abstract contract RuleAddressSet is
+      22                 :            :     AccessControlModuleStandalone,
+      23                 :            :     MetaTxModuleStandalone,
+      24                 :            :     RuleAddressSetInternal,
+      25                 :            :     RuleAddressSetInvariantStorage,
+      26                 :            :     IAddressList
+      27                 :            : {
+      28                 :            :     /*//////////////////////////////////////////////////////////////
+      29                 :            :                                 STATE
+      30                 :            :     //////////////////////////////////////////////////////////////*/
+      31                 :            : 
+      32                 :            :     /// @notice Cached number of currently listed addresses.
+      33                 :            :     uint256 private _listedAddressCountCache;
+      34                 :            : 
+      35                 :            :     /*//////////////////////////////////////////////////////////////
+      36                 :            :                               CONSTRUCTOR
+      37                 :            :     //////////////////////////////////////////////////////////////*/
+      38                 :            : 
+      39                 :            :     /**
+      40                 :            :      * @notice Initializes the RuleAddressSet contract.
+      41                 :            :      * @param admin The address granted the default admin role.
+      42                 :            :      * @param forwarderIrrevocable Address of the ERC2771 forwarder (for meta-transactions).
+      43                 :            :      * @dev Reverts if the admin address is the zero address.
+      44                 :            :      */
+      45                 :            :     constructor(address admin, address forwarderIrrevocable)
+      46                 :            :         MetaTxModuleStandalone(forwarderIrrevocable)
+      47                 :            :         AccessControlModuleStandalone(admin)
+      48                 :            :     {
+      49                 :            :         // nothing to do
+      50                 :            :     }
+      51                 :            : 
+      52                 :            :     /*//////////////////////////////////////////////////////////////
+      53                 :            :                               CORE LOGIC
+      54                 :            :     //////////////////////////////////////////////////////////////*/
+      55                 :            : 
+      56                 :            :     /**
+      57                 :            :      * @notice Adds multiple addresses to the set.
+      58                 :            :      * @dev
+      59                 :            :      * - Does not revert if an address is already listed.
+      60                 :            :      * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`.
+      61                 :            :      * @param targetAddresses Array of addresses to be added.
+      62                 :            :      */
+      63                 :         17 :     function addAddresses(address[] calldata targetAddresses) public onlyRole(ADDRESS_LIST_ADD_ROLE) {
+      64                 :         16 :         _addAddresses(targetAddresses);
+      65                 :         16 :         emit AddAddresses(targetAddresses);
+      66                 :            :     }
+      67                 :            : 
+      68                 :            :     /**
+      69                 :            :      * @notice Removes multiple addresses from the set.
+      70                 :            :      * @dev
+      71                 :            :      * - Does not revert if an address is not listed.
+      72                 :            :      * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`.
+      73                 :            :      * @param targetAddresses Array of addresses to remove.
+      74                 :            :      */
+      75                 :          4 :     function removeAddresses(address[] calldata targetAddresses) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) {
+      76                 :          3 :         _removeAddresses(targetAddresses);
+      77                 :          3 :         emit RemoveAddresses(targetAddresses);
+      78                 :            :     }
+      79                 :            : 
+      80                 :            :     /**
+      81                 :            :      * @notice Adds a single address to the set.
+      82                 :            :      * @dev
+      83                 :            :      * - Reverts if the address is already listed.
+      84                 :            :      * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`.
+      85                 :            :      * @param targetAddress The address to be added.
+      86                 :            :      */
+      87                 :         52 :     function addAddress(address targetAddress) public onlyRole(ADDRESS_LIST_ADD_ROLE) {
+      88            [ + ]:         51 :         if (_isAddressListed(targetAddress)) {
+      89                 :          1 :             revert RuleAddressSet_AddressAlreadyListed();
+      90                 :            :         }
+      91                 :         50 :         _addAddress(targetAddress);
+      92                 :         50 :         emit AddAddress(targetAddress);
+      93                 :            :     }
+      94                 :            : 
+      95                 :            :     /**
+      96                 :            :      * @notice Removes a single address from the set.
+      97                 :            :      * @dev
+      98                 :            :      * - Reverts if the address is not listed.
+      99                 :            :      * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`.
+     100                 :            :      * @param targetAddress The address to be removed.
      101                 :            :      */
-     102                 :            :     function addressIsListed(
-     103                 :            :         address _targetAddress
-     104                 :            :     ) public view returns (bool) {
-     105                 :        159 :         return _addressIsListed(_targetAddress);
-     106                 :            :     }
-     107                 :            : 
-     108                 :            :     /**
-     109                 :            :      * @notice batch version of {addressIsListed}
-     110                 :            :      *
-     111                 :            :      */
-     112                 :            :     function addressIsListedBatch(
-     113                 :            :         address[] memory _targetAddresses
-     114                 :            :     ) public view returns (bool[] memory) {
-     115                 :         28 :         bool[] memory isListed = new bool[](_targetAddresses.length);
-     116                 :         28 :         for (uint256 i = 0; i < _targetAddresses.length; ++i) {
-     117                 :         55 :             isListed[i] = _addressIsListed(_targetAddresses[i]);
-     118                 :            :         }
-     119                 :         28 :         return isListed;
-     120                 :            :     }
-     121                 :            : 
-     122                 :            :     /* ============ ACCESS CONTROL ============ */
-     123                 :            :     /**
-     124                 :            :      * @dev Returns `true` if `account` has been granted `role`.
-     125                 :            :      */
-     126                 :            :     function hasRole(
-     127                 :            :         bytes32 role,
-     128                 :            :         address account
-     129                 :            :     ) public view virtual override(AccessControl) returns (bool) {
-     130                 :            :         // The Default Admin has all roles
-     131            [ + ]:        280 :         if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) {
-     132                 :         78 :             return true;
-     133                 :            :         }
-     134                 :        202 :         return AccessControl.hasRole(role, account);
-     135                 :            :     }
-     136                 :            : 
-     137                 :            :     /*//////////////////////////////////////////////////////////////
-     138                 :            :                            ERC-2771
-     139                 :            :     //////////////////////////////////////////////////////////////*/
-     140                 :            : 
-     141                 :            :     /**
-     142                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
-     143                 :            :      */
-     144                 :            :     function _msgSender()
-     145                 :            :         internal
-     146                 :            :         view
-     147                 :            :         override(ERC2771Context, Context)
-     148                 :            :         returns (address sender)
-     149                 :            :     {
-     150                 :        270 :         return ERC2771Context._msgSender();
-     151                 :            :     }
-     152                 :            : 
-     153                 :            :     /**
-     154                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
-     155                 :            :      */
-     156                 :            :     function _msgData()
-     157                 :            :         internal
-     158                 :            :         view
-     159                 :            :         override(ERC2771Context, Context)
-     160                 :            :         returns (bytes calldata)
-     161                 :            :     {
-     162                 :          0 :         return ERC2771Context._msgData();
-     163                 :            :     }
-     164                 :            : 
-     165                 :            :     /**
-     166                 :            :      * @dev This surcharge is not necessary if you do not use the MetaTxModule
-     167                 :            :      */
-     168                 :            :     function _contextSuffixLength()
-     169                 :            :         internal
-     170                 :            :         view
-     171                 :            :         override(ERC2771Context, Context)
-     172                 :            :         returns (uint256)
-     173                 :            :     {
-     174                 :        270 :         return ERC2771Context._contextSuffixLength();
-     175                 :            :     }
-     176                 :            : }
+     102                 :          3 :     function removeAddress(address targetAddress) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) {
+     103            [ + ]:          2 :         if (!_isAddressListed(targetAddress)) {
+     104                 :          1 :             revert RuleAddressSet_AddressNotFound();
+     105                 :            :         }
+     106                 :          1 :         _removeAddress(targetAddress);
+     107                 :          1 :         emit RemoveAddress(targetAddress);
+     108                 :            :     }
+     109                 :            : 
+     110                 :            :     /**
+     111                 :            :      * @notice Returns the total number of currently listed addresses.
+     112                 :            :      * @return count The number of listed addresses.
+     113                 :            :      */
+     114                 :         24 :     function listedAddressCount() public view returns (uint256 count) {
+     115                 :         24 :         count = _listedAddressCount();
+     116                 :            :     }
+     117                 :            : 
+     118                 :            :     /**
+     119                 :            :      * @notice Checks whether a specific address is currently listed.
+     120                 :            :      * @param targetAddress The address to check.
+     121                 :            :      * @return isListed True if listed, false otherwise.
+     122                 :            :      */
+     123                 :          0 :     function contains(address targetAddress) public view override(IIdentityRegistryContains) returns (bool isListed) {
+     124                 :          0 :         isListed = _isAddressListed(targetAddress);
+     125                 :            :     }
+     126                 :            : 
+     127                 :            :     /**
+     128                 :            :      * @notice Checks whether a specific address is currently listed.
+     129                 :            :      * @param targetAddress The address to check.
+     130                 :            :      * @return isListed True if listed, false otherwise.
+     131                 :            :      */
+     132                 :         60 :     function isAddressListed(address targetAddress) public view returns (bool isListed) {
+     133                 :        187 :         isListed = _isAddressListed(targetAddress);
+     134                 :            :     }
+     135                 :            : 
+     136                 :            :     /**
+     137                 :            :      * @notice Checks multiple addresses in a single call.
+     138                 :            :      * @param targetAddresses Array of addresses to check.
+     139                 :            :      * @return results Array of booleans corresponding to listing status.
+     140                 :            :      */
+     141                 :         62 :     function areAddressesListed(address[] memory targetAddresses) public view returns (bool[] memory results) {
+     142                 :         62 :         results = new bool[](targetAddresses.length);
+     143                 :         62 :         for (uint256 i = 0; i < targetAddresses.length; ++i) {
+     144                 :        139 :             results[i] = _isAddressListed(targetAddresses[i]);
+     145                 :            :         }
+     146                 :            :     }
+     147                 :            :     /*//////////////////////////////////////////////////////////////
+     148                 :            :                              ERC-2771 META TX
+     149                 :            :     //////////////////////////////////////////////////////////////*/
+     150                 :            : 
+     151                 :            :     /// @inheritdoc ERC2771Context
+     152                 :        207 :     function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
+     153                 :        207 :         return ERC2771Context._msgSender();
+     154                 :            :     }
+     155                 :            : 
+     156                 :            :     /// @inheritdoc ERC2771Context
+     157                 :          0 :     function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) {
+     158                 :          0 :         return ERC2771Context._msgData();
+     159                 :            :     }
+     160                 :            : 
+     161                 :            :     /// @inheritdoc ERC2771Context
+     162                 :        207 :     function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
+     163                 :        207 :         return ERC2771Context._contextSuffixLength();
+     164                 :            :     }
+     165                 :            : }
 
@@ -252,7 +241,7 @@
- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func-sort-c.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html similarity index 57% rename from doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func-sort-c.html rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html index 88c2a09..0484ff0 100644 --- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func-sort-c.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - test/RuleConditionalTransfer/utils/RuleCTDeployment.sol - functions + LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,17 +31,17 @@ - - + + - + - - + + @@ -65,12 +65,32 @@
Current view:top level - test/RuleConditionalTransfer/utils - RuleCTDeployment.sol (source / functions)top level - validation/abstract/RuleAddressSet - RuleAddressSetInternal.sol (source / functions) Hitlcov.info Lines:10101414 100.0 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:1166 100.0 %
- + - - + + + + + + + + + + + + + + + + + + + + + +

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

diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html similarity index 57% rename from doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func.html rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html index ead2a6c..54eaa56 100644 --- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/RuleCTDeployment.sol.func.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - test/RuleConditionalTransfer/utils/RuleCTDeployment.sol - functions + LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,17 +31,17 @@ - - + + - + - - + + @@ -66,11 +66,31 @@ - + - - + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test/RuleConditionalTransfer/utils - RuleCTDeployment.sol (source / functions)top level - validation/abstract/RuleAddressSet - RuleAddressSetInternal.sol (source / functions) Hitlcov.info Lines:10101414 100.0 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:1166 100.0 %

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

diff --git a/doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html similarity index 54% rename from doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html index bea5e34..f29faa9 100644 --- a/doc/coverage/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src/rules/validation/RuleBlacklist.sol + LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol @@ -19,7 +19,7 @@ - + @@ -31,17 +31,17 @@ - - + + - + - - + + @@ -49,9 +49,9 @@ - - - + + +
Current view:top level - src/rules/validation - RuleBlacklist.sol (source / functions)top level - validation/abstract/RuleAddressSet - RuleAddressSetInternal.sol (source / functions) Hitlcov.info Lines:13131414 100.0 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:4466 100.0 %
Branches:88100.0 %00-
@@ -70,81 +70,92 @@
           Branch data     Line data    Source code
        1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.20;
-       4                 :            : 
-       5                 :            : import "./abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol";
-       6                 :            : import "./abstract/RuleAddressList/RuleAddressList.sol";
-       7                 :            : import "./abstract/RuleValidateTransfer.sol";
-       8                 :            : 
-       9                 :            : /**
-      10                 :            :  * @title a blacklist manager
-      11                 :            :  */
-      12                 :            : 
-      13                 :            : contract RuleBlacklist is
-      14                 :            :     RuleValidateTransfer,
-      15                 :            :     RuleAddressList,
-      16                 :            :     RuleBlacklistInvariantStorage
-      17                 :            : {
-      18                 :            :     /**
-      19                 :            :      * @param admin Address of the contract (Access Control)
-      20                 :            :      * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
-      21                 :            :      */
-      22                 :            :     constructor(
-      23                 :            :         address admin,
-      24                 :            :         address forwarderIrrevocable
-      25                 :            :     ) RuleAddressList(admin, forwarderIrrevocable) {}
-      26                 :            : 
-      27                 :            :     /**
-      28                 :            :      * @notice Check if an addres is in the whitelist or not
-      29                 :            :      * @param _from the origin address
-      30                 :            :      * @param _to the destination address
-      31                 :            :      * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
-      32                 :            :      **/
-      33                 :            :     function detectTransferRestriction(
-      34                 :            :         address _from,
-      35                 :            :         address _to,
-      36                 :            :         uint256 /*_amount */
-      37                 :            :     ) public view override returns (uint8) {
-      38         [ +  + ]:         10 :         if (addressIsListed(_from)) {
-      39                 :          5 :             return CODE_ADDRESS_FROM_IS_BLACKLISTED;
-      40         [ +  + ]:          5 :         } else if (addressIsListed(_to)) {
-      41                 :          2 :             return CODE_ADDRESS_TO_IS_BLACKLISTED;
-      42                 :            :         } else {
-      43                 :          3 :             return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
-      44                 :            :         }
-      45                 :            :     }
-      46                 :            : 
-      47                 :            :     /**
-      48                 :            :      * @notice To know if the restriction code is valid for this rule or not.
-      49                 :            :      * @param _restrictionCode The target restriction code
-      50                 :            :      * @return true if the restriction code is known, false otherwise
-      51                 :            :      **/
-      52                 :            :     function canReturnTransferRestrictionCode(
-      53                 :            :         uint8 _restrictionCode
-      54                 :            :     ) external pure override returns (bool) {
-      55                 :          4 :         return
-      56                 :          4 :             _restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED ||
-      57                 :          2 :             _restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED;
-      58                 :            :     }
-      59                 :            : 
-      60                 :            :     /**
-      61                 :            :      * @notice Return the corresponding message
-      62                 :            :      * @param _restrictionCode The target restriction code
-      63                 :            :      * @return true if the transfer is valid, false otherwise
-      64                 :            :      **/
-      65                 :            :     function messageForTransferRestriction(
-      66                 :            :         uint8 _restrictionCode
-      67                 :            :     ) external pure override returns (string memory) {
-      68         [ +  + ]:          4 :         if (_restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED) {
-      69                 :          2 :             return TEXT_ADDRESS_FROM_IS_BLACKLISTED;
-      70         [ +  + ]:          2 :         } else if (_restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED) {
-      71                 :          1 :             return TEXT_ADDRESS_TO_IS_BLACKLISTED;
-      72                 :            :         } else {
-      73                 :          1 :             return TEXT_CODE_NOT_FOUND;
-      74                 :            :         }
-      75                 :            :     }
-      76                 :            : }
+       2                 :            : pragma solidity ^0.8.20;
+       3                 :            : 
+       4                 :            : /* ==== OpenZeppelin === */
+       5                 :            : import {EnumerableSet} from "OZ/utils/structs/EnumerableSet.sol";
+       6                 :            : 
+       7                 :            : /**
+       8                 :            :  * @title Rule Address Set (Internal)
+       9                 :            :  * @notice Internal utility for managing a set of rule-related addresses.
+      10                 :            :  * @dev
+      11                 :            :  * - Uses OpenZeppelin's EnumerableSet for efficient enumeration.
+      12                 :            :  * - Designed for internal inheritance and logic composition.
+      13                 :            :  * - Batch operations do not revert when individual entries are invalid.
+      14                 :            :  */
+      15                 :            : abstract contract RuleAddressSetInternal {
+      16                 :            :     using EnumerableSet for EnumerableSet.AddressSet;
+      17                 :            : 
+      18                 :            :     /*//////////////////////////////////////////////////////////////
+      19                 :            :                              STATE VARIABLES
+      20                 :            :     //////////////////////////////////////////////////////////////*/
+      21                 :            : 
+      22                 :            :     /// @dev Storage for all listed addresses.
+      23                 :            :     EnumerableSet.AddressSet private _listedAddresses;
+      24                 :            : 
+      25                 :            :     /*//////////////////////////////////////////////////////////////
+      26                 :            :                               INTERNAL
+      27                 :            :     //////////////////////////////////////////////////////////////*/
+      28                 :            : 
+      29                 :            :     /**
+      30                 :            :      * @notice Adds multiple addresses to the set.
+      31                 :            :      * @dev
+      32                 :            :      * - Does not revert if an address is already listed.
+      33                 :            :      * - Skips existing entries silently.
+      34                 :            :      * @param addressesToAdd The array of addresses to add.
+      35                 :            :      */
+      36                 :         16 :     function _addAddresses(address[] calldata addressesToAdd) internal {
+      37                 :         16 :         for (uint256 i = 0; i < addressesToAdd.length; ++i) {
+      38                 :         34 :             _listedAddresses.add(addressesToAdd[i]);
+      39                 :            :         }
+      40                 :            :     }
+      41                 :            : 
+      42                 :            :     /**
+      43                 :            :      * @notice Removes multiple addresses from the set.
+      44                 :            :      * @dev
+      45                 :            :      * - Does not revert if an address is not found.
+      46                 :            :      * - Skips non-existing entries silently.
+      47                 :            :      * @param addressesToRemove The array of addresses to remove.
+      48                 :            :      */
+      49                 :          3 :     function _removeAddresses(address[] calldata addressesToRemove) internal {
+      50                 :          3 :         for (uint256 i = 0; i < addressesToRemove.length; ++i) {
+      51                 :          7 :             _listedAddresses.remove(addressesToRemove[i]);
+      52                 :            :         }
+      53                 :            :     }
+      54                 :            : 
+      55                 :            :     /**
+      56                 :            :      * @notice Adds a single address to the set.
+      57                 :            :      * @param targetAddress The address to add.
+      58                 :            :      */
+      59                 :         50 :     function _addAddress(address targetAddress) internal {
+      60                 :         50 :         _listedAddresses.add(targetAddress);
+      61                 :            :     }
+      62                 :            : 
+      63                 :            :     /**
+      64                 :            :      * @notice Removes a single address from the set.
+      65                 :            :      * @param targetAddress The address to remove.
+      66                 :            :      */
+      67                 :          1 :     function _removeAddress(address targetAddress) internal {
+      68                 :          1 :         _listedAddresses.remove(targetAddress);
+      69                 :            :     }
+      70                 :            : 
+      71                 :            :     /**
+      72                 :            :      * @notice Returns the total number of listed addresses.
+      73                 :            :      * @return count The number of listed addresses.
+      74                 :            :      */
+      75                 :         24 :     function _listedAddressCount() internal view returns (uint256 count) {
+      76                 :         24 :         count = _listedAddresses.length();
+      77                 :            :     }
+      78                 :            : 
+      79                 :            :     /**
+      80                 :            :      * @notice Checks if an address is listed.
+      81                 :            :      * @param targetAddress The address to check.
+      82                 :            :      * @return isListed True if the address is listed, false otherwise.
+      83                 :            :      */
+      84                 :        379 :     function _isAddressListed(address targetAddress) internal view returns (bool isListed) {
+      85                 :        379 :         isListed = _listedAddresses.contains(targetAddress);
+      86                 :            :     }
+      87                 :            : }
 
diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-b.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html similarity index 71% rename from doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-b.html rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html index 273564b..8ede562 100644 --- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-b.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - test/RuleConditionalTransfer/utils + LCOV - lcov.info - validation/abstract/RuleAddressSet @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/RuleConditionalTransfer/utilstop level - validation/abstract/RuleAddressSet Hitlcov.info Lines:1010100.0 %424691.3 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:11100.0 %151788.2 %
Branches:00-22100.0 %
@@ -82,17 +82,29 @@ Branches Sort by branch coverage - RuleCTDeployment.sol + RuleAddressSetInternal.sol
100.0%
100.0 % - 10 / 10 + 14 / 14 100.0 % - 1 / 1 + 6 / 6 - 0 / 0 + + RuleAddressSet.sol + +
87.5%87.5%
+ + 87.5 % + 28 / 32 + 81.8 % + 9 / 11 + 100.0 % + 2 / 2 +
diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-f.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html similarity index 71% rename from doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-f.html rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html index cfa53fa..90b90d9 100644 --- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-f.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - test/RuleConditionalTransfer/utils + LCOV - lcov.info - validation/abstract/RuleAddressSet @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/RuleConditionalTransfer/utilstop level - validation/abstract/RuleAddressSet Hitlcov.info Lines:1010100.0 %424691.3 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:11100.0 %151788.2 %
Branches:00-22100.0 %
@@ -82,14 +82,26 @@ Branches Sort by branch coverage - RuleCTDeployment.sol + RuleAddressSet.sol + +
87.5%87.5%
+ + 87.5 % + 28 / 32 + 81.8 % + 9 / 11 + 100.0 % + 2 / 2 + + + RuleAddressSetInternal.sol
100.0%
100.0 % - 10 / 10 + 14 / 14 100.0 % - 1 / 1 + 6 / 6 - 0 / 0 diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-l.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html similarity index 71% rename from doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-l.html rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html index 8cfb2ca..244a6fc 100644 --- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index-sort-l.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - test/RuleConditionalTransfer/utils + LCOV - lcov.info - validation/abstract/RuleAddressSet @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/RuleConditionalTransfer/utilstop level - validation/abstract/RuleAddressSet Hitlcov.info Lines:1010100.0 %424691.3 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:11100.0 %151788.2 %
Branches:00-22100.0 %
@@ -82,14 +82,26 @@ Branches Sort by branch coverage - RuleCTDeployment.sol + RuleAddressSet.sol + +
87.5%87.5%
+ + 87.5 % + 28 / 32 + 81.8 % + 9 / 11 + 100.0 % + 2 / 2 + + + RuleAddressSetInternal.sol
100.0%
100.0 % - 10 / 10 + 14 / 14 100.0 % - 1 / 1 + 6 / 6 - 0 / 0 diff --git a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html similarity index 71% rename from doc/coverage/coverage/test/RuleConditionalTransfer/utils/index.html rename to doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html index 0fb4392..7bbaf77 100644 --- a/doc/coverage/coverage/test/RuleConditionalTransfer/utils/index.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - test/RuleConditionalTransfer/utils + LCOV - lcov.info - validation/abstract/RuleAddressSet @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/RuleConditionalTransfer/utilstop level - validation/abstract/RuleAddressSet Hitlcov.info Lines:1010100.0 %424691.3 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:11100.0 %151788.2 %
Branches:00-22100.0 %
@@ -82,14 +82,26 @@ Branches Sort by branch coverage - RuleCTDeployment.sol + RuleAddressSet.sol + +
87.5%87.5%
+ + 87.5 % + 28 / 32 + 81.8 % + 9 / 11 + 100.0 % + 2 / 2 + + + RuleAddressSetInternal.sol
100.0%
100.0 % - 10 / 10 + 14 / 14 100.0 % - 1 / 1 + 6 / 6 - 0 / 0 diff --git a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html similarity index 63% rename from doc/coverage/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html rename to doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html index 32ca64b..e8c66ce 100644 --- a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html +++ b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - test/utils/SanctionListOracle.sol - functions + LCOV - lcov.info - validation/abstract/RuleValidateTransfer.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,18 +31,18 @@ - - - + + + - + - - + + @@ -65,24 +65,28 @@
Current view:top level - test/utils - SanctionListOracle.sol (source / functions)top level - validation/abstract - RuleValidateTransfer.sol (source / functions) Hitlcov.info Lines:2366.7 %81080.0 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:3 475.0 %580.0 %
- + - + - + - - + + + + + + - - + +

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

diff --git a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.func.html b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html similarity index 63% rename from doc/coverage/coverage/test/utils/SanctionListOracle.sol.func.html rename to doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html index 12d4508..f0c093c 100644 --- a/doc/coverage/coverage/test/utils/SanctionListOracle.sol.func.html +++ b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - test/utils/SanctionListOracle.sol - functions + LCOV - lcov.info - validation/abstract/RuleValidateTransfer.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,18 +31,18 @@ - - - + + + - + - - + + @@ -66,22 +66,26 @@ - + - - + + - + + + + + - - + + - +
Current view:top level - test/utils - SanctionListOracle.sol (source / functions)top level - validation/abstract - RuleValidateTransfer.sol (source / functions) Hitlcov.info Lines:2366.7 %81080.0 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:3 475.0 %580.0 %

Function Name Sort by function nameHit count Sort by hit countHit count Sort by hit count
SanctionListOracle.11RuleValidateTransfer.canTransfer.014
SanctionListOracle.addToSanctionsListRuleValidateTransfer.canTransfer.114
RuleValidateTransfer.canTransferFrom.0 10
SanctionListOracle.isSanctioned12RuleValidateTransfer.canTransferFrom.110
SanctionListOracle.removeFromSanctionsListRuleValidateTransfer.supportsInterface 0
diff --git a/doc/coverage/coverage/src/modules/RuleInternal.sol.gcov.html b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html similarity index 50% rename from doc/coverage/coverage/src/modules/RuleInternal.sol.gcov.html rename to doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html index cd50bce..7e35cc9 100644 --- a/doc/coverage/coverage/src/modules/RuleInternal.sol.gcov.html +++ b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src/modules/RuleInternal.sol + LCOV - lcov.info - validation/abstract/RuleValidateTransfer.sol @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - + + - - - + + +
Current view:top level - src/modules - RuleInternal.sol (source / functions)top level - validation/abstract - RuleValidateTransfer.sol (source / functions) Hitlcov.info Lines:2929100.0 %81080.0 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions: 44100.0 %580.0 %
Branches:88100.0 %00-
@@ -72,102 +72,90 @@ 1 : : // SPDX-License-Identifier: MPL-2.0 2 : : 3 : : pragma solidity ^0.8.20; - 4 : : import "./RuleEngineInvariantStorage.sol"; - 5 : : - 6 : : /** - 7 : : * @title Implementation of a ruleEngine defined by the CMTAT - 8 : : */ - 9 : : abstract contract RuleInternal is RuleEngineInvariantStorage { - 10 : : /// @dev Indicate if a rule already exists - 11 : : // Can be shared betwen RuleOperation and RuleValidation since it is a mapping - 12 : : mapping(address => bool) _ruleIsPresent; - 13 : : - 14 : : /** - 15 : : * @notice Set all the rules, will overwrite all the previous rules. \n - 16 : : * Revert if one rule is a zero address or if the rule is already present - 17 : : * - 18 : : */ - 19 : : function _setRules(address[] calldata rules_) internal { - 20 [ + ]: 32 : if (rules_.length == 0) { - 21 : 2 : revert RuleEngine_ArrayIsEmpty(); - 22 : : } - 23 : 30 : for (uint256 i = 0; i < rules_.length; ) { - 24 [ + ]: 48 : if (address(rules_[i]) == address(0x0)) { - 25 : 2 : revert RuleEngine_RuleAddressZeroNotAllowed(); - 26 : : } - 27 [ + ]: 2 : if (_ruleIsPresent[rules_[i]]) { - 28 : 2 : revert RuleEngine_RuleAlreadyExists(); - 29 : : } - 30 : 44 : _ruleIsPresent[rules_[i]] = true; - 31 : 44 : emit AddRule(rules_[i]); - 32 : : unchecked { - 33 : 44 : ++i; - 34 : : } - 35 : : } + 4 : : + 5 : : /* ==== CMTAT === */ + 6 : : import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; + 7 : : import {IERC3643ComplianceRead} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; + 8 : : import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol"; + 9 : : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; + 10 : : /* ==== RuleEngine === */ + 11 : : import {IRule} from "RuleEngine/interfaces/IRule.sol"; + 12 : : import { + 13 : : IERC7943NonFungibleCompliance, + 14 : : IERC7943NonFungibleComplianceExtend + 15 : : } from "../../interfaces/IERC7943NonFungibleCompliance.sol"; + 16 : : + 17 : : abstract contract RuleValidateTransfer is IERC7943NonFungibleComplianceExtend, IRule { + 18 : : /** + 19 : : * @notice Validate a transfer + 20 : : * @param from the origin address + 21 : : * @param to the destination address + 22 : : * @param tokenId ERC-721 or ERC-1155 token Id + 23 : : * @param amount to transfer, 1 for NFT + 24 : : * @return isValid => true if the transfer is valid, false otherwise + 25 : : * + 26 : : */ + 27 : 14 : function canTransfer(address from, address to, uint256 tokenId, uint256 amount) + 28 : : public + 29 : : view + 30 : : override(IERC7943NonFungibleCompliance) + 31 : : returns (bool isValid) + 32 : : { + 33 : : // does not work without `this` keyword => "Undeclared identifier" + 34 : 14 : return this.detectTransferRestriction(from, to, tokenId, amount) + 35 : : == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); 36 : : } 37 : : 38 : : /** - 39 : : * @notice Add a rule to the array of rules - 40 : : * Revert if one rule is a zero address or if the rule is already present - 41 : : * - 42 : : */ - 43 : : function _addRule(address[] storage _rules, address rule_) internal { - 44 [ + ]: 203 : if (address(rule_) == address(0x0)) { - 45 : 2 : revert RuleEngine_RuleAddressZeroNotAllowed(); - 46 : : } - 47 [ + ]: 2 : if (_ruleIsPresent[rule_]) { - 48 : 2 : revert RuleEngine_RuleAlreadyExists(); - 49 : : } - 50 : 199 : _rules.push(rule_); - 51 : 199 : _ruleIsPresent[rule_] = true; - 52 : : } - 53 : : - 54 : : /** - 55 : : * @notice Remove a rule from the array of rules - 56 : : * Revert if the rule found at the specified index does not match the rule in argument - 57 : : * @param rule_ address of the target rule - 58 : : * @param index the position inside the array of rule - 59 : : * @dev To reduce the array size, the last rule is moved to the location occupied - 60 : : * by the rule to remove - 61 : : * - 62 : : * - 63 : : */ - 64 : : function _removeRule( - 65 : : address[] storage _rules, - 66 : : address rule_, - 67 : : uint256 index - 68 : : ) internal { - 69 [ + ]: 55 : if (_rules[index] != rule_) { - 70 : 2 : revert RuleEngine_RuleDoNotMatch(); - 71 : : } - 72 [ + ]: 53 : if (index != _rules.length - 1) { - 73 : 4 : _rules[index] = _rules[_rules.length - 1]; - 74 : : } - 75 : 53 : _rules.pop(); - 76 : 53 : _ruleIsPresent[rule_] = false; - 77 : 53 : emit RemoveRule(rule_); - 78 : : } - 79 : : - 80 : : /** - 81 : : * @notice Get the index of a rule inside the list - 82 : : * @return index if the rule is found, _rules.length otherwise - 83 : : */ - 84 : : function _getRuleIndex( - 85 : : address[] storage _rules, - 86 : : address rule_ - 87 : : ) internal view returns (uint256 index) { - 88 : 6 : uint256 rulesLength = _rules.length; - 89 : 6 : for (index = 0; index < rulesLength; ) { - 90 [ + ]: 10 : if (_rules[index] == rule_) { - 91 : 4 : return index; - 92 : : } - 93 : : unchecked { - 94 : 6 : ++index; - 95 : : } - 96 : : } - 97 : 2 : return _rules.length; - 98 : : } - 99 : : } + 39 : : * @notice Validate a transfer + 40 : : * @param from the origin address + 41 : : * @param to the destination address + 42 : : * @param amount to transfer + 43 : : * @return isValid => true if the transfer is valid, false otherwise + 44 : : * + 45 : : */ + 46 : 14 : function canTransfer(address from, address to, uint256 amount) + 47 : : public + 48 : : view + 49 : : override(IERC3643ComplianceRead) + 50 : : returns (bool isValid) + 51 : : { + 52 : : // does not work without `this` keyword => "Undeclared identifier" + 53 : 14 : return this.detectTransferRestriction(from, to, amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); + 54 : : } + 55 : : + 56 : : /** + 57 : : * @inheritdoc IERC7551Compliance + 58 : : */ + 59 : 10 : function canTransferFrom(address spender, address from, address to, uint256 value) + 60 : : public + 61 : : view + 62 : : virtual + 63 : : override(IERC7551Compliance) + 64 : : returns (bool) + 65 : : { + 66 : 20 : return this.detectTransferRestrictionFrom(spender, from, to, value) + 67 : : == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); + 68 : : } + 69 : : + 70 : : /** + 71 : : * @inheritdoc IERC7943NonFungibleComplianceExtend + 72 : : */ + 73 : 10 : function canTransferFrom(address spender, address from, address to, uint256 tokenId, uint256 value) + 74 : : public + 75 : : view + 76 : : virtual + 77 : : override(IERC7943NonFungibleComplianceExtend) + 78 : : returns (bool) + 79 : : { + 80 : 10 : return canTransferFrom(spender, from, to, value); + 81 : : } + 82 : : + 83 : : + 84 : 0 : function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { + 85 : 0 : return interfaceId == type(IRule).interfaceId; + 86 : : } + 87 : : } diff --git a/doc/coverage/coverage/src/modules/RuleInternal.sol.func-sort-c.html b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html similarity index 57% rename from doc/coverage/coverage/src/modules/RuleInternal.sol.func-sort-c.html rename to doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html index 7456c15..5f0d38b 100644 --- a/doc/coverage/coverage/src/modules/RuleInternal.sol.func-sort-c.html +++ b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src/modules/RuleInternal.sol - functions + LCOV - lcov.info - validation/abstract/RuleWhitelistCommon.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,18 +31,18 @@ - - - + + + - + - - - + + + @@ -50,8 +50,8 @@ - - + +
Current view:top level - src/modules - RuleInternal.sol (source / functions)top level - validation/abstract - RuleWhitelistCommon.sol (source / functions) Hitlcov.info Lines:2929100.0 %141973.7 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:44100.0 %3560.0 %
Branches: 88100.0 %1080.0 %
@@ -65,24 +65,28 @@ - + - - + + + + + + - - + + - - + + - - + +

Function Name Sort by function nameFunction Name Sort by function name Hit count Sort by hit count
RuleInternal._getRuleIndex6RuleWhitelistCommon.transferred.10
RuleWhitelistCommon.transferred.20
RuleInternal._setRules32RuleWhitelistCommon.canReturnTransferRestrictionCode10
RuleInternal._removeRule55RuleWhitelistCommon.transferred.012
RuleInternal._addRule203RuleWhitelistCommon.messageForTransferRestriction14

diff --git a/doc/coverage/coverage/src/modules/RuleInternal.sol.func.html b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html similarity index 57% rename from doc/coverage/coverage/src/modules/RuleInternal.sol.func.html rename to doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html index 239df15..c33f21e 100644 --- a/doc/coverage/coverage/src/modules/RuleInternal.sol.func.html +++ b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src/modules/RuleInternal.sol - functions + LCOV - lcov.info - validation/abstract/RuleWhitelistCommon.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,18 +31,18 @@ - - - + + + - + - - - + + + @@ -50,8 +50,8 @@ - - + +
Current view:top level - src/modules - RuleInternal.sol (source / functions)top level - validation/abstract - RuleWhitelistCommon.sol (source / functions) Hitlcov.info Lines:2929100.0 %141973.7 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:44100.0 %3560.0 %
Branches: 88100.0 %1080.0 %
@@ -66,23 +66,27 @@
Function Name Sort by function name - Hit count Sort by hit count + Hit count Sort by hit count - RuleInternal._addRule - 203 + RuleWhitelistCommon.canReturnTransferRestrictionCode + 10 + + + RuleWhitelistCommon.messageForTransferRestriction + 14 - RuleInternal._getRuleIndex - 6 + RuleWhitelistCommon.transferred.0 + 12 - RuleInternal._removeRule - 55 + RuleWhitelistCommon.transferred.1 + 0 - RuleInternal._setRules - 32 + RuleWhitelistCommon.transferred.2 + 0
diff --git a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html new file mode 100644 index 0000000..5705304 --- /dev/null +++ b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html @@ -0,0 +1,200 @@ + + + + + + + LCOV - lcov.info - validation/abstract/RuleWhitelistCommon.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - validation/abstract - RuleWhitelistCommon.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:141973.7 %
Date:2025-12-03 14:12:50Functions:3560.0 %
Branches:81080.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : pragma solidity ^0.8.20;
+       3                 :            : 
+       4                 :            : /* ==== CMTAT === */
+       5                 :            : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+       6                 :            : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+       7                 :            : /* ==== Abstract contracts === */
+       8                 :            : import {RuleWhitelistInvariantStorage} from "./RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol";
+       9                 :            : import {RuleValidateTransfer} from "./RuleValidateTransfer.sol";
+      10                 :            : /* ==== Interface === */
+      11                 :            : import {
+      12                 :            :     IERC7943NonFungibleCompliance,
+      13                 :            :     IERC7943NonFungibleComplianceExtend
+      14                 :            : } from "../../interfaces/IERC7943NonFungibleCompliance.sol";
+      15                 :            : 
+      16                 :            : /**
+      17                 :            :  * @title Rule Whitelist Common
+      18                 :            :  * @notice Provides common logic for validating whitelist-based transfer restrictions.
+      19                 :            :  * @dev
+      20                 :            :  * - Implements ERC-3643–compatible `transferred` hooks to enforce whitelist checks.
+      21                 :            :  * - Defines utility functions for restriction code validation and message mapping.
+      22                 :            :  * - Inherits restriction code constants and messages from {RuleWhitelistInvariantStorage}.
+      23                 :            :  */
+      24                 :            : abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInvariantStorage {
+      25                 :            :     /**
+      26                 :            :      * Indicate if the spender is verified or not
+      27                 :            :      */
+      28                 :            :     bool public checkSpender;
+      29                 :            : 
+      30                 :            :     /* ============  View Functions ============ */
+      31                 :            :     /**
+      32                 :            :      * @notice Checks whether a restriction code is recognized by this rule.
+      33                 :            :      * @dev
+      34                 :            :      * Used to verify if a returned restriction code belongs to the whitelist rule.
+      35                 :            :      * @param restrictionCode The restriction code to validate.
+      36                 :            :      * @return isKnown True if the restriction code is recognized by this rule, false otherwise.
+      37                 :            :      */
+      38                 :         10 :     function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override returns (bool isKnown) {
+      39                 :         10 :         return restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED
+      40                 :          5 :             || restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED || restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED;
+      41                 :            :     }
+      42                 :            : 
+      43                 :            :     /**
+      44                 :            :      * @notice Returns the human-readable message corresponding to a restriction code.
+      45                 :            :      * @dev
+      46                 :            :      * Returns a descriptive text that explains why a transfer was restricted.
+      47                 :            :      * @param restrictionCode The restriction code to decode.
+      48                 :            :      * @return message A human-readable explanation of the restriction.
+      49                 :            :      */
+      50                 :         14 :     function messageForTransferRestriction(uint8 restrictionCode)
+      51                 :            :         external
+      52                 :            :         pure
+      53                 :            :         override
+      54                 :            :         returns (string memory message)
+      55                 :            :     {
+      56         [ +  + ]:         14 :         if (restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) {
+      57                 :          6 :             return TEXT_ADDRESS_FROM_NOT_WHITELISTED;
+      58         [ +  + ]:          8 :         } else if (restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) {
+      59                 :          4 :             return TEXT_ADDRESS_TO_NOT_WHITELISTED;
+      60         [ +  + ]:          4 :         } else if (restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED) {
+      61                 :          2 :             return TEXT_ADDRESS_SPENDER_NOT_WHITELISTED;
+      62                 :            :         } else {
+      63                 :          2 :             return TEXT_CODE_NOT_FOUND;
+      64                 :            :         }
+      65                 :            :     }
+      66                 :            : 
+      67                 :            :     /* ============  State Functions ============ */
+      68                 :            : 
+      69                 :            :     /**
+      70                 :            :      * @notice ERC-3643 hook called when a transfer occurs.
+      71                 :            :      * @dev
+      72                 :            :      * - Validates that both `from` and `to` addresses are whitelisted.
+      73                 :            :      * - Reverts if any restriction code other than `TRANSFER_OK` is returned.
+      74                 :            :      * - Should be called during token transfer logic to enforce whitelist compliance.
+      75                 :            :      * @param from The address sending tokens.
+      76                 :            :      * @param to The address receiving tokens.
+      77                 :            :      * @param value The token amount being transferred.
+      78                 :            :      */
+      79                 :         12 :     function transferred(address from, address to, uint256 value) public view override(IERC3643IComplianceContract) {
+      80                 :         12 :         uint8 code = this.detectTransferRestriction(from, to, value);
+      81         [ +  + ]:         12 :         require(
+      82                 :            :             code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+      83                 :            :             RuleWhitelist_InvalidTransfer(address(this), from, to, value, code)
+      84                 :            :         );
+      85                 :            :     }
+      86                 :            : 
+      87                 :            :     /**
+      88                 :            :      * @notice hook called when a delegated transfer occurs (`transferFrom`).
+      89                 :            :      * @dev
+      90                 :            :      * - Validates that `spender`, `from`, and `to` are all whitelisted.
+      91                 :            :      * - Reverts if any restriction code other than `TRANSFER_OK` is returned.
+      92                 :            :      * @param spender The address performing the transfer on behalf of another.
+      93                 :            :      * @param from The address from which tokens are transferred.
+      94                 :            :      * @param to The recipient address.
+      95                 :            :      * @param value The token amount being transferred.
+      96                 :            :      */
+      97                 :          0 :     function transferred(address spender, address from, address to, uint256 value) public view override(IRuleEngine) {
+      98                 :          0 :         uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value);
+      99         [ #  # ]:          0 :         require(
+     100                 :            :             code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+     101                 :            :             RuleWhitelist_InvalidTransfer(address(this), from, to, value, code)
+     102                 :            :         );
+     103                 :            :     }
+     104                 :            : 
+     105                 :            :     /**
+     106                 :            :      * @inheritdoc IERC7943NonFungibleComplianceExtend
+     107                 :            :      */
+     108                 :          0 :     function transferred(address spender, address from, address to, uint256, /* tokenId */ uint256 value)
+     109                 :            :         public
+     110                 :            :         view
+     111                 :            :         override(IERC7943NonFungibleComplianceExtend)
+     112                 :            :     {
+     113                 :          0 :         transferred(spender, from, to, value);
+     114                 :            :     }
+     115                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/test/utils/index-sort-b.html b/doc/coverage/coverage/validation/abstract/index-sort-b.html similarity index 71% rename from doc/coverage/coverage/test/utils/index-sort-b.html rename to doc/coverage/coverage/validation/abstract/index-sort-b.html index 500c424..6140e7c 100644 --- a/doc/coverage/coverage/test/utils/index-sort-b.html +++ b/doc/coverage/coverage/validation/abstract/index-sort-b.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - test/utils + LCOV - lcov.info - validation/abstract @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/utilstop level - validation/abstract Hitlcov.info Lines:6785.7 %222975.9 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:4580.0 %71070.0 %
Branches:00-81080.0 %
@@ -82,26 +82,26 @@ Branches Sort by branch coverage - CMTATDeployment.sol + RuleWhitelistCommon.sol -
100.0%
+
73.7%73.7%
- 100.0 % - 4 / 4 - 100.0 % - 1 / 1 - - - 0 / 0 + 73.7 % + 14 / 19 + 60.0 % + 3 / 5 + 80.0 % + 8 / 10 - SanctionListOracle.sol + RuleValidateTransfer.sol -
66.7%66.7%
+
80.0%80.0%
- 66.7 % - 2 / 3 - 75.0 % - 3 / 4 + 80.0 % + 8 / 10 + 80.0 % + 4 / 5 - 0 / 0 diff --git a/doc/coverage/coverage/test/utils/index-sort-f.html b/doc/coverage/coverage/validation/abstract/index-sort-f.html similarity index 71% rename from doc/coverage/coverage/test/utils/index-sort-f.html rename to doc/coverage/coverage/validation/abstract/index-sort-f.html index ff0b711..318c7d0 100644 --- a/doc/coverage/coverage/test/utils/index-sort-f.html +++ b/doc/coverage/coverage/validation/abstract/index-sort-f.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - test/utils + LCOV - lcov.info - validation/abstract @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/utilstop level - validation/abstract Hitlcov.info Lines:6785.7 %222975.9 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:4580.0 %71070.0 %
Branches:00-81080.0 %
@@ -82,26 +82,26 @@ Branches Sort by branch coverage - SanctionListOracle.sol + RuleWhitelistCommon.sol -
66.7%66.7%
+
73.7%73.7%
- 66.7 % - 2 / 3 - 75.0 % - 3 / 4 - - - 0 / 0 + 73.7 % + 14 / 19 + 60.0 % + 3 / 5 + 80.0 % + 8 / 10 - CMTATDeployment.sol + RuleValidateTransfer.sol -
100.0%
+
80.0%80.0%
- 100.0 % - 4 / 4 - 100.0 % - 1 / 1 + 80.0 % + 8 / 10 + 80.0 % + 4 / 5 - 0 / 0 diff --git a/doc/coverage/coverage/test/utils/index-sort-l.html b/doc/coverage/coverage/validation/abstract/index-sort-l.html similarity index 71% rename from doc/coverage/coverage/test/utils/index-sort-l.html rename to doc/coverage/coverage/validation/abstract/index-sort-l.html index b1f3e52..56b6a61 100644 --- a/doc/coverage/coverage/test/utils/index-sort-l.html +++ b/doc/coverage/coverage/validation/abstract/index-sort-l.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - test/utils + LCOV - lcov.info - validation/abstract @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/utilstop level - validation/abstract Hitlcov.info Lines:6785.7 %222975.9 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:4580.0 %71070.0 %
Branches:00-81080.0 %
@@ -82,26 +82,26 @@ Branches Sort by branch coverage - SanctionListOracle.sol + RuleWhitelistCommon.sol -
66.7%66.7%
+
73.7%73.7%
- 66.7 % - 2 / 3 - 75.0 % - 3 / 4 - - - 0 / 0 + 73.7 % + 14 / 19 + 60.0 % + 3 / 5 + 80.0 % + 8 / 10 - CMTATDeployment.sol + RuleValidateTransfer.sol -
100.0%
+
80.0%80.0%
- 100.0 % - 4 / 4 - 100.0 % - 1 / 1 + 80.0 % + 8 / 10 + 80.0 % + 4 / 5 - 0 / 0 diff --git a/doc/coverage/coverage/test/utils/index.html b/doc/coverage/coverage/validation/abstract/index.html similarity index 71% rename from doc/coverage/coverage/test/utils/index.html rename to doc/coverage/coverage/validation/abstract/index.html index 0cb6aec..7d95aca 100644 --- a/doc/coverage/coverage/test/utils/index.html +++ b/doc/coverage/coverage/validation/abstract/index.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - test/utils + LCOV - lcov.info - validation/abstract @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - test/utilstop level - validation/abstract Hitlcov.info Lines:6785.7 %222975.9 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:4580.0 %71070.0 %
Branches:00-81080.0 %
@@ -82,28 +82,28 @@ Branches Sort by branch coverage - CMTATDeployment.sol + RuleValidateTransfer.sol -
100.0%
+
80.0%80.0%
- 100.0 % - 4 / 4 - 100.0 % - 1 / 1 + 80.0 % + 8 / 10 + 80.0 % + 4 / 5 - 0 / 0 - SanctionListOracle.sol + RuleWhitelistCommon.sol -
66.7%66.7%
+
73.7%73.7%
- 66.7 % - 2 / 3 - 75.0 % - 3 / 4 - - - 0 / 0 + 73.7 % + 14 / 19 + 60.0 % + 3 / 5 + 80.0 % + 8 / 10 diff --git a/doc/coverage/coverage/src/index-sort-b.html b/doc/coverage/coverage/validation/index-sort-b.html similarity index 52% rename from doc/coverage/coverage/src/index-sort-b.html rename to doc/coverage/coverage/validation/index-sort-b.html index 576ca6d..7d7889c 100644 --- a/doc/coverage/coverage/src/index-sort-b.html +++ b/doc/coverage/coverage/validation/index-sort-b.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src + LCOV - lcov.info - validation @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - srctop level - validation Hitlcov.info Lines:383997.4 %13416481.7 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:8988.9 %324472.7 %
Branches:88100.0 %445383.0 %
@@ -82,16 +82,52 @@ Branches Sort by branch coverage - RuleEngine.sol + RuleSanctionsList.sol -
97.4%97.4%
+
76.9%76.9%
- 97.4 % - 38 / 39 - 88.9 % - 8 / 9 + 76.9 % + 40 / 52 + 68.8 % + 11 / 16 + 77.8 % + 14 / 18 + + + RuleWhitelistWrapper.sol + +
87.7%87.7%
+ + 87.7 % + 50 / 57 + 81.8 % + 9 / 11 + 78.6 % + 11 / 14 + + + RuleBlacklist.sol + +
80.0%80.0%
+ + 80.0 % + 28 / 35 + 70.0 % + 7 / 10 + 87.5 % + 14 / 16 + + + RuleWhitelist.sol + +
80.0%80.0%
+ + 80.0 % + 16 / 20 + 71.4 % + 5 / 7 100.0 % - 8 / 8 + 5 / 5 diff --git a/doc/coverage/coverage/src/index-sort-f.html b/doc/coverage/coverage/validation/index-sort-f.html similarity index 52% rename from doc/coverage/coverage/src/index-sort-f.html rename to doc/coverage/coverage/validation/index-sort-f.html index 8962246..1049174 100644 --- a/doc/coverage/coverage/src/index-sort-f.html +++ b/doc/coverage/coverage/validation/index-sort-f.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src + LCOV - lcov.info - validation @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - srctop level - validation Hitlcov.info Lines:383997.4 %13416481.7 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:8988.9 %324472.7 %
Branches:88100.0 %445383.0 %
@@ -82,16 +82,52 @@ Branches Sort by branch coverage - RuleEngine.sol + RuleSanctionsList.sol -
97.4%97.4%
+
76.9%76.9%
- 97.4 % - 38 / 39 - 88.9 % - 8 / 9 + 76.9 % + 40 / 52 + 68.8 % + 11 / 16 + 77.8 % + 14 / 18 + + + RuleBlacklist.sol + +
80.0%80.0%
+ + 80.0 % + 28 / 35 + 70.0 % + 7 / 10 + 87.5 % + 14 / 16 + + + RuleWhitelist.sol + +
80.0%80.0%
+ + 80.0 % + 16 / 20 + 71.4 % + 5 / 7 100.0 % - 8 / 8 + 5 / 5 + + + RuleWhitelistWrapper.sol + +
87.7%87.7%
+ + 87.7 % + 50 / 57 + 81.8 % + 9 / 11 + 78.6 % + 11 / 14 diff --git a/doc/coverage/coverage/src/index-sort-l.html b/doc/coverage/coverage/validation/index-sort-l.html similarity index 52% rename from doc/coverage/coverage/src/index-sort-l.html rename to doc/coverage/coverage/validation/index-sort-l.html index f6e4883..b91037f 100644 --- a/doc/coverage/coverage/src/index-sort-l.html +++ b/doc/coverage/coverage/validation/index-sort-l.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src + LCOV - lcov.info - validation @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - srctop level - validation Hitlcov.info Lines:383997.4 %13416481.7 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:8988.9 %324472.7 %
Branches:88100.0 %445383.0 %
@@ -82,16 +82,52 @@ Branches Sort by branch coverage - RuleEngine.sol + RuleSanctionsList.sol -
97.4%97.4%
+
76.9%76.9%
- 97.4 % - 38 / 39 - 88.9 % - 8 / 9 + 76.9 % + 40 / 52 + 68.8 % + 11 / 16 + 77.8 % + 14 / 18 + + + RuleWhitelist.sol + +
80.0%80.0%
+ + 80.0 % + 16 / 20 + 71.4 % + 5 / 7 100.0 % - 8 / 8 + 5 / 5 + + + RuleBlacklist.sol + +
80.0%80.0%
+ + 80.0 % + 28 / 35 + 70.0 % + 7 / 10 + 87.5 % + 14 / 16 + + + RuleWhitelistWrapper.sol + +
87.7%87.7%
+ + 87.7 % + 50 / 57 + 81.8 % + 9 / 11 + 78.6 % + 11 / 14 diff --git a/doc/coverage/coverage/src/index.html b/doc/coverage/coverage/validation/index.html similarity index 52% rename from doc/coverage/coverage/src/index.html rename to doc/coverage/coverage/validation/index.html index 0762168..66084f4 100644 --- a/doc/coverage/coverage/src/index.html +++ b/doc/coverage/coverage/validation/index.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - src + LCOV - lcov.info - validation @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - srctop level - validation Hitlcov.info Lines:383997.4 %13416481.7 %
Date:2024-12-20 10:41:142025-12-03 14:12:50 Functions:8988.9 %324472.7 %
Branches:88100.0 %445383.0 %
@@ -82,16 +82,52 @@ Branches Sort by branch coverage - RuleEngine.sol + RuleBlacklist.sol -
97.4%97.4%
+
80.0%80.0%
- 97.4 % - 38 / 39 - 88.9 % - 8 / 9 + 80.0 % + 28 / 35 + 70.0 % + 7 / 10 + 87.5 % + 14 / 16 + + + RuleSanctionsList.sol + +
76.9%76.9%
+ + 76.9 % + 40 / 52 + 68.8 % + 11 / 16 + 77.8 % + 14 / 18 + + + RuleWhitelist.sol + +
80.0%80.0%
+ + 80.0 % + 16 / 20 + 71.4 % + 5 / 7 100.0 % - 8 / 8 + 5 / 5 + + + RuleWhitelistWrapper.sol + +
87.7%87.7%
+ + 87.7 % + 50 / 57 + 81.8 % + 9 / 11 + 78.6 % + 11 / 14 diff --git a/doc/coverage/lcov.info b/doc/coverage/lcov.info index a4e6aaf..f1972de 100644 --- a/doc/coverage/lcov.info +++ b/doc/coverage/lcov.info @@ -1,1091 +1,542 @@ TN: -SF:script/CMTATWithRuleEngineScript.s.sol -FN:15,CMTATWithRuleEngineScript.run -FNDA:0,CMTATWithRuleEngineScript.run -DA:17,0 -DA:18,0 -DA:19,0 -DA:20,0 -DA:22,0 -DA:23,0 -DA:24,0 -DA:26,0 -DA:30,0 -DA:32,0 -DA:37,0 -DA:38,0 -DA:39,0 -DA:41,0 -FNF:1 -FNH:0 -LF:14 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:script/RuleEngineScript.s.sol -FN:16,RuleEngineScript.run -FNDA:0,RuleEngineScript.run -DA:18,0 -DA:19,0 -DA:20,0 -DA:21,0 -DA:23,0 -DA:24,0 -DA:26,0 -DA:27,0 -DA:28,0 -DA:30,0 -DA:33,0 -BRDA:33,0,0,- -BRDA:33,0,1,- -DA:34,0 -FNF:1 -FNH:0 -LF:12 -LH:0 -BRF:2 -BRH:0 -end_of_record -TN: -SF:src/RuleEngine.sol -FN:29,RuleEngine. -FNDA:205,RuleEngine. -DA:34,205 -BRDA:34,0,0,1 -DA:35,1 -DA:37,204 -BRDA:37,1,0,86 -DA:38,86 -DA:40,204 -FN:50,RuleEngine.detectTransferRestriction -FNDA:20,RuleEngine.detectTransferRestriction -DA:56,32 -DA:61,32 -BRDA:61,2,0,15 -DA:62,15 -DA:66,17 -DA:67,17 -DA:68,12 -DA:70,12 -BRDA:70,3,0,11 -DA:71,11 -DA:75,6 -FN:85,RuleEngine.validateTransfer -FNDA:12,RuleEngine.validateTransfer -DA:90,12 -DA:91,12 -FN:100,RuleEngine.messageForTransferRestriction -FNDA:18,RuleEngine.messageForTransferRestriction -DA:104,18 -DA:105,18 -DA:107,13 -DA:109,10 -BRDA:109,4,0,10 -DA:110,10 -DA:111,10 -DA:116,8 -DA:117,8 -DA:119,2 -DA:121,1 -BRDA:121,5,0,1 -DA:122,1 -DA:123,1 -DA:127,7 -FN:133,RuleEngine.operateOnTransfer -FNDA:69,RuleEngine.operateOnTransfer -DA:140,68 -DA:141,10 -BRDA:141,6,0,10 -DA:142,10 -DA:145,58 -FN:152,RuleEngine.hasRole -FNDA:299,RuleEngine.hasRole -DA:157,597 -BRDA:157,7,0,220 -DA:158,220 -DA:160,377 -FN:170,RuleEngine._msgSender -FNDA:588,RuleEngine._msgSender -DA:176,588 -FN:182,RuleEngine._msgData -FNDA:0,RuleEngine._msgData -DA:188,0 -FN:194,RuleEngine._contextSuffixLength -FNDA:588,RuleEngine._contextSuffixLength -DA:200,588 -FNF:9 -FNH:8 -LF:39 -LH:38 -BRF:8 -BRH:8 -end_of_record -TN: -SF:src/modules/MetaTxModuleStandalone.sol -FN:11,MetaTxModuleStandalone. -FNDA:575,MetaTxModuleStandalone. -FNF:1 -FNH:1 -LF:0 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/modules/RuleEngineOperation.sol -FN:26,RuleEngineOperation.setRulesOperation -FNDA:11,RuleEngineOperation.setRulesOperation -DA:29,11 -BRDA:29,0,0,10 -DA:30,10 -DA:32,11 -DA:33,8 -FN:40,RuleEngineOperation.clearRulesOperation -FNDA:4,RuleEngineOperation.clearRulesOperation -DA:41,4 -FN:48,RuleEngineOperation._clearRulesOperation -FNDA:14,RuleEngineOperation._clearRulesOperation -DA:49,14 -DA:51,14 -DA:54,17 -DA:56,17 -DA:58,14 -FN:66,RuleEngineOperation.addRuleOperation -FNDA:85,RuleEngineOperation.addRuleOperation -DA:69,85 -DA:70,83 -FN:83,RuleEngineOperation.removeRuleOperation -FNDA:5,RuleEngineOperation.removeRuleOperation -DA:87,5 -FN:100,RuleEngineOperation._removeRuleOperation -FNDA:22,RuleEngineOperation._removeRuleOperation -DA:101,22 -DA:102,21 -FN:108,RuleEngineOperation.rulesCountOperation -FNDA:41,RuleEngineOperation.rulesCountOperation -DA:109,41 -FN:116,RuleEngineOperation.getRuleIndexOperation -FNDA:3,RuleEngineOperation.getRuleIndexOperation -DA:119,3 -FN:127,RuleEngineOperation.ruleOperation -FNDA:1,RuleEngineOperation.ruleOperation -DA:130,1 -FN:137,RuleEngineOperation.rulesOperation -FNDA:5,RuleEngineOperation.rulesOperation -DA:143,5 -FN:152,RuleEngineOperation._operateOnTransfer -FNDA:58,RuleEngineOperation._operateOnTransfer -DA:157,58 -DA:158,58 -DA:159,50 -DA:164,50 -BRDA:164,1,0,24 -DA:165,24 -DA:168,34 -FNF:11 -FNH:11 -LF:25 -LH:25 -BRF:2 -BRH:2 -end_of_record -TN: -SF:src/modules/RuleEngineValidation.sol -FN:29,RuleEngineValidation.detectTransferRestrictionValidation -FNDA:3,RuleEngineValidation.detectTransferRestrictionValidation -DA:34,105 -DA:35,105 -DA:36,43 -DA:38,43 -BRDA:38,0,0,28 -DA:39,28 -DA:43,77 -FN:53,RuleEngineValidation.validateTransferValidation -FNDA:2,RuleEngineValidation.validateTransferValidation -DA:58,70 -DA:59,70 +SF:src/modules/AccessControlModuleStandalone.sol +DA:22,161 +FN:22,AccessControlModuleStandalone.constructor +FNDA:161,AccessControlModuleStandalone.constructor +DA:23,161 +BRDA:23,0,0,4 +DA:24,4 +DA:29,157 +DA:38,228 +FN:38,AccessControlModuleStandalone.hasRole +FNDA:228,AccessControlModuleStandalone.hasRole +DA:40,328 +BRDA:40,1,0,152 +BRDA:40,1,1,176 +DA:41,152 +DA:43,176 FNF:2 FNH:2 LF:8 LH:8 -BRF:1 -BRH:1 -end_of_record -TN: -SF:src/modules/RuleEngineValidationCommon.sol -FN:30,RuleEngineValidationCommon.setRulesValidation -FNDA:22,RuleEngineValidationCommon.setRulesValidation -DA:33,21 -BRDA:33,0,0,20 -DA:34,20 -DA:36,21 -DA:37,18 -FN:44,RuleEngineValidationCommon.clearRulesValidation -FNDA:6,RuleEngineValidationCommon.clearRulesValidation -DA:45,5 -FN:53,RuleEngineValidationCommon.addRuleValidation -FNDA:119,RuleEngineValidationCommon.addRuleValidation -DA:56,118 -DA:57,116 -FN:70,RuleEngineValidationCommon.removeRuleValidation -FNDA:6,RuleEngineValidationCommon.removeRuleValidation -DA:74,5 -FN:80,RuleEngineValidationCommon.rulesCountValidation -FNDA:69,RuleEngineValidationCommon.rulesCountValidation -DA:81,69 -FN:88,RuleEngineValidationCommon.getRuleIndexValidation -FNDA:3,RuleEngineValidationCommon.getRuleIndexValidation -DA:91,3 -FN:99,RuleEngineValidationCommon.ruleValidation -FNDA:1,RuleEngineValidationCommon.ruleValidation -DA:102,1 -FN:109,RuleEngineValidationCommon.rulesValidation -FNDA:5,RuleEngineValidationCommon.rulesValidation -DA:115,5 -FN:125,RuleEngineValidationCommon._clearRulesValidation -FNDA:25,RuleEngineValidationCommon._clearRulesValidation -DA:126,25 -DA:128,25 -DA:131,28 -DA:133,28 -DA:135,25 -FN:148,RuleEngineValidationCommon._removeRuleValidation -FNDA:33,RuleEngineValidationCommon._removeRuleValidation -DA:149,33 -DA:150,32 -FNF:10 -FNH:10 -LF:19 -LH:19 -BRF:1 -BRH:1 -end_of_record -TN: -SF:src/modules/RuleInternal.sol -FN:19,RuleInternal._setRules -FNDA:32,RuleInternal._setRules -DA:20,32 -BRDA:20,0,0,2 -DA:21,2 -DA:23,30 -DA:24,48 -BRDA:24,1,0,2 -DA:25,2 -DA:27,2 -BRDA:27,2,0,2 -DA:28,2 -DA:30,44 -DA:31,44 -DA:33,44 -FN:43,RuleInternal._addRule -FNDA:203,RuleInternal._addRule -DA:44,203 -BRDA:44,3,0,2 -DA:45,2 -DA:47,2 -BRDA:47,4,0,2 -DA:48,2 -DA:50,199 -DA:51,199 -FN:64,RuleInternal._removeRule -FNDA:55,RuleInternal._removeRule -DA:69,55 -BRDA:69,5,0,2 -DA:70,2 -DA:72,53 -BRDA:72,6,0,4 -DA:73,4 -DA:75,53 -DA:76,53 -DA:77,53 -FN:84,RuleInternal._getRuleIndex -FNDA:6,RuleInternal._getRuleIndex -DA:88,6 -DA:89,6 -DA:90,10 -BRDA:90,7,0,4 -DA:91,4 -DA:94,6 -DA:97,2 -FNF:4 -FNH:4 -LF:29 -LH:29 -BRF:8 -BRH:8 -end_of_record -TN: -SF:src/rules/operation/RuleConditionalTransfer.sol -FN:27,RuleConditionalTransfer. -FNDA:158,RuleConditionalTransfer. -DA:33,158 -BRDA:33,0,0,1 -DA:34,1 -DA:36,157 -DA:37,157 -BRDA:37,1,0,153 -DA:38,153 -DA:40,157 -FN:51,RuleConditionalTransfer.operateOnTransfer -FNDA:50,RuleConditionalTransfer.operateOnTransfer -DA:61,50 -BRDA:61,2,0,8 -BRDA:61,2,1,24 -DA:62,8 -DA:64,42 -DA:65,42 -BRDA:65,3,0,18 -BRDA:65,3,1,24 -DA:66,18 -DA:67,18 -DA:69,24 -FN:79,RuleConditionalTransfer.createTransferRequest -FNDA:114,RuleConditionalTransfer.createTransferRequest -DA:83,117 -DA:84,117 -DA:85,117 -BRDA:85,4,0,1 -DA:86,1 -DA:88,116 -BRDA:88,5,0,113 -BRDA:88,5,1,3 -DA:89,113 -DA:90,113 -DA:102,113 -DA:103,113 -DA:104,113 -DA:105,113 -DA:108,3 -DA:109,3 -DA:110,3 -FN:123,RuleConditionalTransfer.createTransferRequestBatch -FNDA:3,RuleConditionalTransfer.createTransferRequestBatch -DA:127,3 -BRDA:127,6,0,1 -DA:128,1 -DA:130,2 -BRDA:130,7,0,1 -DA:131,1 -DA:133,1 -DA:134,3 -FN:141,RuleConditionalTransfer.cancelTransferRequest -FNDA:6,RuleConditionalTransfer.cancelTransferRequest -DA:142,6 -FN:148,RuleConditionalTransfer.cancelTransferRequestBatch -FNDA:3,RuleConditionalTransfer.cancelTransferRequestBatch -DA:149,3 -BRDA:149,8,0,1 -DA:150,1 -DA:153,2 -DA:154,5 -BRDA:154,9,0,1 -DA:155,1 -DA:158,1 -DA:159,3 -FN:163,RuleConditionalTransfer.getRequestTrade -FNDA:57,RuleConditionalTransfer.getRequestTrade -DA:168,57 -DA:169,57 -FN:177,RuleConditionalTransfer.getRequestByStatus -FNDA:35,RuleConditionalTransfer.getRequestByStatus -DA:180,35 -DA:181,35 -DA:182,35 -DA:185,35 -DA:186,38 -BRDA:186,10,0,36 -DA:187,36 -DA:192,35 -DA:195,35 -DA:196,38 -BRDA:196,11,0,36 -DA:198,36 -DA:201,36 -DA:202,36 -DA:205,35 -FN:214,RuleConditionalTransfer.detectTransferRestriction -FNDA:56,RuleConditionalTransfer.detectTransferRestriction -DA:220,56 -BRDA:220,12,0,1 -DA:221,1 -DA:223,55 -DA:224,55 -BRDA:224,13,0,8 -BRDA:224,13,1,8 -DA:225,8 -DA:227,47 -FN:236,RuleConditionalTransfer.canReturnTransferRestrictionCode -FNDA:2,RuleConditionalTransfer.canReturnTransferRestrictionCode -DA:239,2 -FN:247,RuleConditionalTransfer.messageForTransferRestriction -FNDA:3,RuleConditionalTransfer.messageForTransferRestriction -DA:250,3 -BRDA:250,14,0,2 -BRDA:250,14,1,1 -DA:251,2 -DA:253,1 -FN:260,RuleConditionalTransfer._validateTransfer -FNDA:106,RuleConditionalTransfer._validateTransfer -DA:265,106 -BRDA:265,15,0,36 -DA:267,36 -DA:268,5 -DA:269,3 -BRDA:269,16,0,3 -DA:270,3 -DA:275,103 -BRDA:275,17,0,6 -DA:276,6 -DA:278,97 -FN:281,RuleConditionalTransfer._cancelTransferRequest -FNDA:9,RuleConditionalTransfer._cancelTransferRequest -DA:282,9 -BRDA:282,18,0,1 -DA:283,1 -DA:285,8 -DA:287,8 -BRDA:287,19,0,1 -DA:288,1 -DA:292,7 -DA:293,2 -DA:294,1 -BRDA:294,20,0,1 -DA:295,1 -DA:297,6 -FN:307,RuleConditionalTransfer._validateBurnMint -FNDA:103,RuleConditionalTransfer._validateBurnMint -DA:313,103 -DA:317,6 -BRDA:317,21,0,6 -DA:318,6 -DA:320,97 -FN:329,RuleConditionalTransfer._validateApproval -FNDA:97,RuleConditionalTransfer._validateApproval -DA:333,97 -DA:335,50 -DA:337,47 -DA:338,50 -BRDA:338,22,0,50 -DA:339,50 -DA:341,47 -DA:342,47 -DA:343,47 -DA:344,20 -BRDA:344,23,0,20 -BRDA:343,23,1,27 -DA:345,20 -DA:348,27 -BRDA:348,24,0,27 -DA:350,27 -DA:355,47 -BRDA:355,25,0,26 -BRDA:355,25,1,21 -DA:356,26 -DA:358,21 -FN:369,RuleConditionalTransfer._msgSender -FNDA:829,RuleConditionalTransfer._msgSender -DA:375,829 -FN:381,RuleConditionalTransfer._msgData -FNDA:0,RuleConditionalTransfer._msgData -DA:387,0 -FN:393,RuleConditionalTransfer._contextSuffixLength -FNDA:829,RuleConditionalTransfer._contextSuffixLength -DA:399,829 -FNF:18 -FNH:17 -LF:106 -LH:105 -BRF:33 -BRH:33 +BRF:3 +BRH:3 end_of_record TN: -SF:src/rules/operation/abstract/RuleConditionalTransferOperator.sol -FN:32,RuleConditionalTransferOperator.setConditionalWhitelist -FNDA:26,RuleConditionalTransferOperator.setConditionalWhitelist -DA:35,26 -DA:36,26 -FN:42,RuleConditionalTransferOperator.setIssuanceOptions -FNDA:7,RuleConditionalTransferOperator.setIssuanceOptions -DA:46,6 -DA:48,3 -BRDA:48,0,0,3 -DA:49,3 -DA:53,6 -DA:55,3 -BRDA:55,1,0,3 -DA:56,3 -FN:66,RuleConditionalTransferOperator.setAutomaticTransfer -FNDA:4,RuleConditionalTransferOperator.setAutomaticTransfer -DA:70,3 -DA:72,2 -BRDA:72,2,0,2 -DA:73,2 -DA:78,3 -DA:80,2 -BRDA:80,3,0,2 -DA:81,2 -FN:90,RuleConditionalTransferOperator.setTimeLimit -FNDA:5,RuleConditionalTransferOperator.setTimeLimit +SF:src/rules/validation/RuleBlacklist.sol +DA:41,16 +FN:41,RuleBlacklist.detectTransferRestriction.0 +FNDA:16,RuleBlacklist.detectTransferRestriction.0 +DA:47,35 +BRDA:47,0,0,12 +BRDA:47,0,1,12 +DA:48,12 +DA:49,23 +BRDA:49,1,0,11 +BRDA:49,1,1,12 +DA:50,11 +DA:52,12 +DA:59,7 +FN:59,RuleBlacklist.detectTransferRestriction.1 +FNDA:7,RuleBlacklist.detectTransferRestriction.1 +DA:65,7 +DA:71,12 +FN:71,RuleBlacklist.detectTransferRestrictionFrom.0 +FNDA:12,RuleBlacklist.detectTransferRestrictionFrom.0 +DA:77,16 +BRDA:77,2,0,4 +BRDA:77,2,1,12 +DA:78,4 +DA:80,12 +DA:87,4 +FN:87,RuleBlacklist.detectTransferRestrictionFrom.1 +FNDA:4,RuleBlacklist.detectTransferRestrictionFrom.1 DA:94,4 -DA:96,4 -BRDA:96,4,0,4 -DA:97,4 -DA:101,4 DA:103,4 -BRDA:103,5,0,4 -DA:104,4 -FN:114,RuleConditionalTransferOperator.setAutomaticApproval -FNDA:10,RuleConditionalTransferOperator.setAutomaticApproval -DA:118,9 -DA:120,6 -BRDA:120,6,0,6 -DA:121,6 -DA:125,9 -DA:127,9 -BRDA:127,7,0,9 -DA:128,9 -FN:138,RuleConditionalTransferOperator.createTransferRequestWithApproval -FNDA:6,RuleConditionalTransferOperator.createTransferRequestWithApproval -DA:141,5 -FN:150,RuleConditionalTransferOperator.approveTransferRequest -FNDA:40,RuleConditionalTransferOperator.approveTransferRequest -DA:155,39 -FN:161,RuleConditionalTransferOperator.approveTransferRequestWithId -FNDA:5,RuleConditionalTransferOperator.approveTransferRequestWithId -DA:165,4 -BRDA:165,8,0,2 -DA:166,2 -DA:168,2 -DA:171,2 -FN:177,RuleConditionalTransferOperator.resetRequestStatus -FNDA:3,RuleConditionalTransferOperator.resetRequestStatus -DA:180,2 -BRDA:180,9,0,1 -DA:181,1 -DA:183,1 -DA:184,1 -FN:191,RuleConditionalTransferOperator.approveTransferRequestBatchWithId -FNDA:7,RuleConditionalTransferOperator.approveTransferRequestBatchWithId -DA:195,5 -BRDA:195,10,0,1 -DA:196,1 -DA:198,4 -BRDA:198,11,0,1 -DA:199,1 -DA:202,3 -DA:203,11 -BRDA:203,12,0,1 -DA:204,1 -DA:207,2 -DA:208,5 -DA:211,5 -FN:218,RuleConditionalTransferOperator.approveTransferRequestBatch -FNDA:7,RuleConditionalTransferOperator.approveTransferRequestBatch -DA:223,6 -BRDA:223,13,0,1 -DA:224,1 -DA:227,5 -DA:229,3 -BRDA:229,14,0,3 -DA:230,3 -DA:232,2 -DA:233,9 -FN:244,RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch -FNDA:3,RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch -DA:247,2 -BRDA:247,15,0,1 -DA:248,1 -DA:250,1 -DA:251,4 -FN:258,RuleConditionalTransferOperator.resetRequestStatusBatch -FNDA:3,RuleConditionalTransferOperator.resetRequestStatusBatch -DA:261,3 -BRDA:261,16,0,1 -DA:262,1 -DA:265,2 -DA:266,4 -BRDA:266,17,0,1 -DA:267,1 -DA:270,1 -DA:271,3 -DA:272,3 -FN:280,RuleConditionalTransferOperator.hasRole -FNDA:310,RuleConditionalTransferOperator.hasRole -DA:285,704 -BRDA:285,18,0,137 -DA:286,137 -DA:288,567 -FN:294,RuleConditionalTransferOperator._approveTransferRequestKeyElement -FNDA:48,RuleConditionalTransferOperator._approveTransferRequestKeyElement -DA:299,48 -BRDA:299,19,0,1 -DA:300,1 -DA:302,47 -DA:305,47 -DA:306,47 -BRDA:306,20,0,9 -BRDA:306,20,1,8 -DA:307,9 -BRDA:307,21,0,1 -DA:308,1 -DA:311,8 -DA:313,8 -DA:321,38 -FN:325,RuleConditionalTransferOperator._createTransferRequestWithApproval -FNDA:17,RuleConditionalTransferOperator._createTransferRequestWithApproval -DA:331,17 -DA:334,17 -BRDA:334,22,0,16 -BRDA:334,22,1,1 -DA:336,16 -DA:346,16 -DA:347,16 -DA:348,16 -DA:355,16 -DA:359,1 -DA:362,1 -DA:363,1 -FN:373,RuleConditionalTransferOperator._resetRequestStatus -FNDA:10,RuleConditionalTransferOperator._resetRequestStatus -DA:374,10 -DA:375,10 -FN:387,RuleConditionalTransferOperator._checkRequestStatus -FNDA:133,RuleConditionalTransferOperator._checkRequestStatus -DA:389,133 -DA:390,133 -FN:394,RuleConditionalTransferOperator._approveRequest -FNDA:53,RuleConditionalTransferOperator._approveRequest -DA:399,53 -BRDA:399,23,0,1 -DA:400,1 -DA:402,32 -BRDA:402,24,0,32 -BRDA:402,24,1,20 -DA:405,32 -DA:407,3 -BRDA:407,25,0,3 -DA:408,3 -DA:411,29 -DA:413,29 -DA:416,29 -DA:424,29 -DA:425,7 -DA:426,7 -BRDA:426,26,0,7 -DA:430,7 -DA:434,3 -BRDA:434,27,0,3 -DA:436,3 -DA:444,20 -DA:445,20 -FN:458,RuleConditionalTransferOperator._updateProcessedTransfer -FNDA:18,RuleConditionalTransferOperator._updateProcessedTransfer -DA:460,18 -DA:461,18 -DA:463,18 -DA:465,18 -FNF:20 -FNH:20 -LF:113 -LH:113 -BRF:31 -BRH:31 -end_of_record -TN: -SF:src/rules/validation/RuleBlacklist.sol -FN:22,RuleBlacklist. -FNDA:12,RuleBlacklist. -FN:33,RuleBlacklist.detectTransferRestriction -FNDA:10,RuleBlacklist.detectTransferRestriction -DA:38,10 -BRDA:38,0,0,5 -BRDA:38,0,1,3 -DA:39,5 -DA:40,5 -BRDA:40,1,0,2 -BRDA:40,1,1,3 -DA:41,2 -DA:43,3 -FN:52,RuleBlacklist.canReturnTransferRestrictionCode +FN:103,RuleBlacklist.canReturnTransferRestrictionCode FNDA:4,RuleBlacklist.canReturnTransferRestrictionCode -DA:55,4 -DA:56,4 -DA:57,2 -FN:65,RuleBlacklist.messageForTransferRestriction -FNDA:4,RuleBlacklist.messageForTransferRestriction -DA:68,4 -BRDA:68,2,0,2 -BRDA:68,2,1,1 -DA:69,2 -DA:70,2 -BRDA:70,3,0,1 -BRDA:70,3,1,1 -DA:71,1 -DA:73,1 -FNF:4 -FNH:4 -LF:13 -LH:13 -BRF:8 -BRH:8 +DA:110,4 +DA:111,2 +DA:120,8 +FN:120,RuleBlacklist.messageForTransferRestriction +FNDA:8,RuleBlacklist.messageForTransferRestriction +DA:127,8 +BRDA:127,3,0,3 +BRDA:127,3,1,2 +DA:128,3 +DA:129,5 +BRDA:129,4,0,2 +BRDA:129,4,1,2 +DA:130,2 +DA:131,3 +BRDA:131,5,0,1 +BRDA:131,5,1,2 +DA:132,1 +DA:134,2 +DA:138,0 +FN:138,RuleBlacklist.supportsInterface +FNDA:0,RuleBlacklist.supportsInterface +DA:139,0 +DA:144,6 +FN:144,RuleBlacklist.transferred.0 +FNDA:6,RuleBlacklist.transferred.0 +DA:150,6 +DA:151,6 +BRDA:151,6,0,4 +BRDA:151,6,1,2 +DA:157,0 +FN:157,RuleBlacklist.transferred.1 +FNDA:0,RuleBlacklist.transferred.1 +DA:163,0 +DA:164,0 +BRDA:164,7,0,- +BRDA:164,7,1,- +DA:170,0 +FN:170,RuleBlacklist.transferred.2 +FNDA:0,RuleBlacklist.transferred.2 +DA:176,0 +FNF:10 +FNH:7 +LF:35 +LH:28 +BRF:16 +BRH:14 end_of_record TN: -SF:src/rules/validation/RuleSanctionList.sol -FN:26,RuleSanctionList. -FNDA:13,RuleSanctionList. -DA:31,13 -BRDA:31,0,0,1 -DA:32,1 -DA:34,12 -BRDA:34,1,0,1 -DA:35,1 -DA:37,12 -FN:45,RuleSanctionList.setSanctionListOracle -FNDA:11,RuleSanctionList.setSanctionListOracle -DA:48,10 -FN:57,RuleSanctionList.detectTransferRestriction -FNDA:7,RuleSanctionList.detectTransferRestriction -DA:62,7 -BRDA:62,2,0,7 -DA:63,7 -BRDA:63,3,0,2 -BRDA:63,3,1,3 -DA:64,2 -DA:65,5 -BRDA:65,4,0,2 -DA:66,2 -DA:69,3 -FN:77,RuleSanctionList.canReturnTransferRestrictionCode -FNDA:3,RuleSanctionList.canReturnTransferRestrictionCode -DA:80,3 -DA:81,3 -DA:82,2 -FN:90,RuleSanctionList.messageForTransferRestriction -FNDA:3,RuleSanctionList.messageForTransferRestriction -DA:93,3 -BRDA:93,5,0,1 -BRDA:93,5,1,1 -DA:94,1 -DA:95,2 -BRDA:95,6,0,1 -BRDA:95,6,1,1 -DA:96,1 -DA:98,1 -FN:106,RuleSanctionList.hasRole -FNDA:13,RuleSanctionList.hasRole -DA:111,24 -BRDA:111,7,0,11 +SF:src/rules/validation/RuleSanctionsList.sol +DA:55,17 +FN:55,RuleSanctionsList.constructor +FNDA:17,RuleSanctionsList.constructor +DA:59,16 +BRDA:59,0,0,1 +DA:60,1 +DA:73,10 +FN:73,RuleSanctionsList.detectTransferRestriction.0 +FNDA:10,RuleSanctionsList.detectTransferRestriction.0 +DA:79,27 +BRDA:79,1,0,22 +DA:80,22 +BRDA:80,2,0,4 +BRDA:80,2,1,10 +DA:81,4 +DA:82,18 +BRDA:82,3,0,8 +DA:83,8 +DA:86,15 +DA:92,9 +FN:92,RuleSanctionsList.detectTransferRestriction.1 +FNDA:9,RuleSanctionsList.detectTransferRestriction.1 +DA:99,9 +DA:105,8 +FN:105,RuleSanctionsList.detectTransferRestrictionFrom.0 +FNDA:8,RuleSanctionsList.detectTransferRestrictionFrom.0 DA:112,11 -DA:114,13 -FN:121,RuleSanctionList._setSanctionListOracle -FNDA:11,RuleSanctionList._setSanctionListOracle -DA:122,11 -DA:123,11 -FN:133,RuleSanctionList._msgSender -FNDA:23,RuleSanctionList._msgSender -DA:139,23 -FN:145,RuleSanctionList._msgData -FNDA:0,RuleSanctionList._msgData -DA:151,0 -FN:157,RuleSanctionList._contextSuffixLength -FNDA:23,RuleSanctionList._contextSuffixLength -DA:163,23 -FNF:10 -FNH:9 -LF:28 -LH:27 -BRF:11 -BRH:11 +BRDA:112,4,0,10 +DA:113,10 +BRDA:113,5,0,2 +BRDA:113,5,1,8 +DA:114,2 +DA:116,8 +DA:119,1 +DA:122,3 +FN:122,RuleSanctionsList.detectTransferRestrictionFrom.1 +FNDA:3,RuleSanctionsList.detectTransferRestrictionFrom.1 +DA:129,3 +DA:138,3 +FN:138,RuleSanctionsList.canReturnTransferRestrictionCode +FNDA:3,RuleSanctionsList.canReturnTransferRestrictionCode +DA:139,3 +DA:140,1 +DA:149,4 +FN:149,RuleSanctionsList.messageForTransferRestriction +FNDA:4,RuleSanctionsList.messageForTransferRestriction +DA:156,4 +BRDA:156,6,0,1 +BRDA:156,6,1,1 +DA:157,1 +DA:158,3 +BRDA:158,7,0,1 +BRDA:158,7,1,1 +DA:159,1 +DA:160,2 +BRDA:160,8,0,1 +BRDA:160,8,1,1 +DA:161,1 +DA:163,1 +DA:167,0 +FN:167,RuleSanctionsList.supportsInterface +FNDA:0,RuleSanctionsList.supportsInterface +DA:168,0 +DA:177,14 +FN:177,RuleSanctionsList.setSanctionListOracle +FNDA:14,RuleSanctionsList.setSanctionListOracle +DA:178,13 +DA:184,0 +FN:184,RuleSanctionsList.transferred.0 +FNDA:0,RuleSanctionsList.transferred.0 +DA:190,0 +DA:191,0 +BRDA:191,9,0,- +BRDA:191,9,1,- +DA:200,0 +FN:200,RuleSanctionsList.transferred.1 +FNDA:0,RuleSanctionsList.transferred.1 +DA:206,0 +DA:207,0 +BRDA:207,10,0,- +BRDA:207,10,1,- +DA:216,0 +FN:216,RuleSanctionsList.transferred.2 +FNDA:0,RuleSanctionsList.transferred.2 +DA:222,0 +DA:229,14 +FN:229,RuleSanctionsList._setSanctionListOracle +FNDA:14,RuleSanctionsList._setSanctionListOracle +DA:230,14 +DA:231,14 +DA:241,30 +FN:241,RuleSanctionsList._msgSender +FNDA:30,RuleSanctionsList._msgSender +DA:242,30 +DA:248,0 +FN:248,RuleSanctionsList._msgData +FNDA:0,RuleSanctionsList._msgData +DA:249,0 +DA:255,30 +FN:255,RuleSanctionsList._contextSuffixLength +FNDA:30,RuleSanctionsList._contextSuffixLength +DA:256,30 +FNF:16 +FNH:11 +LF:52 +LH:40 +BRF:18 +BRH:14 end_of_record TN: SF:src/rules/validation/RuleWhitelist.sol -FN:16,RuleWhitelist. -FNDA:173,RuleWhitelist. -FN:27,RuleWhitelist.detectTransferRestriction -FNDA:28,RuleWhitelist.detectTransferRestriction -DA:32,28 -BRDA:32,0,0,13 -BRDA:32,0,1,10 -DA:33,13 -DA:34,15 -BRDA:34,1,0,5 -BRDA:34,1,1,10 -DA:35,5 -DA:37,10 -FNF:2 -FNH:2 -LF:5 -LH:5 -BRF:4 -BRH:4 +DA:33,102 +FN:33,RuleWhitelist.constructor +FNDA:102,RuleWhitelist.constructor +DA:36,101 +DA:56,16 +FN:56,RuleWhitelist.detectTransferRestriction.0 +FNDA:16,RuleWhitelist.detectTransferRestriction.0 +DA:63,27 +BRDA:63,0,0,9 +BRDA:63,0,1,14 +DA:64,9 +DA:65,18 +BRDA:65,1,0,4 +BRDA:65,1,1,14 +DA:66,4 +DA:68,14 +DA:75,7 +FN:75,RuleWhitelist.detectTransferRestriction.1 +FNDA:7,RuleWhitelist.detectTransferRestriction.1 +DA:82,7 +DA:102,6 +FN:102,RuleWhitelist.detectTransferRestrictionFrom.0 +FNDA:6,RuleWhitelist.detectTransferRestrictionFrom.0 +DA:109,8 +BRDA:109,2,0,4 +DA:110,4 +DA:112,4 +DA:118,2 +FN:118,RuleWhitelist.detectTransferRestrictionFrom.1 +FNDA:2,RuleWhitelist.detectTransferRestrictionFrom.1 +DA:125,2 +DA:133,0 +FN:133,RuleWhitelist.isVerified +FNDA:0,RuleWhitelist.isVerified +DA:140,0 +DA:143,0 +FN:143,RuleWhitelist.supportsInterface +FNDA:0,RuleWhitelist.supportsInterface +DA:144,0 +FNF:7 +FNH:5 +LF:20 +LH:16 +BRF:5 +BRH:5 end_of_record TN: SF:src/rules/validation/RuleWhitelistWrapper.sol -FN:23,RuleWhitelistWrapper. -FNDA:14,RuleWhitelistWrapper. -DA:27,14 -BRDA:27,0,0,1 -DA:28,1 -DA:30,13 -FN:39,RuleWhitelistWrapper.detectTransferRestriction -FNDA:11,RuleWhitelistWrapper.detectTransferRestriction -DA:44,11 -DA:45,11 -DA:46,11 -DA:47,11 -DA:48,11 -DA:49,11 -DA:51,11 -DA:53,25 -DA:55,25 -BRDA:55,1,0,7 -DA:57,7 -DA:59,25 -BRDA:59,2,0,7 -DA:61,7 -DA:63,25 -BRDA:63,3,0,25 -DA:64,25 -DA:67,11 -BRDA:67,4,0,4 -BRDA:67,4,1,5 -DA:68,4 -DA:69,7 -BRDA:69,5,0,2 -BRDA:69,5,1,5 -DA:70,2 -DA:72,5 -FN:80,RuleWhitelistWrapper.hasRole -FNDA:13,RuleWhitelistWrapper.hasRole -DA:85,52 -BRDA:85,6,0,39 -DA:86,39 -DA:88,13 -FN:98,RuleWhitelistWrapper._msgSender -FNDA:52,RuleWhitelistWrapper._msgSender -DA:104,52 -FN:110,RuleWhitelistWrapper._msgData +DA:40,22 +FN:40,RuleWhitelistWrapper.constructor +FNDA:22,RuleWhitelistWrapper.constructor +DA:44,20 +DA:55,15 +FN:55,RuleWhitelistWrapper.detectTransferRestriction.0 +FNDA:15,RuleWhitelistWrapper.detectTransferRestriction.0 +DA:62,19 +DA:63,19 +DA:64,19 +DA:66,19 +DA:67,19 +BRDA:67,0,0,7 +BRDA:67,0,1,8 +DA:68,7 +DA:69,12 +BRDA:69,1,0,4 +BRDA:69,1,1,8 +DA:70,4 +DA:72,8 +DA:76,4 +FN:76,RuleWhitelistWrapper.detectTransferRestriction.1 +FNDA:4,RuleWhitelistWrapper.detectTransferRestriction.1 +DA:83,4 +DA:86,6 +FN:86,RuleWhitelistWrapper.detectTransferRestrictionFrom.0 +FNDA:6,RuleWhitelistWrapper.detectTransferRestrictionFrom.0 +DA:93,8 +BRDA:93,2,0,- +DA:94,0 +DA:97,8 +DA:98,8 +DA:99,8 +DA:100,8 +DA:102,8 +DA:104,8 +BRDA:104,3,0,- +BRDA:104,3,1,4 +DA:105,0 +DA:106,8 +BRDA:106,4,0,- +BRDA:106,4,1,4 +DA:107,0 +DA:108,8 +BRDA:108,5,0,4 +BRDA:108,5,1,4 +DA:109,4 +DA:111,4 +DA:118,2 +FN:118,RuleWhitelistWrapper.detectTransferRestrictionFrom.1 +FNDA:2,RuleWhitelistWrapper.detectTransferRestrictionFrom.1 +DA:125,2 +DA:133,20 +FN:133,RuleWhitelistWrapper.hasRole +FNDA:20,RuleWhitelistWrapper.hasRole +DA:140,80 +DA:147,27 +FN:147,RuleWhitelistWrapper._detectTransferRestriction +FNDA:27,RuleWhitelistWrapper._detectTransferRestriction +DA:148,27 +DA:149,27 +DA:150,27 +DA:152,59 +DA:153,59 +DA:154,42 +BRDA:154,6,0,42 +DA:155,42 +DA:160,59 +DA:161,59 +DA:162,113 +BRDA:162,7,0,47 +DA:163,47 +DA:164,47 +DA:167,12 +BRDA:167,8,0,12 +DA:168,12 +DA:171,27 +DA:174,0 +FN:174,RuleWhitelistWrapper.supportsInterface +FNDA:0,RuleWhitelistWrapper.supportsInterface +DA:175,0 +DA:185,80 +FN:185,RuleWhitelistWrapper._msgSender +FNDA:80,RuleWhitelistWrapper._msgSender +DA:186,80 +DA:192,0 +FN:192,RuleWhitelistWrapper._msgData FNDA:0,RuleWhitelistWrapper._msgData -DA:116,0 -FN:122,RuleWhitelistWrapper._contextSuffixLength -FNDA:52,RuleWhitelistWrapper._contextSuffixLength -DA:128,52 -FNF:6 -FNH:5 -LF:28 -LH:27 -BRF:9 -BRH:9 +DA:193,0 +DA:199,80 +FN:199,RuleWhitelistWrapper._contextSuffixLength +FNDA:80,RuleWhitelistWrapper._contextSuffixLength +DA:200,80 +FNF:11 +FNH:9 +LF:57 +LH:50 +BRF:14 +BRH:11 end_of_record TN: -SF:src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol -FN:27,RuleAddressList. -FNDA:185,RuleAddressList. -DA:31,185 -BRDA:31,0,0,1 -DA:32,1 -DA:34,184 -FN:42,RuleAddressList.addAddressesToTheList -FNDA:17,RuleAddressList.addAddressesToTheList -DA:45,16 -DA:46,16 -FN:55,RuleAddressList.removeAddressesFromTheList -FNDA:4,RuleAddressList.removeAddressesFromTheList -DA:58,3 -DA:59,3 -FN:67,RuleAddressList.addAddressToTheList -FNDA:52,RuleAddressList.addAddressToTheList -DA:70,51 -DA:71,50 -FN:80,RuleAddressList.removeAddressFromTheList -FNDA:3,RuleAddressList.removeAddressFromTheList -DA:83,2 -DA:84,1 -FN:92,RuleAddressList.numberListedAddress -FNDA:24,RuleAddressList.numberListedAddress -DA:93,24 -FN:102,RuleAddressList.addressIsListed -FNDA:101,RuleAddressList.addressIsListed -DA:105,159 -FN:112,RuleAddressList.addressIsListedBatch -FNDA:28,RuleAddressList.addressIsListedBatch -DA:115,28 -DA:116,28 -DA:117,55 -DA:119,28 -FN:126,RuleAddressList.hasRole -FNDA:194,RuleAddressList.hasRole -DA:131,280 -BRDA:131,1,0,78 -DA:132,78 -DA:134,202 -FN:144,RuleAddressList._msgSender -FNDA:270,RuleAddressList._msgSender -DA:150,270 -FN:156,RuleAddressList._msgData -FNDA:0,RuleAddressList._msgData -DA:162,0 -FN:168,RuleAddressList._contextSuffixLength -FNDA:270,RuleAddressList._contextSuffixLength -DA:174,270 -FNF:12 -FNH:11 -LF:23 -LH:22 +SF:src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol +DA:63,17 +FN:63,RuleAddressSet.addAddresses +FNDA:17,RuleAddressSet.addAddresses +DA:64,16 +DA:65,16 +DA:75,4 +FN:75,RuleAddressSet.removeAddresses +FNDA:4,RuleAddressSet.removeAddresses +DA:76,3 +DA:77,3 +DA:87,52 +FN:87,RuleAddressSet.addAddress +FNDA:52,RuleAddressSet.addAddress +DA:88,51 +BRDA:88,0,0,1 +DA:89,1 +DA:91,50 +DA:92,50 +DA:102,3 +FN:102,RuleAddressSet.removeAddress +FNDA:3,RuleAddressSet.removeAddress +DA:103,2 +BRDA:103,1,0,1 +DA:104,1 +DA:106,1 +DA:107,1 +DA:114,24 +FN:114,RuleAddressSet.listedAddressCount +FNDA:24,RuleAddressSet.listedAddressCount +DA:115,24 +DA:123,0 +FN:123,RuleAddressSet.contains +FNDA:0,RuleAddressSet.contains +DA:124,0 +DA:132,60 +FN:132,RuleAddressSet.isAddressListed +FNDA:60,RuleAddressSet.isAddressListed +DA:133,187 +DA:141,62 +FN:141,RuleAddressSet.areAddressesListed +FNDA:62,RuleAddressSet.areAddressesListed +DA:142,62 +DA:143,62 +DA:144,139 +DA:152,207 +FN:152,RuleAddressSet._msgSender +FNDA:207,RuleAddressSet._msgSender +DA:153,207 +DA:157,0 +FN:157,RuleAddressSet._msgData +FNDA:0,RuleAddressSet._msgData +DA:158,0 +DA:162,207 +FN:162,RuleAddressSet._contextSuffixLength +FNDA:207,RuleAddressSet._contextSuffixLength +DA:163,207 +FNF:11 +FNH:9 +LF:32 +LH:28 BRF:2 BRH:2 end_of_record TN: -SF:src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol -FN:22,RuleAddressListInternal._addAddressesToThelist -FNDA:16,RuleAddressListInternal._addAddressesToThelist -DA:25,16 -DA:26,16 -DA:27,34 -BRDA:27,0,0,32 -DA:28,32 -DA:29,32 -DA:32,16 -FN:41,RuleAddressListInternal._removeAddressesFromThelist -FNDA:3,RuleAddressListInternal._removeAddressesFromThelist -DA:44,3 -DA:45,3 -DA:46,6 -BRDA:46,1,0,6 -DA:47,6 -DA:48,6 -DA:51,3 -FN:59,RuleAddressListInternal._addAddressToThelist -FNDA:51,RuleAddressListInternal._addAddressToThelist -DA:60,1 -BRDA:60,2,0,1 -DA:61,1 -DA:63,50 -DA:64,50 -FN:73,RuleAddressListInternal._removeAddressFromThelist -FNDA:2,RuleAddressListInternal._removeAddressFromThelist -DA:74,2 -BRDA:74,3,0,1 -DA:75,1 -DA:77,1 -DA:78,1 -FN:86,RuleAddressListInternal._numberListedAddress -FNDA:24,RuleAddressListInternal._numberListedAddress -DA:87,24 -FN:96,RuleAddressListInternal._addressIsListed -FNDA:214,RuleAddressListInternal._addressIsListed -DA:99,214 +SF:src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol +DA:36,16 +FN:36,RuleAddressSetInternal._addAddresses +FNDA:16,RuleAddressSetInternal._addAddresses +DA:37,16 +DA:38,34 +DA:49,3 +FN:49,RuleAddressSetInternal._removeAddresses +FNDA:3,RuleAddressSetInternal._removeAddresses +DA:50,3 +DA:51,7 +DA:59,50 +FN:59,RuleAddressSetInternal._addAddress +FNDA:50,RuleAddressSetInternal._addAddress +DA:60,50 +DA:67,1 +FN:67,RuleAddressSetInternal._removeAddress +FNDA:1,RuleAddressSetInternal._removeAddress +DA:68,1 +DA:75,24 +FN:75,RuleAddressSetInternal._listedAddressCount +FNDA:24,RuleAddressSetInternal._listedAddressCount +DA:76,24 +DA:84,379 +FN:84,RuleAddressSetInternal._isAddressListed +FNDA:379,RuleAddressSetInternal._isAddressListed +DA:85,379 FNF:6 FNH:6 -LF:22 -LH:22 -BRF:4 -BRH:4 -end_of_record -TN: -SF:src/rules/validation/abstract/RuleValidateTransfer.sol -FN:15,RuleValidateTransfer.validateTransfer -FNDA:40,RuleValidateTransfer.validateTransfer -DA:21,40 -DA:22,40 -FNF:1 -FNH:1 -LF:2 -LH:2 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/rules/validation/abstract/RuleWhitelistCommon.sol -FN:17,RuleWhitelistCommon.canReturnTransferRestrictionCode -FNDA:12,RuleWhitelistCommon.canReturnTransferRestrictionCode -DA:20,12 -DA:21,12 -DA:22,6 -FN:30,RuleWhitelistCommon.messageForTransferRestriction -FNDA:10,RuleWhitelistCommon.messageForTransferRestriction -DA:33,10 -BRDA:33,0,0,6 -BRDA:33,0,1,1 -DA:34,6 -DA:35,4 -BRDA:35,1,0,3 -BRDA:35,1,1,1 -DA:36,3 -DA:38,1 -FNF:2 -FNH:2 -LF:8 -LH:8 -BRF:4 -BRH:4 -end_of_record -TN: -SF:test/HelperContract.sol -FN:95,HelperContract. -FNDA:0,HelperContract. -FNF:1 -FNH:0 -LF:0 -LH:0 +LF:14 +LH:14 BRF:0 BRH:0 end_of_record TN: -SF:test/RuleConditionalTransfer/utils/RuleCTDeployment.sol -FN:13,RuleCTDeployment. -FNDA:13,RuleCTDeployment. -DA:14,13 -DA:19,13 -DA:24,13 -DA:28,13 -DA:33,13 -DA:39,13 -DA:44,13 -DA:45,13 -DA:51,13 -DA:52,13 -FNF:1 -FNH:1 +SF:src/rules/validation/abstract/RuleValidateTransfer.sol +DA:27,14 +FN:27,RuleValidateTransfer.canTransfer.0 +FNDA:14,RuleValidateTransfer.canTransfer.0 +DA:34,14 +DA:46,14 +FN:46,RuleValidateTransfer.canTransfer.1 +FNDA:14,RuleValidateTransfer.canTransfer.1 +DA:53,14 +DA:59,10 +FN:59,RuleValidateTransfer.canTransferFrom.0 +FNDA:10,RuleValidateTransfer.canTransferFrom.0 +DA:66,20 +DA:73,10 +FN:73,RuleValidateTransfer.canTransferFrom.1 +FNDA:10,RuleValidateTransfer.canTransferFrom.1 +DA:80,10 +DA:84,0 +FN:84,RuleValidateTransfer.supportsInterface +FNDA:0,RuleValidateTransfer.supportsInterface +DA:85,0 +FNF:5 +FNH:4 LF:10 -LH:10 -BRF:0 -BRH:0 -end_of_record -TN: -SF:test/utils/CMTATDeployment.sol -FN:15,CMTATDeployment. -FNDA:86,CMTATDeployment. -DA:17,86 -DA:23,86 -DA:30,86 -DA:36,86 -FNF:1 -FNH:1 -LF:4 -LH:4 +LH:8 BRF:0 BRH:0 end_of_record TN: -SF:test/utils/SanctionListOracle.sol -FN:9,SanctionListOracle. -FNDA:11,SanctionListOracle. -FN:13,SanctionListOracle.addToSanctionsList -FNDA:10,SanctionListOracle.addToSanctionsList -DA:14,10 -FN:17,SanctionListOracle.removeFromSanctionsList -FNDA:0,SanctionListOracle.removeFromSanctionsList -DA:18,0 -FN:21,SanctionListOracle.isSanctioned -FNDA:12,SanctionListOracle.isSanctioned -DA:22,12 -FNF:4 +SF:src/rules/validation/abstract/RuleWhitelistCommon.sol +DA:38,10 +FN:38,RuleWhitelistCommon.canReturnTransferRestrictionCode +FNDA:10,RuleWhitelistCommon.canReturnTransferRestrictionCode +DA:39,10 +DA:40,5 +DA:50,14 +FN:50,RuleWhitelistCommon.messageForTransferRestriction +FNDA:14,RuleWhitelistCommon.messageForTransferRestriction +DA:56,14 +BRDA:56,0,0,6 +BRDA:56,0,1,2 +DA:57,6 +DA:58,8 +BRDA:58,1,0,4 +BRDA:58,1,1,2 +DA:59,4 +DA:60,4 +BRDA:60,2,0,2 +BRDA:60,2,1,2 +DA:61,2 +DA:63,2 +DA:79,12 +FN:79,RuleWhitelistCommon.transferred.0 +FNDA:12,RuleWhitelistCommon.transferred.0 +DA:80,12 +DA:81,12 +BRDA:81,3,0,6 +BRDA:81,3,1,6 +DA:97,0 +FN:97,RuleWhitelistCommon.transferred.1 +FNDA:0,RuleWhitelistCommon.transferred.1 +DA:98,0 +DA:99,0 +BRDA:99,4,0,- +BRDA:99,4,1,- +DA:108,0 +FN:108,RuleWhitelistCommon.transferred.2 +FNDA:0,RuleWhitelistCommon.transferred.2 +DA:113,0 +FNF:5 FNH:3 -LF:3 -LH:2 -BRF:0 -BRH:0 +LF:19 +LH:14 +BRF:10 +BRH:8 end_of_record diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol index dc3824f..3212a4f 100644 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -94,7 +94,7 @@ contract RuleWhitelistWrapper is return detectTransferRestriction(from, to, value); } - address[] memory targetAddress = new address[](2); + address[] memory targetAddress = new address[](3); targetAddress[0] = from; targetAddress[1] = to; targetAddress[2] = spender; diff --git a/test/RuleBlacklist/RuleBlacklist.t.sol b/test/RuleBlacklist/RuleBlacklist.t.sol index 0a7651d..60eea0e 100644 --- a/test/RuleBlacklist/RuleBlacklist.t.sol +++ b/test/RuleBlacklist/RuleBlacklist.t.sol @@ -15,6 +15,28 @@ contract RuleBlacklistTest is Test, HelperContract { ruleBlacklist = new RuleBlacklist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); } + function testReturnTheRightMessageForAGivenCode() public { + // Assert + resString = ruleBlacklist.messageForTransferRestriction(CODE_ADDRESS_FROM_IS_BLACKLISTED); + // Assert + assertEq(resString, TEXT_ADDRESS_FROM_IS_BLACKLISTED); + + // Act + resString = ruleBlacklist.messageForTransferRestriction(CODE_ADDRESS_TO_IS_BLACKLISTED); + // Assert + assertEq(resString, TEXT_ADDRESS_TO_IS_BLACKLISTED); + + // Act + resString = ruleBlacklist.messageForTransferRestriction(CODE_ADDRESS_SPENDER_IS_BLACKLISTED); + // Assert + assertEq(resString, TEXT_ADDRESS_SPENDER_IS_BLACKLISTED); + + // Act + resString = ruleBlacklist.messageForTransferRestriction(CODE_NONEXISTENT); + // Assert + assertEq(resString, TEXT_CODE_NOT_FOUND); + } + function testCanRuleBlacklistReturnMessageNotFoundWithUnknownCodeId() public view { // Act string memory message1 = ruleBlacklist.messageForTransferRestriction(255); diff --git a/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol b/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol index 7dfb2d2..5252411 100644 --- a/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol +++ b/test/RuleSanctionList/RuleSanctionListDeploymentTest.t.sol @@ -55,4 +55,33 @@ contract RuleSanctionListDeploymentTest is Test, HelperContract { ruleSanctionList = new RuleSanctionsList(SANCTIONLIST_OPERATOR_ADDRESS, ZERO_ADDRESS, sanctionlistOracle); assertEq(address(ruleSanctionList.sanctionsList()), address(sanctionlistOracle)); } + + function testcanTransferIfNoOracleSet() public { + ruleSanctionList = + new RuleSanctionsList(SANCTIONLIST_OPERATOR_ADDRESS, address(ZERO_ADDRESS), ISanctionsList(ZERO_ADDRESS)); + // Act + // ADDRESS1 -> ADDRESS2 + resBool = ruleSanctionList.canTransfer(ADDRESS1, ADDRESS2, 20); + assertEq(resBool, true); + + resBool = ruleSanctionList.canTransfer(ADDRESS1, ADDRESS2, 0, 20); + assertEq(resBool, true); + + // ADDRESS2 -> ADDRESS1 + resBool = ruleSanctionList.canTransfer(ADDRESS2, ADDRESS1, 20); + assertEq(resBool, true); + + resBool = ruleSanctionList.canTransfer(ADDRESS2, ADDRESS1, 0, 20); + assertEq(resBool, true); + + // Act + resUint8 = ruleSanctionList.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resUint8, NO_ERROR); + + // Act + resUint8 = ruleSanctionList.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resUint8, NO_ERROR); + } } diff --git a/test/RuleSanctionList/RuleSanctionListTest.t.sol b/test/RuleSanctionList/RuleSanctionListTest.t.sol index 65ec3ef..ea2eb18 100644 --- a/test/RuleSanctionList/RuleSanctionListTest.t.sol +++ b/test/RuleSanctionList/RuleSanctionListTest.t.sol @@ -44,10 +44,17 @@ contract RuleSanctionlistTest is Test, HelperContract { 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_ADDRESS_SPENDER_IS_SANCTIONED); + // Assert + assertEq(resString, TEXT_ADDRESS_SPENDER_IS_SANCTIONED); + // Act resString = ruleSanctionList.messageForTransferRestriction(CODE_NONEXISTENT); // Assert @@ -68,6 +75,7 @@ contract RuleSanctionlistTest is Test, HelperContract { assertEq(resBool, true); } + function testTransferFromDetectedAsInvalid() public { // Act resBool = ruleSanctionList.canTransfer(ATTACKER, ADDRESS2, 20); diff --git a/test/RuleWhitelist/RuleWhitelist.t.sol b/test/RuleWhitelist/RuleWhitelist.t.sol index 2910742..589ff5b 100644 --- a/test/RuleWhitelist/RuleWhitelist.t.sol +++ b/test/RuleWhitelist/RuleWhitelist.t.sol @@ -104,6 +104,13 @@ contract RuleWhitelistTest is Test, HelperContract { resString = ruleWhitelist.messageForTransferRestriction(CODE_ADDRESS_TO_NOT_WHITELISTED); // Assert assertEq(resString, TEXT_ADDRESS_TO_NOT_WHITELISTED); + + // Act + resString = ruleWhitelist.messageForTransferRestriction(CODE_ADDRESS_SPENDER_NOT_WHITELISTED); + // Assert + assertEq(resString, TEXT_ADDRESS_SPENDER_NOT_WHITELISTED); + + // Act resString = ruleWhitelist.messageForTransferRestriction(CODE_NONEXISTENT); // Assert @@ -172,6 +179,16 @@ contract RuleWhitelistTest is Test, HelperContract { resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); // Assert assertEq(resUint8, CODE_ADDRESS_FROM_NOT_WHITELISTED); + + // Act + resBool = ruleWhitelist.canTransfer(ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resBool, false); + + // Act + resBool = ruleWhitelist.canTransfer(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resBool, false); } function testDetectTransferRestrictionTo() public { diff --git a/test/RuleWhitelist/WhitelistWrapper.t.sol b/test/RuleWhitelist/WhitelistWrapper.t.sol new file mode 100644 index 0000000..90972e0 --- /dev/null +++ b/test/RuleWhitelist/WhitelistWrapper.t.sol @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import "forge-std/Test.sol"; +import "CMTAT/deployment/CMTATStandalone.sol"; +import "../HelperContract.sol"; +import {AccessControlModuleStandalone} from "../../src/modules/AccessControlModuleStandalone.sol"; +/** + * @title Integration test with the CMTAT + */ + +contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { + uint256 ADDRESS1_BALANCE_INIT = 31; + uint256 ADDRESS2_BALANCE_INIT = 32; + uint256 ADDRESS3_BALANCE_INIT = 33; + + uint256 FLAG = 5; + RuleWhitelist ruleWhitelist2; + RuleWhitelist ruleWhitelist3; + RuleWhitelistWrapper ruleWhitelistWrapper; + + // Arrange + function setUp() public { + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true); + ruleWhitelist2 = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true); + ruleWhitelist3 = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true); + ruleWhitelistWrapper = new RuleWhitelistWrapper(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelistWrapper.addRule(ruleWhitelist); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelistWrapper.addRule(ruleWhitelist2); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelistWrapper.addRule(ruleWhitelist3); + } + + /** + * Deployment ****** + */ + function testCannotDeployContractIfAdminAddressIsZero() public { + vm.prank(WHITELIST_OPERATOR_ADDRESS); + vm.expectRevert(AccessControlModuleStandalone.AccessControlModuleStandalone_AddressZeroNotAllowed.selector); + ruleWhitelistWrapper = new RuleWhitelistWrapper(ZERO_ADDRESS, ZERO_ADDRESS, true); + } + + function testReturnTheRightMessageForAGivenCode() public { + // Assert + resString = ruleWhitelistWrapper.messageForTransferRestriction(CODE_ADDRESS_FROM_NOT_WHITELISTED); + // Assert + assertEq(resString, TEXT_ADDRESS_FROM_NOT_WHITELISTED); + // Act + resString = ruleWhitelistWrapper.messageForTransferRestriction(CODE_ADDRESS_TO_NOT_WHITELISTED); + // Assert + assertEq(resString, TEXT_ADDRESS_TO_NOT_WHITELISTED); + + // Act + resString = ruleWhitelistWrapper.messageForTransferRestriction(CODE_ADDRESS_SPENDER_NOT_WHITELISTED); + // Assert + assertEq(resString, TEXT_ADDRESS_SPENDER_NOT_WHITELISTED); + + // Act + resString = ruleWhitelistWrapper.messageForTransferRestriction(CODE_NONEXISTENT); + // Assert + assertEq(resString, TEXT_CODE_NOT_FOUND); + } + + function testDetectTransferRestrictionFrom() public { + // Act + resUint8 = ruleWhitelistWrapper.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_FROM_NOT_WHITELISTED); + + // Act + resBool = ruleWhitelistWrapper.canTransfer(ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resBool, false); + + // Act + resBool = ruleWhitelistWrapper.canTransfer(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resBool, false); + } + + function testDetectTransferRestrictionTo() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS1); + // Act + resUint8 = ruleWhitelistWrapper.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED); + + // With tokenId + resUint8 = ruleWhitelistWrapper.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED); + } + + function testDetectTransferRestrictionWithSpender() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS1); + + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS2); + // Act + resUint8 = ruleWhitelistWrapper.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_SPENDER_NOT_WHITELISTED); + + // Act + resBool = ruleWhitelistWrapper.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resBool, false); + + // With tokenId + resUint8 = ruleWhitelistWrapper.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, CODE_ADDRESS_SPENDER_NOT_WHITELISTED); + + // Act + resBool = ruleWhitelistWrapper.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resBool, false); + } + + function testDetectTransferRestrictionOk() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS1); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS2); + // Act + resUint8 = ruleWhitelistWrapper.detectTransferRestriction(ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resUint8, NO_ERROR); + + // With tokenId + resUint8 = ruleWhitelistWrapper.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, NO_ERROR); + + // With tokenId + resUint8 = ruleWhitelistWrapper.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, NO_ERROR); + } + + function testDetectTransferRestrictionWithSpenderOk() public { + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS1); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS2); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS3); + // Act + resUint8 = ruleWhitelistWrapper.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resUint8, NO_ERROR); + + // Act + resBool = ruleWhitelistWrapper.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + // Assert + assertEq(resBool, true); + + // Act + resBool = ruleWhitelistWrapper.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resBool, true); + + // With tokenId + resUint8 = ruleWhitelistWrapper.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); + // Assert + assertEq(resUint8, NO_ERROR); + } + + +} From cc2f9591e02d6b5faae4b08ab5b41d9df428f148 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Wed, 3 Dec 2025 15:41:00 +0100 Subject: [PATCH 23/25] Run coverage, static analyser, improve code --- ...ntrolModuleStandalone.sol.func-sort-c.html | 2 +- ...ccessControlModuleStandalone.sol.func.html | 2 +- ...ccessControlModuleStandalone.sol.gcov.html | 2 +- .../dev/Rules/src/modules/index-sort-b.html | 2 +- .../dev/Rules/src/modules/index-sort-f.html | 2 +- .../dev/Rules/src/modules/index-sort-l.html | 2 +- .../Pictures/dev/Rules/src/modules/index.html | 2 +- doc/coverage/coverage/index-sort-b.html | 56 +- doc/coverage/coverage/index-sort-f.html | 56 +- doc/coverage/coverage/index-sort-l.html | 56 +- doc/coverage/coverage/index.html | 46 +- .../RuleBlacklist.sol.func-sort-c.html | 34 +- .../validation/RuleBlacklist.sol.func.html | 28 +- .../validation/RuleBlacklist.sol.gcov.html | 63 +- .../RuleSanctionsList.sol.func-sort-c.html | 54 +- .../RuleSanctionsList.sol.func.html | 44 +- .../RuleSanctionsList.sol.gcov.html | 178 ++--- .../RuleWhitelist.sol.func-sort-c.html | 12 +- .../validation/RuleWhitelist.sol.func.html | 6 +- .../validation/RuleWhitelist.sol.gcov.html | 22 +- .../RuleWhitelistWrapper.sol.func-sort-c.html | 32 +- .../RuleWhitelistWrapper.sol.func.html | 30 +- .../RuleWhitelistWrapper.sol.gcov.html | 374 ++++++----- .../RuleAddressSet.sol.func-sort-c.html | 4 +- .../RuleAddressSet.sol.func.html | 4 +- .../RuleAddressSet.sol.gcov.html | 12 +- ...uleAddressSetInternal.sol.func-sort-c.html | 4 +- .../RuleAddressSetInternal.sol.func.html | 4 +- .../RuleAddressSetInternal.sol.gcov.html | 6 +- .../abstract/RuleAddressSet/index-sort-b.html | 2 +- .../abstract/RuleAddressSet/index-sort-f.html | 2 +- .../abstract/RuleAddressSet/index-sort-l.html | 2 +- .../abstract/RuleAddressSet/index.html | 2 +- .../RuleValidateTransfer.sol.func-sort-c.html | 12 +- .../RuleValidateTransfer.sol.func.html | 12 +- .../RuleValidateTransfer.sol.gcov.html | 158 +++-- .../RuleWhitelistCommon.sol.func-sort-c.html | 36 +- .../RuleWhitelistCommon.sol.func.html | 30 +- .../RuleWhitelistCommon.sol.gcov.html | 62 +- .../validation/abstract/index-sort-b.html | 38 +- .../validation/abstract/index-sort-f.html | 38 +- .../validation/abstract/index-sort-l.html | 38 +- .../coverage/validation/abstract/index.html | 28 +- .../coverage/validation/index-sort-b.html | 66 +- .../coverage/validation/index-sort-f.html | 66 +- .../coverage/validation/index-sort-l.html | 66 +- doc/coverage/coverage/validation/index.html | 46 +- doc/coverage/lcov.info | 492 +++++++------- doc/security/audits/tools/aderyn-report.md | 454 +++++++++++++ doc/security/audits/tools/slither-report.md | 630 ++---------------- .../IERC7943NonFungibleCompliance.sol | 14 + src/rules/validation/RuleBlacklist.sol | 13 +- src/rules/validation/RuleSanctionsList.sol | 16 +- src/rules/validation/RuleWhitelist.sol | 23 + src/rules/validation/RuleWhitelistWrapper.sol | 31 +- .../RuleBlacklistInvariantStorage.sol | 1 + .../RuleWhitelistInvariantStorage.sol | 7 + .../RuleSanctionsListInvariantStorage.sol | 5 +- .../abstract/RuleValidateTransfer.sol | 2 - .../abstract/RuleWhitelistCommon.sol | 18 +- test/RuleBlacklist/RuleBlacklist.t.sol | 94 +++ .../RuleSanctionListTest.t.sol | 93 +++ test/RuleWhitelist/RuleWhitelist.t.sol | 89 +++ test/RuleWhitelist/WhitelistWrapper.t.sol | 96 +++ 64 files changed, 2201 insertions(+), 1720 deletions(-) create mode 100644 doc/security/audits/tools/aderyn-report.md diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func-sort-c.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func-sort-c.html index d863117..5ee975a 100644 --- a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func-sort-c.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 2 diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func.html index 6d00c42..5e3e889 100644 --- a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.func.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 2 diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.gcov.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.gcov.html index cd3a87d..001fd5e 100644 --- a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.gcov.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/AccessControlModuleStandalone.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 2 diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-b.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-b.html index dd04fd8..6514966 100644 --- a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-b.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-b.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 2 diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-f.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-f.html index a1ecac1..d593422 100644 --- a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-f.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 2 diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-l.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-l.html index f87dc66..42bb733 100644 --- a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-l.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 2 diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index.html index 47daaf2..7bed3a1 100644 --- a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/index.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 2 diff --git a/doc/coverage/coverage/index-sort-b.html b/doc/coverage/coverage/index-sort-b.html index abdd86e..2c38638 100644 --- a/doc/coverage/coverage/index-sort-b.html +++ b/doc/coverage/coverage/index-sort-b.html @@ -31,27 +31,27 @@ lcov.info Lines: - 206 - 247 - 83.4 % + 230 + 253 + 90.9 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 56 - 73 - 76.7 % + 66 + 76 + 86.8 % Branches: - 57 + 65 68 - 83.8 % + 95.6 % @@ -81,29 +81,17 @@ Functions Sort by function coverage Branches Sort by branch coverage - - validation/abstract - -
75.9%75.9%
- - 75.9 % - 22 / 29 - 70.0 % - 7 / 10 - 80.0 % - 8 / 10 - validation -
81.7%81.7%
+
89.9%89.9%
- 81.7 % - 134 / 164 - 72.7 % - 32 / 44 - 83.0 % - 44 / 53 + 89.9 % + 151 / 168 + 84.8 % + 39 / 46 + 94.3 % + 50 / 53 validation/abstract/RuleAddressSet @@ -129,6 +117,18 @@ 100.0 % 3 / 3 + + validation/abstract + +
93.5%93.5%
+ + 93.5 % + 29 / 31 + 90.9 % + 10 / 11 + 100.0 % + 10 / 10 +
diff --git a/doc/coverage/coverage/index-sort-f.html b/doc/coverage/coverage/index-sort-f.html index ab33f1e..ddafc17 100644 --- a/doc/coverage/coverage/index-sort-f.html +++ b/doc/coverage/coverage/index-sort-f.html @@ -31,27 +31,27 @@ lcov.info Lines: - 206 - 247 - 83.4 % + 230 + 253 + 90.9 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 56 - 73 - 76.7 % + 66 + 76 + 86.8 % Branches: - 57 + 65 68 - 83.8 % + 95.6 % @@ -81,29 +81,17 @@ Functions Sort by function coverage Branches Sort by branch coverage - - validation/abstract - -
75.9%75.9%
- - 75.9 % - 22 / 29 - 70.0 % - 7 / 10 - 80.0 % - 8 / 10 - validation -
81.7%81.7%
+
89.9%89.9%
- 81.7 % - 134 / 164 - 72.7 % - 32 / 44 - 83.0 % - 44 / 53 + 89.9 % + 151 / 168 + 84.8 % + 39 / 46 + 94.3 % + 50 / 53 validation/abstract/RuleAddressSet @@ -117,6 +105,18 @@ 100.0 % 2 / 2 + + validation/abstract + +
93.5%93.5%
+ + 93.5 % + 29 / 31 + 90.9 % + 10 / 11 + 100.0 % + 10 / 10 + /home/ryan/Pictures/dev/Rules/src/modules diff --git a/doc/coverage/coverage/index-sort-l.html b/doc/coverage/coverage/index-sort-l.html index fc88c8b..53eb3c2 100644 --- a/doc/coverage/coverage/index-sort-l.html +++ b/doc/coverage/coverage/index-sort-l.html @@ -31,27 +31,27 @@ lcov.info Lines: - 206 - 247 - 83.4 % + 230 + 253 + 90.9 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 56 - 73 - 76.7 % + 66 + 76 + 86.8 % Branches: - 57 + 65 68 - 83.8 % + 95.6 % @@ -81,29 +81,17 @@ Functions Sort by function coverage Branches Sort by branch coverage - - validation/abstract - -
75.9%75.9%
- - 75.9 % - 22 / 29 - 70.0 % - 7 / 10 - 80.0 % - 8 / 10 - validation -
81.7%81.7%
+
89.9%89.9%
- 81.7 % - 134 / 164 - 72.7 % - 32 / 44 - 83.0 % - 44 / 53 + 89.9 % + 151 / 168 + 84.8 % + 39 / 46 + 94.3 % + 50 / 53 validation/abstract/RuleAddressSet @@ -117,6 +105,18 @@ 100.0 % 2 / 2 + + validation/abstract + +
93.5%93.5%
+ + 93.5 % + 29 / 31 + 90.9 % + 10 / 11 + 100.0 % + 10 / 10 + /home/ryan/Pictures/dev/Rules/src/modules diff --git a/doc/coverage/coverage/index.html b/doc/coverage/coverage/index.html index 38a03fc..d70aabb 100644 --- a/doc/coverage/coverage/index.html +++ b/doc/coverage/coverage/index.html @@ -31,27 +31,27 @@ lcov.info Lines: - 206 - 247 - 83.4 % + 230 + 253 + 90.9 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 56 - 73 - 76.7 % + 66 + 76 + 86.8 % Branches: - 57 + 65 68 - 83.8 % + 95.6 % @@ -96,26 +96,26 @@ validation -
81.7%81.7%
+
89.9%89.9%
- 81.7 % - 134 / 164 - 72.7 % - 32 / 44 - 83.0 % - 44 / 53 + 89.9 % + 151 / 168 + 84.8 % + 39 / 46 + 94.3 % + 50 / 53 validation/abstract -
75.9%75.9%
+
93.5%93.5%
- 75.9 % - 22 / 29 - 70.0 % - 7 / 10 - 80.0 % - 8 / 10 + 93.5 % + 29 / 31 + 90.9 % + 10 / 11 + 100.0 % + 10 / 10 validation/abstract/RuleAddressSet diff --git a/doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html b/doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html index aed9162..09bb6da 100644 --- a/doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html +++ b/doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html @@ -31,27 +31,27 @@ lcov.info Lines: - 28 35 - 80.0 % + 37 + 94.6 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 7 10 - 70.0 % + 11 + 90.9 % Branches: - 14 16 - 87.5 % + 16 + 100.0 % @@ -74,11 +74,15 @@ RuleBlacklist.transferred.1 - 0 + 2 RuleBlacklist.transferred.2 - 0 + 2 + + + RuleBlacklist.transferred.3 + 3 RuleBlacklist.canReturnTransferRestrictionCode @@ -88,10 +92,6 @@ RuleBlacklist.detectTransferRestrictionFrom.1 4 - - RuleBlacklist.transferred.0 - 6 - RuleBlacklist.detectTransferRestriction.1 7 @@ -100,13 +100,17 @@ RuleBlacklist.messageForTransferRestriction 8 + + RuleBlacklist.transferred.0 + 9 + RuleBlacklist.detectTransferRestrictionFrom.0 - 12 + 16 RuleBlacklist.detectTransferRestriction.0 - 16 + 22
diff --git a/doc/coverage/coverage/validation/RuleBlacklist.sol.func.html b/doc/coverage/coverage/validation/RuleBlacklist.sol.func.html index d35253a..7644183 100644 --- a/doc/coverage/coverage/validation/RuleBlacklist.sol.func.html +++ b/doc/coverage/coverage/validation/RuleBlacklist.sol.func.html @@ -31,27 +31,27 @@ lcov.info Lines: - 28 35 - 80.0 % + 37 + 94.6 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 7 10 - 70.0 % + 11 + 90.9 % Branches: - 14 16 - 87.5 % + 16 + 100.0 % @@ -74,7 +74,7 @@ RuleBlacklist.detectTransferRestriction.0 - 16 + 22 RuleBlacklist.detectTransferRestriction.1 @@ -82,7 +82,7 @@ RuleBlacklist.detectTransferRestrictionFrom.0 - 12 + 16 RuleBlacklist.detectTransferRestrictionFrom.1 @@ -98,15 +98,19 @@ RuleBlacklist.transferred.0 - 6 + 9 RuleBlacklist.transferred.1 - 0 + 2 RuleBlacklist.transferred.2 - 0 + 2 + + + RuleBlacklist.transferred.3 + 3
diff --git a/doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html b/doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html index 7c7d78e..9ee3de4 100644 --- a/doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html +++ b/doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html @@ -31,27 +31,27 @@ lcov.info Lines: - 28 35 - 80.0 % + 37 + 94.6 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 7 10 - 70.0 % + 11 + 90.9 % Branches: - 14 16 - 87.5 % + 16 + 100.0 % @@ -109,18 +109,18 @@ 38 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK 39 : : * 40 : : */ - 41 : 16 : function detectTransferRestriction(address from, address to, uint256 /* value */ ) + 41 : 22 : function detectTransferRestriction(address from, address to, uint256 /* value */ ) 42 : : public 43 : : view 44 : : override(IERC1404) 45 : : returns (uint8) 46 : : { - 47 [ + + ]: 35 : if (isAddressListed(from)) { - 48 : 12 : return CODE_ADDRESS_FROM_IS_BLACKLISTED; - 49 [ + + ]: 23 : } else if (isAddressListed(to)) { - 50 : 11 : return CODE_ADDRESS_TO_IS_BLACKLISTED; + 47 [ + + ]: 43 : if (isAddressListed(from)) { + 48 : 14 : return CODE_ADDRESS_FROM_IS_BLACKLISTED; + 49 [ + + ]: 29 : } else if (isAddressListed(to)) { + 50 : 13 : return CODE_ADDRESS_TO_IS_BLACKLISTED; 51 : : } else { - 52 : 12 : return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); + 52 : 16 : return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); 53 : : } 54 : : } 55 : : @@ -139,16 +139,16 @@ 68 : : /* 69 : : * @inheritdoc IERC1404Extend 70 : : */ - 71 : 12 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) + 71 : 16 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) 72 : : public 73 : : view 74 : : override(IERC1404Extend) 75 : : returns (uint8) 76 : : { - 77 [ + + ]: 16 : if (isAddressListed(spender)) { - 78 : 4 : return CODE_ADDRESS_SPENDER_IS_BLACKLISTED; + 77 [ + + ]: 20 : if (isAddressListed(spender)) { + 78 : 6 : return CODE_ADDRESS_SPENDER_IS_BLACKLISTED; 79 : : } else { - 80 : 12 : return detectTransferRestriction(from, to, value); + 80 : 14 : return detectTransferRestriction(from, to, value); 81 : : } 82 : : } 83 : : @@ -212,41 +212,50 @@ 141 : : 142 : : /* ============ State Functions ============ */ 143 : : - 144 : 6 : function transferred(address from, address to, uint256 value) + 144 : 9 : function transferred(address from, address to, uint256 value) 145 : : public 146 : : view 147 : : virtual 148 : : override(IERC3643IComplianceContract) 149 : : { - 150 : 6 : uint8 code = this.detectTransferRestriction(from, to, value); - 151 [ + + ]: 6 : require( + 150 : 12 : uint8 code = this.detectTransferRestriction(from, to, value); + 151 [ + + ]: 12 : require( 152 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), 153 : : RuleBlacklist_InvalidTransfer(address(this), from, to, value, code) 154 : : ); 155 : : } 156 : : - 157 : 0 : function transferred(address spender, address from, address to, uint256 value) + 157 : 2 : function transferred(address spender, address from, address to, uint256 value) 158 : : public 159 : : view 160 : : virtual 161 : : override(IRuleEngine) 162 : : { - 163 : 0 : uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); - 164 [ # # ]: 0 : require( + 163 : 4 : uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); + 164 [ + + ]: 4 : require( 165 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), - 166 : : RuleBlacklist_InvalidTransfer(address(this), from, to, value, code) + 166 : : RuleBlacklist_InvalidTransferFrom(address(this), spender, from, to, value, code) 167 : : ); 168 : : } 169 : : - 170 : 0 : function transferred(address spender, address from, address to, uint256, /* tokenId */ uint256 value) + 170 : 2 : function transferred(address spender, address from, address to, uint256 /* tokenId */,uint256 value) 171 : : public 172 : : view 173 : : virtual 174 : : override(IERC7943NonFungibleComplianceExtend) 175 : : { - 176 : 0 : transferred(spender, from, to, value); + 176 : 2 : transferred(spender, from, to, value); 177 : : } - 178 : : } + 178 : : + 179 : 3 : function transferred(address from, address to, uint256 /* tokenId */,uint256 value) + 180 : : public + 181 : : view + 182 : : virtual + 183 : : override(IERC7943NonFungibleComplianceExtend) + 184 : : { + 185 : 3 : transferred(from, to, value); + 186 : : } + 187 : : } diff --git a/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html b/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html index 0565295..3e4edde 100644 --- a/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html +++ b/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html @@ -31,27 +31,27 @@ lcov.info Lines: - 40 - 52 - 76.9 % + 50 + 54 + 92.6 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 11 - 16 - 68.8 % + 15 + 17 + 88.2 % Branches: - 14 18 - 77.8 % + 18 + 100.0 % @@ -69,7 +69,7 @@ Hit count Sort by hit count - RuleSanctionsList._msgData + RuleSanctionsList._msgData 0 @@ -77,16 +77,12 @@ 0 - RuleSanctionsList.transferred.0 - 0 - - - RuleSanctionsList.transferred.1 - 0 + RuleSanctionsList.transferred.2 + 1 - RuleSanctionsList.transferred.2 - 0 + RuleSanctionsList.transferred.1 + 2 RuleSanctionsList.canReturnTransferRestrictionCode @@ -96,24 +92,28 @@ RuleSanctionsList.detectTransferRestrictionFrom.1 3 + + RuleSanctionsList.transferred.0 + 3 + RuleSanctionsList.messageForTransferRestriction 4 - RuleSanctionsList.detectTransferRestrictionFrom.0 - 8 + RuleSanctionsList.transferred.3 + 4 RuleSanctionsList.detectTransferRestriction.1 9 - RuleSanctionsList.detectTransferRestriction.0 - 10 + RuleSanctionsList.detectTransferRestrictionFrom.0 + 11 - RuleSanctionsList._setSanctionListOracle + RuleSanctionsList._setSanctionListOracle 14 @@ -125,11 +125,15 @@ 17 - RuleSanctionsList._contextSuffixLength + RuleSanctionsList.detectTransferRestriction.0 + 17 + + + RuleSanctionsList._contextSuffixLength 30 - RuleSanctionsList._msgSender + RuleSanctionsList._msgSender 30 diff --git a/doc/coverage/coverage/validation/RuleSanctionsList.sol.func.html b/doc/coverage/coverage/validation/RuleSanctionsList.sol.func.html index 73e3403..03d8771 100644 --- a/doc/coverage/coverage/validation/RuleSanctionsList.sol.func.html +++ b/doc/coverage/coverage/validation/RuleSanctionsList.sol.func.html @@ -31,27 +31,27 @@ lcov.info Lines: - 40 - 52 - 76.9 % + 50 + 54 + 92.6 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 11 - 16 - 68.8 % + 15 + 17 + 88.2 % Branches: - 14 18 - 77.8 % + 18 + 100.0 % @@ -69,19 +69,19 @@ Hit count Sort by hit count - RuleSanctionsList._contextSuffixLength + RuleSanctionsList._contextSuffixLength 30 - RuleSanctionsList._msgData + RuleSanctionsList._msgData 0 - RuleSanctionsList._msgSender + RuleSanctionsList._msgSender 30 - RuleSanctionsList._setSanctionListOracle + RuleSanctionsList._setSanctionListOracle 14 @@ -94,7 +94,7 @@ RuleSanctionsList.detectTransferRestriction.0 - 10 + 17 RuleSanctionsList.detectTransferRestriction.1 @@ -102,7 +102,7 @@ RuleSanctionsList.detectTransferRestrictionFrom.0 - 8 + 11 RuleSanctionsList.detectTransferRestrictionFrom.1 @@ -122,15 +122,19 @@ RuleSanctionsList.transferred.0 - 0 + 3 - RuleSanctionsList.transferred.1 - 0 + RuleSanctionsList.transferred.1 + 2 - RuleSanctionsList.transferred.2 - 0 + RuleSanctionsList.transferred.2 + 1 + + + RuleSanctionsList.transferred.3 + 4
diff --git a/doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html b/doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html index f308e1e..1d03613 100644 --- a/doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html +++ b/doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html @@ -31,27 +31,27 @@ lcov.info Lines: - 40 - 52 - 76.9 % + 50 + 54 + 92.6 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 11 - 16 - 68.8 % + 15 + 17 + 88.2 % Branches: - 14 18 - 77.8 % + 18 + 100.0 % @@ -141,20 +141,20 @@ 70 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK 71 : : * 72 : : */ - 73 : 10 : function detectTransferRestriction(address from, address to, uint256 /*value */ ) + 73 : 17 : function detectTransferRestriction(address from, address to, uint256 /*value */ ) 74 : : public 75 : : view 76 : : override(IERC1404) 77 : : returns (uint8) 78 : : { - 79 [ + ]: 27 : if (address(sanctionsList) != address(0)) { - 80 [ + + ]: 22 : if (sanctionsList.isSanctioned(from)) { - 81 : 4 : return CODE_ADDRESS_FROM_IS_SANCTIONED; - 82 [ + ]: 18 : } else if (sanctionsList.isSanctioned(to)) { - 83 : 8 : return CODE_ADDRESS_TO_IS_SANCTIONED; + 79 [ + ]: 35 : if (address(sanctionsList) != address(0)) { + 80 [ + + ]: 30 : if (sanctionsList.isSanctioned(from)) { + 81 : 6 : return CODE_ADDRESS_FROM_IS_SANCTIONED; + 82 [ + ]: 24 : } else if (sanctionsList.isSanctioned(to)) { + 83 : 10 : return CODE_ADDRESS_TO_IS_SANCTIONED; 84 : : } 85 : : } - 86 : 15 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 86 : 19 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); 87 : : } 88 : : 89 : : /** @@ -173,18 +173,18 @@ 102 : : /** 103 : : * @inheritdoc IERC1404Extend 104 : : */ - 105 : 8 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) + 105 : 11 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) 106 : : public 107 : : view 108 : : virtual 109 : : override(IERC1404Extend) 110 : : returns (uint8) 111 : : { - 112 [ + ]: 11 : if (address(sanctionsList) != address(0)) { - 113 [ + + ]: 10 : if (sanctionsList.isSanctioned(spender)) { - 114 : 2 : return CODE_ADDRESS_SPENDER_IS_SANCTIONED; + 112 [ + ]: 14 : if (address(sanctionsList) != address(0)) { + 113 [ + + ]: 13 : if (sanctionsList.isSanctioned(spender)) { + 114 : 4 : return CODE_ADDRESS_SPENDER_IS_SANCTIONED; 115 : : } else { - 116 : 8 : return detectTransferRestriction(from, to, value); + 116 : 9 : return detectTransferRestriction(from, to, value); 117 : : } 118 : : } 119 : 1 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); @@ -252,81 +252,87 @@ 181 : : /** 182 : : * @inheritdoc IERC3643IComplianceContract 183 : : */ - 184 : 0 : function transferred(address from, address to, uint256 value) + 184 : 3 : function transferred(address from, address to, uint256 value) 185 : : public 186 : : view 187 : : virtual 188 : : override(IERC3643IComplianceContract) 189 : : { - 190 : 0 : uint8 code = this.detectTransferRestriction(from, to, value); - 191 [ # # ]: 0 : require( + 190 : 7 : uint8 code = this.detectTransferRestriction(from, to, value); + 191 [ + + ]: 7 : require( 192 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), 193 : : RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code) 194 : : ); 195 : : } 196 : : - 197 : : /** - 198 : : * @inheritdoc IRuleEngine - 199 : : */ - 200 : 0 : function transferred(address spender, address from, address to, uint256 value) - 201 : : public - 202 : : view - 203 : : virtual - 204 : : override(IRuleEngine) - 205 : : { - 206 : 0 : uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); - 207 [ # # ]: 0 : require( - 208 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), - 209 : : RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code) - 210 : : ); - 211 : : } - 212 : : - 213 : : /** - 214 : : * @inheritdoc IERC7943NonFungibleComplianceExtend - 215 : : */ - 216 : 0 : function transferred(address spender, address from, address to, uint256, /* tokenId */ uint256 value) - 217 : : public - 218 : : view - 219 : : virtual - 220 : : override(IERC7943NonFungibleComplianceExtend) - 221 : : { - 222 : 0 : transferred(spender, from, to, value); - 223 : : } - 224 : : - 225 : : /*////////////////////////////////////////////////////////////// - 226 : : INTERNAL FUNCTIONS - 227 : : //////////////////////////////////////////////////////////////*/ - 228 : : - 229 : 14 : function _setSanctionListOracle(ISanctionsList sanctionContractOracle_) internal { - 230 : 14 : sanctionsList = sanctionContractOracle_; - 231 : 14 : emit SetSanctionListOracle(sanctionContractOracle_); - 232 : : } - 233 : : - 234 : : /*////////////////////////////////////////////////////////////// - 235 : : ERC-2771 - 236 : : //////////////////////////////////////////////////////////////*/ - 237 : : - 238 : : /** - 239 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 240 : : */ - 241 : 30 : function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) { - 242 : 30 : return ERC2771Context._msgSender(); - 243 : : } - 244 : : - 245 : : /** - 246 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 247 : : */ - 248 : 0 : function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) { - 249 : 0 : return ERC2771Context._msgData(); - 250 : : } - 251 : : - 252 : : /** - 253 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 254 : : */ - 255 : 30 : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { - 256 : 30 : return ERC2771Context._contextSuffixLength(); - 257 : : } - 258 : : } + 197 : : + 198 : : /** + 199 : : * @inheritdoc IRuleEngine + 200 : : */ + 201 : 2 : function transferred(address spender, address from, address to, uint256 value) + 202 : : public + 203 : : view + 204 : : virtual + 205 : : override(IRuleEngine) + 206 : : { + 207 : 3 : uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); + 208 [ + + ]: 3 : require( + 209 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + 210 : : RuleSanctionsList_InvalidTransferFrom(address(this), spender, from, to, value, code) + 211 : : ); + 212 : : } + 213 : : + 214 : 1 : function transferred(address spender, address from, address to, uint256 /* tokenId */,uint256 value) + 215 : : public + 216 : : view + 217 : : virtual + 218 : : override(IERC7943NonFungibleComplianceExtend) + 219 : : { + 220 : 1 : transferred(spender, from, to, value); + 221 : : } + 222 : : + 223 : 4 : function transferred(address from, address to, uint256 /* tokenId */,uint256 value) + 224 : : public + 225 : : view + 226 : : virtual + 227 : : override(IERC7943NonFungibleComplianceExtend) + 228 : : { + 229 : 4 : transferred(from, to, value); + 230 : : } + 231 : : /*////////////////////////////////////////////////////////////// + 232 : : INTERNAL FUNCTIONS + 233 : : //////////////////////////////////////////////////////////////*/ + 234 : : + 235 : 14 : function _setSanctionListOracle(ISanctionsList sanctionContractOracle_) internal { + 236 : 14 : sanctionsList = sanctionContractOracle_; + 237 : 14 : emit SetSanctionListOracle(sanctionContractOracle_); + 238 : : } + 239 : : + 240 : : /*////////////////////////////////////////////////////////////// + 241 : : ERC-2771 + 242 : : //////////////////////////////////////////////////////////////*/ + 243 : : + 244 : : /** + 245 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 246 : : */ + 247 : 30 : function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) { + 248 : 30 : return ERC2771Context._msgSender(); + 249 : : } + 250 : : + 251 : : /** + 252 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 253 : : */ + 254 : 0 : function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) { + 255 : 0 : return ERC2771Context._msgData(); + 256 : : } + 257 : : + 258 : : /** + 259 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 260 : : */ + 261 : 30 : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { + 262 : 30 : return ERC2771Context._contextSuffixLength(); + 263 : : } + 264 : : } diff --git a/doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html b/doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html index 587528e..f9af8e7 100644 --- a/doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html +++ b/doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 5 @@ -80,17 +80,17 @@ RuleWhitelist.detectTransferRestrictionFrom.1 2 - - RuleWhitelist.detectTransferRestrictionFrom.0 - 6 - RuleWhitelist.detectTransferRestriction.1 7 + + RuleWhitelist.detectTransferRestrictionFrom.0 + 10 + RuleWhitelist.detectTransferRestriction.0 - 16 + 20 RuleWhitelist.constructor diff --git a/doc/coverage/coverage/validation/RuleWhitelist.sol.func.html b/doc/coverage/coverage/validation/RuleWhitelist.sol.func.html index a8ca06b..e3f8fe0 100644 --- a/doc/coverage/coverage/validation/RuleWhitelist.sol.func.html +++ b/doc/coverage/coverage/validation/RuleWhitelist.sol.func.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 5 @@ -74,7 +74,7 @@ RuleWhitelist.detectTransferRestriction.0 - 16 + 20 RuleWhitelist.detectTransferRestriction.1 @@ -82,7 +82,7 @@ RuleWhitelist.detectTransferRestrictionFrom.0 - 6 + 10 RuleWhitelist.detectTransferRestrictionFrom.1 diff --git a/doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html b/doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html index b427104..09c1d37 100644 --- a/doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html +++ b/doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 5 @@ -124,19 +124,19 @@ 53 : : * | `to` not whitelisted | `CODE_ADDRESS_TO_NOT_WHITELISTED` | 54 : : * | Both whitelisted | `TRANSFER_OK` | 55 : : */ - 56 : 16 : function detectTransferRestriction(address from, address to, uint256 /* value */ ) + 56 : 20 : function detectTransferRestriction(address from, address to, uint256 /* value */ ) 57 : : public 58 : : view 59 : : virtual 60 : : override(IERC1404) 61 : : returns (uint8 code) 62 : : { - 63 [ + + ]: 27 : if (!isAddressListed(from)) { - 64 : 9 : return CODE_ADDRESS_FROM_NOT_WHITELISTED; - 65 [ + + ]: 18 : } else if (!isAddressListed(to)) { - 66 : 4 : return CODE_ADDRESS_TO_NOT_WHITELISTED; + 63 [ + + ]: 33 : if (!isAddressListed(from)) { + 64 : 11 : return CODE_ADDRESS_FROM_NOT_WHITELISTED; + 65 [ + + ]: 22 : } else if (!isAddressListed(to)) { + 66 : 6 : return CODE_ADDRESS_TO_NOT_WHITELISTED; 67 : : } else { - 68 : 14 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 68 : 16 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); 69 : : } 70 : : } 71 : : @@ -170,17 +170,17 @@ 99 : : * | `from` or `to` not whitelisted | respective restriction code from `detectTransferRestriction` | 100 : : * | All whitelisted | `TRANSFER_OK` | 101 : : */ - 102 : 6 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) + 102 : 10 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) 103 : : public 104 : : view 105 : : virtual 106 : : override(IERC1404Extend) 107 : : returns (uint8 code) 108 : : { - 109 [ + ]: 8 : if (checkSpender && !isAddressListed(spender)) { - 110 : 4 : return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; + 109 [ + ]: 12 : if (checkSpender && !isAddressListed(spender)) { + 110 : 6 : return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; 111 : : } - 112 : 4 : return detectTransferRestriction(from, to, value); + 112 : 6 : return detectTransferRestriction(from, to, value); 113 : : } 114 : : 115 : : /** diff --git a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html index 7fa22b2..19a2bf6 100644 --- a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html +++ b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 9 @@ -69,47 +69,47 @@ Hit count Sort by hit count - RuleWhitelistWrapper._msgData + RuleWhitelistWrapper._msgData 0 - RuleWhitelistWrapper.supportsInterface + RuleWhitelistWrapper.supportsInterface 0 - RuleWhitelistWrapper.detectTransferRestrictionFrom.1 + RuleWhitelistWrapper.detectTransferRestrictionFrom.1 2 - RuleWhitelistWrapper.detectTransferRestriction.1 + RuleWhitelistWrapper.detectTransferRestriction.1 4 - RuleWhitelistWrapper.detectTransferRestrictionFrom.0 - 6 + RuleWhitelistWrapper.detectTransferRestrictionFrom.0 + 10 - RuleWhitelistWrapper.detectTransferRestriction.0 - 15 + RuleWhitelistWrapper.hasRole + 20 - RuleWhitelistWrapper.hasRole - 20 + RuleWhitelistWrapper.detectTransferRestriction.0 + 21 - RuleWhitelistWrapper.constructor + RuleWhitelistWrapper.constructor 22 - RuleWhitelistWrapper._detectTransferRestriction - 27 + RuleWhitelistWrapper._detectTransferRestriction + 37 - RuleWhitelistWrapper._contextSuffixLength + RuleWhitelistWrapper._contextSuffixLength 80 - RuleWhitelistWrapper._msgSender + RuleWhitelistWrapper._msgSender 80 diff --git a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html index 249ce1b..4994cad 100644 --- a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html +++ b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 9 @@ -69,47 +69,47 @@ Hit count Sort by hit count - RuleWhitelistWrapper._contextSuffixLength + RuleWhitelistWrapper._contextSuffixLength 80 - RuleWhitelistWrapper._detectTransferRestriction - 27 + RuleWhitelistWrapper._detectTransferRestriction + 37 - RuleWhitelistWrapper._msgData + RuleWhitelistWrapper._msgData 0 - RuleWhitelistWrapper._msgSender + RuleWhitelistWrapper._msgSender 80 - RuleWhitelistWrapper.constructor + RuleWhitelistWrapper.constructor 22 - RuleWhitelistWrapper.detectTransferRestriction.0 - 15 + RuleWhitelistWrapper.detectTransferRestriction.0 + 21 - RuleWhitelistWrapper.detectTransferRestriction.1 + RuleWhitelistWrapper.detectTransferRestriction.1 4 - RuleWhitelistWrapper.detectTransferRestrictionFrom.0 - 6 + RuleWhitelistWrapper.detectTransferRestrictionFrom.0 + 10 - RuleWhitelistWrapper.detectTransferRestrictionFrom.1 + RuleWhitelistWrapper.detectTransferRestrictionFrom.1 2 - RuleWhitelistWrapper.hasRole + RuleWhitelistWrapper.hasRole 20 - RuleWhitelistWrapper.supportsInterface + RuleWhitelistWrapper.supportsInterface 0 diff --git a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html index a064c2b..325f5a0 100644 --- a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html +++ b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 9 @@ -82,195 +82,193 @@ 11 : : import {RuleWhitelistCommon, RuleValidateTransfer} from "./abstract/RuleWhitelistCommon.sol"; 12 : : /* ==== RuleEngine === */ 13 : : import {RulesManagementModule} from "RuleEngine/modules/RulesManagementModule.sol"; - 14 : : import {RuleEngineInvariantStorage} from "RuleEngine/modules/library/RuleEngineInvariantStorage.sol"; - 15 : : import {IRule} from "RuleEngine/interfaces/IRule.sol"; - 16 : : /* ==== CMTAT === */ - 17 : : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; - 18 : : /* ==== Interfaces === */ - 19 : : import { - 20 : : IERC7943NonFungibleCompliance, - 21 : : IERC7943NonFungibleComplianceExtend - 22 : : } from "../interfaces/IERC7943NonFungibleCompliance.sol"; - 23 : : - 24 : : /** - 25 : : * @title Wrapper to call several different whitelist rules - 26 : : */ - 27 : : contract RuleWhitelistWrapper is - 28 : : RulesManagementModule, - 29 : : AccessControlModuleStandalone, - 30 : : MetaTxModuleStandalone, - 31 : : RuleWhitelistCommon - 32 : : { - 33 : : /*////////////////////////////////////////////////////////////// - 34 : : CONSTRUCTOR - 35 : : //////////////////////////////////////////////////////////////*/ - 36 : : /** - 37 : : * @param admin Address of the contract (Access Control) - 38 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - 39 : : */ - 40 : 22 : constructor(address admin, address forwarderIrrevocable, bool checkSpender_) - 41 : : MetaTxModuleStandalone(forwarderIrrevocable) - 42 : : AccessControlModuleStandalone(admin) - 43 : : { - 44 : 20 : checkSpender = checkSpender_; - 45 : : } - 46 : : - 47 : : /* ============ View Functions ============ */ - 48 : : /** - 49 : : * @notice Go through all the whitelist rules to know if a restriction exists on the transfer - 50 : : * @param from the origin address - 51 : : * @param to the destination address - 52 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK - 53 : : * - 54 : : */ - 55 : 15 : function detectTransferRestriction(address from, address to, uint256 /*value*/ ) - 56 : : public - 57 : : view - 58 : : virtual - 59 : : override(IERC1404) - 60 : : returns (uint8) - 61 : : { - 62 : 19 : address[] memory targetAddress = new address[](2); - 63 : 19 : targetAddress[0] = from; - 64 : 19 : targetAddress[1] = to; - 65 : : - 66 : 19 : bool[] memory result = _detectTransferRestriction(targetAddress); - 67 [ + + ]: 19 : if (!result[0]) { - 68 : 7 : return CODE_ADDRESS_FROM_NOT_WHITELISTED; - 69 [ + + ]: 12 : } else if (!result[1]) { - 70 : 4 : return CODE_ADDRESS_TO_NOT_WHITELISTED; - 71 : : } else { - 72 : 8 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 73 : : } - 74 : : } - 75 : : - 76 : 4 : function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value) - 77 : : public - 78 : : view - 79 : : virtual - 80 : : override(IERC7943NonFungibleComplianceExtend) - 81 : : returns (uint8) - 82 : : { - 83 : 4 : return detectTransferRestriction(from, to, value); - 84 : : } - 85 : : - 86 : 6 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) - 87 : : public - 88 : : view - 89 : : virtual - 90 : : override(IERC1404Extend) - 91 : : returns (uint8) - 92 : : { - 93 [ # ]: 8 : if (!checkSpender) { - 94 : 0 : return detectTransferRestriction(from, to, value); - 95 : : } - 96 : : - 97 : 8 : address[] memory targetAddress = new address[](3); - 98 : 8 : targetAddress[0] = from; - 99 : 8 : targetAddress[1] = to; - 100 : 8 : targetAddress[2] = spender; + 14 : : /* ==== CMTAT === */ + 15 : : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; + 16 : : /* ==== Interfaces === */ + 17 : : import { + 18 : : IERC7943NonFungibleCompliance, + 19 : : IERC7943NonFungibleComplianceExtend + 20 : : } from "../interfaces/IERC7943NonFungibleCompliance.sol"; + 21 : : + 22 : : /** + 23 : : * @title Wrapper to call several different whitelist rules + 24 : : */ + 25 : : contract RuleWhitelistWrapper is + 26 : : RulesManagementModule, + 27 : : AccessControlModuleStandalone, + 28 : : MetaTxModuleStandalone, + 29 : : RuleWhitelistCommon + 30 : : { + 31 : : /*////////////////////////////////////////////////////////////// + 32 : : CONSTRUCTOR + 33 : : //////////////////////////////////////////////////////////////*/ + 34 : : /** + 35 : : * @param admin Address of the contract (Access Control) + 36 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + 37 : : */ + 38 : 22 : constructor(address admin, address forwarderIrrevocable, bool checkSpender_) + 39 : : MetaTxModuleStandalone(forwarderIrrevocable) + 40 : : AccessControlModuleStandalone(admin) + 41 : : { + 42 : 20 : checkSpender = checkSpender_; + 43 : : } + 44 : : + 45 : : /* ============ View Functions ============ */ + 46 : : /** + 47 : : * @notice Go through all the whitelist rules to know if a restriction exists on the transfer + 48 : : * @param from the origin address + 49 : : * @param to the destination address + 50 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + 51 : : * + 52 : : */ + 53 : 21 : function detectTransferRestriction(address from, address to, uint256 /*value*/ ) + 54 : : public + 55 : : view + 56 : : virtual + 57 : : override(IERC1404) + 58 : : returns (uint8) + 59 : : { + 60 : 25 : address[] memory targetAddress = new address[](2); + 61 : 25 : targetAddress[0] = from; + 62 : 25 : targetAddress[1] = to; + 63 : : + 64 : 25 : bool[] memory result = _detectTransferRestriction(targetAddress); + 65 [ + + ]: 25 : if (!result[0]) { + 66 : 9 : return CODE_ADDRESS_FROM_NOT_WHITELISTED; + 67 [ + + ]: 16 : } else if (!result[1]) { + 68 : 6 : return CODE_ADDRESS_TO_NOT_WHITELISTED; + 69 : : } else { + 70 : 10 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 71 : : } + 72 : : } + 73 : : + 74 : 4 : function detectTransferRestriction(address from, address to, uint256, /* tokenId */ uint256 value) + 75 : : public + 76 : : view + 77 : : virtual + 78 : : override(IERC7943NonFungibleComplianceExtend) + 79 : : returns (uint8) + 80 : : { + 81 : 4 : return detectTransferRestriction(from, to, value); + 82 : : } + 83 : : + 84 : 10 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) + 85 : : public + 86 : : view + 87 : : virtual + 88 : : override(IERC1404Extend) + 89 : : returns (uint8) + 90 : : { + 91 [ # ]: 12 : if (!checkSpender) { + 92 : 0 : return detectTransferRestriction(from, to, value); + 93 : : } + 94 : : + 95 : 12 : address[] memory targetAddress = new address[](3); + 96 : 12 : targetAddress[0] = from; + 97 : 12 : targetAddress[1] = to; + 98 : 12 : targetAddress[2] = spender; + 99 : : + 100 : 12 : bool[] memory result = _detectTransferRestriction(targetAddress); 101 : : - 102 : 8 : bool[] memory result = _detectTransferRestriction(targetAddress); - 103 : : - 104 [ # + ]: 8 : if (!result[0]) { - 105 : 0 : return CODE_ADDRESS_FROM_NOT_WHITELISTED; - 106 [ # + ]: 8 : } else if (!result[1]) { - 107 : 0 : return CODE_ADDRESS_TO_NOT_WHITELISTED; - 108 [ + + ]: 8 : } else if (!result[2]) { - 109 : 4 : return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; - 110 : : } else { - 111 : 4 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 112 : : } - 113 : : } - 114 : : - 115 : : /** - 116 : : * @inheritdoc IERC7943NonFungibleComplianceExtend - 117 : : */ - 118 : 2 : function detectTransferRestrictionFrom( - 119 : : address spender, - 120 : : address from, - 121 : : address to, - 122 : : uint256, /* tokenId */ - 123 : : uint256 value - 124 : : ) public view virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) { - 125 : 2 : return detectTransferRestrictionFrom(spender, from, to, value); - 126 : : } + 102 [ # + ]: 12 : if (!result[0]) { + 103 : 0 : return CODE_ADDRESS_FROM_NOT_WHITELISTED; + 104 [ # + ]: 12 : } else if (!result[1]) { + 105 : 0 : return CODE_ADDRESS_TO_NOT_WHITELISTED; + 106 [ + + ]: 12 : } else if (!result[2]) { + 107 : 6 : return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; + 108 : : } else { + 109 : 6 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 110 : : } + 111 : : } + 112 : : + 113 : : /** + 114 : : * @inheritdoc IERC7943NonFungibleComplianceExtend + 115 : : */ + 116 : 2 : function detectTransferRestrictionFrom( + 117 : : address spender, + 118 : : address from, + 119 : : address to, + 120 : : uint256, /* tokenId */ + 121 : : uint256 value + 122 : : ) public view virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) { + 123 : 2 : return detectTransferRestrictionFrom(spender, from, to, value); + 124 : : } + 125 : : + 126 : : /* ============ Access control ============ */ 127 : : - 128 : : /* ============ Access control ============ */ - 129 : : - 130 : : /** - 131 : : * @dev Returns `true` if `account` has been granted `role`. - 132 : : */ - 133 : 20 : function hasRole(bytes32 role, address account) - 134 : : public - 135 : : view - 136 : : virtual - 137 : : override(AccessControl, AccessControlModuleStandalone) - 138 : : returns (bool) - 139 : : { - 140 : 80 : return AccessControlModuleStandalone.hasRole(role, account); - 141 : : } - 142 : : - 143 : : /*////////////////////////////////////////////////////////////// - 144 : : INTERNAL/PRIVATE FUNCTIONS - 145 : : //////////////////////////////////////////////////////////////*/ - 146 : : - 147 : 27 : function _detectTransferRestriction(address[] memory targetAddress) internal view returns (bool[] memory) { - 148 : 27 : uint256 rulesLength = rulesCount(); - 149 : 27 : bool[] memory result = new bool[](targetAddress.length); - 150 : 27 : for (uint256 i = 0; i < rulesLength; ++i) { - 151 : : // Call the whitelist rules - 152 : 59 : bool[] memory isListed = RuleAddressSet(rule(i)).areAddressesListed(targetAddress); - 153 : 59 : for (uint256 j = 0; j < targetAddress.length; ++j) { - 154 [ + ]: 42 : if (isListed[j]) { - 155 : 42 : result[j] = true; - 156 : : } - 157 : : } - 158 : : - 159 : : // Break early if all listed - 160 : 59 : bool allListed = true; - 161 : 59 : for (uint256 k = 0; k < result.length; ++k) { - 162 [ + ]: 113 : if (!result[k]) { - 163 : 47 : allListed = false; - 164 : 47 : break; - 165 : : } - 166 : : } - 167 [ + ]: 12 : if (allListed) { - 168 : 12 : break; - 169 : : } - 170 : : } - 171 : 27 : return result; - 172 : : } - 173 : : - 174 : 0 : function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) { - 175 : 0 : return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId); - 176 : : } - 177 : : - 178 : : /*////////////////////////////////////////////////////////////// - 179 : : ERC-2771 - 180 : : //////////////////////////////////////////////////////////////*/ - 181 : : - 182 : : /** - 183 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 184 : : */ - 185 : 80 : function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) { - 186 : 80 : return ERC2771Context._msgSender(); - 187 : : } - 188 : : - 189 : : /** - 190 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 191 : : */ - 192 : 0 : function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) { - 193 : 0 : return ERC2771Context._msgData(); - 194 : : } - 195 : : - 196 : : /** - 197 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 198 : : */ - 199 : 80 : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { - 200 : 80 : return ERC2771Context._contextSuffixLength(); - 201 : : } - 202 : : } + 128 : : /** + 129 : : * @dev Returns `true` if `account` has been granted `role`. + 130 : : */ + 131 : 20 : function hasRole(bytes32 role, address account) + 132 : : public + 133 : : view + 134 : : virtual + 135 : : override(AccessControl, AccessControlModuleStandalone) + 136 : : returns (bool) + 137 : : { + 138 : 80 : return AccessControlModuleStandalone.hasRole(role, account); + 139 : : } + 140 : : + 141 : : /*////////////////////////////////////////////////////////////// + 142 : : INTERNAL/PRIVATE FUNCTIONS + 143 : : //////////////////////////////////////////////////////////////*/ + 144 : : + 145 : 37 : function _detectTransferRestriction(address[] memory targetAddress) internal view returns (bool[] memory) { + 146 : 37 : uint256 rulesLength = rulesCount(); + 147 : 37 : bool[] memory result = new bool[](targetAddress.length); + 148 : 37 : for (uint256 i = 0; i < rulesLength; ++i) { + 149 : : // Call the whitelist rules + 150 : 81 : bool[] memory isListed = RuleAddressSet(rule(i)).areAddressesListed(targetAddress); + 151 : 81 : for (uint256 j = 0; j < targetAddress.length; ++j) { + 152 [ + ]: 58 : if (isListed[j]) { + 153 : 58 : result[j] = true; + 154 : : } + 155 : : } + 156 : : + 157 : : // Break early if all listed + 158 : 81 : bool allListed = true; + 159 : 81 : for (uint256 k = 0; k < result.length; ++k) { + 160 [ + ]: 159 : if (!result[k]) { + 161 : 65 : allListed = false; + 162 : 65 : break; + 163 : : } + 164 : : } + 165 [ + ]: 16 : if (allListed) { + 166 : 16 : break; + 167 : : } + 168 : : } + 169 : 37 : return result; + 170 : : } + 171 : : + 172 : 0 : function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) { + 173 : 0 : return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId); + 174 : : } + 175 : : + 176 : : /*////////////////////////////////////////////////////////////// + 177 : : ERC-2771 + 178 : : //////////////////////////////////////////////////////////////*/ + 179 : : + 180 : : /** + 181 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 182 : : */ + 183 : 80 : function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) { + 184 : 80 : return ERC2771Context._msgSender(); + 185 : : } + 186 : : + 187 : : /** + 188 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 189 : : */ + 190 : 0 : function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) { + 191 : 0 : return ERC2771Context._msgData(); + 192 : : } + 193 : : + 194 : : /** + 195 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 196 : : */ + 197 : 80 : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) { + 198 : 80 : return ERC2771Context._contextSuffixLength(); + 199 : : } + 200 : : } diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html index 282132f..6808037 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 9 @@ -102,7 +102,7 @@ RuleAddressSet.areAddressesListed - 62 + 84 RuleAddressSet._contextSuffixLength diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html index 5c09f24..3ebf795 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 9 @@ -90,7 +90,7 @@ RuleAddressSet.areAddressesListed - 62 + 84 RuleAddressSet.contains diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html index 92f804f..cded5ef 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 9 @@ -201,7 +201,7 @@ 130 : : * @return isListed True if listed, false otherwise. 131 : : */ 132 : 60 : function isAddressListed(address targetAddress) public view returns (bool isListed) { - 133 : 187 : isListed = _isAddressListed(targetAddress); + 133 : 219 : isListed = _isAddressListed(targetAddress); 134 : : } 135 : : 136 : : /** @@ -209,10 +209,10 @@ 138 : : * @param targetAddresses Array of addresses to check. 139 : : * @return results Array of booleans corresponding to listing status. 140 : : */ - 141 : 62 : function areAddressesListed(address[] memory targetAddresses) public view returns (bool[] memory results) { - 142 : 62 : results = new bool[](targetAddresses.length); - 143 : 62 : for (uint256 i = 0; i < targetAddresses.length; ++i) { - 144 : 139 : results[i] = _isAddressListed(targetAddresses[i]); + 141 : 84 : function areAddressesListed(address[] memory targetAddresses) public view returns (bool[] memory results) { + 142 : 84 : results = new bool[](targetAddresses.length); + 143 : 84 : for (uint256 i = 0; i < targetAddresses.length; ++i) { + 144 : 191 : results[i] = _isAddressListed(targetAddresses[i]); 145 : : } 146 : : } 147 : : /*////////////////////////////////////////////////////////////// diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html index 0484ff0..715669b 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 6 @@ -90,7 +90,7 @@ RuleAddressSetInternal._isAddressListed - 379 + 463
diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html index 54eaa56..bfbd673 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 6 @@ -78,7 +78,7 @@ RuleAddressSetInternal._isAddressListed - 379 + 463 RuleAddressSetInternal._listedAddressCount diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html index f29faa9..c60105a 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 6 @@ -152,8 +152,8 @@ 81 : : * @param targetAddress The address to check. 82 : : * @return isListed True if the address is listed, false otherwise. 83 : : */ - 84 : 379 : function _isAddressListed(address targetAddress) internal view returns (bool isListed) { - 85 : 379 : isListed = _listedAddresses.contains(targetAddress); + 84 : 463 : function _isAddressListed(address targetAddress) internal view returns (bool isListed) { + 85 : 463 : isListed = _listedAddresses.contains(targetAddress); 86 : : } 87 : : } diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html index 8ede562..fe9d655 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 15 diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html index 90b90d9..b79046b 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 15 diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html index 244a6fc..7506cec 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 15 diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html index 7bbaf77..4c0f604 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html +++ b/doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 15 diff --git a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html index e8c66ce..93f72fb 100644 --- a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html +++ b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 4 @@ -69,23 +69,23 @@ Hit count Sort by hit count - RuleValidateTransfer.supportsInterface + RuleValidateTransfer.supportsInterface 0 - RuleValidateTransfer.canTransferFrom.0 + RuleValidateTransfer.canTransferFrom.0 10 - RuleValidateTransfer.canTransferFrom.1 + RuleValidateTransfer.canTransferFrom.1 10 - RuleValidateTransfer.canTransfer.0 + RuleValidateTransfer.canTransfer.0 14 - RuleValidateTransfer.canTransfer.1 + RuleValidateTransfer.canTransfer.1 14 diff --git a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html index f0c093c..f811a3f 100644 --- a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html +++ b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 4 @@ -69,23 +69,23 @@ Hit count Sort by hit count - RuleValidateTransfer.canTransfer.0 + RuleValidateTransfer.canTransfer.0 14 - RuleValidateTransfer.canTransfer.1 + RuleValidateTransfer.canTransfer.1 14 - RuleValidateTransfer.canTransferFrom.0 + RuleValidateTransfer.canTransferFrom.0 10 - RuleValidateTransfer.canTransferFrom.1 + RuleValidateTransfer.canTransferFrom.1 10 - RuleValidateTransfer.supportsInterface + RuleValidateTransfer.supportsInterface 0 diff --git a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html index 7e35cc9..174dc57 100644 --- a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html +++ b/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: 4 @@ -77,85 +77,83 @@ 6 : : import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; 7 : : import {IERC3643ComplianceRead} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; 8 : : import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol"; - 9 : : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; - 10 : : /* ==== RuleEngine === */ - 11 : : import {IRule} from "RuleEngine/interfaces/IRule.sol"; - 12 : : import { - 13 : : IERC7943NonFungibleCompliance, - 14 : : IERC7943NonFungibleComplianceExtend - 15 : : } from "../../interfaces/IERC7943NonFungibleCompliance.sol"; - 16 : : - 17 : : abstract contract RuleValidateTransfer is IERC7943NonFungibleComplianceExtend, IRule { - 18 : : /** - 19 : : * @notice Validate a transfer - 20 : : * @param from the origin address - 21 : : * @param to the destination address - 22 : : * @param tokenId ERC-721 or ERC-1155 token Id - 23 : : * @param amount to transfer, 1 for NFT - 24 : : * @return isValid => true if the transfer is valid, false otherwise - 25 : : * - 26 : : */ - 27 : 14 : function canTransfer(address from, address to, uint256 tokenId, uint256 amount) - 28 : : public - 29 : : view - 30 : : override(IERC7943NonFungibleCompliance) - 31 : : returns (bool isValid) - 32 : : { - 33 : : // does not work without `this` keyword => "Undeclared identifier" - 34 : 14 : return this.detectTransferRestriction(from, to, tokenId, amount) - 35 : : == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); - 36 : : } - 37 : : - 38 : : /** - 39 : : * @notice Validate a transfer - 40 : : * @param from the origin address - 41 : : * @param to the destination address - 42 : : * @param amount to transfer - 43 : : * @return isValid => true if the transfer is valid, false otherwise - 44 : : * - 45 : : */ - 46 : 14 : function canTransfer(address from, address to, uint256 amount) - 47 : : public - 48 : : view - 49 : : override(IERC3643ComplianceRead) - 50 : : returns (bool isValid) - 51 : : { - 52 : : // does not work without `this` keyword => "Undeclared identifier" - 53 : 14 : return this.detectTransferRestriction(from, to, amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); - 54 : : } - 55 : : - 56 : : /** - 57 : : * @inheritdoc IERC7551Compliance - 58 : : */ - 59 : 10 : function canTransferFrom(address spender, address from, address to, uint256 value) - 60 : : public - 61 : : view - 62 : : virtual - 63 : : override(IERC7551Compliance) - 64 : : returns (bool) - 65 : : { - 66 : 20 : return this.detectTransferRestrictionFrom(spender, from, to, value) - 67 : : == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); - 68 : : } - 69 : : - 70 : : /** - 71 : : * @inheritdoc IERC7943NonFungibleComplianceExtend - 72 : : */ - 73 : 10 : function canTransferFrom(address spender, address from, address to, uint256 tokenId, uint256 value) - 74 : : public - 75 : : view - 76 : : virtual - 77 : : override(IERC7943NonFungibleComplianceExtend) - 78 : : returns (bool) - 79 : : { - 80 : 10 : return canTransferFrom(spender, from, to, value); - 81 : : } - 82 : : - 83 : : - 84 : 0 : function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { - 85 : 0 : return interfaceId == type(IRule).interfaceId; - 86 : : } - 87 : : } + 9 : : /* ==== RuleEngine === */ + 10 : : import {IRule} from "RuleEngine/interfaces/IRule.sol"; + 11 : : import { + 12 : : IERC7943NonFungibleCompliance, + 13 : : IERC7943NonFungibleComplianceExtend + 14 : : } from "../../interfaces/IERC7943NonFungibleCompliance.sol"; + 15 : : + 16 : : abstract contract RuleValidateTransfer is IERC7943NonFungibleComplianceExtend, IRule { + 17 : : /** + 18 : : * @notice Validate a transfer + 19 : : * @param from the origin address + 20 : : * @param to the destination address + 21 : : * @param tokenId ERC-721 or ERC-1155 token Id + 22 : : * @param amount to transfer, 1 for NFT + 23 : : * @return isValid => true if the transfer is valid, false otherwise + 24 : : * + 25 : : */ + 26 : 14 : function canTransfer(address from, address to, uint256 tokenId, uint256 amount) + 27 : : public + 28 : : view + 29 : : override(IERC7943NonFungibleCompliance) + 30 : : returns (bool isValid) + 31 : : { + 32 : : // does not work without `this` keyword => "Undeclared identifier" + 33 : 14 : return this.detectTransferRestriction(from, to, tokenId, amount) + 34 : : == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); + 35 : : } + 36 : : + 37 : : /** + 38 : : * @notice Validate a transfer + 39 : : * @param from the origin address + 40 : : * @param to the destination address + 41 : : * @param amount to transfer + 42 : : * @return isValid => true if the transfer is valid, false otherwise + 43 : : * + 44 : : */ + 45 : 14 : function canTransfer(address from, address to, uint256 amount) + 46 : : public + 47 : : view + 48 : : override(IERC3643ComplianceRead) + 49 : : returns (bool isValid) + 50 : : { + 51 : : // does not work without `this` keyword => "Undeclared identifier" + 52 : 14 : return this.detectTransferRestriction(from, to, amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); + 53 : : } + 54 : : + 55 : : /** + 56 : : * @inheritdoc IERC7551Compliance + 57 : : */ + 58 : 10 : function canTransferFrom(address spender, address from, address to, uint256 value) + 59 : : public + 60 : : view + 61 : : virtual + 62 : : override(IERC7551Compliance) + 63 : : returns (bool) + 64 : : { + 65 : 20 : return this.detectTransferRestrictionFrom(spender, from, to, value) + 66 : : == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); + 67 : : } + 68 : : + 69 : : /** + 70 : : * @inheritdoc IERC7943NonFungibleComplianceExtend + 71 : : */ + 72 : 10 : function canTransferFrom(address spender, address from, address to, uint256 tokenId, uint256 value) + 73 : : public + 74 : : view + 75 : : virtual + 76 : : override(IERC7943NonFungibleComplianceExtend) + 77 : : returns (bool) + 78 : : { + 79 : 10 : return canTransferFrom(spender, from, to, value); + 80 : : } + 81 : : + 82 : 0 : function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { + 83 : 0 : return interfaceId == type(IRule).interfaceId; + 84 : : } + 85 : : } diff --git a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html index 5f0d38b..bf6dc6f 100644 --- a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html +++ b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html @@ -31,27 +31,27 @@ lcov.info Lines: - 14 - 19 - 73.7 % + 21 + 21 + 100.0 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 3 - 5 - 60.0 % + 6 + 6 + 100.0 % Branches: - 8 10 - 80.0 % + 10 + 100.0 % @@ -70,24 +70,28 @@ RuleWhitelistCommon.transferred.1 - 0 + 4 - RuleWhitelistCommon.transferred.2 - 0 + RuleWhitelistCommon.transferred.2 + 4 - RuleWhitelistCommon.canReturnTransferRestrictionCode - 10 + RuleWhitelistCommon.transferred.3 + 5 - RuleWhitelistCommon.transferred.0 - 12 + RuleWhitelistCommon.canReturnTransferRestrictionCode + 10 RuleWhitelistCommon.messageForTransferRestriction 14 + + RuleWhitelistCommon.transferred.0 + 17 +
diff --git a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html index c33f21e..2fda202 100644 --- a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html +++ b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html @@ -31,27 +31,27 @@ lcov.info Lines: - 14 - 19 - 73.7 % + 21 + 21 + 100.0 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 3 - 5 - 60.0 % + 6 + 6 + 100.0 % Branches: - 8 10 - 80.0 % + 10 + 100.0 % @@ -78,15 +78,19 @@ RuleWhitelistCommon.transferred.0 - 12 + 17 RuleWhitelistCommon.transferred.1 - 0 + 4 + + + RuleWhitelistCommon.transferred.2 + 4 - RuleWhitelistCommon.transferred.2 - 0 + RuleWhitelistCommon.transferred.3 + 5
diff --git a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html index 5705304..746edeb 100644 --- a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html +++ b/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html @@ -31,27 +31,27 @@ lcov.info Lines: - 14 - 19 - 73.7 % + 21 + 21 + 100.0 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 3 - 5 - 60.0 % + 6 + 6 + 100.0 % Branches: - 8 10 - 80.0 % + 10 + 100.0 % @@ -147,9 +147,9 @@ 76 : : * @param to The address receiving tokens. 77 : : * @param value The token amount being transferred. 78 : : */ - 79 : 12 : function transferred(address from, address to, uint256 value) public view override(IERC3643IComplianceContract) { - 80 : 12 : uint8 code = this.detectTransferRestriction(from, to, value); - 81 [ + + ]: 12 : require( + 79 : 17 : function transferred(address from, address to, uint256 value) public view override(IERC3643IComplianceContract) { + 80 : 22 : uint8 code = this.detectTransferRestriction(from, to, value); + 81 [ + + ]: 22 : require( 82 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), 83 : : RuleWhitelist_InvalidTransfer(address(this), from, to, value, code) 84 : : ); @@ -165,25 +165,33 @@ 94 : : * @param to The recipient address. 95 : : * @param value The token amount being transferred. 96 : : */ - 97 : 0 : function transferred(address spender, address from, address to, uint256 value) public view override(IRuleEngine) { - 98 : 0 : uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); - 99 [ # # ]: 0 : require( + 97 : 4 : function transferred(address spender, address from, address to, uint256 value) public view override(IRuleEngine) { + 98 : 8 : uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); + 99 [ + + ]: 8 : require( 100 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), - 101 : : RuleWhitelist_InvalidTransfer(address(this), from, to, value, code) + 101 : : RuleWhitelist_InvalidTransferFrom(address(this), spender, from, to, value, code) 102 : : ); 103 : : } 104 : : - 105 : : /** - 106 : : * @inheritdoc IERC7943NonFungibleComplianceExtend - 107 : : */ - 108 : 0 : function transferred(address spender, address from, address to, uint256, /* tokenId */ uint256 value) - 109 : : public - 110 : : view - 111 : : override(IERC7943NonFungibleComplianceExtend) - 112 : : { - 113 : 0 : transferred(spender, from, to, value); - 114 : : } - 115 : : } + 105 : : + 106 : 4 : function transferred(address spender, address from, address to, uint256 /* tokenId */,uint256 value) + 107 : : public + 108 : : view + 109 : : virtual + 110 : : override(IERC7943NonFungibleComplianceExtend) + 111 : : { + 112 : 4 : transferred(spender, from, to, value); + 113 : : } + 114 : : + 115 : 5 : function transferred(address from, address to, uint256 /* tokenId */,uint256 value) + 116 : : public + 117 : : view + 118 : : virtual + 119 : : override(IERC7943NonFungibleComplianceExtend) + 120 : : { + 121 : 5 : transferred(from, to, value); + 122 : : } + 123 : : } diff --git a/doc/coverage/coverage/validation/abstract/index-sort-b.html b/doc/coverage/coverage/validation/abstract/index-sort-b.html index 6140e7c..5fe0919 100644 --- a/doc/coverage/coverage/validation/abstract/index-sort-b.html +++ b/doc/coverage/coverage/validation/abstract/index-sort-b.html @@ -31,27 +31,27 @@ lcov.info Lines: - 22 29 - 75.9 % + 31 + 93.5 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 7 10 - 70.0 % + 11 + 90.9 % Branches: - 8 10 - 80.0 % + 10 + 100.0 % @@ -81,18 +81,6 @@ Functions Sort by function coverage Branches Sort by branch coverage - - RuleWhitelistCommon.sol - -
73.7%73.7%
- - 73.7 % - 14 / 19 - 60.0 % - 3 / 5 - 80.0 % - 8 / 10 - RuleValidateTransfer.sol @@ -105,6 +93,18 @@ - 0 / 0 + + RuleWhitelistCommon.sol + +
100.0%
+ + 100.0 % + 21 / 21 + 100.0 % + 6 / 6 + 100.0 % + 10 / 10 +
diff --git a/doc/coverage/coverage/validation/abstract/index-sort-f.html b/doc/coverage/coverage/validation/abstract/index-sort-f.html index 318c7d0..b7e1816 100644 --- a/doc/coverage/coverage/validation/abstract/index-sort-f.html +++ b/doc/coverage/coverage/validation/abstract/index-sort-f.html @@ -31,27 +31,27 @@ lcov.info Lines: - 22 29 - 75.9 % + 31 + 93.5 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 7 10 - 70.0 % + 11 + 90.9 % Branches: - 8 10 - 80.0 % + 10 + 100.0 % @@ -81,18 +81,6 @@ Functions Sort by function coverage Branches Sort by branch coverage - - RuleWhitelistCommon.sol - -
73.7%73.7%
- - 73.7 % - 14 / 19 - 60.0 % - 3 / 5 - 80.0 % - 8 / 10 - RuleValidateTransfer.sol @@ -105,6 +93,18 @@ - 0 / 0 + + RuleWhitelistCommon.sol + +
100.0%
+ + 100.0 % + 21 / 21 + 100.0 % + 6 / 6 + 100.0 % + 10 / 10 +
diff --git a/doc/coverage/coverage/validation/abstract/index-sort-l.html b/doc/coverage/coverage/validation/abstract/index-sort-l.html index 56b6a61..f752721 100644 --- a/doc/coverage/coverage/validation/abstract/index-sort-l.html +++ b/doc/coverage/coverage/validation/abstract/index-sort-l.html @@ -31,27 +31,27 @@ lcov.info Lines: - 22 29 - 75.9 % + 31 + 93.5 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 7 10 - 70.0 % + 11 + 90.9 % Branches: - 8 10 - 80.0 % + 10 + 100.0 % @@ -81,18 +81,6 @@ Functions Sort by function coverage Branches Sort by branch coverage - - RuleWhitelistCommon.sol - -
73.7%73.7%
- - 73.7 % - 14 / 19 - 60.0 % - 3 / 5 - 80.0 % - 8 / 10 - RuleValidateTransfer.sol @@ -105,6 +93,18 @@ - 0 / 0 + + RuleWhitelistCommon.sol + +
100.0%
+ + 100.0 % + 21 / 21 + 100.0 % + 6 / 6 + 100.0 % + 10 / 10 +
diff --git a/doc/coverage/coverage/validation/abstract/index.html b/doc/coverage/coverage/validation/abstract/index.html index 7d95aca..34817f4 100644 --- a/doc/coverage/coverage/validation/abstract/index.html +++ b/doc/coverage/coverage/validation/abstract/index.html @@ -31,27 +31,27 @@ lcov.info Lines: - 22 29 - 75.9 % + 31 + 93.5 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 7 10 - 70.0 % + 11 + 90.9 % Branches: - 8 10 - 80.0 % + 10 + 100.0 % @@ -96,14 +96,14 @@ RuleWhitelistCommon.sol -
73.7%73.7%
+
100.0%
- 73.7 % - 14 / 19 - 60.0 % - 3 / 5 - 80.0 % - 8 / 10 + 100.0 % + 21 / 21 + 100.0 % + 6 / 6 + 100.0 % + 10 / 10 diff --git a/doc/coverage/coverage/validation/index-sort-b.html b/doc/coverage/coverage/validation/index-sort-b.html index 7d7889c..944c1e9 100644 --- a/doc/coverage/coverage/validation/index-sort-b.html +++ b/doc/coverage/coverage/validation/index-sort-b.html @@ -31,27 +31,27 @@ lcov.info Lines: - 134 - 164 - 81.7 % + 151 + 168 + 89.9 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 32 - 44 - 72.7 % + 39 + 46 + 84.8 % Branches: - 44 + 50 53 - 83.0 % + 94.3 % @@ -81,18 +81,6 @@ Functions Sort by function coverage Branches Sort by branch coverage - - RuleSanctionsList.sol - -
76.9%76.9%
- - 76.9 % - 40 / 52 - 68.8 % - 11 / 16 - 77.8 % - 14 / 18 - RuleWhitelistWrapper.sol @@ -105,18 +93,6 @@ 78.6 % 11 / 14 - - RuleBlacklist.sol - -
80.0%80.0%
- - 80.0 % - 28 / 35 - 70.0 % - 7 / 10 - 87.5 % - 14 / 16 - RuleWhitelist.sol @@ -129,6 +105,30 @@ 100.0 % 5 / 5 + + RuleBlacklist.sol + +
94.6%94.6%
+ + 94.6 % + 35 / 37 + 90.9 % + 10 / 11 + 100.0 % + 16 / 16 + + + RuleSanctionsList.sol + +
92.6%92.6%
+ + 92.6 % + 50 / 54 + 88.2 % + 15 / 17 + 100.0 % + 18 / 18 +
diff --git a/doc/coverage/coverage/validation/index-sort-f.html b/doc/coverage/coverage/validation/index-sort-f.html index 1049174..803ea1c 100644 --- a/doc/coverage/coverage/validation/index-sort-f.html +++ b/doc/coverage/coverage/validation/index-sort-f.html @@ -31,27 +31,27 @@ lcov.info Lines: - 134 - 164 - 81.7 % + 151 + 168 + 89.9 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 32 - 44 - 72.7 % + 39 + 46 + 84.8 % Branches: - 44 + 50 53 - 83.0 % + 94.3 % @@ -81,30 +81,6 @@ Functions Sort by function coverage Branches Sort by branch coverage - - RuleSanctionsList.sol - -
76.9%76.9%
- - 76.9 % - 40 / 52 - 68.8 % - 11 / 16 - 77.8 % - 14 / 18 - - - RuleBlacklist.sol - -
80.0%80.0%
- - 80.0 % - 28 / 35 - 70.0 % - 7 / 10 - 87.5 % - 14 / 16 - RuleWhitelist.sol @@ -129,6 +105,30 @@ 78.6 % 11 / 14 + + RuleSanctionsList.sol + +
92.6%92.6%
+ + 92.6 % + 50 / 54 + 88.2 % + 15 / 17 + 100.0 % + 18 / 18 + + + RuleBlacklist.sol + +
94.6%94.6%
+ + 94.6 % + 35 / 37 + 90.9 % + 10 / 11 + 100.0 % + 16 / 16 +
diff --git a/doc/coverage/coverage/validation/index-sort-l.html b/doc/coverage/coverage/validation/index-sort-l.html index b91037f..b4d9395 100644 --- a/doc/coverage/coverage/validation/index-sort-l.html +++ b/doc/coverage/coverage/validation/index-sort-l.html @@ -31,27 +31,27 @@ lcov.info Lines: - 134 - 164 - 81.7 % + 151 + 168 + 89.9 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 32 - 44 - 72.7 % + 39 + 46 + 84.8 % Branches: - 44 + 50 53 - 83.0 % + 94.3 % @@ -81,18 +81,6 @@ Functions Sort by function coverage Branches Sort by branch coverage - - RuleSanctionsList.sol - -
76.9%76.9%
- - 76.9 % - 40 / 52 - 68.8 % - 11 / 16 - 77.8 % - 14 / 18 - RuleWhitelist.sol @@ -105,18 +93,6 @@ 100.0 % 5 / 5 - - RuleBlacklist.sol - -
80.0%80.0%
- - 80.0 % - 28 / 35 - 70.0 % - 7 / 10 - 87.5 % - 14 / 16 - RuleWhitelistWrapper.sol @@ -129,6 +105,30 @@ 78.6 % 11 / 14 + + RuleSanctionsList.sol + +
92.6%92.6%
+ + 92.6 % + 50 / 54 + 88.2 % + 15 / 17 + 100.0 % + 18 / 18 + + + RuleBlacklist.sol + +
94.6%94.6%
+ + 94.6 % + 35 / 37 + 90.9 % + 10 / 11 + 100.0 % + 16 / 16 +
diff --git a/doc/coverage/coverage/validation/index.html b/doc/coverage/coverage/validation/index.html index 66084f4..bffbd19 100644 --- a/doc/coverage/coverage/validation/index.html +++ b/doc/coverage/coverage/validation/index.html @@ -31,27 +31,27 @@ lcov.info Lines: - 134 - 164 - 81.7 % + 151 + 168 + 89.9 % Date: - 2025-12-03 14:12:50 + 2025-12-03 15:05:37 Functions: - 32 - 44 - 72.7 % + 39 + 46 + 84.8 % Branches: - 44 + 50 53 - 83.0 % + 94.3 % @@ -84,26 +84,26 @@ RuleBlacklist.sol -
80.0%80.0%
+
94.6%94.6%
- 80.0 % - 28 / 35 - 70.0 % - 7 / 10 - 87.5 % - 14 / 16 + 94.6 % + 35 / 37 + 90.9 % + 10 / 11 + 100.0 % + 16 / 16 RuleSanctionsList.sol -
76.9%76.9%
+
92.6%92.6%
- 76.9 % - 40 / 52 - 68.8 % - 11 / 16 - 77.8 % - 14 / 18 + 92.6 % + 50 / 54 + 88.2 % + 15 / 17 + 100.0 % + 18 / 18 RuleWhitelist.sol diff --git a/doc/coverage/lcov.info b/doc/coverage/lcov.info index f1972de..3c88298 100644 --- a/doc/coverage/lcov.info +++ b/doc/coverage/lcov.info @@ -24,30 +24,30 @@ BRH:3 end_of_record TN: SF:src/rules/validation/RuleBlacklist.sol -DA:41,16 +DA:41,22 FN:41,RuleBlacklist.detectTransferRestriction.0 -FNDA:16,RuleBlacklist.detectTransferRestriction.0 -DA:47,35 -BRDA:47,0,0,12 -BRDA:47,0,1,12 -DA:48,12 -DA:49,23 -BRDA:49,1,0,11 -BRDA:49,1,1,12 -DA:50,11 -DA:52,12 +FNDA:22,RuleBlacklist.detectTransferRestriction.0 +DA:47,43 +BRDA:47,0,0,14 +BRDA:47,0,1,16 +DA:48,14 +DA:49,29 +BRDA:49,1,0,13 +BRDA:49,1,1,16 +DA:50,13 +DA:52,16 DA:59,7 FN:59,RuleBlacklist.detectTransferRestriction.1 FNDA:7,RuleBlacklist.detectTransferRestriction.1 DA:65,7 -DA:71,12 +DA:71,16 FN:71,RuleBlacklist.detectTransferRestrictionFrom.0 -FNDA:12,RuleBlacklist.detectTransferRestrictionFrom.0 -DA:77,16 -BRDA:77,2,0,4 -BRDA:77,2,1,12 -DA:78,4 -DA:80,12 +FNDA:16,RuleBlacklist.detectTransferRestrictionFrom.0 +DA:77,20 +BRDA:77,2,0,6 +BRDA:77,2,1,14 +DA:78,6 +DA:80,14 DA:87,4 FN:87,RuleBlacklist.detectTransferRestrictionFrom.1 FNDA:4,RuleBlacklist.detectTransferRestrictionFrom.1 @@ -77,30 +77,34 @@ DA:138,0 FN:138,RuleBlacklist.supportsInterface FNDA:0,RuleBlacklist.supportsInterface DA:139,0 -DA:144,6 +DA:144,9 FN:144,RuleBlacklist.transferred.0 -FNDA:6,RuleBlacklist.transferred.0 -DA:150,6 -DA:151,6 -BRDA:151,6,0,4 -BRDA:151,6,1,2 -DA:157,0 +FNDA:9,RuleBlacklist.transferred.0 +DA:150,12 +DA:151,12 +BRDA:151,6,0,8 +BRDA:151,6,1,4 +DA:157,2 FN:157,RuleBlacklist.transferred.1 -FNDA:0,RuleBlacklist.transferred.1 -DA:163,0 -DA:164,0 -BRDA:164,7,0,- -BRDA:164,7,1,- -DA:170,0 +FNDA:2,RuleBlacklist.transferred.1 +DA:163,4 +DA:164,4 +BRDA:164,7,0,2 +BRDA:164,7,1,2 +DA:170,2 FN:170,RuleBlacklist.transferred.2 -FNDA:0,RuleBlacklist.transferred.2 -DA:176,0 -FNF:10 -FNH:7 -LF:35 -LH:28 +FNDA:2,RuleBlacklist.transferred.2 +DA:176,2 +DA:179,3 +FN:179,RuleBlacklist.transferred.3 +FNDA:3,RuleBlacklist.transferred.3 +DA:185,3 +FNF:11 +FNH:10 +LF:37 +LH:35 BRF:16 -BRH:14 +BRH:16 end_of_record TN: SF:src/rules/validation/RuleSanctionsList.sol @@ -110,33 +114,33 @@ FNDA:17,RuleSanctionsList.constructor DA:59,16 BRDA:59,0,0,1 DA:60,1 -DA:73,10 +DA:73,17 FN:73,RuleSanctionsList.detectTransferRestriction.0 -FNDA:10,RuleSanctionsList.detectTransferRestriction.0 -DA:79,27 -BRDA:79,1,0,22 -DA:80,22 -BRDA:80,2,0,4 -BRDA:80,2,1,10 -DA:81,4 -DA:82,18 -BRDA:82,3,0,8 -DA:83,8 -DA:86,15 +FNDA:17,RuleSanctionsList.detectTransferRestriction.0 +DA:79,35 +BRDA:79,1,0,30 +DA:80,30 +BRDA:80,2,0,6 +BRDA:80,2,1,14 +DA:81,6 +DA:82,24 +BRDA:82,3,0,10 +DA:83,10 +DA:86,19 DA:92,9 FN:92,RuleSanctionsList.detectTransferRestriction.1 FNDA:9,RuleSanctionsList.detectTransferRestriction.1 DA:99,9 -DA:105,8 +DA:105,11 FN:105,RuleSanctionsList.detectTransferRestrictionFrom.0 -FNDA:8,RuleSanctionsList.detectTransferRestrictionFrom.0 -DA:112,11 -BRDA:112,4,0,10 -DA:113,10 -BRDA:113,5,0,2 -BRDA:113,5,1,8 -DA:114,2 -DA:116,8 +FNDA:11,RuleSanctionsList.detectTransferRestrictionFrom.0 +DA:112,14 +BRDA:112,4,0,13 +DA:113,13 +BRDA:113,5,0,4 +BRDA:113,5,1,9 +DA:114,4 +DA:116,9 DA:119,1 DA:122,3 FN:122,RuleSanctionsList.detectTransferRestrictionFrom.1 @@ -171,47 +175,51 @@ DA:177,14 FN:177,RuleSanctionsList.setSanctionListOracle FNDA:14,RuleSanctionsList.setSanctionListOracle DA:178,13 -DA:184,0 +DA:184,3 FN:184,RuleSanctionsList.transferred.0 -FNDA:0,RuleSanctionsList.transferred.0 -DA:190,0 -DA:191,0 -BRDA:191,9,0,- -BRDA:191,9,1,- -DA:200,0 -FN:200,RuleSanctionsList.transferred.1 -FNDA:0,RuleSanctionsList.transferred.1 -DA:206,0 -DA:207,0 -BRDA:207,10,0,- -BRDA:207,10,1,- -DA:216,0 -FN:216,RuleSanctionsList.transferred.2 -FNDA:0,RuleSanctionsList.transferred.2 -DA:222,0 -DA:229,14 -FN:229,RuleSanctionsList._setSanctionListOracle +FNDA:3,RuleSanctionsList.transferred.0 +DA:190,7 +DA:191,7 +BRDA:191,9,0,4 +BRDA:191,9,1,3 +DA:201,2 +FN:201,RuleSanctionsList.transferred.1 +FNDA:2,RuleSanctionsList.transferred.1 +DA:207,3 +DA:208,3 +BRDA:208,10,0,2 +BRDA:208,10,1,1 +DA:214,1 +FN:214,RuleSanctionsList.transferred.2 +FNDA:1,RuleSanctionsList.transferred.2 +DA:220,1 +DA:223,4 +FN:223,RuleSanctionsList.transferred.3 +FNDA:4,RuleSanctionsList.transferred.3 +DA:229,4 +DA:235,14 +FN:235,RuleSanctionsList._setSanctionListOracle FNDA:14,RuleSanctionsList._setSanctionListOracle -DA:230,14 -DA:231,14 -DA:241,30 -FN:241,RuleSanctionsList._msgSender +DA:236,14 +DA:237,14 +DA:247,30 +FN:247,RuleSanctionsList._msgSender FNDA:30,RuleSanctionsList._msgSender -DA:242,30 -DA:248,0 -FN:248,RuleSanctionsList._msgData +DA:248,30 +DA:254,0 +FN:254,RuleSanctionsList._msgData FNDA:0,RuleSanctionsList._msgData -DA:249,0 -DA:255,30 -FN:255,RuleSanctionsList._contextSuffixLength +DA:255,0 +DA:261,30 +FN:261,RuleSanctionsList._contextSuffixLength FNDA:30,RuleSanctionsList._contextSuffixLength -DA:256,30 -FNF:16 -FNH:11 -LF:52 -LH:40 +DA:262,30 +FNF:17 +FNH:15 +LF:54 +LH:50 BRF:18 -BRH:14 +BRH:18 end_of_record TN: SF:src/rules/validation/RuleWhitelist.sol @@ -219,29 +227,29 @@ DA:33,102 FN:33,RuleWhitelist.constructor FNDA:102,RuleWhitelist.constructor DA:36,101 -DA:56,16 +DA:56,20 FN:56,RuleWhitelist.detectTransferRestriction.0 -FNDA:16,RuleWhitelist.detectTransferRestriction.0 -DA:63,27 -BRDA:63,0,0,9 -BRDA:63,0,1,14 -DA:64,9 -DA:65,18 -BRDA:65,1,0,4 -BRDA:65,1,1,14 -DA:66,4 -DA:68,14 +FNDA:20,RuleWhitelist.detectTransferRestriction.0 +DA:63,33 +BRDA:63,0,0,11 +BRDA:63,0,1,16 +DA:64,11 +DA:65,22 +BRDA:65,1,0,6 +BRDA:65,1,1,16 +DA:66,6 +DA:68,16 DA:75,7 FN:75,RuleWhitelist.detectTransferRestriction.1 FNDA:7,RuleWhitelist.detectTransferRestriction.1 DA:82,7 -DA:102,6 +DA:102,10 FN:102,RuleWhitelist.detectTransferRestrictionFrom.0 -FNDA:6,RuleWhitelist.detectTransferRestrictionFrom.0 -DA:109,8 -BRDA:109,2,0,4 -DA:110,4 -DA:112,4 +FNDA:10,RuleWhitelist.detectTransferRestrictionFrom.0 +DA:109,12 +BRDA:109,2,0,6 +DA:110,6 +DA:112,6 DA:118,2 FN:118,RuleWhitelist.detectTransferRestrictionFrom.1 FNDA:2,RuleWhitelist.detectTransferRestrictionFrom.1 @@ -263,99 +271,99 @@ BRH:5 end_of_record TN: SF:src/rules/validation/RuleWhitelistWrapper.sol -DA:40,22 -FN:40,RuleWhitelistWrapper.constructor +DA:38,22 +FN:38,RuleWhitelistWrapper.constructor FNDA:22,RuleWhitelistWrapper.constructor -DA:44,20 -DA:55,15 -FN:55,RuleWhitelistWrapper.detectTransferRestriction.0 -FNDA:15,RuleWhitelistWrapper.detectTransferRestriction.0 -DA:62,19 -DA:63,19 -DA:64,19 -DA:66,19 -DA:67,19 -BRDA:67,0,0,7 -BRDA:67,0,1,8 -DA:68,7 -DA:69,12 -BRDA:69,1,0,4 -BRDA:69,1,1,8 -DA:70,4 -DA:72,8 -DA:76,4 -FN:76,RuleWhitelistWrapper.detectTransferRestriction.1 +DA:42,20 +DA:53,21 +FN:53,RuleWhitelistWrapper.detectTransferRestriction.0 +FNDA:21,RuleWhitelistWrapper.detectTransferRestriction.0 +DA:60,25 +DA:61,25 +DA:62,25 +DA:64,25 +DA:65,25 +BRDA:65,0,0,9 +BRDA:65,0,1,10 +DA:66,9 +DA:67,16 +BRDA:67,1,0,6 +BRDA:67,1,1,10 +DA:68,6 +DA:70,10 +DA:74,4 +FN:74,RuleWhitelistWrapper.detectTransferRestriction.1 FNDA:4,RuleWhitelistWrapper.detectTransferRestriction.1 -DA:83,4 -DA:86,6 -FN:86,RuleWhitelistWrapper.detectTransferRestrictionFrom.0 -FNDA:6,RuleWhitelistWrapper.detectTransferRestrictionFrom.0 -DA:93,8 -BRDA:93,2,0,- -DA:94,0 -DA:97,8 -DA:98,8 -DA:99,8 -DA:100,8 -DA:102,8 -DA:104,8 -BRDA:104,3,0,- -BRDA:104,3,1,4 +DA:81,4 +DA:84,10 +FN:84,RuleWhitelistWrapper.detectTransferRestrictionFrom.0 +FNDA:10,RuleWhitelistWrapper.detectTransferRestrictionFrom.0 +DA:91,12 +BRDA:91,2,0,- +DA:92,0 +DA:95,12 +DA:96,12 +DA:97,12 +DA:98,12 +DA:100,12 +DA:102,12 +BRDA:102,3,0,- +BRDA:102,3,1,6 +DA:103,0 +DA:104,12 +BRDA:104,4,0,- +BRDA:104,4,1,6 DA:105,0 -DA:106,8 -BRDA:106,4,0,- -BRDA:106,4,1,4 -DA:107,0 -DA:108,8 -BRDA:108,5,0,4 -BRDA:108,5,1,4 -DA:109,4 -DA:111,4 -DA:118,2 -FN:118,RuleWhitelistWrapper.detectTransferRestrictionFrom.1 +DA:106,12 +BRDA:106,5,0,6 +BRDA:106,5,1,6 +DA:107,6 +DA:109,6 +DA:116,2 +FN:116,RuleWhitelistWrapper.detectTransferRestrictionFrom.1 FNDA:2,RuleWhitelistWrapper.detectTransferRestrictionFrom.1 -DA:125,2 -DA:133,20 -FN:133,RuleWhitelistWrapper.hasRole +DA:123,2 +DA:131,20 +FN:131,RuleWhitelistWrapper.hasRole FNDA:20,RuleWhitelistWrapper.hasRole -DA:140,80 -DA:147,27 -FN:147,RuleWhitelistWrapper._detectTransferRestriction -FNDA:27,RuleWhitelistWrapper._detectTransferRestriction -DA:148,27 -DA:149,27 -DA:150,27 -DA:152,59 -DA:153,59 -DA:154,42 -BRDA:154,6,0,42 -DA:155,42 -DA:160,59 -DA:161,59 -DA:162,113 -BRDA:162,7,0,47 -DA:163,47 -DA:164,47 -DA:167,12 -BRDA:167,8,0,12 -DA:168,12 -DA:171,27 -DA:174,0 -FN:174,RuleWhitelistWrapper.supportsInterface +DA:138,80 +DA:145,37 +FN:145,RuleWhitelistWrapper._detectTransferRestriction +FNDA:37,RuleWhitelistWrapper._detectTransferRestriction +DA:146,37 +DA:147,37 +DA:148,37 +DA:150,81 +DA:151,81 +DA:152,58 +BRDA:152,6,0,58 +DA:153,58 +DA:158,81 +DA:159,81 +DA:160,159 +BRDA:160,7,0,65 +DA:161,65 +DA:162,65 +DA:165,16 +BRDA:165,8,0,16 +DA:166,16 +DA:169,37 +DA:172,0 +FN:172,RuleWhitelistWrapper.supportsInterface FNDA:0,RuleWhitelistWrapper.supportsInterface -DA:175,0 -DA:185,80 -FN:185,RuleWhitelistWrapper._msgSender +DA:173,0 +DA:183,80 +FN:183,RuleWhitelistWrapper._msgSender FNDA:80,RuleWhitelistWrapper._msgSender -DA:186,80 -DA:192,0 -FN:192,RuleWhitelistWrapper._msgData +DA:184,80 +DA:190,0 +FN:190,RuleWhitelistWrapper._msgData FNDA:0,RuleWhitelistWrapper._msgData -DA:193,0 -DA:199,80 -FN:199,RuleWhitelistWrapper._contextSuffixLength +DA:191,0 +DA:197,80 +FN:197,RuleWhitelistWrapper._contextSuffixLength FNDA:80,RuleWhitelistWrapper._contextSuffixLength -DA:200,80 +DA:198,80 FNF:11 FNH:9 LF:57 @@ -402,13 +410,13 @@ DA:124,0 DA:132,60 FN:132,RuleAddressSet.isAddressListed FNDA:60,RuleAddressSet.isAddressListed -DA:133,187 -DA:141,62 +DA:133,219 +DA:141,84 FN:141,RuleAddressSet.areAddressesListed -FNDA:62,RuleAddressSet.areAddressesListed -DA:142,62 -DA:143,62 -DA:144,139 +FNDA:84,RuleAddressSet.areAddressesListed +DA:142,84 +DA:143,84 +DA:144,191 DA:152,207 FN:152,RuleAddressSet._msgSender FNDA:207,RuleAddressSet._msgSender @@ -452,10 +460,10 @@ DA:75,24 FN:75,RuleAddressSetInternal._listedAddressCount FNDA:24,RuleAddressSetInternal._listedAddressCount DA:76,24 -DA:84,379 +DA:84,463 FN:84,RuleAddressSetInternal._isAddressListed -FNDA:379,RuleAddressSetInternal._isAddressListed -DA:85,379 +FNDA:463,RuleAddressSetInternal._isAddressListed +DA:85,463 FNF:6 FNH:6 LF:14 @@ -465,26 +473,26 @@ BRH:0 end_of_record TN: SF:src/rules/validation/abstract/RuleValidateTransfer.sol -DA:27,14 -FN:27,RuleValidateTransfer.canTransfer.0 +DA:26,14 +FN:26,RuleValidateTransfer.canTransfer.0 FNDA:14,RuleValidateTransfer.canTransfer.0 -DA:34,14 -DA:46,14 -FN:46,RuleValidateTransfer.canTransfer.1 +DA:33,14 +DA:45,14 +FN:45,RuleValidateTransfer.canTransfer.1 FNDA:14,RuleValidateTransfer.canTransfer.1 -DA:53,14 -DA:59,10 -FN:59,RuleValidateTransfer.canTransferFrom.0 +DA:52,14 +DA:58,10 +FN:58,RuleValidateTransfer.canTransferFrom.0 FNDA:10,RuleValidateTransfer.canTransferFrom.0 -DA:66,20 -DA:73,10 -FN:73,RuleValidateTransfer.canTransferFrom.1 +DA:65,20 +DA:72,10 +FN:72,RuleValidateTransfer.canTransferFrom.1 FNDA:10,RuleValidateTransfer.canTransferFrom.1 -DA:80,10 -DA:84,0 -FN:84,RuleValidateTransfer.supportsInterface +DA:79,10 +DA:82,0 +FN:82,RuleValidateTransfer.supportsInterface FNDA:0,RuleValidateTransfer.supportsInterface -DA:85,0 +DA:83,0 FNF:5 FNH:4 LF:10 @@ -515,28 +523,32 @@ BRDA:60,2,0,2 BRDA:60,2,1,2 DA:61,2 DA:63,2 -DA:79,12 +DA:79,17 FN:79,RuleWhitelistCommon.transferred.0 -FNDA:12,RuleWhitelistCommon.transferred.0 -DA:80,12 -DA:81,12 -BRDA:81,3,0,6 -BRDA:81,3,1,6 -DA:97,0 +FNDA:17,RuleWhitelistCommon.transferred.0 +DA:80,22 +DA:81,22 +BRDA:81,3,0,14 +BRDA:81,3,1,8 +DA:97,4 FN:97,RuleWhitelistCommon.transferred.1 -FNDA:0,RuleWhitelistCommon.transferred.1 -DA:98,0 -DA:99,0 -BRDA:99,4,0,- -BRDA:99,4,1,- -DA:108,0 -FN:108,RuleWhitelistCommon.transferred.2 -FNDA:0,RuleWhitelistCommon.transferred.2 -DA:113,0 -FNF:5 -FNH:3 -LF:19 -LH:14 +FNDA:4,RuleWhitelistCommon.transferred.1 +DA:98,8 +DA:99,8 +BRDA:99,4,0,4 +BRDA:99,4,1,4 +DA:106,4 +FN:106,RuleWhitelistCommon.transferred.2 +FNDA:4,RuleWhitelistCommon.transferred.2 +DA:112,4 +DA:115,5 +FN:115,RuleWhitelistCommon.transferred.3 +FNDA:5,RuleWhitelistCommon.transferred.3 +DA:121,5 +FNF:6 +FNH:6 +LF:21 +LH:21 BRF:10 -BRH:8 +BRH:10 end_of_record diff --git a/doc/security/audits/tools/aderyn-report.md b/doc/security/audits/tools/aderyn-report.md new file mode 100644 index 0000000..c215e0d --- /dev/null +++ b/doc/security/audits/tools/aderyn-report.md @@ -0,0 +1,454 @@ +# Aderyn Analysis Report + +This report was generated by [Aderyn](https://github.com/Cyfrin/aderyn), a static analysis tool built by [Cyfrin](https://cyfrin.io), a blockchain security company. This report is not a substitute for manual audit or security review. It should not be relied upon for any purpose other than to assist in the identification of potential security vulnerabilities. +# Table of Contents + +- [Summary](#summary) + - [Files Summary](#files-summary) + - [Files Details](#files-details) + - [Issue Summary](#issue-summary) +- [Low Issues](#low-issues) + - [L-1: Centralization Risk](#l-1-centralization-risk) + - [L-2: Unspecific Solidity Pragma](#l-2-unspecific-solidity-pragma) + - [L-3: Address State Variable Set Without Checks](#l-3-address-state-variable-set-without-checks) + - [L-4: PUSH0 Opcode](#l-4-push0-opcode) + - [L-5: Costly operations inside loop](#l-5-costly-operations-inside-loop) + - [L-6: Unchecked Return](#l-6-unchecked-return) + + +# Summary + +## Files Summary + +| Key | Value | +| --- | --- | +| .sol Files | 19 | +| Total nSLOC | 839 | + + +## Files Details + +| Filepath | nSLOC | +| --- | --- | +| src/modules/AccessControlModuleStandalone.sol | 18 | +| src/modules/MetaTxModuleStandalone.sol | 6 | +| src/rules/interfaces/IAddressList.sol | 15 | +| src/rules/interfaces/IERC7943NonFungibleCompliance.sol | 22 | +| src/rules/interfaces/IIdentityRegistry.sol | 7 | +| src/rules/interfaces/ISanctionsList.sol | 4 | +| src/rules/validation/RuleBlacklist.sol | 127 | +| src/rules/validation/RuleSanctionsList.sol | 157 | +| src/rules/validation/RuleWhitelist.sol | 84 | +| src/rules/validation/RuleWhitelistWrapper.sol | 141 | +| src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol | 67 | +| src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol | 28 | +| src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol | 7 | +| src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol | 12 | +| src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol | 13 | +| src/rules/validation/abstract/RuleCommonInvariantStorage.sol | 4 | +| src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol | 15 | +| src/rules/validation/abstract/RuleValidateTransfer.sol | 50 | +| src/rules/validation/abstract/RuleWhitelistCommon.sol | 62 | +| **Total** | **839** | + + +## Issue Summary + +| Category | No. of Issues | +| --- | --- | +| High | 0 | +| Low | 6 | + + +# Low Issues + +## L-1: Centralization Risk + +Contracts have owners with privileged rights to perform admin tasks and need to be trusted to not perform malicious updates or drain funds. + +
8 Found Instances + + +- Found in src/modules/AccessControlModuleStandalone.sol [Line: 8](src/modules/AccessControlModuleStandalone.sol#L8) + + ```solidity + abstract contract AccessControlModuleStandalone is AccessControl { + ``` + +- Found in src/rules/validation/RuleSanctionsList.sol [Line: 177](src/rules/validation/RuleSanctionsList.sol#L177) + + ```solidity + function setSanctionListOracle(ISanctionsList sanctionContractOracle_) public virtual onlyRole(SANCTIONLIST_ROLE) { + ``` + +- Found in src/rules/validation/RuleWhitelist.sol [Line: 157](src/rules/validation/RuleWhitelist.sol#L157) + + ```solidity + onlyRole(DEFAULT_ADMIN_ROLE) // or a dedicated role if you prefer + ``` + +- Found in src/rules/validation/RuleWhitelistWrapper.sol [Line: 155](src/rules/validation/RuleWhitelistWrapper.sol#L155) + + ```solidity + onlyRole(DEFAULT_ADMIN_ROLE) // or a dedicated role if you prefer + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol [Line: 63](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L63) + + ```solidity + function addAddresses(address[] calldata targetAddresses) public onlyRole(ADDRESS_LIST_ADD_ROLE) { + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol [Line: 75](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L75) + + ```solidity + function removeAddresses(address[] calldata targetAddresses) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) { + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol [Line: 87](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L87) + + ```solidity + function addAddress(address targetAddress) public onlyRole(ADDRESS_LIST_ADD_ROLE) { + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol [Line: 102](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L102) + + ```solidity + function removeAddress(address targetAddress) public onlyRole(ADDRESS_LIST_REMOVE_ROLE) { + ``` + +
+ + + +## L-2: Unspecific Solidity Pragma + +Consider using a specific version of Solidity in your contracts instead of a wide version. For example, instead of `pragma solidity ^0.8.0;`, use `pragma solidity 0.8.0;` + +
19 Found Instances + + +- Found in src/modules/AccessControlModuleStandalone.sol [Line: 3](src/modules/AccessControlModuleStandalone.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/MetaTxModuleStandalone.sol [Line: 3](src/modules/MetaTxModuleStandalone.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/interfaces/IAddressList.sol [Line: 2](src/rules/interfaces/IAddressList.sol#L2) + + ```solidity + pragma solidity ^0.8.0; + ``` + +- Found in src/rules/interfaces/IERC7943NonFungibleCompliance.sol [Line: 3](src/rules/interfaces/IERC7943NonFungibleCompliance.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/interfaces/IIdentityRegistry.sol [Line: 3](src/rules/interfaces/IIdentityRegistry.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/interfaces/ISanctionsList.sol [Line: 3](src/rules/interfaces/ISanctionsList.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/RuleBlacklist.sol [Line: 3](src/rules/validation/RuleBlacklist.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/RuleSanctionsList.sol [Line: 3](src/rules/validation/RuleSanctionsList.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/RuleWhitelist.sol [Line: 2](src/rules/validation/RuleWhitelist.sol#L2) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/RuleWhitelistWrapper.sol [Line: 3](src/rules/validation/RuleWhitelistWrapper.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol [Line: 2](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L2) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 2](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L2) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleCommonInvariantStorage.sol [Line: 2](src/rules/validation/abstract/RuleCommonInvariantStorage.sol#L2) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleValidateTransfer.sol [Line: 3](src/rules/validation/abstract/RuleValidateTransfer.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleWhitelistCommon.sol [Line: 2](src/rules/validation/abstract/RuleWhitelistCommon.sol#L2) + + ```solidity + pragma solidity ^0.8.20; + ``` + +
+ + + +## L-3: Address State Variable Set Without Checks + +Check for `address(0)` when assigning values to address state variables. + +
1 Found Instances + + +- Found in src/rules/validation/RuleSanctionsList.sol [Line: 236](src/rules/validation/RuleSanctionsList.sol#L236) + + ```solidity + sanctionsList = sanctionContractOracle_; + ``` + +
+ + + +## L-4: PUSH0 Opcode + +Solc compiler version 0.8.20 switches the default target EVM version to Shanghai, which means that the generated bytecode will include PUSH0 opcodes. Be sure to select the appropriate EVM version in case you intend to deploy on a chain other than mainnet like L2 chains that may not support PUSH0, otherwise deployment of your contracts will fail. + +
19 Found Instances + + +- Found in src/modules/AccessControlModuleStandalone.sol [Line: 3](src/modules/AccessControlModuleStandalone.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/MetaTxModuleStandalone.sol [Line: 3](src/modules/MetaTxModuleStandalone.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/interfaces/IAddressList.sol [Line: 2](src/rules/interfaces/IAddressList.sol#L2) + + ```solidity + pragma solidity ^0.8.0; + ``` + +- Found in src/rules/interfaces/IERC7943NonFungibleCompliance.sol [Line: 3](src/rules/interfaces/IERC7943NonFungibleCompliance.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/interfaces/IIdentityRegistry.sol [Line: 3](src/rules/interfaces/IIdentityRegistry.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/interfaces/ISanctionsList.sol [Line: 3](src/rules/interfaces/ISanctionsList.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/RuleBlacklist.sol [Line: 3](src/rules/validation/RuleBlacklist.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/RuleSanctionsList.sol [Line: 3](src/rules/validation/RuleSanctionsList.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/RuleWhitelist.sol [Line: 2](src/rules/validation/RuleWhitelist.sol#L2) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/RuleWhitelistWrapper.sol [Line: 3](src/rules/validation/RuleWhitelistWrapper.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol [Line: 2](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L2) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 2](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L2) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleAddressSetInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleCommonInvariantStorage.sol [Line: 2](src/rules/validation/abstract/RuleCommonInvariantStorage.sol#L2) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol [Line: 3](src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleValidateTransfer.sol [Line: 3](src/rules/validation/abstract/RuleValidateTransfer.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/rules/validation/abstract/RuleWhitelistCommon.sol [Line: 2](src/rules/validation/abstract/RuleWhitelistCommon.sol#L2) + + ```solidity + pragma solidity ^0.8.20; + ``` + +
+ + + +## L-5: Costly operations inside loop + +Invoking `SSTORE` operations in loops may waste gas. Use a local variable to hold the loop computation result. + +
2 Found Instances + + +- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 37](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L37) + + ```solidity + for (uint256 i = 0; i < addressesToAdd.length; ++i) { + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 50](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L50) + + ```solidity + for (uint256 i = 0; i < addressesToRemove.length; ++i) { + ``` + +
+ + + +## L-6: Unchecked Return + +Function returns a value but it is ignored. Consider checking the return value. + +
5 Found Instances + + +- Found in src/modules/AccessControlModuleStandalone.sol [Line: 29](src/modules/AccessControlModuleStandalone.sol#L29) + + ```solidity + _grantRole(DEFAULT_ADMIN_ROLE, admin); + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 38](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L38) + + ```solidity + _listedAddresses.add(addressesToAdd[i]); + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 51](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L51) + + ```solidity + _listedAddresses.remove(addressesToRemove[i]); + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 60](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L60) + + ```solidity + _listedAddresses.add(targetAddress); + ``` + +- Found in src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol [Line: 68](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L68) + + ```solidity + _listedAddresses.remove(targetAddress); + ``` + +
+ + + diff --git a/doc/security/audits/tools/slither-report.md b/doc/security/audits/tools/slither-report.md index fb021eb..19aabf7 100644 --- a/doc/security/audits/tools/slither-report.md +++ b/doc/security/audits/tools/slither-report.md @@ -1,643 +1,157 @@ **THIS CHECKLIST IS NOT COMPLETE**. Use `--show-ignored-findings` to show all the results. Summary - - [incorrect-equality](#incorrect-equality) (4 results) (Medium) - - [calls-loop](#calls-loop) (8 results) (Low) - - [timestamp](#timestamp) (5 results) (Low) - - [costly-loop](#costly-loop) (2 results) (Informational) - - [dead-code](#dead-code) (5 results) (Informational) + - [unused-return](#unused-return) (4 results) (Medium) + - [dead-code](#dead-code) (3 results) (Informational) - [solc-version](#solc-version) (1 results) (Informational) - - [naming-convention](#naming-convention) (50 results) (Informational) - - [similar-names](#similar-names) (7 results) (Informational) - - [unused-import](#unused-import) (1 results) (Informational) - - [var-read-using-this](#var-read-using-this) (1 results) (Optimization) -## incorrect-equality - -> Strict equality is required to check the request status - + - [naming-convention](#naming-convention) (2 results) (Informational) + - [constable-states](#constable-states) (1 results) (Optimization) + - [var-read-using-this](#var-read-using-this) (9 results) (Optimization) +## unused-return Impact: Medium -Confidence: High +Confidence: Medium - [ ] ID-0 - [RuleConditionalTransfer.getRequestByStatus(RuleConditionalTransferInvariantStorage.STATUS)](src/rules/operation/RuleConditionalTransfer.sol#L177-L206) uses a dangerous strict equality: - - [transferRequests[IdToKey[i_scope_0]].status == _targetStatus](src/rules/operation/RuleConditionalTransfer.sol#L196) +[RuleAddressSetInternal._addAddresses(address[])](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L36-L40) ignores return value by [_listedAddresses.add(addressesToAdd[i])](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L38) -src/rules/operation/RuleConditionalTransfer.sol#L177-L206 +src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L36-L40 - [ ] ID-1 - [RuleConditionalTransfer._validateApproval(bytes32)](src/rules/operation/RuleConditionalTransfer.sol#L329-L349) uses a dangerous strict equality: - - [isTransferApproved = (transferRequests[key].status == STATUS.APPROVED) && (transferRequests[key].maxTime >= block.timestamp)](src/rules/operation/RuleConditionalTransfer.sol#L341-L343) +[RuleAddressSetInternal._addAddress(address)](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L59-L61) ignores return value by [_listedAddresses.add(targetAddress)](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L60) -src/rules/operation/RuleConditionalTransfer.sol#L329-L349 +src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L59-L61 - [ ] ID-2 - [RuleConditionalTransferOperator._checkRequestStatus(bytes32)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L383-L388) uses a dangerous strict equality: - - [(transferRequests[key].status == STATUS.NONE) && (transferRequests[key].key == 0x0)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L385-L387) +[RuleAddressSetInternal._removeAddresses(address[])](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L49-L53) ignores return value by [_listedAddresses.remove(addressesToRemove[i])](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L51) -src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L383-L388 +src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L49-L53 - [ ] ID-3 - [RuleConditionalTransfer.getRequestByStatus(RuleConditionalTransferInvariantStorage.STATUS)](src/rules/operation/RuleConditionalTransfer.sol#L177-L206) uses a dangerous strict equality: - - [transferRequests[IdToKey[i]].status == _targetStatus](src/rules/operation/RuleConditionalTransfer.sol#L186) +[RuleAddressSetInternal._removeAddress(address)](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L67-L69) ignores return value by [_listedAddresses.remove(targetAddress)](src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L68) -src/rules/operation/RuleConditionalTransfer.sol#L177-L206 +src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol#L67-L69 -## calls-loop -> Acknowledge - -Impact: Low +## dead-code +Impact: Informational Confidence: Medium - [ ] ID-4 -[RuleWhitelistWrapper.detectTransferRestriction(address,address,uint256)](src/rules/validation/RuleWhitelistWrapper.sol#L39-L74) has external calls inside a loop: [isListed = RuleAddressList(_rulesValidation[i]).addressIsListedBatch(targetAddress)](src/rules/validation/RuleWhitelistWrapper.sol#L53-L54) +[RuleAddressSet._msgData()](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L157-L159) is never used and should be removed -src/rules/validation/RuleWhitelistWrapper.sol#L39-L74 +src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L157-L159 - [ ] ID-5 -[RuleEngineValidation.detectTransferRestrictionValidation(address,address,uint256)](src/modules/RuleEngineValidation.sol#L29-L44) has external calls inside a loop: [restriction = IRuleValidation(_rulesValidation[i]).detectTransferRestriction(_from,_to,_amount)](src/modules/RuleEngineValidation.sol#L36-L37) +[RuleSanctionsList._msgData()](src/rules/validation/RuleSanctionsList.sol#L254-L256) is never used and should be removed -src/modules/RuleEngineValidation.sol#L29-L44 +src/rules/validation/RuleSanctionsList.sol#L254-L256 - [ ] ID-6 -[RuleEngine.messageForTransferRestriction(uint8)](src/RuleEngine.sol#L100-L128) has external calls inside a loop: [IRuleValidation(_rulesOperation[i_scope_0]).messageForTransferRestriction(_restrictionCode)](src/RuleEngine.sol#L122-L124) +[RuleWhitelistWrapper._msgData()](src/rules/validation/RuleWhitelistWrapper.sol#L215-L217) is never used and should be removed -src/RuleEngine.sol#L100-L128 +src/rules/validation/RuleWhitelistWrapper.sol#L215-L217 +## solc-version +Impact: Informational +Confidence: High - [ ] ID-7 -[RuleEngine.messageForTransferRestriction(uint8)](src/RuleEngine.sol#L100-L128) has external calls inside a loop: [IRuleValidation(_rulesValidation[i]).canReturnTransferRestrictionCode(_restrictionCode)](src/RuleEngine.sol#L107-L108) +Version constraint ^0.8.0 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html) + - FullInlinerNonExpressionSplitArgumentEvaluationOrder + - MissingSideEffectsOnSelectorAccess + - AbiReencodingHeadOverflowWithStaticArrayCleanup + - DirtyBytesArrayToStorage + - DataLocationChangeInInternalOverride + - NestedCalldataArrayAbiReencodingSizeValidation + - SignedImmutables + - ABIDecodeTwoDimensionalArrayMemory + - KeccakCaching. +It is used by: + - [^0.8.0](src/rules/interfaces/IAddressList.sol#L2) -src/RuleEngine.sol#L100-L128 +src/rules/interfaces/IAddressList.sol#L2 +## naming-convention +Impact: Informational +Confidence: High - [ ] ID-8 -[RuleEngine.messageForTransferRestriction(uint8)](src/RuleEngine.sol#L100-L128) has external calls inside a loop: [IRuleValidation(_rulesValidation[i]).messageForTransferRestriction(_restrictionCode)](src/RuleEngine.sol#L110-L112) +Parameter [RuleBlacklist.canReturnTransferRestrictionCode(uint8)._restrictionCode](src/rules/validation/RuleBlacklist.sol#L103) is not in mixedCase -src/RuleEngine.sol#L100-L128 +src/rules/validation/RuleBlacklist.sol#L103 - [ ] ID-9 -[RuleConditionalTransferOperator._approveRequest(RuleConditionalTransferInvariantStorage.TransferRequest,bool)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L390-L449) has external calls inside a loop: [options.automaticTransfer.cmtat.allowance(transferRequest.keyElement.from,address(this)) >= transferRequest.keyElement.value](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L426-L429) +Parameter [RuleBlacklist.messageForTransferRestriction(uint8)._restrictionCode](src/rules/validation/RuleBlacklist.sol#L120) is not in mixedCase -src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L390-L449 +src/rules/validation/RuleBlacklist.sol#L120 +## constable-states +Impact: Optimization +Confidence: High - [ ] ID-10 -[RuleEngine.messageForTransferRestriction(uint8)](src/RuleEngine.sol#L100-L128) has external calls inside a loop: [IRuleValidation(_rulesOperation[i_scope_0]).canReturnTransferRestrictionCode(_restrictionCode)](src/RuleEngine.sol#L119-L120) +[RuleAddressSet._listedAddressCountCache](src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L33) should be constant -src/RuleEngine.sol#L100-L128 +src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol#L33 +## var-read-using-this +Impact: Optimization +Confidence: High - [ ] ID-11 -[RuleEngine.detectTransferRestriction(address,address,uint256)](src/RuleEngine.sol#L50-L76) has external calls inside a loop: [restriction = IRuleValidation(_rulesOperation[i]).detectTransferRestriction(_from,_to,_amount)](src/RuleEngine.sol#L68-L69) +The function [RuleSanctionsList.transferred(address,address,address,uint256)](src/rules/validation/RuleSanctionsList.sol#L201-L212) reads [code = this.detectTransferRestrictionFrom(spender,from,to,value)](src/rules/validation/RuleSanctionsList.sol#L207) with `this` which adds an extra STATICCALL. -src/RuleEngine.sol#L50-L76 +src/rules/validation/RuleSanctionsList.sol#L201-L212 -## timestamp - -> With the Proof of Work, it was possible for a miner to modify the timestamp in a range of about 15 seconds -> -> With the Proof Of Stake, a new block is created every 12 seconds -> -> In all cases, we are not looking for such precision -> -> btw, ID-13 and ID-15 don't use timestamp in their comparison - -Impact: Low -Confidence: Medium - [ ] ID-12 - [RuleConditionalTransfer._validateApproval(bytes32)](src/rules/operation/RuleConditionalTransfer.sol#L329-L349) uses timestamp for comparisons - Dangerous comparisons: - - [automaticApprovalCondition = options.automaticApproval.isActivate && block.timestamp >= (transferRequests[key].askTime + options.automaticApproval.timeLimitBeforeAutomaticApproval)](src/rules/operation/RuleConditionalTransfer.sol#L334-L339) - - [isTransferApproved = (transferRequests[key].status == STATUS.APPROVED) && (transferRequests[key].maxTime >= block.timestamp)](src/rules/operation/RuleConditionalTransfer.sol#L341-L343) - - [automaticApprovalCondition || isTransferApproved](src/rules/operation/RuleConditionalTransfer.sol#L344) +The function [RuleWhitelistCommon.transferred(address,address,address,uint256)](src/rules/validation/abstract/RuleWhitelistCommon.sol#L97-L103) reads [code = this.detectTransferRestrictionFrom(spender,from,to,value)](src/rules/validation/abstract/RuleWhitelistCommon.sol#L98) with `this` which adds an extra STATICCALL. -src/rules/operation/RuleConditionalTransfer.sol#L329-L349 +src/rules/validation/abstract/RuleWhitelistCommon.sol#L97-L103 - [ ] ID-13 - [RuleConditionalTransferOperator._checkRequestStatus(bytes32)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L383-L388) uses timestamp for comparisons - Dangerous comparisons: - - [(transferRequests[key].status == STATUS.NONE) && (transferRequests[key].key == 0x0)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L385-L387) +The function [RuleBlacklist.transferred(address,address,uint256)](src/rules/validation/RuleBlacklist.sol#L144-L155) reads [code = this.detectTransferRestriction(from,to,value)](src/rules/validation/RuleBlacklist.sol#L150) with `this` which adds an extra STATICCALL. -src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L383-L388 +src/rules/validation/RuleBlacklist.sol#L144-L155 - [ ] ID-14 - [RuleConditionalTransfer.getRequestByStatus(RuleConditionalTransferInvariantStorage.STATUS)](src/rules/operation/RuleConditionalTransfer.sol#L177-L206) uses timestamp for comparisons - Dangerous comparisons: - - [transferRequests[IdToKey[i]].status == _targetStatus](src/rules/operation/RuleConditionalTransfer.sol#L186) - - [transferRequests[IdToKey[i_scope_0]].status == _targetStatus](src/rules/operation/RuleConditionalTransfer.sol#L196) +The function [RuleBlacklist.transferred(address,address,address,uint256)](src/rules/validation/RuleBlacklist.sol#L157-L168) reads [code = this.detectTransferRestrictionFrom(spender,from,to,value)](src/rules/validation/RuleBlacklist.sol#L163) with `this` which adds an extra STATICCALL. -src/rules/operation/RuleConditionalTransfer.sol#L177-L206 +src/rules/validation/RuleBlacklist.sol#L157-L168 - [ ] ID-15 - [RuleConditionalTransfer._cancelTransferRequest(uint256)](src/rules/operation/RuleConditionalTransfer.sol#L281-L298) uses timestamp for comparisons - Dangerous comparisons: - - [transferRequests[key].keyElement.from != _msgSender()](src/rules/operation/RuleConditionalTransfer.sol#L287) +The function [RuleWhitelistCommon.transferred(address,address,uint256)](src/rules/validation/abstract/RuleWhitelistCommon.sol#L79-L85) reads [code = this.detectTransferRestriction(from,to,value)](src/rules/validation/abstract/RuleWhitelistCommon.sol#L80) with `this` which adds an extra STATICCALL. -src/rules/operation/RuleConditionalTransfer.sol#L281-L298 +src/rules/validation/abstract/RuleWhitelistCommon.sol#L79-L85 - [ ] ID-16 - [RuleConditionalTransferOperator._approveRequest(RuleConditionalTransferInvariantStorage.TransferRequest,bool)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L390-L449) uses timestamp for comparisons - Dangerous comparisons: - - [transferRequest.status != STATUS.WAIT](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L395) - - [block.timestamp > (transferRequest.askTime + options.timeLimit.timeLimitToApprove)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L401-L402) - - [options.automaticTransfer.cmtat.allowance(transferRequest.keyElement.from,address(this)) >= transferRequest.keyElement.value](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L426-L429) - -src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L390-L449 +The function [RuleValidateTransfer.canTransfer(address,address,uint256)](src/rules/validation/abstract/RuleValidateTransfer.sol#L45-L53) reads [this.detectTransferRestriction(from,to,amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK)](src/rules/validation/abstract/RuleValidateTransfer.sol#L52) with `this` which adds an extra STATICCALL. -## costly-loop +src/rules/validation/abstract/RuleValidateTransfer.sol#L45-L53 -> Acknowledge -Impact: Informational -Confidence: Medium - [ ] ID-17 - [RuleConditionalTransfer.createTransferRequest(address,uint256)](src/rules/operation/RuleConditionalTransfer.sol#L79-L118) has costly operations inside a loop: - - [++ requestId](src/rules/operation/RuleConditionalTransfer.sol#L105) +The function [RuleValidateTransfer.canTransferFrom(address,address,address,uint256)](src/rules/validation/abstract/RuleValidateTransfer.sol#L58-L67) reads [this.detectTransferRestrictionFrom(spender,from,to,value) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK)](src/rules/validation/abstract/RuleValidateTransfer.sol#L65-L66) with `this` which adds an extra STATICCALL. -src/rules/operation/RuleConditionalTransfer.sol#L79-L118 +src/rules/validation/abstract/RuleValidateTransfer.sol#L58-L67 - [ ] ID-18 - [RuleConditionalTransferOperator._createTransferRequestWithApproval(RuleConditionalTransferInvariantStorage.TransferRequestKeyElement)](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L325-L370) has costly operations inside a loop: - - [++ requestId](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L354) +The function [RuleSanctionsList.transferred(address,address,uint256)](src/rules/validation/RuleSanctionsList.sol#L184-L195) reads [code = this.detectTransferRestriction(from,to,value)](src/rules/validation/RuleSanctionsList.sol#L190) with `this` which adds an extra STATICCALL. -src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L325-L370 - -## dead-code +src/rules/validation/RuleSanctionsList.sol#L184-L195 -> - Implemented to be gasless compatible (see MetaTxModule) -> -> - If we remove this function, we will have the following error: -> -> "Derived contract must override function "_msgData". Two or more base classes define function with same name and parameter types." - -Impact: Informational -Confidence: Medium - [ ] ID-19 -[RuleSanctionList._msgData()](src/rules/validation/RuleSanctionList.sol#L145-L152) is never used and should be removed - -src/rules/validation/RuleSanctionList.sol#L145-L152 - - - - [ ] ID-20 -[RuleAddressList._msgData()](src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol#L156-L163) is never used and should be removed - -src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol#L156-L163 - - - - [ ] ID-21 -[RuleWhitelistWrapper._msgData()](src/rules/validation/RuleWhitelistWrapper.sol#L110-L117) is never used and should be removed - -src/rules/validation/RuleWhitelistWrapper.sol#L110-L117 - - - - [ ] ID-22 -[RuleConditionalTransfer._msgData()](src/rules/operation/RuleConditionalTransfer.sol#L370-L377) is never used and should be removed - -src/rules/operation/RuleConditionalTransfer.sol#L370-L377 - - - - [ ] ID-23 -[RuleEngine._msgData()](src/RuleEngine.sol#L182-L189) is never used and should be removed - -src/RuleEngine.sol#L182-L189 - -## solc-version - -> The version set in the config file is 0.8.27 - -Impact: Informational -Confidence: High - - - [ ] ID-24 - Version constraint ^0.8.20 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html) - - VerbatimInvalidDeduplication - - FullInlinerNonExpressionSplitArgumentEvaluationOrder - - MissingSideEffectsOnSelectorAccess. - It is used by: - - lib/CMTAT/contracts/interfaces/draft-IERC1404/draft-IERC1404.sol#3 - - lib/CMTAT/contracts/interfaces/draft-IERC1404/draft-IERC1404EnumCode.sol#3 - - lib/CMTAT/contracts/interfaces/draft-IERC1404/draft-IERC1404Wrapper.sol#3 - - lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol#3 - - lib/openzeppelin-contracts/contracts/access/AccessControl.sol#4 - - lib/openzeppelin-contracts/contracts/access/IAccessControl.sol#4 - - lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol#4 - - lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol#4 - - lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol#4 - - lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol#4 - - lib/openzeppelin-contracts/contracts/utils/Address.sol#4 - - lib/openzeppelin-contracts/contracts/utils/Context.sol#4 - - lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol#4 - - lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol#4 - - src/RuleEngine.sol#3 - - src/interfaces/IRuleEngineOperation.sol#3 - - src/interfaces/IRuleEngineValidation.sol#3 - - src/interfaces/IRuleOperation.sol#3 - - src/interfaces/IRuleValidation.sol#3 - - src/modules/MetaTxModuleStandalone.sol#3 - - src/modules/RuleEngineInvariantStorage.sol#3 - - src/modules/RuleEngineOperation.sol#3 - - src/modules/RuleEngineValidation.sol#3 - - src/modules/RuleEngineValidationCommon.sol#3 - - src/modules/RuleInternal.sol#3 - - src/rules/operation/RuleConditionalTransfer.sol#3 - - src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#3 - - src/rules/operation/abstract/RuleConditionalTransferOperator.sol#3 - - src/rules/validation/RuleBlacklist.sol#3 - - src/rules/validation/RuleSanctionList.sol#3 - - src/rules/validation/RuleWhitelist.sol#3 - - src/rules/validation/RuleWhitelistWrapper.sol#3 - - src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol#3 - - src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol#3 - - src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol#3 - - src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol#3 - - src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol#3 - - src/rules/validation/abstract/RuleCommonInvariantStorage.sol#2 - - src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol#3 - - src/rules/validation/abstract/RuleValidateTransfer.sol#3 - - src/rules/validation/abstract/RuleWhitelistCommon.sol#3 - -## naming-convention - -> Acknowledge - -Impact: Informational -Confidence: High - - - [ ] ID-25 -Event [RuleConditionalTransferInvariantStorage.transferDenied(bytes32,address,address,uint256,uint256)](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L124-L130) is not in CapWords - -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L124-L130 - - - - [ ] ID-26 -Parameter [RuleConditionalTransfer.operateOnTransfer(address,address,uint256)._amount](src/rules/operation/RuleConditionalTransfer.sol#L54) is not in mixedCase - -src/rules/operation/RuleConditionalTransfer.sol#L54 - - - - [ ] ID-27 -Parameter [RuleWhitelistCommon.canReturnTransferRestrictionCode(uint8)._restrictionCode](src/rules/validation/abstract/RuleWhitelistCommon.sol#L18) is not in mixedCase - -src/rules/validation/abstract/RuleWhitelistCommon.sol#L18 - - - - [ ] ID-28 -Parameter [RuleValidateTransfer.validateTransfer(address,address,uint256)._from](src/rules/validation/abstract/RuleValidateTransfer.sol#L16) is not in mixedCase - -src/rules/validation/abstract/RuleValidateTransfer.sol#L16 - - - - [ ] ID-29 -Parameter [RuleEngine.detectTransferRestriction(address,address,uint256)._amount](src/RuleEngine.sol#L53) is not in mixedCase - -src/RuleEngine.sol#L53 - - - - [ ] ID-30 -Event [RuleConditionalTransferInvariantStorage.transferReset(bytes32,address,address,uint256,uint256)](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L131-L137) is not in CapWords - -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L131-L137 - - - - [ ] ID-31 -Parameter [RuleEngineValidation.detectTransferRestrictionValidation(address,address,uint256)._amount](src/modules/RuleEngineValidation.sol#L32) is not in mixedCase - -src/modules/RuleEngineValidation.sol#L32 - - - - [ ] ID-32 -Parameter [RuleBlacklist.canReturnTransferRestrictionCode(uint8)._restrictionCode](src/rules/validation/RuleBlacklist.sol#L53) is not in mixedCase - -src/rules/validation/RuleBlacklist.sol#L53 - - - - [ ] ID-33 -Parameter [RuleWhitelistCommon.messageForTransferRestriction(uint8)._restrictionCode](src/rules/validation/abstract/RuleWhitelistCommon.sol#L31) is not in mixedCase - -src/rules/validation/abstract/RuleWhitelistCommon.sol#L31 - - - - [ ] ID-34 -Variable [RuleConditionalTransferOperator.IdToKey](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L21) is not in mixedCase - -src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L21 - - - - [ ] ID-35 -Parameter [RuleSanctionList.detectTransferRestriction(address,address,uint256)._to](src/rules/validation/RuleSanctionList.sol#L59) is not in mixedCase - -src/rules/validation/RuleSanctionList.sol#L59 - - - - [ ] ID-36 -Parameter [RuleBlacklist.detectTransferRestriction(address,address,uint256)._to](src/rules/validation/RuleBlacklist.sol#L35) is not in mixedCase - -src/rules/validation/RuleBlacklist.sol#L35 - - - - [ ] ID-37 -Parameter [RuleEngine.detectTransferRestriction(address,address,uint256)._to](src/RuleEngine.sol#L52) is not in mixedCase - -src/RuleEngine.sol#L52 - - - - [ ] ID-38 -Parameter [RuleConditionalTransfer.detectTransferRestriction(address,address,uint256)._amount](src/rules/operation/RuleConditionalTransfer.sol#L217) is not in mixedCase - -src/rules/operation/RuleConditionalTransfer.sol#L217 - - - - [ ] ID-39 -Parameter [RuleConditionalTransfer.getRequestByStatus(RuleConditionalTransferInvariantStorage.STATUS)._targetStatus](src/rules/operation/RuleConditionalTransfer.sol#L178) is not in mixedCase - -src/rules/operation/RuleConditionalTransfer.sol#L178 - - - - [ ] ID-40 -Parameter [RuleEngine.detectTransferRestriction(address,address,uint256)._from](src/RuleEngine.sol#L51) is not in mixedCase - -src/RuleEngine.sol#L51 - - - - [ ] ID-41 -Parameter [RuleWhitelistWrapper.detectTransferRestriction(address,address,uint256)._to](src/rules/validation/RuleWhitelistWrapper.sol#L41) is not in mixedCase - -src/rules/validation/RuleWhitelistWrapper.sol#L41 - - - - [ ] ID-42 -Parameter [RuleConditionalTransfer.operateOnTransfer(address,address,uint256)._from](src/rules/operation/RuleConditionalTransfer.sol#L52) is not in mixedCase - -src/rules/operation/RuleConditionalTransfer.sol#L52 - - - - [ ] ID-43 -Parameter [RuleBlacklist.messageForTransferRestriction(uint8)._restrictionCode](src/rules/validation/RuleBlacklist.sol#L66) is not in mixedCase - -src/rules/validation/RuleBlacklist.sol#L66 - - - - [ ] ID-44 -Parameter [RuleEngine.messageForTransferRestriction(uint8)._restrictionCode](src/RuleEngine.sol#L101) is not in mixedCase - -src/RuleEngine.sol#L101 - - - - [ ] ID-45 -Parameter [RuleSanctionList.canReturnTransferRestrictionCode(uint8)._restrictionCode](src/rules/validation/RuleSanctionList.sol#L78) is not in mixedCase - -src/rules/validation/RuleSanctionList.sol#L78 - +The function [RuleValidateTransfer.canTransfer(address,address,uint256,uint256)](src/rules/validation/abstract/RuleValidateTransfer.sol#L26-L35) reads [this.detectTransferRestriction(from,to,tokenId,amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK)](src/rules/validation/abstract/RuleValidateTransfer.sol#L33-L34) with `this` which adds an extra STATICCALL. - - [ ] ID-46 -Parameter [RuleAddressList.addressIsListed(address)._targetAddress](src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol#L103) is not in mixedCase - -src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol#L103 - - - - [ ] ID-47 -Parameter [RuleEngineValidation.validateTransferValidation(address,address,uint256)._to](src/modules/RuleEngineValidation.sol#L55) is not in mixedCase - -src/modules/RuleEngineValidation.sol#L55 - - - - [ ] ID-48 -Event [RuleConditionalTransferInvariantStorage.transferWaiting(bytes32,address,address,uint256,uint256)](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L110-L116) is not in CapWords - -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L110-L116 - - - - [ ] ID-49 -Struct [RuleConditionalTransferInvariantStorage.TIME_LIMIT](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L30-L35) is not in CapWords - -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L30-L35 - - - - [ ] ID-50 -Parameter [RuleConditionalTransfer.canReturnTransferRestrictionCode(uint8)._restrictionCode](src/rules/operation/RuleConditionalTransfer.sol#L237) is not in mixedCase - -src/rules/operation/RuleConditionalTransfer.sol#L237 - - - - [ ] ID-51 -Parameter [RuleEngine.validateTransfer(address,address,uint256)._amount](src/RuleEngine.sol#L88) is not in mixedCase - -src/RuleEngine.sol#L88 - - - - [ ] ID-52 -Struct [RuleConditionalTransferInvariantStorage.AUTOMATIC_APPROVAL](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L37-L44) is not in CapWords - -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L37-L44 - - - - [ ] ID-53 -Parameter [RuleEngineValidation.validateTransferValidation(address,address,uint256)._from](src/modules/RuleEngineValidation.sol#L54) is not in mixedCase - -src/modules/RuleEngineValidation.sol#L54 - - - - [ ] ID-54 -Parameter [RuleSanctionList.detectTransferRestriction(address,address,uint256)._from](src/rules/validation/RuleSanctionList.sol#L58) is not in mixedCase - -src/rules/validation/RuleSanctionList.sol#L58 - - - - [ ] ID-55 -Parameter [RuleConditionalTransfer.detectTransferRestriction(address,address,uint256)._to](src/rules/operation/RuleConditionalTransfer.sol#L216) is not in mixedCase - -src/rules/operation/RuleConditionalTransfer.sol#L216 - - - - [ ] ID-56 -Parameter [RuleEngineValidation.detectTransferRestrictionValidation(address,address,uint256)._from](src/modules/RuleEngineValidation.sol#L30) is not in mixedCase - -src/modules/RuleEngineValidation.sol#L30 - - - - [ ] ID-57 -Parameter [RuleEngineValidation.validateTransferValidation(address,address,uint256)._amount](src/modules/RuleEngineValidation.sol#L56) is not in mixedCase - -src/modules/RuleEngineValidation.sol#L56 - - - - [ ] ID-58 -Parameter [RuleWhitelistWrapper.detectTransferRestriction(address,address,uint256)._from](src/rules/validation/RuleWhitelistWrapper.sol#L40) is not in mixedCase - -src/rules/validation/RuleWhitelistWrapper.sol#L40 - - - - [ ] ID-59 -Parameter [RuleWhitelist.detectTransferRestriction(address,address,uint256)._to](src/rules/validation/RuleWhitelist.sol#L29) is not in mixedCase - -src/rules/validation/RuleWhitelist.sol#L29 - - - - [ ] ID-60 -Struct [RuleConditionalTransferInvariantStorage.AUTOMATIC_TRANSFER](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L18-L21) is not in CapWords - -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L18-L21 - - - - [ ] ID-61 -Parameter [RuleValidateTransfer.validateTransfer(address,address,uint256)._to](src/rules/validation/abstract/RuleValidateTransfer.sol#L17) is not in mixedCase - -src/rules/validation/abstract/RuleValidateTransfer.sol#L17 - - - - [ ] ID-62 -Event [RuleConditionalTransferInvariantStorage.transferProcessed(bytes32,address,address,uint256,uint256)](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L103-L109) is not in CapWords - -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L103-L109 - - - - [ ] ID-63 -Parameter [RuleWhitelist.detectTransferRestriction(address,address,uint256)._from](src/rules/validation/RuleWhitelist.sol#L28) is not in mixedCase - -src/rules/validation/RuleWhitelist.sol#L28 - - - - [ ] ID-64 -Parameter [RuleValidateTransfer.validateTransfer(address,address,uint256)._amount](src/rules/validation/abstract/RuleValidateTransfer.sol#L18) is not in mixedCase - -src/rules/validation/abstract/RuleValidateTransfer.sol#L18 - - - - [ ] ID-65 -Parameter [RuleEngine.validateTransfer(address,address,uint256)._from](src/RuleEngine.sol#L86) is not in mixedCase - -src/RuleEngine.sol#L86 - - - - [ ] ID-66 -Parameter [RuleConditionalTransfer.operateOnTransfer(address,address,uint256)._to](src/rules/operation/RuleConditionalTransfer.sol#L53) is not in mixedCase - -src/rules/operation/RuleConditionalTransfer.sol#L53 - - - - [ ] ID-67 -Parameter [RuleConditionalTransfer.detectTransferRestriction(address,address,uint256)._from](src/rules/operation/RuleConditionalTransfer.sol#L215) is not in mixedCase - -src/rules/operation/RuleConditionalTransfer.sol#L215 - - - - [ ] ID-68 -Parameter [RuleEngineValidation.detectTransferRestrictionValidation(address,address,uint256)._to](src/modules/RuleEngineValidation.sol#L31) is not in mixedCase - -src/modules/RuleEngineValidation.sol#L31 - - - - [ ] ID-69 -Parameter [RuleBlacklist.detectTransferRestriction(address,address,uint256)._from](src/rules/validation/RuleBlacklist.sol#L34) is not in mixedCase - -src/rules/validation/RuleBlacklist.sol#L34 - - - - [ ] ID-70 -Parameter [RuleConditionalTransfer.messageForTransferRestriction(uint8)._restrictionCode](src/rules/operation/RuleConditionalTransfer.sol#L248) is not in mixedCase - -src/rules/operation/RuleConditionalTransfer.sol#L248 - - - - [ ] ID-71 -Parameter [RuleSanctionList.messageForTransferRestriction(uint8)._restrictionCode](src/rules/validation/RuleSanctionList.sol#L91) is not in mixedCase - -src/rules/validation/RuleSanctionList.sol#L91 - - - - [ ] ID-72 -Parameter [RuleAddressList.addressIsListedBatch(address[])._targetAddresses](src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol#L113) is not in mixedCase - -src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol#L113 - - - - [ ] ID-73 -Parameter [RuleEngine.validateTransfer(address,address,uint256)._to](src/RuleEngine.sol#L87) is not in mixedCase - -src/RuleEngine.sol#L87 - - - - [ ] ID-74 -Event [RuleConditionalTransferInvariantStorage.transferApproved(bytes32,address,address,uint256,uint256)](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L117-L123) is not in CapWords - -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L117-L123 - -## similar-names - -> Acknowlege - -Impact: Informational -Confidence: Medium - - [ ] ID-75 -Variable [RuleSanctionlistInvariantStorage.CODE_ADDRESS_FROM_IS_SANCTIONED](src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol#L27) is too similar to [RuleSanctionlistInvariantStorage.TEXT_ADDRESS_FROM_IS_SANCTIONED](src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol#L20-L21) - -src/rules/validation/abstract/RuleSanctionListInvariantStorage.sol#L27 - - - - [ ] ID-76 -Variable [RuleConditionalTransferOperator._createTransferRequestWithApproval(RuleConditionalTransferInvariantStorage.TransferRequestKeyElement).keyElement_](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L326) is too similar to [RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch(RuleConditionalTransferInvariantStorage.TransferRequestKeyElement[]).keyElements](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L245) - -src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L326 - - - - [ ] ID-77 -Variable [RuleConditionalTransferOperator._createTransferRequestWithApproval(RuleConditionalTransferInvariantStorage.TransferRequestKeyElement).keyElement_](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L326) is too similar to [RuleConditionalTransferOperator.approveTransferRequestBatch(RuleConditionalTransferInvariantStorage.TransferRequestKeyElement[],uint256[],bool[]).keyElements](src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L219) - -src/rules/operation/abstract/RuleConditionalTransferOperator.sol#L326 - - - - [ ] ID-78 -Variable [RuleConditionalTransferInvariantStorage.CODE_TRANSFER_REQUEST_NOT_APPROVED](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L87) is too similar to [RuleConditionalTransferInvariantStorage.TEXT_TRANSFER_REQUEST_NOT_APPROVED](src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L83-L84) - -src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol#L87 - - - - [ ] ID-79 -Variable [RuleBlacklistInvariantStorage.CODE_ADDRESS_FROM_IS_BLACKLISTED](src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol#L16) is too similar to [RuleBlacklistInvariantStorage.TEXT_ADDRESS_FROM_IS_BLACKLISTED](src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol#L9-L10) - -src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol#L16 - - - - [ ] ID-80 -Variable [RuleWhitelistInvariantStorage.CODE_ADDRESS_TO_NOT_WHITELISTED](src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol#L17) is too similar to [RuleWhitelistInvariantStorage.TEXT_ADDRESS_TO_NOT_WHITELISTED](src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol#L11-L12) - -src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol#L17 - - - - [ ] ID-81 -Variable [RuleWhitelistInvariantStorage.CODE_ADDRESS_FROM_NOT_WHITELISTED](src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol#L16) is too similar to [RuleWhitelistInvariantStorage.TEXT_ADDRESS_FROM_NOT_WHITELISTED](src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol#L9-L10) - -src/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol#L16 - -## unused-import - -> Concerns OpenZeppelin library - -Impact: Informational -Confidence: High - - [ ] ID-82 - The following unused import(s) in lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol should be removed: - -import {IERC20Permit} from "../extensions/IERC20Permit.sol"; (lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol#7) - -## var-read-using-this - -> Don't manage to find a better solution - -Impact: Optimization -Confidence: High - - [ ] ID-83 -The function [RuleValidateTransfer.validateTransfer(address,address,uint256)](src/rules/validation/abstract/RuleValidateTransfer.sol#L15-L24) reads [this.detectTransferRestriction(_from,_to,_amount) == uint8(REJECTED_CODE_BASE.TRANSFER_OK)](src/rules/validation/abstract/RuleValidateTransfer.sol#L21-L23) with `this` which adds an extra STATICCALL. +src/rules/validation/abstract/RuleValidateTransfer.sol#L26-L35 -src/rules/validation/abstract/RuleValidateTransfer.sol#L15-L24 diff --git a/src/rules/interfaces/IERC7943NonFungibleCompliance.sol b/src/rules/interfaces/IERC7943NonFungibleCompliance.sol index 9fa9730..5807cb7 100644 --- a/src/rules/interfaces/IERC7943NonFungibleCompliance.sol +++ b/src/rules/interfaces/IERC7943NonFungibleCompliance.sol @@ -99,6 +99,20 @@ interface IERC7943NonFungibleComplianceExtend is IERC7943NonFungibleCompliance { external returns (bool allowed); + /** + * @notice Notifies the rule engine or compliance module that a transfer has been executed. + * @dev + * - MAY modify compliance-related state (e.g., consumption of approvals, updating limits). + * - MUST be called by the token contract after a successful transfer. + * - MUST revert if called by unauthorized contracts. + * + * @param from The previous owner of the token. + * @param to The new owner of the token. + * @param tokenId The token ID that was transferred. + * @param value The transfer amount (always `1` for ERC-721). + */ + function transferred(address from, address to, uint256 tokenId, uint256 value) external; + /** * @notice Notifies the rule engine or compliance module that a transfer has been executed. * @dev diff --git a/src/rules/validation/RuleBlacklist.sol b/src/rules/validation/RuleBlacklist.sol index a71ee65..3c31225 100644 --- a/src/rules/validation/RuleBlacklist.sol +++ b/src/rules/validation/RuleBlacklist.sol @@ -163,11 +163,11 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); require( code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), - RuleBlacklist_InvalidTransfer(address(this), from, to, value, code) + RuleBlacklist_InvalidTransferFrom(address(this), spender, from, to, value, code) ); } - function transferred(address spender, address from, address to, uint256, /* tokenId */ uint256 value) + function transferred(address spender, address from, address to, uint256 /* tokenId */,uint256 value) public view virtual @@ -175,4 +175,13 @@ contract RuleBlacklist is RuleValidateTransfer, RuleAddressSet, RuleBlacklistInv { transferred(spender, from, to, value); } + + function transferred(address from, address to, uint256 /* tokenId */,uint256 value) + public + view + virtual + override(IERC7943NonFungibleComplianceExtend) + { + transferred(from, to, value); + } } diff --git a/src/rules/validation/RuleSanctionsList.sol b/src/rules/validation/RuleSanctionsList.sol index 8a91605..81a1fb5 100644 --- a/src/rules/validation/RuleSanctionsList.sol +++ b/src/rules/validation/RuleSanctionsList.sol @@ -194,6 +194,7 @@ contract RuleSanctionsList is ); } + /** * @inheritdoc IRuleEngine */ @@ -206,14 +207,11 @@ contract RuleSanctionsList is uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); require( code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), - RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code) + RuleSanctionsList_InvalidTransferFrom(address(this), spender, from, to, value, code) ); } - /** - * @inheritdoc IERC7943NonFungibleComplianceExtend - */ - function transferred(address spender, address from, address to, uint256, /* tokenId */ uint256 value) + function transferred(address spender, address from, address to, uint256 /* tokenId */,uint256 value) public view virtual @@ -222,6 +220,14 @@ contract RuleSanctionsList is transferred(spender, from, to, value); } + function transferred(address from, address to, uint256 /* tokenId */,uint256 value) + public + view + virtual + override(IERC7943NonFungibleComplianceExtend) + { + transferred(from, to, value); + } /*////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ diff --git a/src/rules/validation/RuleWhitelist.sol b/src/rules/validation/RuleWhitelist.sol index 07e1dca..adf2c20 100644 --- a/src/rules/validation/RuleWhitelist.sol +++ b/src/rules/validation/RuleWhitelist.sol @@ -143,4 +143,27 @@ contract RuleWhitelist is RuleAddressSet, RuleWhitelistCommon, IIdentityRegistry function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) { return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId); } + + /** + * @notice Sets whether the rule should enforce spender-based checks. + * @dev + * - Restricted to holders of the `DEFAULT_ADMIN_ROLE`. + * - Updates the internal `checkSpender` flag. + * - Emits a {CheckSpenderUpdated} event. + * @param value The new state of the `checkSpender` flag. + */ + function setCheckSpender(bool value) + public virtual + onlyRole(DEFAULT_ADMIN_ROLE) // or a dedicated role if you prefer + { + _setCheckSpender(value); + emit CheckSpenderUpdated(value); + } + + /** + * @dev Internal helper to update the `checkSpender` flag. + */ + function _setCheckSpender(bool value) internal { + checkSpender = value; + } } diff --git a/src/rules/validation/RuleWhitelistWrapper.sol b/src/rules/validation/RuleWhitelistWrapper.sol index 3212a4f..6309c5c 100644 --- a/src/rules/validation/RuleWhitelistWrapper.sol +++ b/src/rules/validation/RuleWhitelistWrapper.sol @@ -11,8 +11,6 @@ import {RuleAddressSet} from "./abstract/RuleAddressSet/RuleAddressSet.sol"; import {RuleWhitelistCommon, RuleValidateTransfer} from "./abstract/RuleWhitelistCommon.sol"; /* ==== RuleEngine === */ import {RulesManagementModule} from "RuleEngine/modules/RulesManagementModule.sol"; -import {RuleEngineInvariantStorage} from "RuleEngine/modules/library/RuleEngineInvariantStorage.sol"; -import {IRule} from "RuleEngine/interfaces/IRule.sol"; /* ==== CMTAT === */ import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; /* ==== Interfaces === */ @@ -125,6 +123,10 @@ contract RuleWhitelistWrapper is return detectTransferRestrictionFrom(spender, from, to, value); } + function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) { + return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId); + } + /* ============ Access control ============ */ /** @@ -140,6 +142,23 @@ contract RuleWhitelistWrapper is return AccessControlModuleStandalone.hasRole(role, account); } + /** + * @notice Sets whether the rule should enforce spender-based checks. + * @dev + * - Restricted to holders of the `DEFAULT_ADMIN_ROLE`. + * - Updates the internal `checkSpender` flag. + * - Emits a {CheckSpenderUpdated} event. + * @param value The new state of the `checkSpender` flag. + */ + function setCheckSpender(bool value) + public virtual + onlyRole(DEFAULT_ADMIN_ROLE) // or a dedicated role if you prefer + { + _setCheckSpender(value); + emit CheckSpenderUpdated(value); + } + + /*////////////////////////////////////////////////////////////// INTERNAL/PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////*/ @@ -171,8 +190,12 @@ contract RuleWhitelistWrapper is return result; } - function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, RuleValidateTransfer) returns (bool) { - return AccessControl.supportsInterface(interfaceId) || RuleValidateTransfer.supportsInterface(interfaceId); + + /** + * @dev Internal helper to update the `checkSpender` flag. + */ + function _setCheckSpender(bool value) internal { + checkSpender = value; } /*////////////////////////////////////////////////////////////// diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol index 16e74ce..261f3d8 100644 --- a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol @@ -6,6 +6,7 @@ import {RuleCommonInvariantStorage} from "../../RuleCommonInvariantStorage.sol"; abstract contract RuleBlacklistInvariantStorage is RuleCommonInvariantStorage { error RuleBlacklist_InvalidTransfer(address rule, address from, address to, uint256 value, uint8 code); + error RuleBlacklist_InvalidTransferFrom(address rule, address spender, address from, address to, uint256 value, uint8 code); /* ============ String message ============ */ string constant TEXT_ADDRESS_FROM_IS_BLACKLISTED = "The sender is blacklisted"; diff --git a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol index 7f12df5..4a3561b 100644 --- a/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol @@ -6,6 +6,7 @@ import {RuleCommonInvariantStorage} from "../../RuleCommonInvariantStorage.sol"; abstract contract RuleWhitelistInvariantStorage is RuleCommonInvariantStorage { error RuleWhitelist_InvalidTransfer(address rule, address from, address to, uint256 value, uint8 code); + error RuleWhitelist_InvalidTransferFrom(address rule, address spender, address from, address to, uint256 value, uint8 code); /* ============ String message ============ */ string constant TEXT_ADDRESS_FROM_NOT_WHITELISTED = "The sender is not in the whitelist"; @@ -17,4 +18,10 @@ abstract contract RuleWhitelistInvariantStorage is RuleCommonInvariantStorage { uint8 public constant CODE_ADDRESS_FROM_NOT_WHITELISTED = 21; uint8 public constant CODE_ADDRESS_TO_NOT_WHITELISTED = 22; uint8 public constant CODE_ADDRESS_SPENDER_NOT_WHITELISTED = 23; + + + /* ============ Events ============ */ + /// @dev Emitted when the `checkSpender` flag is updated. + event CheckSpenderUpdated(bool newValue); + } diff --git a/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol index b9f96fd..318d5d2 100644 --- a/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol +++ b/src/rules/validation/abstract/RuleSanctionsListInvariantStorage.sol @@ -9,11 +9,8 @@ abstract contract RuleSanctionsListInvariantStorage is RuleCommonInvariantStorag /* ============ Event ============ */ event SetSanctionListOracle(ISanctionsList newOracle); /* ============ Custom errors ============ */ - error RuleSanctionsList_InvalidTransfer(address rule, address from, address to, uint256 value, uint8 code); - error RuleSanctionList_AdminWithAddressZeroNotAllowed(); - error RuleSanctionList_AddressAlreadyWhitelisted(); - + error RuleSanctionsList_InvalidTransferFrom(address rule, address spender, address from, address to, uint256 value, uint8 code); /* ============ Role ============ */ bytes32 public constant SANCTIONLIST_ROLE = keccak256("SANCTIONLIST_ROLE"); diff --git a/src/rules/validation/abstract/RuleValidateTransfer.sol b/src/rules/validation/abstract/RuleValidateTransfer.sol index 10d3a0e..f9c3d31 100644 --- a/src/rules/validation/abstract/RuleValidateTransfer.sol +++ b/src/rules/validation/abstract/RuleValidateTransfer.sol @@ -6,7 +6,6 @@ pragma solidity ^0.8.20; import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; import {IERC3643ComplianceRead} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol"; -import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; /* ==== RuleEngine === */ import {IRule} from "RuleEngine/interfaces/IRule.sol"; import { @@ -80,7 +79,6 @@ abstract contract RuleValidateTransfer is IERC7943NonFungibleComplianceExtend, I return canTransferFrom(spender, from, to, value); } - function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IRule).interfaceId; } diff --git a/src/rules/validation/abstract/RuleWhitelistCommon.sol b/src/rules/validation/abstract/RuleWhitelistCommon.sol index 245750c..5d72ac5 100644 --- a/src/rules/validation/abstract/RuleWhitelistCommon.sol +++ b/src/rules/validation/abstract/RuleWhitelistCommon.sol @@ -98,18 +98,26 @@ abstract contract RuleWhitelistCommon is RuleValidateTransfer, RuleWhitelistInva uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value); require( code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), - RuleWhitelist_InvalidTransfer(address(this), from, to, value, code) + RuleWhitelist_InvalidTransferFrom(address(this), spender, from, to, value, code) ); } - /** - * @inheritdoc IERC7943NonFungibleComplianceExtend - */ - function transferred(address spender, address from, address to, uint256, /* tokenId */ uint256 value) + + function transferred(address spender, address from, address to, uint256 /* tokenId */,uint256 value) public view + virtual override(IERC7943NonFungibleComplianceExtend) { transferred(spender, from, to, value); } + + function transferred(address from, address to, uint256 /* tokenId */,uint256 value) + public + view + virtual + override(IERC7943NonFungibleComplianceExtend) + { + transferred(from, to, value); + } } diff --git a/test/RuleBlacklist/RuleBlacklist.t.sol b/test/RuleBlacklist/RuleBlacklist.t.sol index 60eea0e..f35fa71 100644 --- a/test/RuleBlacklist/RuleBlacklist.t.sol +++ b/test/RuleBlacklist/RuleBlacklist.t.sol @@ -69,6 +69,11 @@ contract RuleBlacklistTest is Test, HelperContract { resBool = ruleBlacklist.canTransfer(ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resBool, true); + + // No revert + // Act + ruleBlacklist.transferred(ADDRESS1, ADDRESS2, 20); + ruleBlacklist.transferred(ADDRESS1, ADDRESS2, 0, 20); } function testDetectTransferRestrictionFRom() public { @@ -94,6 +99,33 @@ contract RuleBlacklistTest is Test, HelperContract { resBool = ruleBlacklist.canTransfer(ADDRESS1, ADDRESS2, 0, 20); // Assert assertFalse(resBool); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleBlacklist_InvalidTransfer.selector, + address(ruleBlacklist), + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_FROM_IS_BLACKLISTED + ) + ); + // Act + ruleBlacklist.transferred(ADDRESS1, ADDRESS2, 20); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleBlacklist_InvalidTransfer.selector, + address(ruleBlacklist), + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_FROM_IS_BLACKLISTED + ) + ); + ruleBlacklist.transferred(ADDRESS1, ADDRESS2, 0, 20); } function testDetectTransferRestrictionTO() public { @@ -118,6 +150,33 @@ contract RuleBlacklistTest is Test, HelperContract { resBool = ruleBlacklist.canTransfer(ADDRESS1, ADDRESS2, 0, 20); // Assert assertFalse(resBool); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleBlacklist_InvalidTransfer.selector, + address(ruleBlacklist), + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_TO_IS_BLACKLISTED + ) + ); + // Act + ruleBlacklist.transferred(ADDRESS1, ADDRESS2, 20); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleBlacklist_InvalidTransfer.selector, + address(ruleBlacklist), + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_TO_IS_BLACKLISTED + ) + ); + ruleBlacklist.transferred(ADDRESS1, ADDRESS2, 0, 20); } function testDetectTransferRestrictionSpender() public { @@ -142,6 +201,36 @@ contract RuleBlacklistTest is Test, HelperContract { resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); // Assert assertFalse(resBool); + + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleBlacklist_InvalidTransferFrom.selector, + address(ruleBlacklist), + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_SPENDER_IS_BLACKLISTED + ) + ); + // Act + ruleBlacklist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 20); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleBlacklist_InvalidTransferFrom.selector, + address(ruleBlacklist), + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_SPENDER_IS_BLACKLISTED + ) + ); + ruleBlacklist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); } function testDetectTransferRestrictionSpenderTo() public { @@ -209,6 +298,11 @@ contract RuleBlacklistTest is Test, HelperContract { resBool = ruleBlacklist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resBool, true); + + // No revert + // Act + ruleBlacklist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 20); + ruleBlacklist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); } } diff --git a/test/RuleSanctionList/RuleSanctionListTest.t.sol b/test/RuleSanctionList/RuleSanctionListTest.t.sol index ea2eb18..058ed3f 100644 --- a/test/RuleSanctionList/RuleSanctionListTest.t.sol +++ b/test/RuleSanctionList/RuleSanctionListTest.t.sol @@ -109,6 +109,33 @@ contract RuleSanctionlistTest is Test, HelperContract { resUint8 = ruleSanctionList.detectTransferRestriction(ATTACKER, ADDRESS2, 0, 20); // Assert assertEq(resUint8, CODE_ADDRESS_FROM_IS_SANCTIONED); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleSanctionsList_InvalidTransfer.selector, + address(ruleSanctionList), + ATTACKER, + ADDRESS2, + 20, + CODE_ADDRESS_FROM_IS_SANCTIONED + ) + ); + // Act + ruleSanctionList.transferred(ATTACKER, ADDRESS2, 20); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleSanctionsList_InvalidTransfer.selector, + address(ruleSanctionList), + ATTACKER, + ADDRESS2, + 20, + CODE_ADDRESS_FROM_IS_SANCTIONED + ) + ); + ruleSanctionList.transferred(ATTACKER, ADDRESS2, 0, 20); } function testDetectTransferRestrictionTo() public { @@ -121,6 +148,33 @@ contract RuleSanctionlistTest is Test, HelperContract { resUint8 = ruleSanctionList.detectTransferRestriction(ADDRESS1, ATTACKER, 0, 20); // Assert assertEq(resUint8, CODE_ADDRESS_TO_IS_SANCTIONED); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleSanctionsList_InvalidTransfer.selector, + address(ruleSanctionList), + ADDRESS1, + ATTACKER, + 20, + CODE_ADDRESS_TO_IS_SANCTIONED + ) + ); + // Act + ruleSanctionList.transferred(ADDRESS1, ATTACKER, 20); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleSanctionsList_InvalidTransfer.selector, + address(ruleSanctionList), + ADDRESS1, + ATTACKER, + 20, + CODE_ADDRESS_TO_IS_SANCTIONED + ) + ); + ruleSanctionList.transferred(ADDRESS1, ATTACKER, 0, 20); } function testDetectTransferRestrictionOk() public { @@ -133,6 +187,11 @@ contract RuleSanctionlistTest is Test, HelperContract { resUint8 = ruleSanctionList.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resUint8, NO_ERROR); + + // No revert + // Act + ruleSanctionList.transferred(ADDRESS1, ADDRESS2, 20); + ruleSanctionList.transferred(ADDRESS1, ADDRESS2, 0, 20); } function testDetectTransferRestrictionWitSpenderOk() public { @@ -152,6 +211,11 @@ contract RuleSanctionlistTest is Test, HelperContract { resBool = ruleSanctionList.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); assertEq(resBool, true); + + // No revert + // Act + ruleSanctionList.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 20); + ruleSanctionList.transferred(ADDRESS3, ADDRESS2, 0, 20); } function testDetectTransferRestrictionWitSpender() public { @@ -164,6 +228,35 @@ contract RuleSanctionlistTest is Test, HelperContract { resUint8 = ruleSanctionList.detectTransferRestrictionFrom(ATTACKER, ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resUint8, CODE_ADDRESS_SPENDER_IS_SANCTIONED); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleSanctionsList_InvalidTransferFrom.selector, + address(ruleSanctionList), + ATTACKER, + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_SPENDER_IS_SANCTIONED + ) + ); + // Act + ruleSanctionList.transferred(ATTACKER, ADDRESS1, ADDRESS2, 20); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleSanctionsList_InvalidTransferFrom.selector, + address(ruleSanctionList), + ATTACKER, + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_SPENDER_IS_SANCTIONED + ) + ); + ruleSanctionList.transferred(ATTACKER, ADDRESS1, ADDRESS2, 0, 20); } function testDetectTransferRestrictionWitSpenderTo() public { diff --git a/test/RuleWhitelist/RuleWhitelist.t.sol b/test/RuleWhitelist/RuleWhitelist.t.sol index 589ff5b..8a1535a 100644 --- a/test/RuleWhitelist/RuleWhitelist.t.sol +++ b/test/RuleWhitelist/RuleWhitelist.t.sol @@ -189,6 +189,33 @@ contract RuleWhitelistTest is Test, HelperContract { resBool = ruleWhitelist.canTransfer(ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resBool, false); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleWhitelist_InvalidTransfer.selector, + address(ruleWhitelist), + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_FROM_NOT_WHITELISTED + ) + ); + // Act + ruleWhitelist.transferred(ADDRESS1, ADDRESS2, 20); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleWhitelist_InvalidTransfer.selector, + address(ruleWhitelist), + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_FROM_NOT_WHITELISTED + ) + ); + ruleWhitelist.transferred(ADDRESS1, ADDRESS2, 0, 20); } function testDetectTransferRestrictionTo() public { @@ -204,6 +231,33 @@ contract RuleWhitelistTest is Test, HelperContract { resUint8 = ruleWhitelist.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleWhitelist_InvalidTransfer.selector, + address(ruleWhitelist), + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_TO_NOT_WHITELISTED + ) + ); + // Act + ruleWhitelist.transferred(ADDRESS1, ADDRESS2, 20); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleWhitelist_InvalidTransfer.selector, + address(ruleWhitelist), + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_TO_NOT_WHITELISTED + ) + ); + ruleWhitelist.transferred(ADDRESS1, ADDRESS2, 0, 20); } function testDetectTransferRestrictionWithSpender() public { @@ -232,6 +286,36 @@ contract RuleWhitelistTest is Test, HelperContract { resBool = ruleWhitelist.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resBool, false); + + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleWhitelist_InvalidTransferFrom.selector, + address(ruleWhitelist), + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_SPENDER_NOT_WHITELISTED + ) + ); + // Act + ruleWhitelist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 20); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleWhitelist_InvalidTransferFrom.selector, + address(ruleWhitelist), + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_SPENDER_NOT_WHITELISTED + ) + ); + ruleWhitelist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); } function testDetectTransferRestrictionOk() public { @@ -283,5 +367,10 @@ contract RuleWhitelistTest is Test, HelperContract { resUint8 = ruleWhitelist.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resUint8, NO_ERROR); + + // No revert + // Act + ruleWhitelist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 20); + ruleWhitelist.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); } } diff --git a/test/RuleWhitelist/WhitelistWrapper.t.sol b/test/RuleWhitelist/WhitelistWrapper.t.sol index 90972e0..99b31df 100644 --- a/test/RuleWhitelist/WhitelistWrapper.t.sol +++ b/test/RuleWhitelist/WhitelistWrapper.t.sol @@ -79,6 +79,34 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { resBool = ruleWhitelistWrapper.canTransfer(ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resBool, false); + + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleWhitelist_InvalidTransfer.selector, + address(ruleWhitelistWrapper), + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_FROM_NOT_WHITELISTED + ) + ); + // Act + ruleWhitelistWrapper.transferred(ADDRESS1, ADDRESS2, 20); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleWhitelist_InvalidTransfer.selector, + address(ruleWhitelistWrapper), + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_FROM_NOT_WHITELISTED + ) + ); + ruleWhitelistWrapper.transferred(ADDRESS1, ADDRESS2, 0, 20); } function testDetectTransferRestrictionTo() public { @@ -94,6 +122,35 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { resUint8 = ruleWhitelistWrapper.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED); + + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleWhitelist_InvalidTransfer.selector, + address(ruleWhitelistWrapper), + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_TO_NOT_WHITELISTED + ) + ); + // Act + ruleWhitelistWrapper.transferred(ADDRESS1, ADDRESS2, 20); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleWhitelist_InvalidTransfer.selector, + address(ruleWhitelistWrapper), + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_TO_NOT_WHITELISTED + ) + ); + ruleWhitelistWrapper.transferred(ADDRESS1, ADDRESS2, 0, 20); + } function testDetectTransferRestrictionWithSpender() public { @@ -122,6 +179,35 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { resBool = ruleWhitelistWrapper.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resBool, false); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleWhitelist_InvalidTransferFrom.selector, + address(ruleWhitelistWrapper), + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_SPENDER_NOT_WHITELISTED + ) + ); + // Act + ruleWhitelistWrapper.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 20); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleWhitelist_InvalidTransferFrom.selector, + address(ruleWhitelistWrapper), + ADDRESS3, + ADDRESS1, + ADDRESS2, + 20, + CODE_ADDRESS_SPENDER_NOT_WHITELISTED + ) + ); + ruleWhitelistWrapper.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); } function testDetectTransferRestrictionOk() public { @@ -144,6 +230,11 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { resUint8 = ruleWhitelistWrapper.detectTransferRestriction(ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resUint8, NO_ERROR); + + // No revert + // Act + ruleWhitelistWrapper.transferred(ADDRESS1, ADDRESS2, 20); + ruleWhitelistWrapper.transferred(ADDRESS1, ADDRESS2, 0, 20); } function testDetectTransferRestrictionWithSpenderOk() public { @@ -173,6 +264,11 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { resUint8 = ruleWhitelistWrapper.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); // Assert assertEq(resUint8, NO_ERROR); + + // No revert + // Act + ruleWhitelistWrapper.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 20); + ruleWhitelistWrapper.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); } From ec01b04f17dee305d15f20f09145323ee747b1ee Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Wed, 3 Dec 2025 15:44:09 +0100 Subject: [PATCH 24/25] Remove ToC --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 484ef6f..92e0b5f 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,6 @@ Each rule can be used **standalone**, directly plugged into a CMTAT token, **or* **Status:** *Repository under active development* -[TOC] - ## Overview The **RuleEngine** is an external smart contract that applies transfer restrictions to security tokens such as **CMTAT** or ERC-3643-compatible tokens through a RuleEngine. From b8ff95f26ef8e6c030e12afabeaef4e6f63f71d6 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Wed, 3 Dec 2025 16:08:25 +0100 Subject: [PATCH 25/25] Improve test, add direct test with CMTAT --- test/RuleBlacklist/CMTATIntegration.t.sol | 3 - .../CMTATIntegrationDirect.t.sol | 193 ++++++++++++++++++ test/RuleWhitelist/CMTATIntegration.t.sol | 2 - .../CMTATIntegrationWhitelistWrapper.t.sol | 3 +- 4 files changed, 194 insertions(+), 7 deletions(-) create mode 100644 test/RuleBlacklist/CMTATIntegrationDirect.t.sol diff --git a/test/RuleBlacklist/CMTATIntegration.t.sol b/test/RuleBlacklist/CMTATIntegration.t.sol index fbae761..171f08b 100644 --- a/test/RuleBlacklist/CMTATIntegration.t.sol +++ b/test/RuleBlacklist/CMTATIntegration.t.sol @@ -13,9 +13,6 @@ contract CMTATIntegration is Test, HelperContract { uint256 ADDRESS1_BALANCE_INIT = 31; uint256 ADDRESS2_BALANCE_INIT = 32; uint256 ADDRESS3_BALANCE_INIT = 33; - - uint256 FLAG = 5; - // Arrange function setUp() public { // CMTAT diff --git a/test/RuleBlacklist/CMTATIntegrationDirect.t.sol b/test/RuleBlacklist/CMTATIntegrationDirect.t.sol new file mode 100644 index 0000000..2ce8e1f --- /dev/null +++ b/test/RuleBlacklist/CMTATIntegrationDirect.t.sol @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import "forge-std/Test.sol"; +import "CMTAT/deployment/CMTATStandalone.sol"; +import "../HelperContract.sol"; + + +/** + * @title Integration test with the CMTAT using direct RuleBlacklist + */ +contract CMTATIntegrationDirectBlacklist is Test, HelperContract { + uint256 ADDRESS1_BALANCE_INIT = 31; + uint256 ADDRESS2_BALANCE_INIT = 32; + uint256 ADDRESS3_BALANCE_INIT = 33; + + function setUp() public { + // Deploy CMTAT + cmtatDeployment = new CMTATDeployment(); + CMTAT_CONTRACT = cmtatDeployment.cmtat(); + + // Deploy RuleBlacklist directly + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleBlacklist = new RuleBlacklist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); + + // Mint initial balances + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT); + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT.mint(ADDRESS2, ADDRESS2_BALANCE_INIT); + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT.mint(ADDRESS3, ADDRESS3_BALANCE_INIT); + + // Directly plug the blacklist into CMTAT + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT.setRuleEngine(IRuleEngine(address(ruleBlacklist))); + } + + /* ---------------- Transfer Tests ---------------- */ + + function testCanTransferIfAddressNotBlacklisted() public { + vm.prank(ADDRESS1); + CMTAT_CONTRACT.transfer(ADDRESS2, 21); + } + + function testCannotTransferIfAddressToIsBlacklisted() public { + uint256 amount = 21; + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleBlacklist.addAddress(ADDRESS2); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleBlacklist_InvalidTransfer.selector, + address(ruleBlacklist), + ADDRESS1, + ADDRESS2, + amount, + CODE_ADDRESS_TO_IS_BLACKLISTED + ) + ); + CMTAT_CONTRACT.transfer(ADDRESS2, amount); + } + + function testCannotTransferIfAddressFromIsBlacklisted() public { + uint256 amount = 21; + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleBlacklist.addAddress(ADDRESS1); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleBlacklist_InvalidTransfer.selector, + address(ruleBlacklist), + ADDRESS1, + ADDRESS2, + amount, + CODE_ADDRESS_FROM_IS_BLACKLISTED + ) + ); + CMTAT_CONTRACT.transfer(ADDRESS2, amount); + } + + function testCannotTransferIfBothAddressesAreBlacklisted() public { + uint256 amount = 21; + address[] memory blacklist = new address[](2); + blacklist[0] = ADDRESS1; + blacklist[1] = ADDRESS2; + vm.prank(DEFAULT_ADMIN_ADDRESS); + (bool success,) = address(ruleBlacklist).call(abi.encodeWithSignature("addAddresses(address[])", blacklist)); + require(success); + + vm.prank(ADDRESS1); + vm.expectRevert( + abi.encodeWithSelector( + RuleBlacklist_InvalidTransfer.selector, + address(ruleBlacklist), + ADDRESS1, + ADDRESS2, + amount, + CODE_ADDRESS_FROM_IS_BLACKLISTED + ) + ); + CMTAT_CONTRACT.transfer(ADDRESS2, amount); + } + + /* ---------------- Detect & Message Tests ---------------- */ + + function testDetectAndMessageWithToBlacklisted() public { + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleBlacklist.addAddress(ADDRESS2); + bool resBool = ruleBlacklist.isAddressListed(ADDRESS2); + assertEq(resBool, true); + + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); + assertEq(res1, CODE_ADDRESS_TO_IS_BLACKLISTED); + + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); + assertEq(message1, TEXT_ADDRESS_TO_IS_BLACKLISTED); + } + + function testDetectAndMessageWithFromBlacklisted() public { + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleBlacklist.addAddress(ADDRESS1); + bool resBool = ruleBlacklist.isAddressListed(ADDRESS1); + assertEq(resBool, true); + + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); + assertEq(res1, CODE_ADDRESS_FROM_IS_BLACKLISTED); + + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); + assertEq(message1, TEXT_ADDRESS_FROM_IS_BLACKLISTED); + } + + function testDetectAndMessageWithFromAndToNotBlacklisted() public view { + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); + assertEq(res1, TRANSFER_OK); + + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); + assertEq(message1, TEXT_TRANSFER_OK); + } + + function testDetectAndMessageWithFromAndToBlacklisted() public { + address[] memory blacklist = new address[](2); + blacklist[0] = ADDRESS1; + blacklist[1] = ADDRESS2; + vm.prank(DEFAULT_ADMIN_ADDRESS); + (bool success,) = address(ruleBlacklist).call(abi.encodeWithSignature("addAddresses(address[])", blacklist)); + require(success); + + uint8 res1 = CMTAT_CONTRACT.detectTransferRestriction(ADDRESS1, ADDRESS2, 11); + assertEq(res1, CODE_ADDRESS_FROM_IS_BLACKLISTED); + + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(res1); + assertEq(message1, TEXT_ADDRESS_FROM_IS_BLACKLISTED); + } + + /* ---------------- Mint Tests ---------------- */ + + function testCanMintIfAddressNotInTheBlacklist() public { + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT.mint(ADDRESS1, 11); + + uint256 resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1); + assertEq(resUint256, ADDRESS1_BALANCE_INIT + 11); + } + + function testCannotMintIfAddressIsInTheBlacklist() public { + uint256 amount = 11; + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleBlacklist.addAddress(ADDRESS1); + bool resBool = ruleBlacklist.isAddressListed(ADDRESS1); + assertEq(resBool, true); + + vm.expectRevert( + abi.encodeWithSelector( + RuleBlacklist_InvalidTransfer.selector, + address(ruleBlacklist), + ZERO_ADDRESS, + ADDRESS1, + amount, + CODE_ADDRESS_TO_IS_BLACKLISTED + ) + ); + vm.prank(DEFAULT_ADMIN_ADDRESS); + CMTAT_CONTRACT.mint(ADDRESS1, amount); + } + + function testCanReturnMessageNotFoundWithUnknownCodeId() public view { + string memory message1 = CMTAT_CONTRACT.messageForTransferRestriction(255); + assertEq(message1, TEXT_CODE_NOT_FOUND); + } +} \ No newline at end of file diff --git a/test/RuleWhitelist/CMTATIntegration.t.sol b/test/RuleWhitelist/CMTATIntegration.t.sol index 4e7720d..2693f93 100644 --- a/test/RuleWhitelist/CMTATIntegration.t.sol +++ b/test/RuleWhitelist/CMTATIntegration.t.sol @@ -13,8 +13,6 @@ contract CMTATIntegration is Test, HelperContract { uint256 ADDRESS2_BALANCE_INIT = 32; uint256 ADDRESS3_BALANCE_INIT = 33; - uint256 FLAG = 5; - // Arrange function setUp() public { vm.prank(DEFAULT_ADMIN_ADDRESS); diff --git a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol index d2b450c..e2e0641 100644 --- a/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol +++ b/test/RuleWhitelist/CMTATIntegrationWhitelistWrapper.t.sol @@ -13,8 +13,7 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { uint256 ADDRESS1_BALANCE_INIT = 31; uint256 ADDRESS2_BALANCE_INIT = 32; uint256 ADDRESS3_BALANCE_INIT = 33; - - uint256 FLAG = 5; + RuleWhitelist ruleWhitelist2; RuleWhitelist ruleWhitelist3; RuleWhitelistWrapper ruleWhitelistWrapper;