From 86fe1f1d73011e32597120692bda6b6130dd2c45 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Tue, 10 Mar 2026 11:29:20 +0100 Subject: [PATCH 1/2] Update code coverage and add missing tests --- README.md | 46 +- .../RuleAddressSet.sol.func-sort-c.html | 88 +- .../RuleAddressSet.sol.func.html | 88 +- .../RuleAddressSet.sol.gcov.html | 338 +-- ...uleAddressSetInternal.sol.func-sort-c.html | 54 +- .../RuleAddressSetInternal.sol.func.html | 54 +- .../RuleAddressSetInternal.sol.gcov.html | 150 +- .../RuleAddressSet}/index-sort-b.html | 44 +- .../RuleAddressSet}/index-sort-f.html | 46 +- .../RuleAddressSet}/index-sort-l.html | 46 +- .../RuleAddressSet}/index.html | 44 +- .../RuleERC2980Internal.sol.func-sort-c.html | 129 + .../RuleERC2980Internal.sol.func.html | 129 + .../RuleERC2980Internal.sol.gcov.html | 205 ++ .../abstract/RuleERC2980/index-sort-b.html | 107 + .../abstract/RuleERC2980/index-sort-f.html | 107 + .../abstract/RuleERC2980/index-sort-l.html | 107 + .../coverage/abstract/RuleERC2980/index.html | 107 + .../RuleBlacklistBase.sol.func-sort-c.html | 117 + .../base/RuleBlacklistBase.sol.func.html | 117 + .../base/RuleBlacklistBase.sol.gcov.html | 210 ++ .../base/RuleERC2980Base.sol.func-sort-c.html | 213 ++ .../base/RuleERC2980Base.sol.func.html | 213 ++ .../base/RuleERC2980Base.sol.gcov.html | 473 ++++ ...eIdentityRegistryBase.sol.func-sort-c.html | 129 + .../RuleIdentityRegistryBase.sol.func.html | 129 + .../RuleIdentityRegistryBase.sol.gcov.html | 229 ++ ...uleMaxTotalSupplyBase.sol.func-sort-c.html | 129 + .../base/RuleMaxTotalSupplyBase.sol.func.html | 129 + .../base/RuleMaxTotalSupplyBase.sol.gcov.html | 204 ++ ...RuleSanctionsListBase.sol.func-sort-c.html | 133 ++ .../base/RuleSanctionsListBase.sol.func.html | 133 ++ .../base/RuleSanctionsListBase.sol.gcov.html | 227 ++ .../RuleWhitelistBase.sol.func-sort-c.html | 113 + .../base/RuleWhitelistBase.sol.func.html | 113 + .../base/RuleWhitelistBase.sol.gcov.html | 166 ++ ...eWhitelistWrapperBase.sol.func-sort-c.html | 137 ++ .../RuleWhitelistWrapperBase.sol.func.html | 137 ++ .../RuleWhitelistWrapperBase.sol.gcov.html} | 525 ++-- .../coverage/abstract/base/index-sort-b.html | 179 ++ .../coverage/abstract/base/index-sort-f.html | 179 ++ .../coverage/abstract/base/index-sort-l.html | 179 ++ .../coverage/abstract/base/index.html | 179 ++ .../core/RuleNFTAdapter.sol.func-sort-c.html | 113 + .../core/RuleNFTAdapter.sol.func.html | 113 + .../core/RuleNFTAdapter.sol.gcov.html} | 300 ++- ...leTransferValidation.sol.func-sort-c.html} | 36 +- .../RuleTransferValidation.sol.func.html} | 36 +- .../RuleTransferValidation.sol.gcov.html} | 176 +- .../RuleWhitelistShared.sol.func-sort-c.html} | 30 +- .../core/RuleWhitelistShared.sol.func.html} | 32 +- .../core/RuleWhitelistShared.sol.gcov.html} | 227 +- .../coverage/abstract/core/index-sort-b.html | 131 + .../coverage/abstract/core/index-sort-f.html | 131 + .../coverage/abstract/core/index-sort-l.html | 131 + .../coverage/abstract/core/index.html | 131 + .../RuleBlacklist.sol.func-sort-c.html | 68 +- .../RuleBlacklist.sol.func.html | 68 +- .../deployment/RuleBlacklist.sol.gcov.html | 138 ++ ...BlacklistOwnable2Step.sol.func-sort-c.html | 101 + .../RuleBlacklistOwnable2Step.sol.func.html | 101 + .../RuleBlacklistOwnable2Step.sol.gcov.html | 120 + .../RuleERC2980.sol.func-sort-c.html | 113 + .../deployment/RuleERC2980.sol.func.html | 113 + .../deployment/RuleERC2980.sol.gcov.html | 168 ++ ...leERC2980Ownable2Step.sol.func-sort-c.html | 109 + .../RuleERC2980Ownable2Step.sol.func.html | 109 + .../RuleERC2980Ownable2Step.sol.gcov.html | 124 + .../RuleIdentityRegistry.sol.func-sort-c.html | 89 + .../RuleIdentityRegistry.sol.func.html | 89 + .../RuleIdentityRegistry.sol.gcov.html | 121 + ...yRegistryOwnable2Step.sol.func-sort-c.html | 85 + ...IdentityRegistryOwnable2Step.sol.func.html | 85 + ...IdentityRegistryOwnable2Step.sol.gcov.html | 101 + .../RuleMaxTotalSupply.sol.func-sort-c.html | 89 + .../RuleMaxTotalSupply.sol.func.html | 89 + .../RuleMaxTotalSupply.sol.gcov.html | 125 + ...talSupplyOwnable2Step.sol.func-sort-c.html | 85 + ...leMaxTotalSupplyOwnable2Step.sol.func.html | 85 + ...leMaxTotalSupplyOwnable2Step.sol.gcov.html | 104 + .../RuleSanctionsList.sol.func-sort-c.html | 101 + .../RuleSanctionsList.sol.func.html | 101 + .../RuleSanctionsList.sol.gcov.html | 143 ++ ...tionsListOwnable2Step.sol.func-sort-c.html | 97 + ...uleSanctionsListOwnable2Step.sol.func.html | 97 + ...uleSanctionsListOwnable2Step.sol.gcov.html | 119 + .../RuleWhitelist.sol.func-sort-c.html | 50 +- .../RuleWhitelist.sol.func.html | 50 +- .../deployment/RuleWhitelist.sol.gcov.html | 158 ++ ...WhitelistOwnable2Step.sol.func-sort-c.html | 105 + .../RuleWhitelistOwnable2Step.sol.func.html | 105 + .../RuleWhitelistOwnable2Step.sol.gcov.html | 122 + .../RuleWhitelistWrapper.sol.func-sort-c.html | 64 +- .../RuleWhitelistWrapper.sol.func.html | 66 +- .../RuleWhitelistWrapper.sol.gcov.html | 183 ++ ...stWrapperOwnable2Step.sol.func-sort-c.html | 101 + ...WhitelistWrapperOwnable2Step.sol.func.html | 101 + ...WhitelistWrapperOwnable2Step.sol.gcov.html | 136 ++ .../coverage/deployment/index-sort-b.html | 263 ++ .../coverage/deployment/index-sort-f.html | 263 ++ .../coverage/deployment/index-sort-l.html | 263 ++ doc/coverage/coverage/deployment/index.html | 263 ++ ...ntrolModuleStandalone.sol.func-sort-c.html | 16 +- ...ccessControlModuleStandalone.sol.func.html | 16 +- ...ccessControlModuleStandalone.sol.gcov.html | 75 +- .../VersionModule.sol.func-sort-c.html | 85 + .../src/modules/VersionModule.sol.func.html | 85 + .../src/modules/VersionModule.sol.gcov.html | 102 + .../dev/Rules/src/modules/index-sort-b.html | 30 +- .../dev/Rules/src/modules/index-sort-f.html | 30 +- .../dev/Rules/src/modules/index-sort-l.html | 30 +- .../Pictures/dev/Rules/src/modules/index.html | 30 +- ...ditionalTransferLight.sol.func-sort-c.html | 105 + ...RuleConditionalTransferLight.sol.func.html | 105 + ...RuleConditionalTransferLight.sol.gcov.html | 141 ++ ...sferLightOwnable2Step.sol.func-sort-c.html | 93 + ...nalTransferLightOwnable2Step.sol.func.html | 93 + ...nalTransferLightOwnable2Step.sol.gcov.html | 114 + ...onalTransferLightBase.sol.func-sort-c.html | 153 ++ ...ConditionalTransferLightBase.sol.func.html | 153 ++ ...onditionalTransferLightBase.sol.gcov.html} | 403 ++-- .../operation/abstract/index-sort-b.html | 107 + .../operation/abstract/index-sort-f.html | 107 + .../operation/abstract/index-sort-l.html | 107 + .../src/rules/operation/abstract/index.html | 107 + .../src/rules/operation}/index-sort-b.html | 56 +- .../src/rules/operation}/index-sort-f.html | 60 +- .../src/rules/operation}/index-sort-l.html | 60 +- .../dev/Rules/src/rules/operation}/index.html | 56 +- doc/coverage/coverage/index-sort-b.html | 114 +- doc/coverage/coverage/index-sort-f.html | 116 +- doc/coverage/coverage/index-sort-l.html | 116 +- doc/coverage/coverage/index.html | 116 +- .../RuleSanctionsList.sol.func-sort-c.html | 149 -- .../RuleSanctionsList.sol.func.html | 149 -- .../RuleWhitelistWrapper.sol.gcov.html | 285 --- .../coverage/validation/index-sort-b.html | 143 -- .../coverage/validation/index-sort-f.html | 143 -- .../coverage/validation/index-sort-l.html | 143 -- doc/coverage/coverage/validation/index.html | 143 -- doc/coverage/lcov.info | 2125 +++++++++++++---- doc/schema/{RuleEngine => RuleEngine.drawio} | 0 .../rule/IncomeVault-claimDividend.drawio.png | Bin 100066 -> 0 bytes .../conditionalTransfer-Storage.drawio.png | Bin 89794 -> 0 bytes ...ionalTransfer-automaticTransfer.drawio.png | Bin 83764 -> 0 bytes ...nditionalTransfer-state machine.drawio.png | Bin 53914 -> 0 bytes doc/schema/rule/conditionalTransfer.drawio | 1 - .../rule/conditionalTransferCMTAT.drawio.png | Bin 84882 -> 0 bytes doc/schema/rule/conditionalTransferTime.png | Bin 29921 -> 0 bytes doc/script/convert_links_for_pdf.sh | 47 + .../access-control-RuleEngine.png | Bin 30462 -> 0 bytes doc/technical/RuleBlacklist.md | 2 +- .../RuleConditionalTransferLight.sol | 5 +- .../DeploymentOperationCoverage.t.sol | 195 ++ ...ionalTransferLightApproveAndTransfer.t.sol | 41 + ...alTransferLightRuleEngineIntegration.t.sol | 4 +- .../RuleConditionalTransferLightUnit.t.sol | 19 + test/RuleERC2980/RuleERC2980.t.sol | 32 + .../RuleIdentityRegistryOwnable2Step.t.sol | 52 + .../RuleIdentityRegistryUnit.t.sol | 39 + .../RuleMaxTotalSupplyOwnable2Step.t.sol | 51 + .../RuleMaxTotalSupplyUnit.t.sol | 20 + .../RuleSanctionsListOwnable2Step.t.sol | 72 + test/RuleWhitelist/RuleWhitelist.t.sol | 21 + test/RuleWhitelist/WhitelistWrapper.t.sol | 59 + test/TransferContext/TransferContext.t.sol | 24 + 166 files changed, 16943 insertions(+), 3600 deletions(-) rename doc/coverage/coverage/{validation => }/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html (50%) rename doc/coverage/coverage/{validation => }/abstract/RuleAddressSet/RuleAddressSet.sol.func.html (50%) rename doc/coverage/coverage/{validation => }/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html (75%) rename doc/coverage/coverage/{validation => }/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html (56%) rename doc/coverage/coverage/{validation => }/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html (56%) rename doc/coverage/coverage/{validation => }/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html (67%) rename doc/coverage/coverage/{validation/abstract => abstract/RuleAddressSet}/index-sort-b.html (74%) rename doc/coverage/coverage/{validation/abstract => abstract/RuleAddressSet}/index-sort-f.html (74%) rename doc/coverage/coverage/{validation/abstract => abstract/RuleAddressSet}/index-sort-l.html (74%) rename doc/coverage/coverage/{validation/abstract => abstract/RuleAddressSet}/index.html (74%) create mode 100644 doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.func.html create mode 100644 doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.gcov.html create mode 100644 doc/coverage/coverage/abstract/RuleERC2980/index-sort-b.html create mode 100644 doc/coverage/coverage/abstract/RuleERC2980/index-sort-f.html create mode 100644 doc/coverage/coverage/abstract/RuleERC2980/index-sort-l.html create mode 100644 doc/coverage/coverage/abstract/RuleERC2980/index.html create mode 100644 doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.func.html create mode 100644 doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.gcov.html create mode 100644 doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.func.html create mode 100644 doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.gcov.html create mode 100644 doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.func.html create mode 100644 doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.gcov.html create mode 100644 doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.func.html create mode 100644 doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.gcov.html create mode 100644 doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.func.html create mode 100644 doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.gcov.html create mode 100644 doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.func.html create mode 100644 doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.gcov.html create mode 100644 doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.func.html rename doc/coverage/coverage/{validation/RuleSanctionsList.sol.gcov.html => abstract/base/RuleWhitelistWrapperBase.sol.gcov.html} (55%) create mode 100644 doc/coverage/coverage/abstract/base/index-sort-b.html create mode 100644 doc/coverage/coverage/abstract/base/index-sort-f.html create mode 100644 doc/coverage/coverage/abstract/base/index-sort-l.html create mode 100644 doc/coverage/coverage/abstract/base/index.html create mode 100644 doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.func.html rename doc/coverage/coverage/{validation/RuleWhitelist.sol.gcov.html => abstract/core/RuleNFTAdapter.sol.gcov.html} (52%) rename doc/coverage/coverage/{validation/abstract/RuleValidateTransfer.sol.func-sort-c.html => abstract/core/RuleTransferValidation.sol.func-sort-c.html} (62%) rename doc/coverage/coverage/{validation/abstract/RuleValidateTransfer.sol.func.html => abstract/core/RuleTransferValidation.sol.func.html} (62%) rename doc/coverage/coverage/{validation/abstract/RuleValidateTransfer.sol.gcov.html => abstract/core/RuleTransferValidation.sol.gcov.html} (66%) rename doc/coverage/coverage/{validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html => abstract/core/RuleWhitelistShared.sol.func-sort-c.html} (71%) rename doc/coverage/coverage/{validation/abstract/RuleWhitelistCommon.sol.func.html => abstract/core/RuleWhitelistShared.sol.func.html} (71%) rename doc/coverage/coverage/{validation/abstract/RuleWhitelistCommon.sol.gcov.html => abstract/core/RuleWhitelistShared.sol.gcov.html} (82%) create mode 100644 doc/coverage/coverage/abstract/core/index-sort-b.html create mode 100644 doc/coverage/coverage/abstract/core/index-sort-f.html create mode 100644 doc/coverage/coverage/abstract/core/index-sort-l.html create mode 100644 doc/coverage/coverage/abstract/core/index.html rename doc/coverage/coverage/{validation => deployment}/RuleBlacklist.sol.func-sort-c.html (61%) rename doc/coverage/coverage/{validation => deployment}/RuleBlacklist.sol.func.html (61%) create mode 100644 doc/coverage/coverage/deployment/RuleBlacklist.sol.gcov.html create mode 100644 doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.func.html create mode 100644 doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.gcov.html create mode 100644 doc/coverage/coverage/deployment/RuleERC2980.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/deployment/RuleERC2980.sol.func.html create mode 100644 doc/coverage/coverage/deployment/RuleERC2980.sol.gcov.html create mode 100644 doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.func.html create mode 100644 doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.gcov.html create mode 100644 doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.func.html create mode 100644 doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.gcov.html create mode 100644 doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.func.html create mode 100644 doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.gcov.html create mode 100644 doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.func.html create mode 100644 doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.gcov.html create mode 100644 doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.func.html create mode 100644 doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.gcov.html create mode 100644 doc/coverage/coverage/deployment/RuleSanctionsList.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/deployment/RuleSanctionsList.sol.func.html create mode 100644 doc/coverage/coverage/deployment/RuleSanctionsList.sol.gcov.html create mode 100644 doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.func.html create mode 100644 doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.gcov.html rename doc/coverage/coverage/{validation => deployment}/RuleWhitelist.sol.func-sort-c.html (73%) rename doc/coverage/coverage/{validation => deployment}/RuleWhitelist.sol.func.html (73%) create mode 100644 doc/coverage/coverage/deployment/RuleWhitelist.sol.gcov.html create mode 100644 doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.func.html create mode 100644 doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.gcov.html rename doc/coverage/coverage/{validation => deployment}/RuleWhitelistWrapper.sol.func-sort-c.html (64%) rename doc/coverage/coverage/{validation => deployment}/RuleWhitelistWrapper.sol.func.html (64%) create mode 100644 doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.gcov.html create mode 100644 doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.func.html create mode 100644 doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.gcov.html create mode 100644 doc/coverage/coverage/deployment/index-sort-b.html create mode 100644 doc/coverage/coverage/deployment/index-sort-f.html create mode 100644 doc/coverage/coverage/deployment/index-sort-l.html create mode 100644 doc/coverage/coverage/deployment/index.html create mode 100644 doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.func.html create mode 100644 doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.gcov.html create mode 100644 doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.func.html create mode 100644 doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.gcov.html create mode 100644 doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.func.html create mode 100644 doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.gcov.html create mode 100644 doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.func.html rename doc/coverage/coverage/{validation/RuleBlacklist.sol.gcov.html => home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.gcov.html} (50%) create mode 100644 doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-b.html create mode 100644 doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-f.html create mode 100644 doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-l.html create mode 100644 doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index.html rename doc/coverage/coverage/{validation/abstract/RuleAddressSet => home/ryan/Pictures/dev/Rules/src/rules/operation}/index-sort-b.html (54%) rename doc/coverage/coverage/{validation/abstract/RuleAddressSet => home/ryan/Pictures/dev/Rules/src/rules/operation}/index-sort-f.html (54%) rename doc/coverage/coverage/{validation/abstract/RuleAddressSet => home/ryan/Pictures/dev/Rules/src/rules/operation}/index-sort-l.html (54%) rename doc/coverage/coverage/{validation/abstract/RuleAddressSet => home/ryan/Pictures/dev/Rules/src/rules/operation}/index.html (54%) delete mode 100644 doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html delete mode 100644 doc/coverage/coverage/validation/RuleSanctionsList.sol.func.html delete mode 100644 doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html delete mode 100644 doc/coverage/coverage/validation/index-sort-b.html delete mode 100644 doc/coverage/coverage/validation/index-sort-f.html delete mode 100644 doc/coverage/coverage/validation/index-sort-l.html delete mode 100644 doc/coverage/coverage/validation/index.html rename doc/schema/{RuleEngine => RuleEngine.drawio} (100%) delete mode 100644 doc/schema/rule/IncomeVault-claimDividend.drawio.png delete mode 100644 doc/schema/rule/conditionalTransfer-Storage.drawio.png delete mode 100644 doc/schema/rule/conditionalTransfer-automaticTransfer.drawio.png delete mode 100644 doc/schema/rule/conditionalTransfer-state machine.drawio.png delete mode 100644 doc/schema/rule/conditionalTransfer.drawio delete mode 100644 doc/schema/rule/conditionalTransferCMTAT.drawio.png delete mode 100644 doc/schema/rule/conditionalTransferTime.png create mode 100755 doc/script/convert_links_for_pdf.sh delete mode 100644 doc/security/accessControl/access-control-RuleEngine.png create mode 100644 test/Coverage/DeploymentOperationCoverage.t.sol create mode 100644 test/RuleIdentityRegistry/Ownable/RuleIdentityRegistryOwnable2Step.t.sol create mode 100644 test/RuleMaxTotalSupply/Ownable/RuleMaxTotalSupplyOwnable2Step.t.sol create mode 100644 test/RuleSanctionList/Ownable/RuleSanctionsListOwnable2Step.t.sol diff --git a/README.md b/README.md index 6f437b2..ace16e8 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ Each rule can be used **standalone**, directly plugged into a CMTAT token, **or* **Status:** *Repository under active development* +Latest update: completed 100% coverage across `src/` contracts, including direct coverage for `RuleAddressSet.contains(address)`, mint/burn-path coverage for `RuleConditionalTransferLightBase.detectTransferRestriction(...)`, and removal of an unreachable duplicate admin-zero check in `RuleConditionalTransferLight` constructor. + ## Table of Contents [TOC] @@ -58,7 +60,7 @@ forge test 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). +This interface declares the ERC-3643 functions `transferred`(read-write) and `canTransfer`(read-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). ## Specifications @@ -344,18 +346,18 @@ Several rules are available in multiple access-control variants. Use the simples ### Summary tab -| Rule | Type
[ready-only / read-write] | ERC-721 / ERC-1155 | ERC-3643 | Security Audit planned in the roadmap | Description | +| Rule | Type
[read-only / read-write] | ERC-721 / ERC-1155 | ERC-3643 | Security Audit planned in the roadmap | Description | | ------------------------------------------------------------ | ------------------------------------ | ------------------ | -------- | ------------------------------------- | ------------------------------------------------------------ | -| RuleWhitelist | Ready-only | ☑ | ☑ | ☑ | This rule can be used to restrict transfers from/to only addresses inside a whitelist. | -| RuleWhitelistWrapper | Ready-only | ☑ | ☑ | ☑ | This rule can be used to restrict transfers from/to only addresses inside a group of whitelist rules managed by different operators. | -| RuleBlacklist | Ready-only | ☑ | ☑ | ☑ | This rule can be used to forbid transfer from/to addresses in the blacklist | -| RuleSanctionList | Ready-only | ☑ | ☑ | ☑ | The purpose of this contract is to use the oracle contract from [Chainalysis](https://go.chainalysis.com/chainalysis-oracle-docs.html) to forbid transfer from/to an address included in a sanctions designation (US, EU, or UN). | -| RuleMaxTotalSupply | Ready-only | — | ☑ | ☑ | This rule limits minting so that the total supply never exceeds a configured maximum. | -| RuleIdentityRegistry | Ready-only | ☑ | ☑ | ☑ | This rule checks the ERC-3643 Identity Registry for transfer participants when configured. | -| RuleERC2980 | Ready-only | ☑ | ☑ | ☒ | ERC-2980 Swiss Compliant rule combining a whitelist (recipient-only) and a frozenlist (blocks both sender and recipient). Frozenlist takes priority over whitelist. | -| RuleConditionalTransferLight | Ready-Write | — | ☑ | ☒
(experimental rule) | This rule requires that transfers have to be approved by an operator before being executed. Each approval is consumed once and the same transfer can be approved multiple times. | -| [RuleConditionalTransfer](https://github.com/CMTA/RuleConditionalTransfer) (external) | Ready-Write | — | ☑ | ☒
(experimental rule) | Full-featured approval-based transfer rule implementing Swiss law *Vinkulierung*. Supports automatic approval after three months, automatic transfer execution, and a conditional whitelist for address pairs that bypass approval. Maintained in a separate repository. | -| [RuleSelf](https://github.com/rya-sge/ruleself) (community) | — | — | — | ☒
(community project) | Community-maintained rule project. Not developed or maintained by CMTA. | +| RuleWhitelist | Read-only | | | | This rule can be used to restrict transfers from/to only addresses inside a whitelist. | +| RuleWhitelistWrapper | Read-Only | | | | This rule can be used to restrict transfers from/to only addresses inside a group of whitelist rules managed by different operators. | +| RuleBlacklist | Read-Only | | | | This rule can be used to forbid transfer from/to addresses in the blacklist | +| RuleSanctionList | Read-Only | | | | The purpose of this contract is to use the oracle contract from [Chainalysis](https://go.chainalysis.com/chainalysis-oracle-docs.html) to forbid transfer from/to an address included in a sanctions designation (US, EU, or UN). | +| RuleMaxTotalSupply | Read-Only | | | | This rule limits minting so that the total supply never exceeds a configured maximum. | +| RuleIdentityRegistry | Read-Only | | | | This rule checks the ERC-3643 Identity Registry for transfer participants when configured. | +| RuleERC2980 | Read-Only | | | | ERC-2980 Swiss Compliant rule combining a whitelist (recipient-only) and a frozenlist (blocks both sender and recipient). Frozenlist takes priority over whitelist. | +| RuleConditionalTransferLight | Read-Write | | | | This rule requires that transfers have to be approved by an operator before being executed. Each approval is consumed once and the same transfer can be approved multiple times. | +| [RuleConditionalTransfer](https://github.com/CMTA/RuleConditionalTransfer) (external) | Read-Write | | |
(experimental rule) | Full-featured approval-based transfer rule implementing Swiss law *Vinkulierung*. Supports automatic approval after three months, automatic transfer execution, and a conditional whitelist for address pairs that bypass approval. Maintained in a separate repository. | +| [RuleSelf](https://github.com/rya-sge/ruleself) (community) | — | | — |
(community project) | Use [Self](https://self.xyz), a zero-knowledge identity solution to determine which is allowed to interact with the token.
Community-maintained rule project. Not developed or maintained by CMTA. | All rules are compatible with CMTAT, as noted earlier in this README. @@ -365,14 +367,14 @@ Detailed technical documentation for each rule is available in [`doc/technical/` | Rule | Document | | ---- | -------- | -| RuleWhitelist | [RuleWhitelist.md](doc/technical/RuleWhitelist.md) | -| RuleWhitelistWrapper | [RuleWhitelistWrapper.md](doc/technical/RuleWhitelistWrapper.md) | -| RuleBlacklist | [RuleBlacklist.md](doc/technical/RuleBlacklist.md) | -| RuleSanctionsList | [RuleSanctionList.md](doc/technical/RuleSanctionList.md) | -| RuleMaxTotalSupply | [RuleMaxTotalSupply.md](doc/technical/RuleMaxTotalSupply.md) | -| RuleIdentityRegistry | [RuleIdentityRegistry.md](doc/technical/RuleIdentityRegistry.md) | -| RuleERC2980 | [RuleERC2980.md](doc/technical/RuleERC2980.md) | -| RuleConditionalTransferLight | [RuleConditionalTransferLight.md](doc/technical/RuleConditionalTransferLight.md) | +| RuleWhitelist | [RuleWhitelist.md](./doc/technical/RuleWhitelist.md) | +| RuleWhitelistWrapper | [RuleWhitelistWrapper.md](./doc/technical/RuleWhitelistWrapper.md) | +| RuleBlacklist | [RuleBlacklist.md](./doc/technical/RuleBlacklist.md) | +| RuleSanctionsList | [RuleSanctionList.md](./doc/technical/RuleSanctionList.md) | +| RuleMaxTotalSupply | [RuleMaxTotalSupply.md](./doc/technical/RuleMaxTotalSupply.md) | +| RuleIdentityRegistry | [RuleIdentityRegistry.md](./doc/technical/RuleIdentityRegistry.md) | +| RuleERC2980 | [RuleERC2980.md](./doc/technical/RuleERC2980.md) | +| RuleConditionalTransferLight | [RuleConditionalTransferLight.md](./doc/technical/RuleConditionalTransferLight.md) | ### Operational Notes @@ -667,6 +669,10 @@ To run a specific test, use forge test --match-contract --match-test ``` +- For `RuleConditionalTransferLight` fuzz/integration tests, note that mint and burn paths (`from == address(0)` or `to == address(0)`) are intentionally exempt from approval consumption. +- Ownable2Step variants also include dedicated tests for ownership transfer and manager-only functions (IdentityRegistry, MaxTotalSupply, SanctionsList). +- Coverage-focused tests also target deployment wrappers and operation-rule overloads (`created`, `destroyed`, spender-aware `transferred`) to improve line/function coverage in `src/rules/operation` and `src/rules/validation/deployment`. + Generate gas report ```bash diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html similarity index 50% rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html rename to doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html index 6808037..65bc64a 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html +++ b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.func-sort-c.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSet.sol - functions - + LCOV - lcov.info - abstract/RuleAddressSet/RuleAddressSet.sol - functions + - + - +
LCOV - code coverage report
- + @@ -31,92 +31,100 @@ - - - + + + - + - - - + + + - - + + - +
Current view:top level - validation/abstract/RuleAddressSet - RuleAddressSet.sol (source / functions)top level - abstract/RuleAddressSet - RuleAddressSet.sol (source / functions) Hitlcov.info Lines:283287.5 %3434100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:91181.8 %1313100.0 %
Branches:2244 100.0 %
- - + + - - + + - - + + - - + + - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + +

Function Name Sort by function nameHit count Sort by hit countFunction Name Sort by function nameHit count Sort by hit count
RuleAddressSet._msgData0RuleAddressSet.contains2
RuleAddressSet.contains0RuleAddressSet._msgData4
RuleAddressSet.removeAddress3RuleAddressSet.onlyAddressListRemove8
RuleAddressSet.removeAddresses4RuleAddressSet.removeAddress8
RuleAddressSet.isAddressListed67
RuleAddressSet.addAddress105
RuleAddressSet.addAddresses17RuleAddressSet.areAddressesListed108
RuleAddressSet.listedAddressCount24RuleAddressSet.removeAddresses260
RuleAddressSet.addAddress52RuleAddressSet.addAddresses275
RuleAddressSet.isAddressListed60RuleAddressSet.onlyAddressListAdd275
RuleAddressSet.areAddressesListed84RuleAddressSet.listedAddressCount536
RuleAddressSet._contextSuffixLength207RuleAddressSet._msgSender882
RuleAddressSet._msgSender207RuleAddressSet._contextSuffixLength886

- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.func.html similarity index 50% rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html rename to doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.func.html index 3ebf795..5984b78 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.func.html +++ b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.func.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSet.sol - functions - + LCOV - lcov.info - abstract/RuleAddressSet/RuleAddressSet.sol - functions + - + - +
LCOV - code coverage report
- + @@ -31,92 +31,100 @@ - - - + + + - + - - - + + + - - + + - +
Current view:top level - validation/abstract/RuleAddressSet - RuleAddressSet.sol (source / functions)top level - abstract/RuleAddressSet - RuleAddressSet.sol (source / functions) Hitlcov.info Lines:283287.5 %3434100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:91181.8 %1313100.0 %
Branches:2244 100.0 %
- - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit countFunction Name Sort by function nameHit count Sort by hit count
RuleAddressSet._contextSuffixLength207RuleAddressSet._contextSuffixLength886
RuleAddressSet._msgData0RuleAddressSet._msgData4
RuleAddressSet._msgSender207RuleAddressSet._msgSender882
RuleAddressSet.addAddress52RuleAddressSet.addAddress105
RuleAddressSet.addAddresses17RuleAddressSet.addAddresses275
RuleAddressSet.areAddressesListed84RuleAddressSet.areAddressesListed108
RuleAddressSet.contains0RuleAddressSet.contains2
RuleAddressSet.isAddressListed60RuleAddressSet.isAddressListed67
RuleAddressSet.listedAddressCount24RuleAddressSet.listedAddressCount536
RuleAddressSet.removeAddress3RuleAddressSet.onlyAddressListAdd275
RuleAddressSet.removeAddresses4RuleAddressSet.onlyAddressListRemove8
RuleAddressSet.removeAddress8
RuleAddressSet.removeAddresses260

- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html similarity index 75% rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html rename to doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html index cded5ef..cef3ac8 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html +++ b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSet.sol.gcov.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSet.sol - + LCOV - lcov.info - abstract/RuleAddressSet/RuleAddressSet.sol + - + - +
LCOV - code coverage report
- + @@ -31,34 +31,34 @@ - - - + + + - + - - - + + + - - + + - +
Current view:top level - validation/abstract/RuleAddressSet - RuleAddressSet.sol (source / functions)top level - abstract/RuleAddressSet - RuleAddressSet.sol (source / functions) Hitlcov.info Lines:283287.5 %3434100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:91181.8 %1313100.0 %
Branches:2244 100.0 %
@@ -72,168 +72,170 @@ 1 : : // SPDX-License-Identifier: MPL-2.0 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 : : //////////////////////////////////////////////////////////////*/ + 4 : : import {MetaTxModuleStandalone, ERC2771Context} from "../../../../modules/MetaTxModuleStandalone.sol"; + 5 : : import {RuleAddressSetInternal} from "./RuleAddressSetInternal.sol"; + 6 : : import {RuleAddressSetInvariantStorage} from "./invariantStorage/RuleAddressSetInvariantStorage.sol"; + 7 : : /* ==== Interfaces === */ + 8 : : import {IIdentityRegistryContains} from "../../../interfaces/IIdentityRegistry.sol"; + 9 : : import {IAddressList} from "../../../interfaces/IAddressList.sol"; + 10 : : /** + 11 : : * @title Rule Address Set + 12 : : * @notice Manages a permissioned set of addresses related to rule logic. + 13 : : * @dev + 14 : : * - Provides controlled functions for adding and removing addresses. + 15 : : * - Integrates `AccessControl` for role-based access. + 16 : : * - Supports gasless transactions via ERC-2771 meta-transactions. + 17 : : * - Extends internal logic defined in {RuleAddressSetInternal}. + 18 : : */ + 19 : : + 20 : : abstract contract RuleAddressSet is + 21 : : MetaTxModuleStandalone, + 22 : : RuleAddressSetInternal, + 23 : : RuleAddressSetInvariantStorage, + 24 : : IAddressList + 25 : : { + 26 : : /*////////////////////////////////////////////////////////////// + 27 : : STATE + 28 : : //////////////////////////////////////////////////////////////*/ + 29 : : + 30 : : /*////////////////////////////////////////////////////////////// + 31 : : CONSTRUCTOR + 32 : : //////////////////////////////////////////////////////////////*/ + 33 : : + 34 : : /** + 35 : : * @notice Initializes the RuleAddressSet contract. + 36 : : * @param forwarderIrrevocable Address of the ERC2771 forwarder (for meta-transactions). + 37 : : */ + 38 : : constructor(address forwarderIrrevocable) MetaTxModuleStandalone(forwarderIrrevocable) {} + 39 : : + 40 : : /*////////////////////////////////////////////////////////////// + 41 : : CORE LOGIC + 42 : : //////////////////////////////////////////////////////////////*/ + 43 : : + 44 : : /** + 45 : : * @notice Adds multiple addresses to the set. + 46 : : * @dev + 47 : : * - Does not revert if an address is already listed. + 48 : : * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`. + 49 : : * @param targetAddresses Array of addresses to be added. + 50 : : */ + 51 : 275 : function addAddresses(address[] calldata targetAddresses) public onlyAddressListAdd { + 52 : 274 : _addAddresses(targetAddresses); + 53 : 274 : emit AddAddresses(targetAddresses); + 54 : : } 55 : : 56 : : /** - 57 : : * @notice Adds multiple addresses to the set. + 57 : : * @notice Removes multiple addresses from 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. + 59 : : * - Does not revert if an address is not listed. + 60 : : * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`. + 61 : : * @param targetAddresses Array of addresses to remove. 62 : : */ - 63 : 17 : function addAddresses(address[] calldata targetAddresses) public onlyRole(ADDRESS_LIST_ADD_ROLE) { - 64 : 16 : _addAddresses(targetAddresses); - 65 : 16 : emit AddAddresses(targetAddresses); + 63 : 260 : function removeAddresses(address[] calldata targetAddresses) public onlyAddressListRemove { + 64 : 259 : _removeAddresses(targetAddresses); + 65 : 259 : emit RemoveAddresses(targetAddresses); 66 : : } 67 : : 68 : : /** - 69 : : * @notice Removes multiple addresses from the set. + 69 : : * @notice Adds a single address to 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. + 71 : : * - Reverts if the address is already listed. + 72 : : * - Accessible only by accounts with the `ADDRESS_LIST_ADD_ROLE`. + 73 : : * @param targetAddress The address to be added. 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 : 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 : : } + 75 : 105 : function addAddress(address targetAddress) public onlyAddressListAdd { + 76 [ + + ]: 102 : require(!_isAddressListed(targetAddress), RuleAddressSet_AddressAlreadyListed()); + 77 : 101 : _addAddress(targetAddress); + 78 : 101 : emit AddAddress(targetAddress); + 79 : : } + 80 : : + 81 : : /** + 82 : : * @notice Removes a single address from the set. + 83 : : * @dev + 84 : : * - Reverts if the address is not listed. + 85 : : * - Accessible only by accounts with the `ADDRESS_LIST_REMOVE_ROLE`. + 86 : : * @param targetAddress The address to be removed. + 87 : : */ + 88 : 8 : function removeAddress(address targetAddress) public onlyAddressListRemove { + 89 [ + + ]: 5 : require(_isAddressListed(targetAddress), RuleAddressSet_AddressNotFound()); + 90 : 4 : _removeAddress(targetAddress); + 91 : 4 : emit RemoveAddress(targetAddress); + 92 : : } + 93 : : + 94 : : /*////////////////////////////////////////////////////////////// + 95 : : ACCESS CONTROL + 96 : : //////////////////////////////////////////////////////////////*/ + 97 : : + 98 : 275 : modifier onlyAddressListAdd() { + 99 : 275 : _authorizeAddressListAdd(); + 100 : : _; + 101 : : } + 102 : : + 103 : 8 : modifier onlyAddressListRemove() { + 104 : 8 : _authorizeAddressListRemove(); + 105 : : _; + 106 : : } + 107 : : + 108 : : function _authorizeAddressListAdd() internal view virtual; 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 : 219 : 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 : 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 : : /*////////////////////////////////////////////////////////////// - 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 : : } + 110 : : function _authorizeAddressListRemove() internal view virtual; + 111 : : + 112 : : /** + 113 : : * @notice Returns the total number of currently listed addresses. + 114 : : * @return count The number of listed addresses. + 115 : : */ + 116 : 536 : function listedAddressCount() public view returns (uint256 count) { + 117 : 536 : count = _listedAddressCount(); + 118 : : } + 119 : : + 120 : : /** + 121 : : * @notice Checks whether a specific address is currently listed. + 122 : : * @param targetAddress The address to check. + 123 : : * @return isListed True if listed, false otherwise. + 124 : : */ + 125 : 2 : function contains(address targetAddress) public view override(IIdentityRegistryContains) returns (bool isListed) { + 126 : 2 : isListed = _isAddressListed(targetAddress); + 127 : : } + 128 : : + 129 : : /** + 130 : : * @notice Checks whether a specific address is currently listed. + 131 : : * @param targetAddress The address to check. + 132 : : * @return isListed True if listed, false otherwise. + 133 : : */ + 134 : 67 : function isAddressListed(address targetAddress) public view returns (bool isListed) { + 135 : 383 : isListed = _isAddressListed(targetAddress); + 136 : : } + 137 : : + 138 : : /** + 139 : : * @notice Checks multiple addresses in a single call. + 140 : : * @param targetAddresses Array of addresses to check. + 141 : : * @return results Array of booleans corresponding to listing status. + 142 : : */ + 143 : 108 : function areAddressesListed(address[] memory targetAddresses) public view returns (bool[] memory results) { + 144 : 108 : results = new bool[](targetAddresses.length); + 145 : 108 : for (uint256 i = 0; i < targetAddresses.length; ++i) { + 146 : 244 : results[i] = _isAddressListed(targetAddresses[i]); + 147 : : } + 148 : : } + 149 : : /*////////////////////////////////////////////////////////////// + 150 : : ERC-2771 META TX + 151 : : //////////////////////////////////////////////////////////////*/ + 152 : : + 153 : : /// @inheritdoc ERC2771Context + 154 : 882 : function _msgSender() internal view virtual override(ERC2771Context) returns (address sender) { + 155 : 882 : return ERC2771Context._msgSender(); + 156 : : } + 157 : : + 158 : : /// @inheritdoc ERC2771Context + 159 : 4 : function _msgData() internal view virtual override(ERC2771Context) returns (bytes calldata) { + 160 : 4 : return ERC2771Context._msgData(); + 161 : : } + 162 : : + 163 : : /// @inheritdoc ERC2771Context + 164 : 886 : function _contextSuffixLength() internal view virtual override(ERC2771Context) returns (uint256) { + 165 : 886 : return ERC2771Context._contextSuffixLength(); + 166 : : } + 167 : : } @@ -241,7 +243,7 @@
- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html similarity index 56% rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html rename to doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html index 715669b..a58da58 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html +++ b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func-sort-c.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol - functions - + LCOV - lcov.info - abstract/RuleAddressSet/RuleAddressSetInternal.sol - functions + - + - +
LCOV - code coverage report
- + @@ -31,13 +31,13 @@ - - + + - + @@ -49,54 +49,54 @@ - - - + + + - +
Current view:top level - validation/abstract/RuleAddressSet - RuleAddressSetInternal.sol (source / functions)top level - abstract/RuleAddressSet - RuleAddressSetInternal.sol (source / functions) Hitlcov.info Lines:14141818 100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions: 6 Branches:00-44100.0 %
- - + + - - + + - - + + - - + + - - + + - - + + - - + +

Function Name Sort by function nameHit count Sort by hit countFunction Name Sort by function nameHit count Sort by hit count
RuleAddressSetInternal._removeAddress1RuleAddressSetInternal._removeAddress4
RuleAddressSetInternal._removeAddresses3RuleAddressSetInternal._addAddress101
RuleAddressSetInternal._addAddresses16RuleAddressSetInternal._removeAddresses259
RuleAddressSetInternal._listedAddressCount24RuleAddressSetInternal._addAddresses274
RuleAddressSetInternal._addAddress50RuleAddressSetInternal._listedAddressCount536
RuleAddressSetInternal._isAddressListed463RuleAddressSetInternal._isAddressListed738

- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html similarity index 56% rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html rename to doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html index bfbd673..c1510d8 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html +++ b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.func.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol - functions - + LCOV - lcov.info - abstract/RuleAddressSet/RuleAddressSetInternal.sol - functions + - + - +
LCOV - code coverage report
- + @@ -31,13 +31,13 @@ - - + + - + @@ -49,54 +49,54 @@ - - - + + + - +
Current view:top level - validation/abstract/RuleAddressSet - RuleAddressSetInternal.sol (source / functions)top level - abstract/RuleAddressSet - RuleAddressSetInternal.sol (source / functions) Hitlcov.info Lines:14141818 100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions: 6 Branches:00-44100.0 %
- - + + - - + + - - + + - - + + - - + + - - + + - - + +

Function Name Sort by function nameHit count Sort by hit countFunction Name Sort by function nameHit count Sort by hit count
RuleAddressSetInternal._addAddress50RuleAddressSetInternal._addAddress101
RuleAddressSetInternal._addAddresses16RuleAddressSetInternal._addAddresses274
RuleAddressSetInternal._isAddressListed463RuleAddressSetInternal._isAddressListed738
RuleAddressSetInternal._listedAddressCount24RuleAddressSetInternal._listedAddressCount536
RuleAddressSetInternal._removeAddress1RuleAddressSetInternal._removeAddress4
RuleAddressSetInternal._removeAddresses3RuleAddressSetInternal._removeAddresses259

- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html similarity index 67% rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html rename to doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html index c60105a..9518c01 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html +++ b/doc/coverage/coverage/abstract/RuleAddressSet/RuleAddressSetInternal.sol.gcov.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol - + LCOV - lcov.info - abstract/RuleAddressSet/RuleAddressSetInternal.sol + - + - +
LCOV - code coverage report
- + @@ -31,13 +31,13 @@ - - + + - + @@ -49,16 +49,16 @@ - - - + + + - +
Current view:top level - validation/abstract/RuleAddressSet - RuleAddressSetInternal.sol (source / functions)top level - abstract/RuleAddressSet - RuleAddressSetInternal.sol (source / functions) Hitlcov.info Lines:14141818 100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions: 6 Branches:00-44100.0 %
@@ -103,59 +103,77 @@ 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 : 463 : function _isAddressListed(address targetAddress) internal view returns (bool isListed) { - 85 : 463 : isListed = _listedAddresses.contains(targetAddress); - 86 : : } - 87 : : } + 35 : : * @return added The number of newly added addresses. + 36 : : * @return skipped The number of addresses that were already listed. + 37 : : */ + 38 : 274 : function _addAddresses(address[] calldata addressesToAdd) + 39 : : internal + 40 : : returns (uint256 added, uint256 skipped) + 41 : : { + 42 : 274 : for (uint256 i = 0; i < addressesToAdd.length; ++i) { + 43 [ + + ]: 806 : if (_listedAddresses.add(addressesToAdd[i])) { + 44 : 548 : added += 1; + 45 : : } else { + 46 : 258 : skipped += 1; + 47 : : } + 48 : : } + 49 : : } + 50 : : + 51 : : /** + 52 : : * @notice Removes multiple addresses from the set. + 53 : : * @dev + 54 : : * - Does not revert if an address is not found. + 55 : : * - Skips non-existing entries silently. + 56 : : * @param addressesToRemove The array of addresses to remove. + 57 : : * @return removed The number of addresses removed. + 58 : : * @return skipped The number of addresses that were not listed. + 59 : : */ + 60 : 259 : function _removeAddresses(address[] calldata addressesToRemove) + 61 : : internal + 62 : : returns (uint256 removed, uint256 skipped) + 63 : : { + 64 : 259 : for (uint256 i = 0; i < addressesToRemove.length; ++i) { + 65 [ + + ]: 775 : if (_listedAddresses.remove(addressesToRemove[i])) { + 66 : 518 : removed += 1; + 67 : : } else { + 68 : 257 : skipped += 1; + 69 : : } + 70 : : } + 71 : : } + 72 : : + 73 : : /** + 74 : : * @notice Adds a single address to the set. + 75 : : * @param targetAddress The address to add. + 76 : : */ + 77 : 101 : function _addAddress(address targetAddress) internal virtual { + 78 : 101 : _listedAddresses.add(targetAddress); + 79 : : } + 80 : : + 81 : : /** + 82 : : * @notice Removes a single address from the set. + 83 : : * @param targetAddress The address to remove. + 84 : : */ + 85 : 4 : function _removeAddress(address targetAddress) internal virtual { + 86 : 4 : _listedAddresses.remove(targetAddress); + 87 : : } + 88 : : + 89 : : /** + 90 : : * @notice Returns the total number of listed addresses. + 91 : : * @return count The number of listed addresses. + 92 : : */ + 93 : 536 : function _listedAddressCount() internal view virtual returns (uint256 count) { + 94 : 536 : count = _listedAddresses.length(); + 95 : : } + 96 : : + 97 : : /** + 98 : : * @notice Checks if an address is listed. + 99 : : * @param targetAddress The address to check. + 100 : : * @return isListed True if the address is listed, false otherwise. + 101 : : */ + 102 : 738 : function _isAddressListed(address targetAddress) internal view virtual returns (bool isListed) { + 103 : 738 : isListed = _listedAddresses.contains(targetAddress); + 104 : : } + 105 : : } @@ -163,7 +181,7 @@
- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/validation/abstract/index-sort-b.html b/doc/coverage/coverage/abstract/RuleAddressSet/index-sort-b.html similarity index 74% rename from doc/coverage/coverage/validation/abstract/index-sort-b.html rename to doc/coverage/coverage/abstract/RuleAddressSet/index-sort-b.html index 5fe0919..f299290 100644 --- a/doc/coverage/coverage/validation/abstract/index-sort-b.html +++ b/doc/coverage/coverage/abstract/RuleAddressSet/index-sort-b.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/abstract + LCOV - lcov.info - abstract/RuleAddressSet @@ -19,7 +19,7 @@ - + @@ -31,26 +31,26 @@ - - - + + + - + - - - + + + - - + + @@ -82,28 +82,28 @@ - + - - - - - - + + + + + + - + - + - +
Current view:top level - validation/abstracttop level - abstract/RuleAddressSet Hitlcov.info Lines:293193.5 %5252100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:101190.9 %1919100.0 %
Branches:101088 100.0 %
Branches Sort by branch coverage
RuleValidateTransfer.solRuleAddressSet.sol -
80.0%80.0%
+
100.0%
80.0 %8 / 1080.0 %4 / 5-0 / 0100.0 %34 / 34100.0 %13 / 13100.0 %4 / 4
RuleWhitelistCommon.solRuleAddressSetInternal.sol
100.0%
100.0 %21 / 2118 / 18 100.0 % 6 / 6 100.0 %10 / 104 / 4
diff --git a/doc/coverage/coverage/validation/abstract/index-sort-f.html b/doc/coverage/coverage/abstract/RuleAddressSet/index-sort-f.html similarity index 74% rename from doc/coverage/coverage/validation/abstract/index-sort-f.html rename to doc/coverage/coverage/abstract/RuleAddressSet/index-sort-f.html index b7e1816..3713f5e 100644 --- a/doc/coverage/coverage/validation/abstract/index-sort-f.html +++ b/doc/coverage/coverage/abstract/RuleAddressSet/index-sort-f.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/abstract + LCOV - lcov.info - abstract/RuleAddressSet @@ -19,7 +19,7 @@ - + @@ -31,26 +31,26 @@ - - - + + + - + - - - + + + - - + + @@ -82,28 +82,28 @@ - + - - - - - - + + + + + + - + - + - + - +
Current view:top level - validation/abstracttop level - abstract/RuleAddressSet Hitlcov.info Lines:293193.5 %5252100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:101190.9 %1919100.0 %
Branches:101088 100.0 %
Branches Sort by branch coverage
RuleValidateTransfer.solRuleAddressSetInternal.sol -
80.0%80.0%
+
100.0%
80.0 %8 / 1080.0 %4 / 5-0 / 0100.0 %18 / 18100.0 %6 / 6100.0 %4 / 4
RuleWhitelistCommon.solRuleAddressSet.sol
100.0%
100.0 %21 / 2134 / 34 100.0 %6 / 613 / 13 100.0 %10 / 104 / 4
diff --git a/doc/coverage/coverage/validation/abstract/index-sort-l.html b/doc/coverage/coverage/abstract/RuleAddressSet/index-sort-l.html similarity index 74% rename from doc/coverage/coverage/validation/abstract/index-sort-l.html rename to doc/coverage/coverage/abstract/RuleAddressSet/index-sort-l.html index f752721..2a0de5c 100644 --- a/doc/coverage/coverage/validation/abstract/index-sort-l.html +++ b/doc/coverage/coverage/abstract/RuleAddressSet/index-sort-l.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/abstract + LCOV - lcov.info - abstract/RuleAddressSet @@ -19,7 +19,7 @@ - + @@ -31,26 +31,26 @@ - - - + + + - + - - - + + + - - + + @@ -82,28 +82,28 @@ - + - - - - - - + + + + + + - + - + - + - +
Current view:top level - validation/abstracttop level - abstract/RuleAddressSet Hitlcov.info Lines:293193.5 %5252100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:101190.9 %1919100.0 %
Branches:101088 100.0 %
Branches Sort by branch coverage
RuleValidateTransfer.solRuleAddressSetInternal.sol -
80.0%80.0%
+
100.0%
80.0 %8 / 1080.0 %4 / 5-0 / 0100.0 %18 / 18100.0 %6 / 6100.0 %4 / 4
RuleWhitelistCommon.solRuleAddressSet.sol
100.0%
100.0 %21 / 2134 / 34 100.0 %6 / 613 / 13 100.0 %10 / 104 / 4
diff --git a/doc/coverage/coverage/validation/abstract/index.html b/doc/coverage/coverage/abstract/RuleAddressSet/index.html similarity index 74% rename from doc/coverage/coverage/validation/abstract/index.html rename to doc/coverage/coverage/abstract/RuleAddressSet/index.html index 34817f4..9eb35f0 100644 --- a/doc/coverage/coverage/validation/abstract/index.html +++ b/doc/coverage/coverage/abstract/RuleAddressSet/index.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/abstract + LCOV - lcov.info - abstract/RuleAddressSet @@ -19,7 +19,7 @@ - + @@ -31,26 +31,26 @@ - - - + + + - + - - - + + + - - + + @@ -82,28 +82,28 @@ - + - - - - - - + + + + + + - + - + - +
Current view:top level - validation/abstracttop level - abstract/RuleAddressSet Hitlcov.info Lines:293193.5 %5252100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:101190.9 %1919100.0 %
Branches:101088 100.0 %
Branches Sort by branch coverage
RuleValidateTransfer.solRuleAddressSet.sol -
80.0%80.0%
+
100.0%
80.0 %8 / 1080.0 %4 / 5-0 / 0100.0 %34 / 34100.0 %13 / 13100.0 %4 / 4
RuleWhitelistCommon.solRuleAddressSetInternal.sol
100.0%
100.0 %21 / 2118 / 18 100.0 % 6 / 6 100.0 %10 / 104 / 4
diff --git a/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.func-sort-c.html b/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.func-sort-c.html new file mode 100644 index 0000000..d226506 --- /dev/null +++ b/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.func-sort-c.html @@ -0,0 +1,129 @@ + + + + + + + LCOV - lcov.info - abstract/RuleERC2980/RuleERC2980Internal.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/RuleERC2980 - RuleERC2980Internal.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:3636100.0 %
Date:2026-03-10 10:55:10Functions:1212100.0 %
Branches:88100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleERC2980Internal._removeFrozenlistAddresses2
RuleERC2980Internal._removeWhitelistAddresses3
RuleERC2980Internal._addFrozenlistAddresses4
RuleERC2980Internal._addWhitelistAddresses4
RuleERC2980Internal._frozenlistCount4
RuleERC2980Internal._removeFrozenlistAddress4
RuleERC2980Internal._removeWhitelistAddress4
RuleERC2980Internal._whitelistCount5
RuleERC2980Internal._addFrozenlistAddress18
RuleERC2980Internal._addWhitelistAddress39
RuleERC2980Internal._isWhitelisted82
RuleERC2980Internal._isFrozen90
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.func.html b/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.func.html new file mode 100644 index 0000000..446e1ca --- /dev/null +++ b/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.func.html @@ -0,0 +1,129 @@ + + + + + + + LCOV - lcov.info - abstract/RuleERC2980/RuleERC2980Internal.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/RuleERC2980 - RuleERC2980Internal.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:3636100.0 %
Date:2026-03-10 10:55:10Functions:1212100.0 %
Branches:88100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleERC2980Internal._addFrozenlistAddress18
RuleERC2980Internal._addFrozenlistAddresses4
RuleERC2980Internal._addWhitelistAddress39
RuleERC2980Internal._addWhitelistAddresses4
RuleERC2980Internal._frozenlistCount4
RuleERC2980Internal._isFrozen90
RuleERC2980Internal._isWhitelisted82
RuleERC2980Internal._removeFrozenlistAddress4
RuleERC2980Internal._removeFrozenlistAddresses2
RuleERC2980Internal._removeWhitelistAddress4
RuleERC2980Internal._removeWhitelistAddresses3
RuleERC2980Internal._whitelistCount5
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.gcov.html b/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.gcov.html new file mode 100644 index 0000000..324d892 --- /dev/null +++ b/doc/coverage/coverage/abstract/RuleERC2980/RuleERC2980Internal.sol.gcov.html @@ -0,0 +1,205 @@ + + + + + + + LCOV - lcov.info - abstract/RuleERC2980/RuleERC2980Internal.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/RuleERC2980 - RuleERC2980Internal.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:3636100.0 %
Date:2026-03-10 10:55:10Functions:1212100.0 %
Branches:88100.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : pragma solidity ^0.8.20;
+       3                 :            : 
+       4                 :            : /* ==== OpenZeppelin === */
+       5                 :            : import {EnumerableSet} from "OZ/utils/structs/EnumerableSet.sol";
+       6                 :            : 
+       7                 :            : /**
+       8                 :            :  * @title RuleERC2980Internal
+       9                 :            :  * @notice Internal storage and helpers for two independent address sets:
+      10                 :            :  *         a whitelist and a frozenlist, following the same pattern as {RuleAddressSetInternal}.
+      11                 :            :  * @dev
+      12                 :            :  * - Whitelist: only whitelisted addresses may receive tokens.
+      13                 :            :  * - Frozenlist: frozen addresses may neither send nor receive tokens.
+      14                 :            :  * - Batch operations do not revert when individual entries are already present or absent.
+      15                 :            :  */
+      16                 :            : abstract contract RuleERC2980Internal {
+      17                 :            :     using EnumerableSet for EnumerableSet.AddressSet;
+      18                 :            : 
+      19                 :            :     /*//////////////////////////////////////////////////////////////
+      20                 :            :                              STATE VARIABLES
+      21                 :            :     //////////////////////////////////////////////////////////////*/
+      22                 :            : 
+      23                 :            :     /// @dev Addresses allowed to receive tokens.
+      24                 :            :     EnumerableSet.AddressSet private _whitelist;
+      25                 :            : 
+      26                 :            :     /// @dev Addresses completely blocked from sending and receiving tokens.
+      27                 :            :     EnumerableSet.AddressSet private _frozenlist;
+      28                 :            : 
+      29                 :            :     /*//////////////////////////////////////////////////////////////
+      30                 :            :                           WHITELIST — INTERNAL
+      31                 :            :     //////////////////////////////////////////////////////////////*/
+      32                 :            : 
+      33                 :          4 :     function _addWhitelistAddresses(address[] calldata addressesToAdd)
+      34                 :            :         internal
+      35                 :            :         returns (uint256 added, uint256 skipped)
+      36                 :            :     {
+      37                 :          4 :         for (uint256 i = 0; i < addressesToAdd.length; ++i) {
+      38         [ +  + ]:          6 :             if (_whitelist.add(addressesToAdd[i])) {
+      39                 :          5 :                 added += 1;
+      40                 :            :             } else {
+      41                 :          1 :                 skipped += 1;
+      42                 :            :             }
+      43                 :            :         }
+      44                 :            :     }
+      45                 :            : 
+      46                 :          3 :     function _removeWhitelistAddresses(address[] calldata addressesToRemove)
+      47                 :            :         internal
+      48                 :            :         returns (uint256 removed, uint256 skipped)
+      49                 :            :     {
+      50                 :          3 :         for (uint256 i = 0; i < addressesToRemove.length; ++i) {
+      51         [ +  + ]:          3 :             if (_whitelist.remove(addressesToRemove[i])) {
+      52                 :          2 :                 removed += 1;
+      53                 :            :             } else {
+      54                 :          1 :                 skipped += 1;
+      55                 :            :             }
+      56                 :            :         }
+      57                 :            :     }
+      58                 :            : 
+      59                 :         39 :     function _addWhitelistAddress(address targetAddress) internal virtual {
+      60                 :         39 :         _whitelist.add(targetAddress);
+      61                 :            :     }
+      62                 :            : 
+      63                 :          4 :     function _removeWhitelistAddress(address targetAddress) internal virtual {
+      64                 :          4 :         _whitelist.remove(targetAddress);
+      65                 :            :     }
+      66                 :            : 
+      67                 :         82 :     function _isWhitelisted(address targetAddress) internal view virtual returns (bool) {
+      68                 :         82 :         return _whitelist.contains(targetAddress);
+      69                 :            :     }
+      70                 :            : 
+      71                 :          5 :     function _whitelistCount() internal view virtual returns (uint256) {
+      72                 :          5 :         return _whitelist.length();
+      73                 :            :     }
+      74                 :            : 
+      75                 :            :     /*//////////////////////////////////////////////////////////////
+      76                 :            :                          FROZENLIST — INTERNAL
+      77                 :            :     //////////////////////////////////////////////////////////////*/
+      78                 :            : 
+      79                 :          4 :     function _addFrozenlistAddresses(address[] calldata addressesToAdd)
+      80                 :            :         internal
+      81                 :            :         returns (uint256 added, uint256 skipped)
+      82                 :            :     {
+      83                 :          4 :         for (uint256 i = 0; i < addressesToAdd.length; ++i) {
+      84         [ +  + ]:          6 :             if (_frozenlist.add(addressesToAdd[i])) {
+      85                 :          5 :                 added += 1;
+      86                 :            :             } else {
+      87                 :          1 :                 skipped += 1;
+      88                 :            :             }
+      89                 :            :         }
+      90                 :            :     }
+      91                 :            : 
+      92                 :          2 :     function _removeFrozenlistAddresses(address[] calldata addressesToRemove)
+      93                 :            :         internal
+      94                 :            :         returns (uint256 removed, uint256 skipped)
+      95                 :            :     {
+      96                 :          2 :         for (uint256 i = 0; i < addressesToRemove.length; ++i) {
+      97         [ +  + ]:          2 :             if (_frozenlist.remove(addressesToRemove[i])) {
+      98                 :          1 :                 removed += 1;
+      99                 :            :             } else {
+     100                 :          1 :                 skipped += 1;
+     101                 :            :             }
+     102                 :            :         }
+     103                 :            :     }
+     104                 :            : 
+     105                 :         18 :     function _addFrozenlistAddress(address targetAddress) internal virtual {
+     106                 :         18 :         _frozenlist.add(targetAddress);
+     107                 :            :     }
+     108                 :            : 
+     109                 :          4 :     function _removeFrozenlistAddress(address targetAddress) internal virtual {
+     110                 :          4 :         _frozenlist.remove(targetAddress);
+     111                 :            :     }
+     112                 :            : 
+     113                 :         90 :     function _isFrozen(address targetAddress) internal view virtual returns (bool) {
+     114                 :         90 :         return _frozenlist.contains(targetAddress);
+     115                 :            :     }
+     116                 :            : 
+     117                 :          4 :     function _frozenlistCount() internal view virtual returns (uint256) {
+     118                 :          4 :         return _frozenlist.length();
+     119                 :            :     }
+     120                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/RuleERC2980/index-sort-b.html b/doc/coverage/coverage/abstract/RuleERC2980/index-sort-b.html new file mode 100644 index 0000000..446dbb6 --- /dev/null +++ b/doc/coverage/coverage/abstract/RuleERC2980/index-sort-b.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - abstract/RuleERC2980 + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/RuleERC2980HitTotalCoverage
Test:lcov.infoLines:3636100.0 %
Date:2026-03-10 10:55:10Functions:1212100.0 %
Branches:88100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleERC2980Internal.sol +
100.0%
+
100.0 %36 / 36100.0 %12 / 12100.0 %8 / 8
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/RuleERC2980/index-sort-f.html b/doc/coverage/coverage/abstract/RuleERC2980/index-sort-f.html new file mode 100644 index 0000000..774722e --- /dev/null +++ b/doc/coverage/coverage/abstract/RuleERC2980/index-sort-f.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - abstract/RuleERC2980 + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/RuleERC2980HitTotalCoverage
Test:lcov.infoLines:3636100.0 %
Date:2026-03-10 10:55:10Functions:1212100.0 %
Branches:88100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleERC2980Internal.sol +
100.0%
+
100.0 %36 / 36100.0 %12 / 12100.0 %8 / 8
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/RuleERC2980/index-sort-l.html b/doc/coverage/coverage/abstract/RuleERC2980/index-sort-l.html new file mode 100644 index 0000000..c94493f --- /dev/null +++ b/doc/coverage/coverage/abstract/RuleERC2980/index-sort-l.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - abstract/RuleERC2980 + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/RuleERC2980HitTotalCoverage
Test:lcov.infoLines:3636100.0 %
Date:2026-03-10 10:55:10Functions:1212100.0 %
Branches:88100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleERC2980Internal.sol +
100.0%
+
100.0 %36 / 36100.0 %12 / 12100.0 %8 / 8
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/RuleERC2980/index.html b/doc/coverage/coverage/abstract/RuleERC2980/index.html new file mode 100644 index 0000000..07b52e2 --- /dev/null +++ b/doc/coverage/coverage/abstract/RuleERC2980/index.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - abstract/RuleERC2980 + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/RuleERC2980HitTotalCoverage
Test:lcov.infoLines:3636100.0 %
Date:2026-03-10 10:55:10Functions:1212100.0 %
Branches:88100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleERC2980Internal.sol +
100.0%
+
100.0 %36 / 36100.0 %12 / 12100.0 %8 / 8
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.func-sort-c.html b/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.func-sort-c.html new file mode 100644 index 0000000..72252b1 --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.func-sort-c.html @@ -0,0 +1,117 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleBlacklistBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleBlacklistBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:3333100.0 %
Date:2026-03-10 10:55:10Functions:99100.0 %
Branches:1414100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleBlacklistBase.transferred.12
RuleBlacklistBase._transferredFrom4
RuleBlacklistBase.canReturnTransferRestrictionCode4
RuleBlacklistBase.messageForTransferRestriction12
RuleBlacklistBase._detectTransferRestrictionFrom22
RuleBlacklistBase.transferred.058
RuleBlacklistBase._transferred61
RuleBlacklistBase.supportsInterface61
RuleBlacklistBase._detectTransferRestriction106
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.func.html b/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.func.html new file mode 100644 index 0000000..44a9b55 --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.func.html @@ -0,0 +1,117 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleBlacklistBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleBlacklistBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:3333100.0 %
Date:2026-03-10 10:55:10Functions:99100.0 %
Branches:1414100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleBlacklistBase._detectTransferRestriction106
RuleBlacklistBase._detectTransferRestrictionFrom22
RuleBlacklistBase._transferred61
RuleBlacklistBase._transferredFrom4
RuleBlacklistBase.canReturnTransferRestrictionCode4
RuleBlacklistBase.messageForTransferRestriction12
RuleBlacklistBase.supportsInterface61
RuleBlacklistBase.transferred.058
RuleBlacklistBase.transferred.12
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.gcov.html b/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.gcov.html new file mode 100644 index 0000000..a3fe955 --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleBlacklistBase.sol.gcov.html @@ -0,0 +1,210 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleBlacklistBase.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleBlacklistBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:3333100.0 %
Date:2026-03-10 10:55:10Functions:99100.0 %
Branches:1414100.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : pragma solidity ^0.8.20;
+       3                 :            : 
+       4                 :            : import {RuleAddressSet} from "../RuleAddressSet/RuleAddressSet.sol";
+       5                 :            : import {RuleNFTAdapter} from "../core/RuleNFTAdapter.sol";
+       6                 :            : import {RuleTransferValidation} from "../core/RuleTransferValidation.sol";
+       7                 :            : import {RuleBlacklistInvariantStorage} from "../RuleAddressSet/invariantStorage/RuleBlacklistInvariantStorage.sol";
+       8                 :            : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+       9                 :            : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+      10                 :            : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+      11                 :            : import {IRule} from "RuleEngine/interfaces/IRule.sol";
+      12                 :            : 
+      13                 :            : /**
+      14                 :            :  * @title RuleBlacklistBase
+      15                 :            :  * @notice Core blacklist logic without access-control policy.
+      16                 :            :  */
+      17                 :            : abstract contract RuleBlacklistBase is RuleAddressSet, RuleNFTAdapter, RuleBlacklistInvariantStorage {
+      18                 :            :     constructor(address forwarderIrrevocable) RuleAddressSet(forwarderIrrevocable) {}
+      19                 :            : 
+      20                 :        106 :     function _detectTransferRestriction(address from, address to, uint256 /* value */ )
+      21                 :            :         internal
+      22                 :            :         view
+      23                 :            :         override
+      24                 :            :         returns (uint8)
+      25                 :            :     {
+      26         [ +  + ]:        106 :         if (isAddressListed(from)) {
+      27                 :         23 :             return CODE_ADDRESS_FROM_IS_BLACKLISTED;
+      28            [ + ]:         83 :         } else if (isAddressListed(to)) {
+      29                 :         19 :             return CODE_ADDRESS_TO_IS_BLACKLISTED;
+      30                 :            :         }
+      31                 :         64 :         return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+      32                 :            :     }
+      33                 :            : 
+      34                 :         22 :     function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+      35                 :            :         internal
+      36                 :            :         view
+      37                 :            :         override
+      38                 :            :         returns (uint8)
+      39                 :            :     {
+      40            [ + ]:         22 :         if (isAddressListed(spender)) {
+      41                 :          8 :             return CODE_ADDRESS_SPENDER_IS_BLACKLISTED;
+      42                 :            :         }
+      43                 :         14 :         return _detectTransferRestriction(from, to, value);
+      44                 :            :     }
+      45                 :            : 
+      46                 :          4 :     function canReturnTransferRestrictionCode(uint8 restrictionCode)
+      47                 :            :         public
+      48                 :            :         pure
+      49                 :            :         virtual
+      50                 :            :         override(IRule)
+      51                 :            :         returns (bool)
+      52                 :            :     {
+      53                 :          4 :         return restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED || restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED
+      54                 :          1 :             || restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED;
+      55                 :            :     }
+      56                 :            : 
+      57                 :         12 :     function messageForTransferRestriction(uint8 restrictionCode)
+      58                 :            :         public
+      59                 :            :         pure
+      60                 :            :         virtual
+      61                 :            :         override(IERC1404)
+      62                 :            :         returns (string memory)
+      63                 :            :     {
+      64         [ +  + ]:         12 :         if (restrictionCode == CODE_ADDRESS_FROM_IS_BLACKLISTED) {
+      65                 :          5 :             return TEXT_ADDRESS_FROM_IS_BLACKLISTED;
+      66         [ +  + ]:          7 :         } else if (restrictionCode == CODE_ADDRESS_TO_IS_BLACKLISTED) {
+      67                 :          3 :             return TEXT_ADDRESS_TO_IS_BLACKLISTED;
+      68         [ +  + ]:          4 :         } else if (restrictionCode == CODE_ADDRESS_SPENDER_IS_BLACKLISTED) {
+      69                 :          1 :             return TEXT_ADDRESS_SPENDER_IS_BLACKLISTED;
+      70                 :            :         } else {
+      71                 :          3 :             return TEXT_CODE_NOT_FOUND;
+      72                 :            :         }
+      73                 :            :     }
+      74                 :            : 
+      75                 :         61 :     function supportsInterface(bytes4 interfaceId) public view virtual override(RuleTransferValidation) returns (bool) {
+      76                 :         61 :         return RuleTransferValidation.supportsInterface(interfaceId);
+      77                 :            :     }
+      78                 :            : 
+      79                 :            :     /**
+      80                 :            :      * @inheritdoc IERC3643IComplianceContract
+      81                 :            :      * @dev Validation only; does not modify state.
+      82                 :            :      */
+      83                 :         58 :     function transferred(address from, address to, uint256 value)
+      84                 :            :         public
+      85                 :            :         view
+      86                 :            :         virtual
+      87                 :            :         override(IERC3643IComplianceContract)
+      88                 :            :     {
+      89                 :         58 :         _transferred(from, to, value);
+      90                 :            :     }
+      91                 :            : 
+      92                 :            :     /**
+      93                 :            :      * @inheritdoc IRuleEngine
+      94                 :            :      * @dev Validation only; does not modify state.
+      95                 :            :      */
+      96                 :          2 :     function transferred(address spender, address from, address to, uint256 value)
+      97                 :            :         public
+      98                 :            :         view
+      99                 :            :         virtual
+     100                 :            :         override(IRuleEngine)
+     101                 :            :     {
+     102                 :          2 :         _transferredFrom(spender, from, to, value);
+     103                 :            :     }
+     104                 :            : 
+     105                 :         61 :     function _transferred(address from, address to, uint256 value) internal view virtual override {
+     106                 :         61 :         uint8 code = _detectTransferRestriction(from, to, value);
+     107         [ +  + ]:         61 :         require(
+     108                 :            :             code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+     109                 :            :             RuleBlacklist_InvalidTransfer(address(this), from, to, value, code)
+     110                 :            :         );
+     111                 :            :     }
+     112                 :            : 
+     113                 :          4 :     function _transferredFrom(address spender, address from, address to, uint256 value)
+     114                 :            :         internal
+     115                 :            :         view
+     116                 :            :         virtual
+     117                 :            :         override
+     118                 :            :     {
+     119                 :          4 :         uint8 code = _detectTransferRestrictionFrom(spender, from, to, value);
+     120         [ +  + ]:          4 :         require(
+     121                 :            :             code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
+     122                 :            :             RuleBlacklist_InvalidTransferFrom(address(this), spender, from, to, value, code)
+     123                 :            :         );
+     124                 :            :     }
+     125                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.func-sort-c.html b/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.func-sort-c.html new file mode 100644 index 0000000..b58d1b5 --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.func-sort-c.html @@ -0,0 +1,213 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleERC2980Base.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleERC2980Base.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:102102100.0 %
Date:2026-03-10 10:55:10Functions:3333100.0 %
Branches:2525100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleERC2980Base.areFrozen1
RuleERC2980Base.areWhitelisted1
RuleERC2980Base.supportsInterface1
RuleERC2980Base._msgData2
RuleERC2980Base.onlyFrozenlistRemove2
RuleERC2980Base.removeFrozenlistAddresses2
RuleERC2980Base.transferred.12
RuleERC2980Base._transferredFrom3
RuleERC2980Base.isVerified3
RuleERC2980Base.frozenlist4
RuleERC2980Base.frozenlistAddressCount4
RuleERC2980Base.removeWhitelistAddresses4
RuleERC2980Base.transferred.04
RuleERC2980Base._transferred5
RuleERC2980Base.canReturnTransferRestrictionCode5
RuleERC2980Base.messageForTransferRestriction5
RuleERC2980Base.whitelist5
RuleERC2980Base.whitelistAddressCount5
RuleERC2980Base.addFrozenlistAddresses6
RuleERC2980Base.addWhitelistAddresses6
RuleERC2980Base.onlyFrozenlistAdd6
RuleERC2980Base.onlyWhitelistAdd6
RuleERC2980Base.onlyWhitelistRemove7
RuleERC2980Base.removeFrozenlistAddress7
RuleERC2980Base.removeWhitelistAddress7
RuleERC2980Base._detectTransferRestrictionFrom8
RuleERC2980Base.isFrozen12
RuleERC2980Base.isWhitelisted13
RuleERC2980Base._detectTransferRestriction22
RuleERC2980Base.addFrozenlistAddress22
RuleERC2980Base.addWhitelistAddress43
RuleERC2980Base._msgSender267
RuleERC2980Base._contextSuffixLength269
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.func.html b/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.func.html new file mode 100644 index 0000000..fa4bcca --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.func.html @@ -0,0 +1,213 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleERC2980Base.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleERC2980Base.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:102102100.0 %
Date:2026-03-10 10:55:10Functions:3333100.0 %
Branches:2525100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleERC2980Base._contextSuffixLength269
RuleERC2980Base._detectTransferRestriction22
RuleERC2980Base._detectTransferRestrictionFrom8
RuleERC2980Base._msgData2
RuleERC2980Base._msgSender267
RuleERC2980Base._transferred5
RuleERC2980Base._transferredFrom3
RuleERC2980Base.addFrozenlistAddress22
RuleERC2980Base.addFrozenlistAddresses6
RuleERC2980Base.addWhitelistAddress43
RuleERC2980Base.addWhitelistAddresses6
RuleERC2980Base.areFrozen1
RuleERC2980Base.areWhitelisted1
RuleERC2980Base.canReturnTransferRestrictionCode5
RuleERC2980Base.frozenlist4
RuleERC2980Base.frozenlistAddressCount4
RuleERC2980Base.isFrozen12
RuleERC2980Base.isVerified3
RuleERC2980Base.isWhitelisted13
RuleERC2980Base.messageForTransferRestriction5
RuleERC2980Base.onlyFrozenlistAdd6
RuleERC2980Base.onlyFrozenlistRemove2
RuleERC2980Base.onlyWhitelistAdd6
RuleERC2980Base.onlyWhitelistRemove7
RuleERC2980Base.removeFrozenlistAddress7
RuleERC2980Base.removeFrozenlistAddresses2
RuleERC2980Base.removeWhitelistAddress7
RuleERC2980Base.removeWhitelistAddresses4
RuleERC2980Base.supportsInterface1
RuleERC2980Base.transferred.04
RuleERC2980Base.transferred.12
RuleERC2980Base.whitelist5
RuleERC2980Base.whitelistAddressCount5
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.gcov.html b/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.gcov.html new file mode 100644 index 0000000..89784e8 --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleERC2980Base.sol.gcov.html @@ -0,0 +1,473 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleERC2980Base.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleERC2980Base.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:102102100.0 %
Date:2026-03-10 10:55:10Functions:3333100.0 %
Branches:2525100.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : pragma solidity ^0.8.20;
+       3                 :            : 
+       4                 :            : import {MetaTxModuleStandalone, ERC2771Context} from "../../../../modules/MetaTxModuleStandalone.sol";
+       5                 :            : import {RuleERC2980Internal} from "../RuleERC2980/RuleERC2980Internal.sol";
+       6                 :            : import {RuleERC2980InvariantStorage} from "../RuleERC2980/invariantStorage/RuleERC2980InvariantStorage.sol";
+       7                 :            : import {RuleNFTAdapter} from "../core/RuleNFTAdapter.sol";
+       8                 :            : import {RuleTransferValidation} from "../core/RuleTransferValidation.sol";
+       9                 :            : /* ==== Interfaces === */
+      10                 :            : import {IERC2980} from "../../../interfaces/IERC2980.sol";
+      11                 :            : import {IIdentityRegistryVerified} from "../../../interfaces/IIdentityRegistry.sol";
+      12                 :            : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+      13                 :            : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+      14                 :            : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+      15                 :            : import {IRule} from "RuleEngine/interfaces/IRule.sol";
+      16                 :            : 
+      17                 :            : /**
+      18                 :            :  * @title RuleERC2980Base
+      19                 :            :  * @notice Core ERC-2980 Swiss Compliant transfer restriction logic combining a whitelist and a frozenlist.
+      20                 :            :  * @dev
+      21                 :            :  * Transfer logic (frozenlist takes priority over whitelist):
+      22                 :            :  * 1. If `from`, `to`, or `spender` is frozen → transfer is blocked.
+      23                 :            :  * 2. If `to` is not whitelisted → transfer is blocked.
+      24                 :            :  * Note: `from` does NOT need to be whitelisted to send tokens it already holds.
+      25                 :            :  *
+      26                 :            :  * Provides public management functions for both lists with abstract authorization hooks
+      27                 :            :  * so concrete subclasses can plug in their preferred access-control mechanism.
+      28                 :            :  */
+      29                 :            : abstract contract RuleERC2980Base is
+      30                 :            :     MetaTxModuleStandalone,
+      31                 :            :     RuleERC2980Internal,
+      32                 :            :     RuleERC2980InvariantStorage,
+      33                 :            :     RuleNFTAdapter,
+      34                 :            :     IERC2980,
+      35                 :            :     IIdentityRegistryVerified
+      36                 :            : {
+      37                 :            :     /*//////////////////////////////////////////////////////////////
+      38                 :            :                               CONSTRUCTOR
+      39                 :            :     //////////////////////////////////////////////////////////////*/
+      40                 :            : 
+      41                 :            :     constructor(address forwarderIrrevocable) MetaTxModuleStandalone(forwarderIrrevocable) {}
+      42                 :            : 
+      43                 :            :     /*//////////////////////////////////////////////////////////////
+      44                 :            :                          TRANSFER RESTRICTION LOGIC
+      45                 :            :     //////////////////////////////////////////////////////////////*/
+      46                 :            : 
+      47                 :         22 :     function _detectTransferRestriction(address from, address to, uint256 /* value */ )
+      48                 :            :         internal
+      49                 :            :         view
+      50                 :            :         virtual
+      51                 :            :         override
+      52                 :            :         returns (uint8)
+      53                 :            :     {
+      54                 :            :         // Frozenlist check has priority
+      55         [ +  + ]:         22 :         if (_isFrozen(from)) {
+      56                 :          4 :             return CODE_ADDRESS_FROM_IS_FROZEN;
+      57            [ + ]:         18 :         } else if (_isFrozen(to)) {
+      58                 :          4 :             return CODE_ADDRESS_TO_IS_FROZEN;
+      59                 :            :         }
+      60                 :            :         // Whitelist check: only the recipient must be whitelisted
+      61            [ + ]:         14 :         if (!_isWhitelisted(to)) {
+      62                 :          4 :             return CODE_ADDRESS_TO_NOT_WHITELISTED;
+      63                 :            :         }
+      64                 :         10 :         return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+      65                 :            :     }
+      66                 :            : 
+      67                 :          8 :     function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+      68                 :            :         internal
+      69                 :            :         view
+      70                 :            :         virtual
+      71                 :            :         override
+      72                 :            :         returns (uint8)
+      73                 :            :     {
+      74            [ + ]:          8 :         if (_isFrozen(spender)) {
+      75                 :          4 :             return CODE_ADDRESS_SPENDER_IS_FROZEN;
+      76                 :            :         }
+      77                 :          4 :         return _detectTransferRestriction(from, to, value);
+      78                 :            :     }
+      79                 :            : 
+      80                 :            :     /*//////////////////////////////////////////////////////////////
+      81                 :            :                         ERC-3643 / IRuleEngine HOOKS
+      82                 :            :     //////////////////////////////////////////////////////////////*/
+      83                 :            : 
+      84                 :          4 :     function transferred(address from, address to, uint256 value)
+      85                 :            :         public
+      86                 :            :         view
+      87                 :            :         virtual
+      88                 :            :         override(IERC3643IComplianceContract)
+      89                 :            :     {
+      90                 :          4 :         _transferred(from, to, value);
+      91                 :            :     }
+      92                 :            : 
+      93                 :          2 :     function transferred(address spender, address from, address to, uint256 value)
+      94                 :            :         public
+      95                 :            :         view
+      96                 :            :         virtual
+      97                 :            :         override(IRuleEngine)
+      98                 :            :     {
+      99                 :          2 :         _transferredFrom(spender, from, to, value);
+     100                 :            :     }
+     101                 :            : 
+     102                 :          5 :     function _transferred(address from, address to, uint256 value) internal view virtual override {
+     103                 :          5 :         uint8 code = _detectTransferRestriction(from, to, value);
+     104         [ +  + ]:          5 :         require(
+     105                 :            :             code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+     106                 :            :             RuleERC2980_InvalidTransfer(address(this), from, to, value, code)
+     107                 :            :         );
+     108                 :            :     }
+     109                 :            : 
+     110                 :          3 :     function _transferredFrom(address spender, address from, address to, uint256 value)
+     111                 :            :         internal
+     112                 :            :         view
+     113                 :            :         virtual
+     114                 :            :         override
+     115                 :            :     {
+     116                 :          3 :         uint8 code = _detectTransferRestrictionFrom(spender, from, to, value);
+     117         [ +  + ]:          3 :         require(
+     118                 :            :             code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+     119                 :            :             RuleERC2980_InvalidTransferFrom(address(this), spender, from, to, value, code)
+     120                 :            :         );
+     121                 :            :     }
+     122                 :            : 
+     123                 :            :     /*//////////////////////////////////////////////////////////////
+     124                 :            :                       RESTRICTION CODE HELPERS
+     125                 :            :     //////////////////////////////////////////////////////////////*/
+     126                 :            : 
+     127                 :          5 :     function canReturnTransferRestrictionCode(uint8 restrictionCode)
+     128                 :            :         public
+     129                 :            :         pure
+     130                 :            :         virtual
+     131                 :            :         override(IRule)
+     132                 :            :         returns (bool)
+     133                 :            :     {
+     134                 :          5 :         return restrictionCode == CODE_ADDRESS_FROM_IS_FROZEN || restrictionCode == CODE_ADDRESS_TO_IS_FROZEN
+     135                 :          3 :             || restrictionCode == CODE_ADDRESS_SPENDER_IS_FROZEN
+     136                 :          2 :             || restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED;
+     137                 :            :     }
+     138                 :            : 
+     139                 :          5 :     function messageForTransferRestriction(uint8 restrictionCode)
+     140                 :            :         public
+     141                 :            :         pure
+     142                 :            :         virtual
+     143                 :            :         override(IERC1404)
+     144                 :            :         returns (string memory)
+     145                 :            :     {
+     146         [ +  + ]:          5 :         if (restrictionCode == CODE_ADDRESS_FROM_IS_FROZEN) {
+     147                 :          1 :             return TEXT_ADDRESS_FROM_IS_FROZEN;
+     148         [ +  + ]:          4 :         } else if (restrictionCode == CODE_ADDRESS_TO_IS_FROZEN) {
+     149                 :          1 :             return TEXT_ADDRESS_TO_IS_FROZEN;
+     150         [ +  + ]:          3 :         } else if (restrictionCode == CODE_ADDRESS_SPENDER_IS_FROZEN) {
+     151                 :          1 :             return TEXT_ADDRESS_SPENDER_IS_FROZEN;
+     152         [ +  + ]:          2 :         } else if (restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) {
+     153                 :          1 :             return TEXT_ADDRESS_TO_NOT_WHITELISTED;
+     154                 :            :         } else {
+     155                 :          1 :             return TEXT_CODE_NOT_FOUND;
+     156                 :            :         }
+     157                 :            :     }
+     158                 :            : 
+     159                 :            :     /*//////////////////////////////////////////////////////////////
+     160                 :            :                        WHITELIST MANAGEMENT
+     161                 :            :     //////////////////////////////////////////////////////////////*/
+     162                 :            : 
+     163                 :            :     /**
+     164                 :            :      * @notice Adds multiple addresses to the whitelist.
+     165                 :            :      * @dev Does not revert if an address is already listed.
+     166                 :            :      */
+     167                 :          6 :     function addWhitelistAddresses(address[] calldata targetAddresses) public onlyWhitelistAdd {
+     168                 :          4 :         _addWhitelistAddresses(targetAddresses);
+     169                 :          4 :         emit AddWhitelistAddresses(targetAddresses);
+     170                 :            :     }
+     171                 :            : 
+     172                 :            :     /**
+     173                 :            :      * @notice Removes multiple addresses from the whitelist.
+     174                 :            :      * @dev Does not revert if an address is not listed.
+     175                 :            :      */
+     176                 :          4 :     function removeWhitelistAddresses(address[] calldata targetAddresses) public onlyWhitelistRemove {
+     177                 :          3 :         _removeWhitelistAddresses(targetAddresses);
+     178                 :          3 :         emit RemoveWhitelistAddresses(targetAddresses);
+     179                 :            :     }
+     180                 :            : 
+     181                 :            :     /**
+     182                 :            :      * @notice Adds a single address to the whitelist.
+     183                 :            :      * @dev
+     184                 :            :      * Reverts if the address is already listed.
+     185                 :            :      * Deviation from ERC-2980 `Whitelistable` example interface: the spec's `addAddressToWhitelist`
+     186                 :            :      * returns `false` on duplicates instead of reverting. This implementation follows the codebase
+     187                 :            :      * convention of reverting on invalid single-item operations.
+     188                 :            :      */
+     189                 :         43 :     function addWhitelistAddress(address targetAddress) public onlyWhitelistAdd {
+     190         [ +  + ]:         40 :         require(!_isWhitelisted(targetAddress), RuleERC2980_AddressAlreadyListed());
+     191                 :         39 :         _addWhitelistAddress(targetAddress);
+     192                 :         39 :         emit AddWhitelistAddress(targetAddress);
+     193                 :            :     }
+     194                 :            : 
+     195                 :            :     /**
+     196                 :            :      * @notice Removes a single address from the whitelist.
+     197                 :            :      * @dev
+     198                 :            :      * Reverts if the address is not listed.
+     199                 :            :      * Deviation from ERC-2980 `Whitelistable` example interface: the spec's `removeAddressFromWhitelist`
+     200                 :            :      * returns `false` when not found instead of reverting. This implementation follows the codebase
+     201                 :            :      * convention of reverting on invalid single-item operations.
+     202                 :            :      */
+     203                 :          7 :     function removeWhitelistAddress(address targetAddress) public onlyWhitelistRemove {
+     204         [ +  + ]:          5 :         require(_isWhitelisted(targetAddress), RuleERC2980_AddressNotFound());
+     205                 :          4 :         _removeWhitelistAddress(targetAddress);
+     206                 :          4 :         emit RemoveWhitelistAddress(targetAddress);
+     207                 :            :     }
+     208                 :            : 
+     209                 :            :     /**
+     210                 :            :      * @notice Returns the number of whitelisted addresses.
+     211                 :            :      */
+     212                 :          5 :     function whitelistAddressCount() public view returns (uint256) {
+     213                 :          5 :         return _whitelistCount();
+     214                 :            :     }
+     215                 :            : 
+     216                 :            :     /**
+     217                 :            :      * @notice Returns true if the address is in the whitelist.
+     218                 :            :      */
+     219                 :         13 :     function isWhitelisted(address targetAddress) public view returns (bool) {
+     220                 :         13 :         return _isWhitelisted(targetAddress);
+     221                 :            :     }
+     222                 :            : 
+     223                 :            :     /**
+     224                 :            :      * @notice ERC-2980 getter: returns true if the address is whitelisted.
+     225                 :            :      */
+     226                 :          5 :     function whitelist(address _operator) public view virtual override(IERC2980) returns (bool) {
+     227                 :          5 :         return _isWhitelisted(_operator);
+     228                 :            :     }
+     229                 :            : 
+     230                 :            :     /**
+     231                 :            :      * @notice Returns true if the address is whitelisted (identity-verified).
+     232                 :            :      * @dev Reflects whitelist membership only. Frozen status is intentionally excluded:
+     233                 :            :      * freezing is a temporary enforcement action and does not revoke identity verification.
+     234                 :            :      */
+     235                 :          3 :     function isVerified(address targetAddress)
+     236                 :            :         public
+     237                 :            :         view
+     238                 :            :         virtual
+     239                 :            :         override(IIdentityRegistryVerified)
+     240                 :            :         returns (bool)
+     241                 :            :     {
+     242                 :          3 :         return _isWhitelisted(targetAddress);
+     243                 :            :     }
+     244                 :            : 
+     245                 :            :     /**
+     246                 :            :      * @notice Checks multiple addresses for whitelist membership.
+     247                 :            :      */
+     248                 :          1 :     function areWhitelisted(address[] memory targetAddresses) public view returns (bool[] memory results) {
+     249                 :          1 :         results = new bool[](targetAddresses.length);
+     250                 :          1 :         for (uint256 i = 0; i < targetAddresses.length; ++i) {
+     251                 :          2 :             results[i] = _isWhitelisted(targetAddresses[i]);
+     252                 :            :         }
+     253                 :            :     }
+     254                 :            : 
+     255                 :            :     /*//////////////////////////////////////////////////////////////
+     256                 :            :                       FROZENLIST MANAGEMENT
+     257                 :            :     //////////////////////////////////////////////////////////////*/
+     258                 :            : 
+     259                 :            :     /**
+     260                 :            :      * @notice Adds multiple addresses to the frozenlist.
+     261                 :            :      * @dev Does not revert if an address is already listed.
+     262                 :            :      */
+     263                 :          6 :     function addFrozenlistAddresses(address[] calldata targetAddresses) public onlyFrozenlistAdd {
+     264                 :          4 :         _addFrozenlistAddresses(targetAddresses);
+     265                 :          4 :         emit AddFrozenlistAddresses(targetAddresses);
+     266                 :            :     }
+     267                 :            : 
+     268                 :            :     /**
+     269                 :            :      * @notice Removes multiple addresses from the frozenlist.
+     270                 :            :      * @dev Does not revert if an address is not listed.
+     271                 :            :      */
+     272                 :          2 :     function removeFrozenlistAddresses(address[] calldata targetAddresses) public onlyFrozenlistRemove {
+     273                 :          2 :         _removeFrozenlistAddresses(targetAddresses);
+     274                 :          2 :         emit RemoveFrozenlistAddresses(targetAddresses);
+     275                 :            :     }
+     276                 :            : 
+     277                 :            :     /**
+     278                 :            :      * @notice Adds a single address to the frozenlist.
+     279                 :            :      * @dev
+     280                 :            :      * Reverts if the address is already listed.
+     281                 :            :      * Deviation from ERC-2980 `Freezable` example interface: the spec's `addAddressToFrozenlist`
+     282                 :            :      * returns `false` on duplicates instead of reverting. This implementation follows the codebase
+     283                 :            :      * convention of reverting on invalid single-item operations.
+     284                 :            :      */
+     285                 :         22 :     function addFrozenlistAddress(address targetAddress) public onlyFrozenlistAdd {
+     286         [ +  + ]:         19 :         require(!_isFrozen(targetAddress), RuleERC2980_AddressAlreadyListed());
+     287                 :         18 :         _addFrozenlistAddress(targetAddress);
+     288                 :         18 :         emit AddFrozenlistAddress(targetAddress);
+     289                 :            :     }
+     290                 :            : 
+     291                 :            :     /**
+     292                 :            :      * @notice Removes a single address from the frozenlist.
+     293                 :            :      * @dev
+     294                 :            :      * Reverts if the address is not listed.
+     295                 :            :      * Deviation from ERC-2980 `Freezable` example interface: the spec's `removeAddressFromFrozenlist`
+     296                 :            :      * returns `false` when not found instead of reverting. This implementation follows the codebase
+     297                 :            :      * convention of reverting on invalid single-item operations.
+     298                 :            :      */
+     299                 :          7 :     function removeFrozenlistAddress(address targetAddress) public onlyFrozenlistRemove {
+     300         [ +  + ]:          5 :         require(_isFrozen(targetAddress), RuleERC2980_AddressNotFound());
+     301                 :          4 :         _removeFrozenlistAddress(targetAddress);
+     302                 :          4 :         emit RemoveFrozenlistAddress(targetAddress);
+     303                 :            :     }
+     304                 :            : 
+     305                 :            :     /**
+     306                 :            :      * @notice Returns the number of frozen addresses.
+     307                 :            :      */
+     308                 :          4 :     function frozenlistAddressCount() public view returns (uint256) {
+     309                 :          4 :         return _frozenlistCount();
+     310                 :            :     }
+     311                 :            : 
+     312                 :            :     /**
+     313                 :            :      * @notice Returns true if the address is in the frozenlist.
+     314                 :            :      */
+     315                 :         12 :     function isFrozen(address targetAddress) public view returns (bool) {
+     316                 :         12 :         return _isFrozen(targetAddress);
+     317                 :            :     }
+     318                 :            : 
+     319                 :            :     /**
+     320                 :            :      * @notice ERC-2980 getter: returns true if the address is frozen.
+     321                 :            :      */
+     322                 :          4 :     function frozenlist(address _operator) public view virtual override(IERC2980) returns (bool) {
+     323                 :          4 :         return _isFrozen(_operator);
+     324                 :            :     }
+     325                 :            : 
+     326                 :            :     /**
+     327                 :            :      * @notice Checks multiple addresses for frozenlist membership.
+     328                 :            :      */
+     329                 :          1 :     function areFrozen(address[] memory targetAddresses) public view returns (bool[] memory results) {
+     330                 :          1 :         results = new bool[](targetAddresses.length);
+     331                 :          1 :         for (uint256 i = 0; i < targetAddresses.length; ++i) {
+     332                 :          2 :             results[i] = _isFrozen(targetAddresses[i]);
+     333                 :            :         }
+     334                 :            :     }
+     335                 :            : 
+     336                 :            :     /*//////////////////////////////////////////////////////////////
+     337                 :            :                           INTERFACE SUPPORT
+     338                 :            :     //////////////////////////////////////////////////////////////*/
+     339                 :            : 
+     340                 :          1 :     function supportsInterface(bytes4 interfaceId) public view virtual override(RuleTransferValidation) returns (bool) {
+     341                 :          1 :         return RuleTransferValidation.supportsInterface(interfaceId);
+     342                 :            :     }
+     343                 :            : 
+     344                 :            :     /*//////////////////////////////////////////////////////////////
+     345                 :            :                             ACCESS CONTROL
+     346                 :            :     //////////////////////////////////////////////////////////////*/
+     347                 :            : 
+     348                 :          6 :     modifier onlyWhitelistAdd() {
+     349                 :          6 :         _authorizeWhitelistAdd();
+     350                 :            :         _;
+     351                 :            :     }
+     352                 :            : 
+     353                 :          7 :     modifier onlyWhitelistRemove() {
+     354                 :          7 :         _authorizeWhitelistRemove();
+     355                 :            :         _;
+     356                 :            :     }
+     357                 :            : 
+     358                 :          6 :     modifier onlyFrozenlistAdd() {
+     359                 :          6 :         _authorizeFrozenlistAdd();
+     360                 :            :         _;
+     361                 :            :     }
+     362                 :            : 
+     363                 :          2 :     modifier onlyFrozenlistRemove() {
+     364                 :          2 :         _authorizeFrozenlistRemove();
+     365                 :            :         _;
+     366                 :            :     }
+     367                 :            : 
+     368                 :            :     function _authorizeWhitelistAdd() internal view virtual;
+     369                 :            :     function _authorizeWhitelistRemove() internal view virtual;
+     370                 :            :     function _authorizeFrozenlistAdd() internal view virtual;
+     371                 :            :     function _authorizeFrozenlistRemove() internal view virtual;
+     372                 :            : 
+     373                 :            :     /*//////////////////////////////////////////////////////////////
+     374                 :            :                              ERC-2771 META TX
+     375                 :            :     //////////////////////////////////////////////////////////////*/
+     376                 :            : 
+     377                 :        267 :     function _msgSender() internal view virtual override(ERC2771Context) returns (address sender) {
+     378                 :        267 :         return ERC2771Context._msgSender();
+     379                 :            :     }
+     380                 :            : 
+     381                 :          2 :     function _msgData() internal view virtual override(ERC2771Context) returns (bytes calldata) {
+     382                 :          2 :         return ERC2771Context._msgData();
+     383                 :            :     }
+     384                 :            : 
+     385                 :        269 :     function _contextSuffixLength() internal view virtual override(ERC2771Context) returns (uint256) {
+     386                 :        269 :         return ERC2771Context._contextSuffixLength();
+     387                 :            :     }
+     388                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.func-sort-c.html b/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.func-sort-c.html new file mode 100644 index 0000000..2aa4d9c --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.func-sort-c.html @@ -0,0 +1,129 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleIdentityRegistryBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleIdentityRegistryBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:5151100.0 %
Date:2026-03-10 10:55:10Functions:1212100.0 %
Branches:1919100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleIdentityRegistryBase._transferred2
RuleIdentityRegistryBase._transferredFrom2
RuleIdentityRegistryBase.transferred.02
RuleIdentityRegistryBase.transferred.12
RuleIdentityRegistryBase.canReturnTransferRestrictionCode4
RuleIdentityRegistryBase.messageForTransferRestriction4
RuleIdentityRegistryBase.setIdentityRegistry4
RuleIdentityRegistryBase.clearIdentityRegistry5
RuleIdentityRegistryBase.onlyIdentityRegistryManager5
RuleIdentityRegistryBase._detectTransferRestrictionFrom9
RuleIdentityRegistryBase._detectTransferRestriction16
RuleIdentityRegistryBase.constructor26
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.func.html b/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.func.html new file mode 100644 index 0000000..9fdf83a --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.func.html @@ -0,0 +1,129 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleIdentityRegistryBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleIdentityRegistryBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:5151100.0 %
Date:2026-03-10 10:55:10Functions:1212100.0 %
Branches:1919100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleIdentityRegistryBase._detectTransferRestriction16
RuleIdentityRegistryBase._detectTransferRestrictionFrom9
RuleIdentityRegistryBase._transferred2
RuleIdentityRegistryBase._transferredFrom2
RuleIdentityRegistryBase.canReturnTransferRestrictionCode4
RuleIdentityRegistryBase.clearIdentityRegistry5
RuleIdentityRegistryBase.constructor26
RuleIdentityRegistryBase.messageForTransferRestriction4
RuleIdentityRegistryBase.onlyIdentityRegistryManager5
RuleIdentityRegistryBase.setIdentityRegistry4
RuleIdentityRegistryBase.transferred.02
RuleIdentityRegistryBase.transferred.12
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.gcov.html b/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.gcov.html new file mode 100644 index 0000000..a9ee475 --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleIdentityRegistryBase.sol.gcov.html @@ -0,0 +1,229 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleIdentityRegistryBase.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleIdentityRegistryBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:5151100.0 %
Date:2026-03-10 10:55:10Functions:1212100.0 %
Branches:1919100.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : pragma solidity ^0.8.20;
+       3                 :            : 
+       4                 :            : import {RuleNFTAdapter} from "../core/RuleNFTAdapter.sol";
+       5                 :            : import {RuleIdentityRegistryInvariantStorage} from "../invariant/RuleIdentityRegistryInvariantStorage.sol";
+       6                 :            : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+       7                 :            : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+       8                 :            : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+       9                 :            : import {IIdentityRegistryVerified} from "../../../interfaces/IIdentityRegistry.sol";
+      10                 :            : 
+      11                 :            : /**
+      12                 :            :  * @title RuleIdentityRegistryBase
+      13                 :            :  * @notice Checks the ERC-3643 Identity Registry for transfer participants when configured.
+      14                 :            :  * @dev Burns (to == address(0)) are allowed even if the sender is not verified.
+      15                 :            :  */
+      16                 :            : abstract contract RuleIdentityRegistryBase is RuleNFTAdapter, RuleIdentityRegistryInvariantStorage {
+      17                 :            :     IIdentityRegistryVerified public identityRegistry;
+      18                 :            : 
+      19                 :         26 :     constructor(address identityRegistry_) {
+      20            [ + ]:         26 :         if (identityRegistry_ != address(0)) {
+      21                 :         25 :             identityRegistry = IIdentityRegistryVerified(identityRegistry_);
+      22                 :            :         }
+      23                 :            :     }
+      24                 :            : 
+      25                 :          4 :     function setIdentityRegistry(address newRegistry) public onlyIdentityRegistryManager {
+      26         [ +  + ]:          2 :         require(newRegistry != address(0), RuleIdentityRegistry_RegistryAddressZeroNotAllowed());
+      27                 :          1 :         identityRegistry = IIdentityRegistryVerified(newRegistry);
+      28                 :          1 :         emit IdentityRegistryUpdated(newRegistry);
+      29                 :            :     }
+      30                 :            : 
+      31                 :          5 :     function clearIdentityRegistry() public onlyIdentityRegistryManager {
+      32                 :          3 :         identityRegistry = IIdentityRegistryVerified(address(0));
+      33                 :          3 :         emit IdentityRegistryUpdated(address(0));
+      34                 :            :     }
+      35                 :            : 
+      36                 :         16 :     function _detectTransferRestriction(address from, address to, uint256 /* value */)
+      37                 :            :         internal
+      38                 :            :         view
+      39                 :            :         override
+      40                 :            :         returns (uint8)
+      41                 :            :     {
+      42            [ + ]:         16 :         if (address(identityRegistry) == address(0)) {
+      43                 :          3 :             return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+      44                 :            :         }
+      45            [ + ]:         13 :         if (to == address(0)) {
+      46                 :          2 :             return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+      47                 :            :         }
+      48                 :            : 
+      49            [ + ]:         11 :         if (from != address(0) && !identityRegistry.isVerified(from)) {
+      50                 :          4 :             return CODE_ADDRESS_FROM_NOT_VERIFIED;
+      51                 :            :         }
+      52            [ + ]:          7 :         if (to != address(0) && !identityRegistry.isVerified(to)) {
+      53                 :          1 :             return CODE_ADDRESS_TO_NOT_VERIFIED;
+      54                 :            :         }
+      55                 :          6 :         return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+      56                 :            :     }
+      57                 :            : 
+      58                 :          9 :     function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+      59                 :            :         internal
+      60                 :            :         view
+      61                 :            :         override
+      62                 :            :         returns (uint8)
+      63                 :            :     {
+      64            [ + ]:          9 :         if (address(identityRegistry) == address(0)) {
+      65                 :          1 :             return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+      66                 :            :         }
+      67            [ + ]:          8 :         if (to == address(0)) {
+      68                 :          1 :             return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+      69                 :            :         }
+      70            [ + ]:          7 :         if (spender != address(0) && !identityRegistry.isVerified(spender)) {
+      71                 :          4 :             return CODE_ADDRESS_SPENDER_NOT_VERIFIED;
+      72                 :            :         }
+      73                 :          3 :         return _detectTransferRestriction(from, to, value);
+      74                 :            :     }
+      75                 :            : 
+      76                 :          2 :     function transferred(address from, address to, uint256 value)
+      77                 :            :         public
+      78                 :            :         view
+      79                 :            :         override(IERC3643IComplianceContract)
+      80                 :            :     {
+      81                 :          2 :         _transferred(from, to, value);
+      82                 :            :     }
+      83                 :            : 
+      84                 :          2 :     function transferred(address spender, address from, address to, uint256 value)
+      85                 :            :         public
+      86                 :            :         view
+      87                 :            :         override(IRuleEngine)
+      88                 :            :     {
+      89                 :          2 :         _transferredFrom(spender, from, to, value);
+      90                 :            :     }
+      91                 :            : 
+      92                 :          2 :     function _transferred(address from, address to, uint256 value) internal view virtual override {
+      93                 :          2 :         uint8 code = _detectTransferRestriction(from, to, value);
+      94         [ +  + ]:          2 :         require(
+      95                 :            :             code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+      96                 :            :             RuleIdentityRegistry_InvalidTransfer(address(this), from, to, value, code)
+      97                 :            :         );
+      98                 :            :     }
+      99                 :            : 
+     100                 :          2 :     function _transferredFrom(address spender, address from, address to, uint256 value)
+     101                 :            :         internal
+     102                 :            :         view
+     103                 :            :         virtual
+     104                 :            :         override
+     105                 :            :     {
+     106                 :          2 :         uint8 code = _detectTransferRestrictionFrom(spender, from, to, value);
+     107         [ +  + ]:          2 :         require(
+     108                 :            :             code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+     109                 :            :             RuleIdentityRegistry_InvalidTransferFrom(address(this), spender, from, to, value, code)
+     110                 :            :         );
+     111                 :            :     }
+     112                 :            : 
+     113                 :          4 :     function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override returns (bool) {
+     114                 :          4 :         return restrictionCode == CODE_ADDRESS_FROM_NOT_VERIFIED || restrictionCode == CODE_ADDRESS_TO_NOT_VERIFIED
+     115                 :          2 :             || restrictionCode == CODE_ADDRESS_SPENDER_NOT_VERIFIED;
+     116                 :            :     }
+     117                 :            : 
+     118                 :          4 :     function messageForTransferRestriction(uint8 restrictionCode)
+     119                 :            :         public
+     120                 :            :         pure
+     121                 :            :         override(IERC1404)
+     122                 :            :         returns (string memory)
+     123                 :            :     {
+     124         [ +  + ]:          4 :         if (restrictionCode == CODE_ADDRESS_FROM_NOT_VERIFIED) {
+     125                 :          1 :             return TEXT_ADDRESS_FROM_NOT_VERIFIED;
+     126         [ +  + ]:          3 :         } else if (restrictionCode == CODE_ADDRESS_TO_NOT_VERIFIED) {
+     127                 :          1 :             return TEXT_ADDRESS_TO_NOT_VERIFIED;
+     128            [ + ]:          2 :         } else if (restrictionCode == CODE_ADDRESS_SPENDER_NOT_VERIFIED) {
+     129                 :          1 :             return TEXT_ADDRESS_SPENDER_NOT_VERIFIED;
+     130                 :            :         }
+     131                 :          1 :         return TEXT_CODE_NOT_FOUND;
+     132                 :            :     }
+     133                 :            : 
+     134                 :            :     /*//////////////////////////////////////////////////////////////
+     135                 :            :                             ACCESS CONTROL
+     136                 :            :     //////////////////////////////////////////////////////////////*/
+     137                 :            : 
+     138                 :          5 :     modifier onlyIdentityRegistryManager() {
+     139                 :          5 :         _authorizeIdentityRegistryManager();
+     140                 :            :         _;
+     141                 :            :     }
+     142                 :            : 
+     143                 :            :     function _authorizeIdentityRegistryManager() internal view virtual;
+     144                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.func-sort-c.html b/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.func-sort-c.html new file mode 100644 index 0000000..b09fc06 --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.func-sort-c.html @@ -0,0 +1,129 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleMaxTotalSupplyBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleMaxTotalSupplyBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:3737100.0 %
Date:2026-03-10 10:55:10Functions:1212100.0 %
Branches:1111100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleMaxTotalSupplyBase._detectTransferRestrictionFrom2
RuleMaxTotalSupplyBase._transferred2
RuleMaxTotalSupplyBase._transferredFrom2
RuleMaxTotalSupplyBase.canReturnTransferRestrictionCode2
RuleMaxTotalSupplyBase.messageForTransferRestriction2
RuleMaxTotalSupplyBase.transferred.02
RuleMaxTotalSupplyBase.transferred.12
RuleMaxTotalSupplyBase.setTokenContract4
RuleMaxTotalSupplyBase.constructor25
RuleMaxTotalSupplyBase.onlyMaxTotalSupplyManager260
RuleMaxTotalSupplyBase.setMaxTotalSupply260
RuleMaxTotalSupplyBase._detectTransferRestriction271
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.func.html b/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.func.html new file mode 100644 index 0000000..d697da8 --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.func.html @@ -0,0 +1,129 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleMaxTotalSupplyBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleMaxTotalSupplyBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:3737100.0 %
Date:2026-03-10 10:55:10Functions:1212100.0 %
Branches:1111100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleMaxTotalSupplyBase._detectTransferRestriction271
RuleMaxTotalSupplyBase._detectTransferRestrictionFrom2
RuleMaxTotalSupplyBase._transferred2
RuleMaxTotalSupplyBase._transferredFrom2
RuleMaxTotalSupplyBase.canReturnTransferRestrictionCode2
RuleMaxTotalSupplyBase.constructor25
RuleMaxTotalSupplyBase.messageForTransferRestriction2
RuleMaxTotalSupplyBase.onlyMaxTotalSupplyManager260
RuleMaxTotalSupplyBase.setMaxTotalSupply260
RuleMaxTotalSupplyBase.setTokenContract4
RuleMaxTotalSupplyBase.transferred.02
RuleMaxTotalSupplyBase.transferred.12
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.gcov.html b/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.gcov.html new file mode 100644 index 0000000..d9659ad --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleMaxTotalSupplyBase.sol.gcov.html @@ -0,0 +1,204 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleMaxTotalSupplyBase.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleMaxTotalSupplyBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:3737100.0 %
Date:2026-03-10 10:55:10Functions:1212100.0 %
Branches:1111100.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : pragma solidity ^0.8.20;
+       3                 :            : 
+       4                 :            : import {RuleMaxTotalSupplyInvariantStorage} from "../invariant/RuleMaxTotalSupplyInvariantStorage.sol";
+       5                 :            : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+       6                 :            : import {ITotalSupply} from "../../../interfaces/ITotalSupply.sol";
+       7                 :            : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+       8                 :            : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+       9                 :            : import {RuleTransferValidation} from "../core/RuleTransferValidation.sol";
+      10                 :            : 
+      11                 :            : /**
+      12                 :            :  * @title RuleMaxTotalSupplyBase
+      13                 :            :  * @notice Restricts minting so that total supply never exceeds a maximum value.
+      14                 :            :  */
+      15                 :            : abstract contract RuleMaxTotalSupplyBase is RuleTransferValidation, RuleMaxTotalSupplyInvariantStorage {
+      16                 :            :     /// @dev tokenContract is trusted to return a correct totalSupply.
+      17                 :            :     ITotalSupply public tokenContract;
+      18                 :            :     uint256 public maxTotalSupply;
+      19                 :            : 
+      20                 :         25 :     constructor(address tokenContract_, uint256 maxTotalSupply_) {
+      21         [ +  + ]:         25 :         require(tokenContract_ != address(0), RuleMaxTotalSupply_TokenAddressZeroNotAllowed());
+      22                 :         24 :         tokenContract = ITotalSupply(tokenContract_);
+      23                 :         24 :         maxTotalSupply = maxTotalSupply_;
+      24                 :            :     }
+      25                 :            : 
+      26                 :        260 :     function setMaxTotalSupply(uint256 newMaxTotalSupply) public onlyMaxTotalSupplyManager {
+      27                 :        258 :         maxTotalSupply = newMaxTotalSupply;
+      28                 :        258 :         emit MaxTotalSupplyUpdated(newMaxTotalSupply);
+      29                 :            :     }
+      30                 :            : 
+      31                 :          4 :     function setTokenContract(address newTokenContract) public onlyMaxTotalSupplyManager {
+      32         [ +  + ]:          2 :         require(newTokenContract != address(0), RuleMaxTotalSupply_TokenAddressZeroNotAllowed());
+      33                 :          1 :         tokenContract = ITotalSupply(newTokenContract);
+      34                 :          1 :         emit TokenContractUpdated(newTokenContract);
+      35                 :            :     }
+      36                 :            : 
+      37                 :        271 :     function _detectTransferRestriction(address from, address /* to */, uint256 value)
+      38                 :            :         internal
+      39                 :            :         view
+      40                 :            :         override
+      41                 :            :         returns (uint8)
+      42                 :            :     {
+      43            [ + ]:        271 :         if (from == address(0)) {
+      44                 :        268 :             uint256 currentSupply = tokenContract.totalSupply();
+      45            [ + ]:        268 :             if (currentSupply + value > maxTotalSupply) {
+      46                 :        179 :                 return CODE_MAX_TOTAL_SUPPLY_EXCEEDED;
+      47                 :            :             }
+      48                 :            :         }
+      49                 :         92 :         return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+      50                 :            :     }
+      51                 :            : 
+      52                 :          2 :     function _detectTransferRestrictionFrom(address, address from, address to, uint256 value)
+      53                 :            :         internal
+      54                 :            :         view
+      55                 :            :         override
+      56                 :            :         returns (uint8)
+      57                 :            :     {
+      58                 :          2 :         return _detectTransferRestriction(from, to, value);
+      59                 :            :     }
+      60                 :            : 
+      61                 :          2 :     function transferred(address from, address to, uint256 value)
+      62                 :            :         public
+      63                 :            :         view
+      64                 :            :         override(IERC3643IComplianceContract)
+      65                 :            :     {
+      66                 :          2 :         _transferred(from, to, value);
+      67                 :            :     }
+      68                 :            : 
+      69                 :          2 :     function transferred(address spender, address from, address to, uint256 value)
+      70                 :            :         public
+      71                 :            :         view
+      72                 :            :         override(IRuleEngine)
+      73                 :            :     {
+      74                 :          2 :         _transferredFrom(spender, from, to, value);
+      75                 :            :     }
+      76                 :            : 
+      77                 :          2 :     function _transferred(address from, address to, uint256 value) internal view virtual {
+      78                 :          2 :         uint8 code = _detectTransferRestriction(from, to, value);
+      79         [ +  + ]:          2 :         require(
+      80                 :            :             code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+      81                 :            :             RuleMaxTotalSupply_InvalidTransfer(address(this), from, to, value, code)
+      82                 :            :         );
+      83                 :            :     }
+      84                 :            : 
+      85                 :          2 :     function _transferredFrom(address spender, address from, address to, uint256 value) internal view virtual {
+      86                 :          2 :         uint8 code = _detectTransferRestrictionFrom(spender, from, to, value);
+      87         [ +  + ]:          2 :         require(
+      88                 :            :             code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+      89                 :            :             RuleMaxTotalSupply_InvalidTransferFrom(address(this), spender, from, to, value, code)
+      90                 :            :         );
+      91                 :            :     }
+      92                 :            : 
+      93                 :          2 :     function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override returns (bool) {
+      94                 :          2 :         return restrictionCode == CODE_MAX_TOTAL_SUPPLY_EXCEEDED;
+      95                 :            :     }
+      96                 :            : 
+      97                 :          2 :     function messageForTransferRestriction(uint8 restrictionCode)
+      98                 :            :         public
+      99                 :            :         pure
+     100                 :            :         override(IERC1404)
+     101                 :            :         returns (string memory)
+     102                 :            :     {
+     103            [ + ]:          2 :         if (restrictionCode == CODE_MAX_TOTAL_SUPPLY_EXCEEDED) {
+     104                 :          1 :             return TEXT_MAX_TOTAL_SUPPLY_EXCEEDED;
+     105                 :            :         }
+     106                 :          1 :         return TEXT_CODE_NOT_FOUND;
+     107                 :            :     }
+     108                 :            : 
+     109                 :            :     /*//////////////////////////////////////////////////////////////
+     110                 :            :                             ACCESS CONTROL
+     111                 :            :     //////////////////////////////////////////////////////////////*/
+     112                 :            : 
+     113                 :        260 :     modifier onlyMaxTotalSupplyManager() {
+     114                 :        260 :         _authorizeMaxTotalSupplyManager();
+     115                 :            :         _;
+     116                 :            :     }
+     117                 :            : 
+     118                 :            :     function _authorizeMaxTotalSupplyManager() internal view virtual;
+     119                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.func-sort-c.html b/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.func-sort-c.html new file mode 100644 index 0000000..9280236 --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.func-sort-c.html @@ -0,0 +1,133 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleSanctionsListBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleSanctionsListBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:4747100.0 %
Date:2026-03-10 10:55:10Functions:1313100.0 %
Branches:1818100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleSanctionsListBase.transferred.12
RuleSanctionsListBase._transferredFrom3
RuleSanctionsListBase.canReturnTransferRestrictionCode3
RuleSanctionsListBase.clearSanctionListOracle3
RuleSanctionsListBase.onlySanctionListManager3
RuleSanctionsListBase.messageForTransferRestriction4
RuleSanctionsListBase._detectTransferRestrictionFrom16
RuleSanctionsListBase.setSanctionListOracle17
RuleSanctionsListBase._setSanctionListOracle37
RuleSanctionsListBase.transferred.043
RuleSanctionsListBase.constructor46
RuleSanctionsListBase._transferred47
RuleSanctionsListBase._detectTransferRestriction84
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.func.html b/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.func.html new file mode 100644 index 0000000..7fac67d --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.func.html @@ -0,0 +1,133 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleSanctionsListBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleSanctionsListBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:4747100.0 %
Date:2026-03-10 10:55:10Functions:1313100.0 %
Branches:1818100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleSanctionsListBase._detectTransferRestriction84
RuleSanctionsListBase._detectTransferRestrictionFrom16
RuleSanctionsListBase._setSanctionListOracle37
RuleSanctionsListBase._transferred47
RuleSanctionsListBase._transferredFrom3
RuleSanctionsListBase.canReturnTransferRestrictionCode3
RuleSanctionsListBase.clearSanctionListOracle3
RuleSanctionsListBase.constructor46
RuleSanctionsListBase.messageForTransferRestriction4
RuleSanctionsListBase.onlySanctionListManager3
RuleSanctionsListBase.setSanctionListOracle17
RuleSanctionsListBase.transferred.043
RuleSanctionsListBase.transferred.12
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.gcov.html b/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.gcov.html new file mode 100644 index 0000000..aa0ff72 --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleSanctionsListBase.sol.gcov.html @@ -0,0 +1,227 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleSanctionsListBase.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleSanctionsListBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:4747100.0 %
Date:2026-03-10 10:55:10Functions:1313100.0 %
Branches:1818100.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : pragma solidity ^0.8.20;
+       3                 :            : 
+       4                 :            : import {MetaTxModuleStandalone} from "../../../../modules/MetaTxModuleStandalone.sol";
+       5                 :            : import {RuleSanctionsListInvariantStorage} from "../invariant/RuleSanctionsListInvariantStorage.sol";
+       6                 :            : import {RuleNFTAdapter} from "../core/RuleNFTAdapter.sol";
+       7                 :            : import {ISanctionsList} from "../../../interfaces/ISanctionsList.sol";
+       8                 :            : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+       9                 :            : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+      10                 :            : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+      11                 :            : import {IRule} from "RuleEngine/interfaces/IRule.sol";
+      12                 :            : 
+      13                 :            : /**
+      14                 :            :  * @title RuleSanctionsListBase
+      15                 :            :  * @notice Compliance rule enforcing sanctions-screening for token transfers.
+      16                 :            :  */
+      17                 :            : abstract contract RuleSanctionsListBase is MetaTxModuleStandalone, RuleNFTAdapter, RuleSanctionsListInvariantStorage {
+      18                 :            :     ISanctionsList public sanctionsList;
+      19                 :            : 
+      20                 :         46 :     constructor(address forwarderIrrevocable, ISanctionsList sanctionContractOracle_)
+      21                 :            :         MetaTxModuleStandalone(forwarderIrrevocable)
+      22                 :            :     {
+      23            [ + ]:         45 :         if (address(sanctionContractOracle_) != address(0)) {
+      24                 :         20 :             _setSanctionListOracle(sanctionContractOracle_);
+      25                 :            :         }
+      26                 :            :     }
+      27                 :            : 
+      28                 :         84 :     function _detectTransferRestriction(address from, address to, uint256 /* value */)
+      29                 :            :         internal
+      30                 :            :         view
+      31                 :            :         override
+      32                 :            :         returns (uint8)
+      33                 :            :     {
+      34            [ + ]:         84 :         if (address(sanctionsList) != address(0)) {
+      35         [ +  + ]:         77 :             if (sanctionsList.isSanctioned(from)) {
+      36                 :         10 :                 return CODE_ADDRESS_FROM_IS_SANCTIONED;
+      37            [ + ]:         67 :             } else if (sanctionsList.isSanctioned(to)) {
+      38                 :         12 :                 return CODE_ADDRESS_TO_IS_SANCTIONED;
+      39                 :            :             }
+      40                 :            :         }
+      41                 :         62 :         return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+      42                 :            :     }
+      43                 :            : 
+      44                 :         16 :     function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+      45                 :            :         internal
+      46                 :            :         view
+      47                 :            :         virtual
+      48                 :            :         override
+      49                 :            :         returns (uint8)
+      50                 :            :     {
+      51            [ + ]:         16 :         if (address(sanctionsList) != address(0)) {
+      52            [ + ]:         15 :             if (sanctionsList.isSanctioned(spender)) {
+      53                 :          6 :                 return CODE_ADDRESS_SPENDER_IS_SANCTIONED;
+      54                 :            :             }
+      55                 :          9 :             return _detectTransferRestriction(from, to, value);
+      56                 :            :         }
+      57                 :          1 :         return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+      58                 :            :     }
+      59                 :            : 
+      60                 :          3 :     function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override(IRule) returns (bool) {
+      61                 :          3 :         return restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED || restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED
+      62                 :          1 :             || restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED;
+      63                 :            :     }
+      64                 :            : 
+      65                 :          4 :     function messageForTransferRestriction(uint8 restrictionCode)
+      66                 :            :         public
+      67                 :            :         pure
+      68                 :            :         override(IERC1404)
+      69                 :            :         returns (string memory)
+      70                 :            :     {
+      71         [ +  + ]:          4 :         if (restrictionCode == CODE_ADDRESS_FROM_IS_SANCTIONED) {
+      72                 :          1 :             return TEXT_ADDRESS_FROM_IS_SANCTIONED;
+      73         [ +  + ]:          3 :         } else if (restrictionCode == CODE_ADDRESS_TO_IS_SANCTIONED) {
+      74                 :          1 :             return TEXT_ADDRESS_TO_IS_SANCTIONED;
+      75            [ + ]:          2 :         } else if (restrictionCode == CODE_ADDRESS_SPENDER_IS_SANCTIONED) {
+      76                 :          1 :             return TEXT_ADDRESS_SPENDER_IS_SANCTIONED;
+      77                 :            :         }
+      78                 :          1 :         return TEXT_CODE_NOT_FOUND;
+      79                 :            :     }
+      80                 :            : 
+      81                 :         17 :     function setSanctionListOracle(ISanctionsList sanctionContractOracle_) public virtual onlySanctionListManager {
+      82         [ +  + ]:         15 :         require(address(sanctionContractOracle_) != address(0), RuleSanctionsList_OracleAddressZeroNotAllowed());
+      83                 :         14 :         _setSanctionListOracle(sanctionContractOracle_);
+      84                 :            :     }
+      85                 :            : 
+      86                 :          3 :     function clearSanctionListOracle() public virtual onlySanctionListManager {
+      87                 :          3 :         _setSanctionListOracle(ISanctionsList(address(0)));
+      88                 :            :     }
+      89                 :            : 
+      90                 :         43 :     function transferred(address from, address to, uint256 value)
+      91                 :            :         public
+      92                 :            :         view
+      93                 :            :         override(IERC3643IComplianceContract)
+      94                 :            :     {
+      95                 :         43 :         _transferred(from, to, value);
+      96                 :            :     }
+      97                 :            : 
+      98                 :          2 :     function transferred(address spender, address from, address to, uint256 value)
+      99                 :            :         public
+     100                 :            :         view
+     101                 :            :         override(IRuleEngine)
+     102                 :            :     {
+     103                 :          2 :         _transferredFrom(spender, from, to, value);
+     104                 :            :     }
+     105                 :            : 
+     106                 :         47 :     function _transferred(address from, address to, uint256 value) internal view virtual override {
+     107                 :         47 :         uint8 code = _detectTransferRestriction(from, to, value);
+     108         [ +  + ]:         47 :         require(
+     109                 :            :             code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+     110                 :            :             RuleSanctionsList_InvalidTransfer(address(this), from, to, value, code)
+     111                 :            :         );
+     112                 :            :     }
+     113                 :            : 
+     114                 :          3 :     function _transferredFrom(address spender, address from, address to, uint256 value)
+     115                 :            :         internal
+     116                 :            :         view
+     117                 :            :         virtual
+     118                 :            :         override
+     119                 :            :     {
+     120                 :          3 :         uint8 code = _detectTransferRestrictionFrom(spender, from, to, value);
+     121         [ +  + ]:          3 :         require(
+     122                 :            :             code == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK),
+     123                 :            :             RuleSanctionsList_InvalidTransferFrom(address(this), spender, from, to, value, code)
+     124                 :            :         );
+     125                 :            :     }
+     126                 :            : 
+     127                 :         37 :     function _setSanctionListOracle(ISanctionsList sanctionContractOracle_) internal virtual {
+     128                 :         37 :         sanctionsList = sanctionContractOracle_;
+     129                 :         37 :         emit SetSanctionListOracle(sanctionContractOracle_);
+     130                 :            :     }
+     131                 :            : 
+     132                 :            :     /*//////////////////////////////////////////////////////////////
+     133                 :            :                             ACCESS CONTROL
+     134                 :            :     //////////////////////////////////////////////////////////////*/
+     135                 :            : 
+     136                 :          3 :     modifier onlySanctionListManager() {
+     137                 :          3 :         _authorizeSanctionListManager();
+     138                 :            :         _;
+     139                 :            :     }
+     140                 :            : 
+     141                 :            :     function _authorizeSanctionListManager() internal view virtual;
+     142                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.func-sort-c.html b/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.func-sort-c.html new file mode 100644 index 0000000..33acb11 --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.func-sort-c.html @@ -0,0 +1,113 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleWhitelistBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleWhitelistBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2323100.0 %
Date:2026-03-10 10:55:10Functions:88100.0 %
Branches:44100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistBase._setCheckSpender2
RuleWhitelistBase.isVerified2
RuleWhitelistBase.onlyCheckSpenderManager3
RuleWhitelistBase.setCheckSpender3
RuleWhitelistBase._detectTransferRestrictionFrom18
RuleWhitelistBase.supportsInterface27
RuleWhitelistBase._detectTransferRestriction51
RuleWhitelistBase.constructor157
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.func.html b/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.func.html new file mode 100644 index 0000000..d99a4bf --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.func.html @@ -0,0 +1,113 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleWhitelistBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleWhitelistBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2323100.0 %
Date:2026-03-10 10:55:10Functions:88100.0 %
Branches:44100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistBase._detectTransferRestriction51
RuleWhitelistBase._detectTransferRestrictionFrom18
RuleWhitelistBase._setCheckSpender2
RuleWhitelistBase.constructor157
RuleWhitelistBase.isVerified2
RuleWhitelistBase.onlyCheckSpenderManager3
RuleWhitelistBase.setCheckSpender3
RuleWhitelistBase.supportsInterface27
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.gcov.html b/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.gcov.html new file mode 100644 index 0000000..cb753c6 --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleWhitelistBase.sol.gcov.html @@ -0,0 +1,166 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleWhitelistBase.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleWhitelistBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2323100.0 %
Date:2026-03-10 10:55:10Functions:88100.0 %
Branches:44100.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : pragma solidity ^0.8.20;
+       3                 :            : 
+       4                 :            : import {RuleAddressSet} from "../RuleAddressSet/RuleAddressSet.sol";
+       5                 :            : import {RuleWhitelistShared} from "../core/RuleWhitelistShared.sol";
+       6                 :            : import {RuleTransferValidation} from "../core/RuleTransferValidation.sol";
+       7                 :            : import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+       8                 :            : import {IIdentityRegistryVerified} from "../../../interfaces/IIdentityRegistry.sol";
+       9                 :            : 
+      10                 :            : /**
+      11                 :            :  * @title RuleWhitelistBase
+      12                 :            :  * @notice Core whitelist logic without access-control policy.
+      13                 :            :  */
+      14                 :            : abstract contract RuleWhitelistBase is RuleAddressSet, RuleWhitelistShared, IIdentityRegistryVerified {
+      15                 :        157 :     constructor(address forwarderIrrevocable, bool checkSpender_) RuleAddressSet(forwarderIrrevocable) {
+      16                 :        157 :         checkSpender = checkSpender_;
+      17                 :            :     }
+      18                 :            : 
+      19                 :         51 :     function _detectTransferRestriction(address from, address to, uint256 /* value */ )
+      20                 :            :         internal
+      21                 :            :         view
+      22                 :            :         virtual
+      23                 :            :         override
+      24                 :            :         returns (uint8)
+      25                 :            :     {
+      26         [ +  + ]:         51 :         if (!isAddressListed(from)) {
+      27                 :         13 :             return CODE_ADDRESS_FROM_NOT_WHITELISTED;
+      28            [ + ]:         38 :         } else if (!isAddressListed(to)) {
+      29                 :         10 :             return CODE_ADDRESS_TO_NOT_WHITELISTED;
+      30                 :            :         }
+      31                 :         28 :         return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+      32                 :            :     }
+      33                 :            : 
+      34                 :         18 :     function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
+      35                 :            :         internal
+      36                 :            :         view
+      37                 :            :         virtual
+      38                 :            :         override
+      39                 :            :         returns (uint8)
+      40                 :            :     {
+      41            [ + ]:         18 :         if (checkSpender && !isAddressListed(spender)) {
+      42                 :          8 :             return CODE_ADDRESS_SPENDER_NOT_WHITELISTED;
+      43                 :            :         }
+      44                 :         10 :         return _detectTransferRestriction(from, to, value);
+      45                 :            :     }
+      46                 :            : 
+      47                 :            : 
+      48                 :          2 :     function isVerified(address targetAddress)
+      49                 :            :         public
+      50                 :            :         view
+      51                 :            :         virtual
+      52                 :            :         override(IIdentityRegistryVerified)
+      53                 :            :         returns (bool isListed)
+      54                 :            :     {
+      55                 :          2 :         isListed = _isAddressListed(targetAddress);
+      56                 :            :     }
+      57                 :            : 
+      58                 :          3 :     function setCheckSpender(bool value) public virtual onlyCheckSpenderManager {
+      59                 :          2 :         _setCheckSpender(value);
+      60                 :          2 :         emit CheckSpenderUpdated(value);
+      61                 :            :     }
+      62                 :            : 
+      63                 :          2 :     function _setCheckSpender(bool value) internal virtual {
+      64                 :          2 :         checkSpender = value;
+      65                 :            :     }
+      66                 :            : 
+      67                 :         27 :     function supportsInterface(bytes4 interfaceId) public view virtual override(RuleTransferValidation) returns (bool) {
+      68                 :         27 :         return RuleTransferValidation.supportsInterface(interfaceId);
+      69                 :            :     }
+      70                 :            : 
+      71                 :            :     /*//////////////////////////////////////////////////////////////
+      72                 :            :                             ACCESS CONTROL
+      73                 :            :     //////////////////////////////////////////////////////////////*/
+      74                 :            : 
+      75                 :          3 :     modifier onlyCheckSpenderManager() {
+      76                 :          3 :         _authorizeCheckSpenderManager();
+      77                 :            :         _;
+      78                 :            :     }
+      79                 :            : 
+      80                 :            :     function _authorizeCheckSpenderManager() internal view virtual;
+      81                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.func-sort-c.html b/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.func-sort-c.html new file mode 100644 index 0000000..62a206a --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.func-sort-c.html @@ -0,0 +1,137 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleWhitelistWrapperBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleWhitelistWrapperBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:6767100.0 %
Date:2026-03-10 10:55:10Functions:1414100.0 %
Branches:1414100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistWrapperBase._transferred.11
RuleWhitelistWrapperBase._msgData2
RuleWhitelistWrapperBase._setCheckSpender3
RuleWhitelistWrapperBase.isVerified4
RuleWhitelistWrapperBase.onlyCheckSpenderManager4
RuleWhitelistWrapperBase.setCheckSpender4
RuleWhitelistWrapperBase._transferred.013
RuleWhitelistWrapperBase._detectTransferRestrictionFrom20
RuleWhitelistWrapperBase._detectTransferRestriction34
RuleWhitelistWrapperBase.constructor44
RuleWhitelistWrapperBase._detectTransferRestrictionForTargets57
RuleWhitelistWrapperBase.supportsInterface62
RuleWhitelistWrapperBase._msgSender145
RuleWhitelistWrapperBase._contextSuffixLength147
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.func.html b/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.func.html new file mode 100644 index 0000000..643e123 --- /dev/null +++ b/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.func.html @@ -0,0 +1,137 @@ + + + + + + + LCOV - lcov.info - abstract/base/RuleWhitelistWrapperBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/base - RuleWhitelistWrapperBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:6767100.0 %
Date:2026-03-10 10:55:10Functions:1414100.0 %
Branches:1414100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistWrapperBase._contextSuffixLength147
RuleWhitelistWrapperBase._detectTransferRestriction34
RuleWhitelistWrapperBase._detectTransferRestrictionForTargets57
RuleWhitelistWrapperBase._detectTransferRestrictionFrom20
RuleWhitelistWrapperBase._msgData2
RuleWhitelistWrapperBase._msgSender145
RuleWhitelistWrapperBase._setCheckSpender3
RuleWhitelistWrapperBase._transferred.013
RuleWhitelistWrapperBase._transferred.11
RuleWhitelistWrapperBase.constructor44
RuleWhitelistWrapperBase.isVerified4
RuleWhitelistWrapperBase.onlyCheckSpenderManager4
RuleWhitelistWrapperBase.setCheckSpender4
RuleWhitelistWrapperBase.supportsInterface62
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html b/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.gcov.html similarity index 55% rename from doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html rename to doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.gcov.html index 1d03613..2a4e421 100644 --- a/doc/coverage/coverage/validation/RuleSanctionsList.sol.gcov.html +++ b/doc/coverage/coverage/abstract/base/RuleWhitelistWrapperBase.sol.gcov.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - validation/RuleSanctionsList.sol - + LCOV - lcov.info - abstract/base/RuleWhitelistWrapperBase.sol + - + - +
LCOV - code coverage report
- + @@ -31,34 +31,34 @@ - - - + + + - + - - - + + + - - + + - +
Current view:top level - validation - RuleSanctionsList.sol (source / functions)top level - abstract/base - RuleWhitelistWrapperBase.sol (source / functions) Hitlcov.info Lines:505492.6 %6767100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:151788.2 %1414100.0 %
Branches:18181414 100.0 %
@@ -73,266 +73,249 @@ 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"; + 5 : : /* ==== OpenZeppelin === */ + 6 : : import {AccessControl} from "OZ/access/AccessControl.sol"; + 7 : : /* ==== Abstract contracts === */ + 8 : : import {MetaTxModuleStandalone, ERC2771Context} from "../../../../modules/MetaTxModuleStandalone.sol"; + 9 : : import {Context} from "OZ/utils/Context.sol"; + 10 : : import {RuleWhitelistShared} from "../core/RuleWhitelistShared.sol"; + 11 : : import {RuleTransferValidation} from "../core/RuleTransferValidation.sol"; + 12 : : /* ==== RuleEngine === */ + 13 : : import {RulesManagementModule} from "RuleEngine/modules/RulesManagementModule.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 : 17 : function detectTransferRestriction(address from, address to, uint256 /*value */ ) - 74 : : public - 75 : : view - 76 : : override(IERC1404) - 77 : : returns (uint8) - 78 : : { - 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 : 19 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 87 : : } + 16 : : /* ==== Interfaces === */ + 17 : : import {IAddressList} from "../../../interfaces/IAddressList.sol"; + 18 : : import {IIdentityRegistryVerified} from "../../../interfaces/IIdentityRegistry.sol"; + 19 : : + 20 : : /** + 21 : : * @title Wrapper to call several different whitelist rules (base) + 22 : : * @dev Child rules must implement {IAddressList}. + 23 : : */ + 24 : : abstract contract RuleWhitelistWrapperBase is + 25 : : RulesManagementModule, + 26 : : MetaTxModuleStandalone, + 27 : : RuleWhitelistShared, + 28 : : IIdentityRegistryVerified + 29 : : { + 30 : : /*////////////////////////////////////////////////////////////// + 31 : : CONSTRUCTOR + 32 : : //////////////////////////////////////////////////////////////*/ + 33 : : /** + 34 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + 35 : : */ + 36 : 44 : constructor(address forwarderIrrevocable, bool checkSpender_) + 37 : : MetaTxModuleStandalone(forwarderIrrevocable) + 38 : : { + 39 : 44 : checkSpender = checkSpender_; + 40 : : } + 41 : : + 42 : : /* ============ View Functions ============ */ + 43 : : /** + 44 : : * @notice Go through all the whitelist rules to know if a restriction exists on the transfer + 45 : : * @param from the origin address + 46 : : * @param to the destination address + 47 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + 48 : : * + 49 : : */ + 50 : 34 : function _detectTransferRestriction(address from, address to, uint256 /* value */) + 51 : : internal + 52 : : view + 53 : : virtual + 54 : : override + 55 : : returns (uint8) + 56 : : { + 57 : 34 : address[] memory targetAddress = new address[](2); + 58 : 34 : targetAddress[0] = from; + 59 : 34 : targetAddress[1] = to; + 60 : : + 61 : 34 : bool[] memory result = _detectTransferRestrictionForTargets(targetAddress); + 62 [ + + ]: 34 : if (!result[0]) { + 63 : 13 : return CODE_ADDRESS_FROM_NOT_WHITELISTED; + 64 [ + + ]: 21 : } else if (!result[1]) { + 65 : 8 : return CODE_ADDRESS_TO_NOT_WHITELISTED; + 66 : : } else { + 67 : 13 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 68 : : } + 69 : : } + 70 : : + 71 : 20 : function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) + 72 : : internal + 73 : : view + 74 : : virtual + 75 : : override + 76 : : returns (uint8) + 77 : : { + 78 [ + ]: 20 : if (!checkSpender) { + 79 : 1 : return _detectTransferRestriction(from, to, value); + 80 : : } + 81 : : + 82 : 19 : address[] memory targetAddress = new address[](3); + 83 : 19 : targetAddress[0] = from; + 84 : 19 : targetAddress[1] = to; + 85 : 19 : targetAddress[2] = spender; + 86 : : + 87 : 19 : bool[] memory result = _detectTransferRestrictionForTargets(targetAddress); 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 : : } + 89 [ + + ]: 19 : if (!result[0]) { + 90 : 1 : return CODE_ADDRESS_FROM_NOT_WHITELISTED; + 91 [ + + ]: 18 : } else if (!result[1]) { + 92 : 1 : return CODE_ADDRESS_TO_NOT_WHITELISTED; + 93 [ + + ]: 17 : } else if (!result[2]) { + 94 : 8 : return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; + 95 : : } else { + 96 : 9 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 97 : : } + 98 : : } + 99 : : + 100 : : // ERC-7943 tokenId overloads are provided by {RuleNFTAdapter} via RuleWhitelistShared. 101 : : - 102 : : /** - 103 : : * @inheritdoc IERC1404Extend - 104 : : */ - 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 [ + ]: 14 : if (address(sanctionsList) != address(0)) { - 113 [ + + ]: 13 : if (sanctionsList.isSanctioned(spender)) { - 114 : 4 : return CODE_ADDRESS_SPENDER_IS_SANCTIONED; - 115 : : } else { - 116 : 9 : 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 : 3 : function transferred(address from, address to, uint256 value) - 185 : : public - 186 : : view - 187 : : virtual - 188 : : override(IERC3643IComplianceContract) - 189 : : { - 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 : : /** - 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 : : } + 102 : 62 : function supportsInterface(bytes4 interfaceId) + 103 : : public + 104 : : view + 105 : : virtual + 106 : : override(AccessControl, RuleTransferValidation) + 107 : : returns (bool) + 108 : : { + 109 : 62 : return AccessControl.supportsInterface(interfaceId) || RuleTransferValidation.supportsInterface(interfaceId); + 110 : : } + 111 : : + 112 : : /** + 113 : : * @notice Returns true if the address is listed in at least one child whitelist rule. + 114 : : * @dev Delegates to the same child-rule scan used by transfer restriction checks. + 115 : : */ + 116 : 4 : function isVerified(address targetAddress) + 117 : : public + 118 : : view + 119 : : virtual + 120 : : override(IIdentityRegistryVerified) + 121 : : returns (bool) + 122 : : { + 123 : 4 : address[] memory targets = new address[](1); + 124 : 4 : targets[0] = targetAddress; + 125 : 4 : bool[] memory result = _detectTransferRestrictionForTargets(targets); + 126 : 4 : return result[0]; + 127 : : } + 128 : : + 129 : : /* ============ Access control ============ */ + 130 : : + 131 : : /** + 132 : : * @notice Sets whether the rule should enforce spender-based checks. + 133 : : * @dev + 134 : : * - Restricted to holders of the manager role. + 135 : : * - Updates the internal `checkSpender` flag. + 136 : : * - Emits a {CheckSpenderUpdated} event. + 137 : : * @param value The new state of the `checkSpender` flag. + 138 : : */ + 139 : 4 : function setCheckSpender(bool value) public virtual onlyCheckSpenderManager { + 140 : 3 : _setCheckSpender(value); + 141 : 3 : emit CheckSpenderUpdated(value); + 142 : : } + 143 : : + 144 : 13 : function _transferred(address from, address to, uint256 value) + 145 : : internal + 146 : : view + 147 : : virtual + 148 : : override(RulesManagementModule, RuleWhitelistShared) + 149 : : { + 150 : 13 : RuleWhitelistShared._transferred(from, to, value); + 151 : : } + 152 : : + 153 : 1 : function _transferred(address spender, address from, address to, uint256 value) + 154 : : internal + 155 : : view + 156 : : virtual + 157 : : override(RulesManagementModule) + 158 : : { + 159 : 1 : RuleWhitelistShared._transferredFrom(spender, from, to, value); + 160 : : } + 161 : : + 162 : : /*////////////////////////////////////////////////////////////// + 163 : : INTERNAL/PRIVATE FUNCTIONS + 164 : : //////////////////////////////////////////////////////////////*/ + 165 : : + 166 : : /** + 167 : : * @notice Evaluates target addresses across all child rules. + 168 : : * @param targetAddress Addresses to validate (from/to[/spender]). + 169 : : * @return result Boolean array aligned with targetAddress indicating if each address is listed. + 170 : : */ + 171 : 57 : function _detectTransferRestrictionForTargets(address[] memory targetAddress) + 172 : : internal + 173 : : view + 174 : : virtual + 175 : : returns (bool[] memory) + 176 : : { + 177 : 57 : uint256 rulesLength = rulesCount(); + 178 : 57 : bool[] memory result = new bool[](targetAddress.length); + 179 : 57 : for (uint256 i = 0; i < rulesLength; ++i) { + 180 : : // Call the whitelist rules + 181 : : // Gas cost grows with the number of rules. Keep the wrapper list bounded. + 182 : 105 : bool[] memory isListed = IAddressList(rule(i)).areAddressesListed(targetAddress); + 183 : 105 : for (uint256 j = 0; j < targetAddress.length; ++j) { + 184 [ + ]: 85 : if (isListed[j]) { + 185 : 85 : result[j] = true; + 186 : : } + 187 : : } + 188 : : + 189 : : // Break early if all listed + 190 : 105 : bool allListed = true; + 191 : 105 : for (uint256 k = 0; k < result.length; ++k) { + 192 [ + ]: 201 : if (!result[k]) { + 193 : 81 : allListed = false; + 194 : 81 : break; + 195 : : } + 196 : : } + 197 [ + ]: 24 : if (allListed) { + 198 : 24 : break; + 199 : : } + 200 : : } + 201 : 57 : return result; + 202 : : } + 203 : : + 204 : : /** + 205 : : * @notice Internal helper to update the `checkSpender` flag. + 206 : : * @param value New flag value. + 207 : : */ + 208 : 3 : function _setCheckSpender(bool value) internal virtual { + 209 : 3 : checkSpender = value; + 210 : : } + 211 : : + 212 : : /*////////////////////////////////////////////////////////////// + 213 : : ACCESS CONTROL + 214 : : //////////////////////////////////////////////////////////////*/ + 215 : : + 216 : 4 : modifier onlyCheckSpenderManager() { + 217 : 4 : _authorizeCheckSpenderManager(); + 218 : : _; + 219 : : } + 220 : : + 221 : : function _authorizeCheckSpenderManager() internal virtual; 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 : : } + 223 : : /*////////////////////////////////////////////////////////////// + 224 : : ERC-2771 + 225 : : //////////////////////////////////////////////////////////////*/ + 226 : : + 227 : : /** + 228 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 229 : : */ + 230 : 145 : function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) { + 231 : 145 : return ERC2771Context._msgSender(); + 232 : : } + 233 : : + 234 : : /** + 235 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 236 : : */ + 237 : 2 : function _msgData() internal view virtual override(ERC2771Context, Context) returns (bytes calldata) { + 238 : 2 : return ERC2771Context._msgData(); + 239 : : } + 240 : : + 241 : : /** + 242 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 243 : : */ + 244 : 147 : function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) { + 245 : 147 : return ERC2771Context._contextSuffixLength(); + 246 : : } + 247 : : } @@ -340,7 +323,7 @@
- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/abstract/base/index-sort-b.html b/doc/coverage/coverage/abstract/base/index-sort-b.html new file mode 100644 index 0000000..c0dd6a1 --- /dev/null +++ b/doc/coverage/coverage/abstract/base/index-sort-b.html @@ -0,0 +1,179 @@ + + + + + + + LCOV - lcov.info - abstract/base + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/baseHitTotalCoverage
Test:lcov.infoLines:360360100.0 %
Date:2026-03-10 10:55:10Functions:101101100.0 %
Branches:105105100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleWhitelistBase.sol +
100.0%
+
100.0 %23 / 23100.0 %8 / 8100.0 %4 / 4
RuleMaxTotalSupplyBase.sol +
100.0%
+
100.0 %37 / 37100.0 %12 / 12100.0 %11 / 11
RuleBlacklistBase.sol +
100.0%
+
100.0 %33 / 33100.0 %9 / 9100.0 %14 / 14
RuleWhitelistWrapperBase.sol +
100.0%
+
100.0 %67 / 67100.0 %14 / 14100.0 %14 / 14
RuleSanctionsListBase.sol +
100.0%
+
100.0 %47 / 47100.0 %13 / 13100.0 %18 / 18
RuleIdentityRegistryBase.sol +
100.0%
+
100.0 %51 / 51100.0 %12 / 12100.0 %19 / 19
RuleERC2980Base.sol +
100.0%
+
100.0 %102 / 102100.0 %33 / 33100.0 %25 / 25
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/index-sort-f.html b/doc/coverage/coverage/abstract/base/index-sort-f.html new file mode 100644 index 0000000..fd1f168 --- /dev/null +++ b/doc/coverage/coverage/abstract/base/index-sort-f.html @@ -0,0 +1,179 @@ + + + + + + + LCOV - lcov.info - abstract/base + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/baseHitTotalCoverage
Test:lcov.infoLines:360360100.0 %
Date:2026-03-10 10:55:10Functions:101101100.0 %
Branches:105105100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleWhitelistBase.sol +
100.0%
+
100.0 %23 / 23100.0 %8 / 8100.0 %4 / 4
RuleBlacklistBase.sol +
100.0%
+
100.0 %33 / 33100.0 %9 / 9100.0 %14 / 14
RuleIdentityRegistryBase.sol +
100.0%
+
100.0 %51 / 51100.0 %12 / 12100.0 %19 / 19
RuleMaxTotalSupplyBase.sol +
100.0%
+
100.0 %37 / 37100.0 %12 / 12100.0 %11 / 11
RuleSanctionsListBase.sol +
100.0%
+
100.0 %47 / 47100.0 %13 / 13100.0 %18 / 18
RuleWhitelistWrapperBase.sol +
100.0%
+
100.0 %67 / 67100.0 %14 / 14100.0 %14 / 14
RuleERC2980Base.sol +
100.0%
+
100.0 %102 / 102100.0 %33 / 33100.0 %25 / 25
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/index-sort-l.html b/doc/coverage/coverage/abstract/base/index-sort-l.html new file mode 100644 index 0000000..10250aa --- /dev/null +++ b/doc/coverage/coverage/abstract/base/index-sort-l.html @@ -0,0 +1,179 @@ + + + + + + + LCOV - lcov.info - abstract/base + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/baseHitTotalCoverage
Test:lcov.infoLines:360360100.0 %
Date:2026-03-10 10:55:10Functions:101101100.0 %
Branches:105105100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleWhitelistBase.sol +
100.0%
+
100.0 %23 / 23100.0 %8 / 8100.0 %4 / 4
RuleBlacklistBase.sol +
100.0%
+
100.0 %33 / 33100.0 %9 / 9100.0 %14 / 14
RuleMaxTotalSupplyBase.sol +
100.0%
+
100.0 %37 / 37100.0 %12 / 12100.0 %11 / 11
RuleSanctionsListBase.sol +
100.0%
+
100.0 %47 / 47100.0 %13 / 13100.0 %18 / 18
RuleIdentityRegistryBase.sol +
100.0%
+
100.0 %51 / 51100.0 %12 / 12100.0 %19 / 19
RuleWhitelistWrapperBase.sol +
100.0%
+
100.0 %67 / 67100.0 %14 / 14100.0 %14 / 14
RuleERC2980Base.sol +
100.0%
+
100.0 %102 / 102100.0 %33 / 33100.0 %25 / 25
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/base/index.html b/doc/coverage/coverage/abstract/base/index.html new file mode 100644 index 0000000..a56fb4a --- /dev/null +++ b/doc/coverage/coverage/abstract/base/index.html @@ -0,0 +1,179 @@ + + + + + + + LCOV - lcov.info - abstract/base + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/baseHitTotalCoverage
Test:lcov.infoLines:360360100.0 %
Date:2026-03-10 10:55:10Functions:101101100.0 %
Branches:105105100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleBlacklistBase.sol +
100.0%
+
100.0 %33 / 33100.0 %9 / 9100.0 %14 / 14
RuleERC2980Base.sol +
100.0%
+
100.0 %102 / 102100.0 %33 / 33100.0 %25 / 25
RuleIdentityRegistryBase.sol +
100.0%
+
100.0 %51 / 51100.0 %12 / 12100.0 %19 / 19
RuleMaxTotalSupplyBase.sol +
100.0%
+
100.0 %37 / 37100.0 %12 / 12100.0 %11 / 11
RuleSanctionsListBase.sol +
100.0%
+
100.0 %47 / 47100.0 %13 / 13100.0 %18 / 18
RuleWhitelistBase.sol +
100.0%
+
100.0 %23 / 23100.0 %8 / 8100.0 %4 / 4
RuleWhitelistWrapperBase.sol +
100.0%
+
100.0 %67 / 67100.0 %14 / 14100.0 %14 / 14
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.func-sort-c.html b/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.func-sort-c.html new file mode 100644 index 0000000..2a2a676 --- /dev/null +++ b/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.func-sort-c.html @@ -0,0 +1,113 @@ + + + + + + + LCOV - lcov.info - abstract/core/RuleNFTAdapter.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/core - RuleNFTAdapter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2020100.0 %
Date:2026-03-10 10:55:10Functions:88100.0 %
Branches:44100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleNFTAdapter.transferred.22
RuleNFTAdapter.transferred.32
RuleNFTAdapter.transferred.18
RuleNFTAdapter.canTransferFrom10
RuleNFTAdapter.detectTransferRestrictionFrom12
RuleNFTAdapter.transferred.013
RuleNFTAdapter.canTransfer14
RuleNFTAdapter.detectTransferRestriction16
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.func.html b/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.func.html new file mode 100644 index 0000000..0ee21a8 --- /dev/null +++ b/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.func.html @@ -0,0 +1,113 @@ + + + + + + + LCOV - lcov.info - abstract/core/RuleNFTAdapter.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/core - RuleNFTAdapter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2020100.0 %
Date:2026-03-10 10:55:10Functions:88100.0 %
Branches:44100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleNFTAdapter.canTransfer14
RuleNFTAdapter.canTransferFrom10
RuleNFTAdapter.detectTransferRestriction16
RuleNFTAdapter.detectTransferRestrictionFrom12
RuleNFTAdapter.transferred.013
RuleNFTAdapter.transferred.18
RuleNFTAdapter.transferred.22
RuleNFTAdapter.transferred.32
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html b/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.gcov.html similarity index 52% rename from doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html rename to doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.gcov.html index 09c1d37..ea62082 100644 --- a/doc/coverage/coverage/validation/RuleWhitelist.sol.gcov.html +++ b/doc/coverage/coverage/abstract/core/RuleNFTAdapter.sol.gcov.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - validation/RuleWhitelist.sol - + LCOV - lcov.info - abstract/core/RuleNFTAdapter.sol + - + - +
LCOV - code coverage report
- + @@ -31,34 +31,34 @@ - - + + - + - - - + + + - - + + - +
Current view:top level - validation - RuleWhitelist.sol (source / functions)top level - abstract/core - RuleNFTAdapter.sol (source / functions) Hitlcov.info Lines:16 2080.0 %20100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:5771.4 %88100.0 %
Branches:5544 100.0 %
@@ -72,149 +72,135 @@ 1 : : // SPDX-License-Identifier: MPL-2.0 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 : 20 : function detectTransferRestriction(address from, address to, uint256 /* value */ ) - 57 : : public - 58 : : view - 59 : : virtual - 60 : : override(IERC1404) - 61 : : returns (uint8 code) - 62 : : { - 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 : 16 : 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 : 10 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) - 103 : : public - 104 : : view + 4 : : import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; + 5 : : import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; + 6 : : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; + 7 : : import { + 8 : : IERC7943NonFungibleCompliance, + 9 : : IERC7943NonFungibleComplianceExtend + 10 : : } from "../../../interfaces/IERC7943NonFungibleCompliance.sol"; + 11 : : import {RuleTransferValidation} from "./RuleTransferValidation.sol"; + 12 : : import {ITransferContext} from "../../../interfaces/ITransferContext.sol"; + 13 : : + 14 : : /** + 15 : : * @title Rule NFT Adapter + 16 : : * @notice Provides ERC-7943 overloads for rules that already implement core transfer checks. + 17 : : * @dev Delegates tokenId overloads to RuleTransferValidation's internal hooks. + 18 : : */ + 19 : : abstract contract RuleNFTAdapter is RuleTransferValidation, IERC7943NonFungibleComplianceExtend, ITransferContext { + 20 : : bytes4 internal constant TRANSFERRED_SELECTOR_ERC3643 = + 21 : : IERC3643IComplianceContract.transferred.selector; + 22 : : bytes4 internal constant TRANSFERRED_SELECTOR_RULE_ENGINE = + 23 : : IRuleEngine.transferred.selector; + 24 : : bytes4 internal constant TRANSFERRED_SELECTOR_ERC7943 = + 25 : : bytes4(keccak256("transferred(address,address,uint256,uint256)")); + 26 : : bytes4 internal constant TRANSFERRED_SELECTOR_ERC7943_FROM = + 27 : : bytes4(keccak256("transferred(address,address,address,uint256,uint256)")); + 28 : : /** + 29 : : * @notice Internal hook for post-transfer validation or state updates. + 30 : : */ + 31 : : function _transferred(address from, address to, uint256 value) internal virtual; + 32 : : + 33 : : /** + 34 : : * @notice Internal hook for post-transfer validation or state updates (spender-aware). + 35 : : */ + 36 : : function _transferredFrom(address spender, address from, address to, uint256 value) internal virtual; + 37 : : /** + 38 : : * @inheritdoc IERC7943NonFungibleComplianceExtend + 39 : : */ + 40 : 16 : function detectTransferRestriction(address from, address to, uint256 /* tokenId */, uint256 value) + 41 : : public + 42 : : view + 43 : : virtual + 44 : : override(IERC7943NonFungibleComplianceExtend) + 45 : : returns (uint8) + 46 : : { + 47 : 16 : return _detectTransferRestriction(from, to, value); + 48 : : } + 49 : : + 50 : : /** + 51 : : * @inheritdoc IERC7943NonFungibleComplianceExtend + 52 : : */ + 53 : 12 : function detectTransferRestrictionFrom( + 54 : : address spender, + 55 : : address from, + 56 : : address to, + 57 : : uint256 /* tokenId */, + 58 : : uint256 value + 59 : : ) public view virtual override(IERC7943NonFungibleComplianceExtend) returns (uint8) { + 60 : 12 : return _detectTransferRestrictionFrom(spender, from, to, value); + 61 : : } + 62 : : + 63 : : /** + 64 : : * @inheritdoc IERC7943NonFungibleCompliance + 65 : : */ + 66 : 14 : function canTransfer(address from, address to, uint256 /* tokenId */, uint256 amount) + 67 : : public + 68 : : view + 69 : : override(IERC7943NonFungibleCompliance) + 70 : : returns (bool) + 71 : : { + 72 : 14 : return _detectTransferRestriction(from, to, amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); + 73 : : } + 74 : : + 75 : : /** + 76 : : * @inheritdoc IERC7943NonFungibleComplianceExtend + 77 : : */ + 78 : 10 : function canTransferFrom(address spender, address from, address to, uint256 /* tokenId */, uint256 value) + 79 : : public + 80 : : view + 81 : : virtual + 82 : : override(IERC7943NonFungibleComplianceExtend) + 83 : : returns (bool) + 84 : : { + 85 : 10 : return _detectTransferRestrictionFrom(spender, from, to, value) + 86 : : == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); + 87 : : } + 88 : : + 89 : : /** + 90 : : * @inheritdoc IERC7943NonFungibleComplianceExtend + 91 : : */ + 92 : 13 : function transferred(address from, address to, uint256 /* tokenId */, uint256 value) + 93 : : public + 94 : : virtual + 95 : : override(IERC7943NonFungibleComplianceExtend) + 96 : : { + 97 : 13 : _transferred(from, to, value); + 98 : : } + 99 : : + 100 : : /** + 101 : : * @inheritdoc IERC7943NonFungibleComplianceExtend + 102 : : */ + 103 : 8 : function transferred(address spender, address from, address to, uint256 /* tokenId */, uint256 value) + 104 : : public 105 : : virtual - 106 : : override(IERC1404Extend) - 107 : : returns (uint8 code) - 108 : : { - 109 [ + ]: 12 : if (checkSpender && !isAddressListed(spender)) { - 110 : 6 : return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; - 111 : : } - 112 : 6 : 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 : : } + 106 : : override(IERC7943NonFungibleComplianceExtend) + 107 : : { + 108 : 8 : _transferredFrom(spender, from, to, value); + 109 : : } + 110 : : + 111 : : /** + 112 : : * @inheritdoc ITransferContext + 113 : : */ + 114 : 2 : function transferred(MultiTokenTransferContext calldata ctx) external virtual override { + 115 [ + + ]: 2 : if (ctx.sender != address(0)) { + 116 : 1 : _transferredFrom(ctx.sender, ctx.from, ctx.to, ctx.value); + 117 : : } else { + 118 : 1 : _transferred(ctx.from, ctx.to, ctx.value); + 119 : : } + 120 : : } + 121 : : + 122 : : /** + 123 : : * @inheritdoc ITransferContext + 124 : : */ + 125 : 2 : function transferred(FungibleTransferContext calldata ctx) external virtual override { + 126 [ + + ]: 2 : if (ctx.sender != address(0)) { + 127 : 1 : _transferredFrom(ctx.sender, ctx.from, ctx.to, ctx.value); + 128 : : } else { + 129 : 1 : _transferred(ctx.from, ctx.to, ctx.value); + 130 : : } + 131 : : } + 132 : : } @@ -222,7 +208,7 @@
- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html b/doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.func-sort-c.html similarity index 62% rename from doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html rename to doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.func-sort-c.html index 93f72fb..13a68b1 100644 --- a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html +++ b/doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.func-sort-c.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/abstract/RuleValidateTransfer.sol - functions + LCOV - lcov.info - abstract/core/RuleTransferValidation.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,18 +31,18 @@ - - + + - + - - + + @@ -65,28 +65,28 @@
Current view:top level - validation/abstract - RuleValidateTransfer.sol (source / functions)top level - abstract/core - RuleTransferValidation.sol (source / functions) Hitlcov.info Lines:8 1080.0 %10100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:4 580.0 %5100.0 %
- + - - + + - - + + - - + + - - + + - - + +

Function Name Sort by function nameFunction Name Sort by function name Hit count Sort by hit count
RuleValidateTransfer.supportsInterface0RuleTransferValidation.canTransferFrom12
RuleValidateTransfer.canTransferFrom.010RuleTransferValidation.canTransfer20
RuleValidateTransfer.canTransferFrom.110RuleTransferValidation.detectTransferRestrictionFrom36
RuleValidateTransfer.canTransfer.014RuleTransferValidation.supportsInterface195
RuleValidateTransfer.canTransfer.114RuleTransferValidation.detectTransferRestriction348

diff --git a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html b/doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.func.html similarity index 62% rename from doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html rename to doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.func.html index f811a3f..91fe5a9 100644 --- a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.func.html +++ b/doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.func.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/abstract/RuleValidateTransfer.sol - functions + LCOV - lcov.info - abstract/core/RuleTransferValidation.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,18 +31,18 @@ - - + + - + - - + + @@ -66,27 +66,27 @@ - + - - + + - - + + - - + + - - + + - - + +
Current view:top level - validation/abstract - RuleValidateTransfer.sol (source / functions)top level - abstract/core - RuleTransferValidation.sol (source / functions) Hitlcov.info Lines:8 1080.0 %10100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:4 580.0 %5100.0 %

Function Name Sort by function nameHit count Sort by hit countHit count Sort by hit count
RuleValidateTransfer.canTransfer.014RuleTransferValidation.canTransfer20
RuleValidateTransfer.canTransfer.114RuleTransferValidation.canTransferFrom12
RuleValidateTransfer.canTransferFrom.010RuleTransferValidation.detectTransferRestriction348
RuleValidateTransfer.canTransferFrom.110RuleTransferValidation.detectTransferRestrictionFrom36
RuleValidateTransfer.supportsInterface0RuleTransferValidation.supportsInterface195

diff --git a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html b/doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.gcov.html similarity index 66% rename from doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html rename to doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.gcov.html index 174dc57..67c4f57 100644 --- a/doc/coverage/coverage/validation/abstract/RuleValidateTransfer.sol.gcov.html +++ b/doc/coverage/coverage/abstract/core/RuleTransferValidation.sol.gcov.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/abstract/RuleValidateTransfer.sol + LCOV - lcov.info - abstract/core/RuleTransferValidation.sol @@ -19,7 +19,7 @@ - + @@ -31,18 +31,18 @@ - - + + - + - - + + @@ -74,86 +74,104 @@ 3 : : pragma solidity ^0.8.20; 4 : : 5 : : /* ==== CMTAT === */ - 6 : : import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; + 6 : : import {IERC1404, 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 : : /* ==== 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); + 11 : : import {RuleInterfaceId} from "RuleEngine/modules/library/RuleInterfaceId.sol"; + 12 : : /* ==== Modules === */ + 13 : : import {VersionModule} from "../../../../modules/VersionModule.sol"; + 14 : : + 15 : : abstract contract RuleTransferValidation is VersionModule, IERC1404Extend, IERC3643ComplianceRead, IERC7551Compliance, IRule { + 16 : : /** + 17 : : * @notice Internal transfer restriction check. + 18 : : * @param from the origin address + 19 : : * @param to the destination address + 20 : : * @param value amount to transfer + 21 : : * @return restrictionCode The restriction code for this rule. + 22 : : */ + 23 : : function _detectTransferRestriction(address from, address to, uint256 value) + 24 : : internal + 25 : : view + 26 : : virtual + 27 : : returns (uint8 restrictionCode); + 28 : : + 29 : : /** + 30 : : * @notice Internal transfer restriction check for spender-initiated transfers. + 31 : : * @param spender the caller executing the transfer + 32 : : * @param from the origin address + 33 : : * @param to the destination address + 34 : : * @param value amount to transfer + 35 : : * @return restrictionCode The restriction code for this rule. + 36 : : */ + 37 : : function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) + 38 : : internal + 39 : : view + 40 : : virtual + 41 : : returns (uint8 restrictionCode); + 42 : : + 43 : : /** + 44 : : * @inheritdoc IERC1404 + 45 : : */ + 46 : 348 : function detectTransferRestriction(address from, address to, uint256 value) + 47 : : public + 48 : : view + 49 : : virtual + 50 : : override(IERC1404) + 51 : : returns (uint8) + 52 : : { + 53 : 348 : return _detectTransferRestriction(from, to, value); + 54 : : } + 55 : : + 56 : : /** + 57 : : * @inheritdoc IERC1404Extend + 58 : : */ + 59 : 36 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) + 60 : : public + 61 : : view + 62 : : virtual + 63 : : override(IERC1404Extend) + 64 : : returns (uint8) + 65 : : { + 66 : 36 : return _detectTransferRestrictionFrom(spender, from, to, value); 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; + 70 : : * @notice Validate a transfer + 71 : : * @param from the origin address + 72 : : * @param to the destination address + 73 : : * @param amount to transfer + 74 : : * @return isValid => true if the transfer is valid, false otherwise + 75 : : * + 76 : : */ + 77 : 20 : function canTransfer(address from, address to, uint256 amount) + 78 : : public + 79 : : view + 80 : : override(IERC3643ComplianceRead) + 81 : : returns (bool isValid) + 82 : : { + 83 : 20 : return _detectTransferRestriction(from, to, amount) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); 84 : : } - 85 : : } + 85 : : + 86 : : /** + 87 : : * @inheritdoc IERC7551Compliance + 88 : : */ + 89 : 12 : function canTransferFrom(address spender, address from, address to, uint256 value) + 90 : : public + 91 : : view + 92 : : virtual + 93 : : override(IERC7551Compliance) + 94 : : returns (bool) + 95 : : { + 96 : 12 : return _detectTransferRestrictionFrom(spender, from, to, value) + 97 : : == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK); + 98 : : } + 99 : : + 100 : 195 : function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { + 101 : 195 : return interfaceId == type(IRule).interfaceId || interfaceId == RuleInterfaceId.IRULE_INTERFACE_ID; + 102 : : } + 103 : : } diff --git a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html b/doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.func-sort-c.html similarity index 71% rename from doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html rename to doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.func-sort-c.html index bf6dc6f..588fc1b 100644 --- a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func-sort-c.html +++ b/doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.func-sort-c.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/abstract/RuleWhitelistCommon.sol - functions + LCOV - lcov.info - abstract/core/RuleWhitelistShared.sol - functions @@ -19,7 +19,7 @@
Current view:top level - validation/abstract - RuleValidateTransfer.sol (source / functions)top level - abstract/core - RuleTransferValidation.sol (source / functions) Hitlcov.info Lines:8 1080.0 %10100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:4 580.0 %5100.0 %
- + @@ -37,7 +37,7 @@ - + @@ -65,32 +65,32 @@
Current view:top level - validation/abstract - RuleWhitelistCommon.sol (source / functions)top level - abstract/core - RuleWhitelistShared.sol (source / functions) Hit
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions: 6
- + - + - - + + - - + + - - + + - - + + - - + +

Function Name Sort by function nameFunction Name Sort by function name Hit count Sort by hit count
RuleWhitelistCommon.transferred.1RuleWhitelistShared.transferred.1 4
RuleWhitelistCommon.transferred.24RuleWhitelistShared.canReturnTransferRestrictionCode10
RuleWhitelistCommon.transferred.35RuleWhitelistShared._transferredFrom11
RuleWhitelistCommon.canReturnTransferRestrictionCode10RuleWhitelistShared.messageForTransferRestriction14
RuleWhitelistCommon.messageForTransferRestriction14RuleWhitelistShared.transferred.019
RuleWhitelistCommon.transferred.017RuleWhitelistShared._transferred26

diff --git a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html b/doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.func.html similarity index 71% rename from doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html rename to doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.func.html index 2fda202..956fe25 100644 --- a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.func.html +++ b/doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.func.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/abstract/RuleWhitelistCommon.sol - functions + LCOV - lcov.info - abstract/core/RuleWhitelistShared.sol - functions @@ -19,7 +19,7 @@ - + @@ -37,7 +37,7 @@ - + @@ -66,31 +66,31 @@ - + - - + + - - + + - - + + - - + + - - + + - - + +
Current view:top level - validation/abstract - RuleWhitelistCommon.sol (source / functions)top level - abstract/core - RuleWhitelistShared.sol (source / functions) Hit
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions: 6

Function Name Sort by function nameHit count Sort by hit countHit count Sort by hit count
RuleWhitelistCommon.canReturnTransferRestrictionCode10RuleWhitelistShared._transferred26
RuleWhitelistCommon.messageForTransferRestriction14RuleWhitelistShared._transferredFrom11
RuleWhitelistCommon.transferred.017RuleWhitelistShared.canReturnTransferRestrictionCode10
RuleWhitelistCommon.transferred.14RuleWhitelistShared.messageForTransferRestriction14
RuleWhitelistCommon.transferred.24RuleWhitelistShared.transferred.019
RuleWhitelistCommon.transferred.35RuleWhitelistShared.transferred.14

diff --git a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html b/doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.gcov.html similarity index 82% rename from doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html rename to doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.gcov.html index 746edeb..e0552e4 100644 --- a/doc/coverage/coverage/validation/abstract/RuleWhitelistCommon.sol.gcov.html +++ b/doc/coverage/coverage/abstract/core/RuleWhitelistShared.sol.gcov.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/abstract/RuleWhitelistCommon.sol + LCOV - lcov.info - abstract/core/RuleWhitelistShared.sol @@ -19,7 +19,7 @@ - + @@ -37,7 +37,7 @@ - + @@ -76,122 +76,115 @@ 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 : 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 : : ); - 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 : 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_InvalidTransferFrom(address(this), spender, from, to, value, code) - 102 : : ); - 103 : : } - 104 : : - 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); + 8 : : import {RuleWhitelistInvariantStorage} from "../RuleAddressSet/invariantStorage/RuleWhitelistInvariantStorage.sol"; + 9 : : import {RuleNFTAdapter} from "./RuleNFTAdapter.sol"; + 10 : : + 11 : : /** + 12 : : * @title Rule Whitelist Shared + 13 : : * @notice Provides common logic for validating whitelist-based transfer restrictions. + 14 : : * @dev + 15 : : * - Implements ERC-3643–compatible `transferred` hooks to enforce whitelist checks. + 16 : : * - Defines utility functions for restriction code validation and message mapping. + 17 : : * - Inherits restriction code constants and messages from {RuleWhitelistInvariantStorage}. + 18 : : */ + 19 : : abstract contract RuleWhitelistShared is RuleNFTAdapter, RuleWhitelistInvariantStorage { + 20 : : /** + 21 : : * Indicate if the spender is verified or not + 22 : : */ + 23 : : bool public checkSpender; + 24 : : + 25 : : /* ============ View Functions ============ */ + 26 : : /** + 27 : : * @notice Checks whether a restriction code is recognized by this rule. + 28 : : * @dev + 29 : : * Used to verify if a returned restriction code belongs to the whitelist rule. + 30 : : * @param restrictionCode The restriction code to validate. + 31 : : * @return isKnown True if the restriction code is recognized by this rule, false otherwise. + 32 : : */ + 33 : 10 : function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override returns (bool isKnown) { + 34 : 10 : return restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED + 35 : 5 : || restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED || restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED; + 36 : : } + 37 : : + 38 : : /** + 39 : : * @notice Returns the human-readable message corresponding to a restriction code. + 40 : : * @dev + 41 : : * Returns a descriptive text that explains why a transfer was restricted. + 42 : : * @param restrictionCode The restriction code to decode. + 43 : : * @return message A human-readable explanation of the restriction. + 44 : : */ + 45 : 14 : function messageForTransferRestriction(uint8 restrictionCode) + 46 : : external + 47 : : pure + 48 : : override + 49 : : returns (string memory message) + 50 : : { + 51 [ + + ]: 14 : if (restrictionCode == CODE_ADDRESS_FROM_NOT_WHITELISTED) { + 52 : 6 : return TEXT_ADDRESS_FROM_NOT_WHITELISTED; + 53 [ + + ]: 8 : } else if (restrictionCode == CODE_ADDRESS_TO_NOT_WHITELISTED) { + 54 : 4 : return TEXT_ADDRESS_TO_NOT_WHITELISTED; + 55 [ + + ]: 4 : } else if (restrictionCode == CODE_ADDRESS_SPENDER_NOT_WHITELISTED) { + 56 : 2 : return TEXT_ADDRESS_SPENDER_NOT_WHITELISTED; + 57 : : } else { + 58 : 2 : return TEXT_CODE_NOT_FOUND; + 59 : : } + 60 : : } + 61 : : + 62 : : /* ============ State Functions ============ */ + 63 : : + 64 : : /** + 65 : : * @notice ERC-3643 hook called when a transfer occurs. + 66 : : * @dev + 67 : : * - Validates that both `from` and `to` addresses are whitelisted. + 68 : : * - Reverts if any restriction code other than `TRANSFER_OK` is returned. + 69 : : * - Validation only; does not modify state. + 70 : : * - Should be called during token transfer logic to enforce whitelist compliance. + 71 : : * @param from The address sending tokens. + 72 : : * @param to The address receiving tokens. + 73 : : * @param value The token amount being transferred. + 74 : : */ + 75 : 19 : function transferred(address from, address to, uint256 value) public view override(IERC3643IComplianceContract) { + 76 : 19 : _transferred(from, to, value); + 77 : : } + 78 : : + 79 : : /** + 80 : : * @notice hook called when a delegated transfer occurs (`transferFrom`). + 81 : : * @dev + 82 : : * - Validates that `spender`, `from`, and `to` are all whitelisted. + 83 : : * - Reverts if any restriction code other than `TRANSFER_OK` is returned. + 84 : : * - Validation only; does not modify state. + 85 : : * @param spender The address performing the transfer on behalf of another. + 86 : : * @param from The address from which tokens are transferred. + 87 : : * @param to The recipient address. + 88 : : * @param value The token amount being transferred. + 89 : : */ + 90 : 4 : function transferred(address spender, address from, address to, uint256 value) public view override(IRuleEngine) { + 91 : 4 : _transferredFrom(spender, from, to, value); + 92 : : } + 93 : : + 94 : 26 : function _transferred(address from, address to, uint256 value) internal view virtual override { + 95 : 26 : uint8 code = _detectTransferRestriction(from, to, value); + 96 [ + + ]: 26 : require( + 97 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + 98 : : RuleWhitelist_InvalidTransfer(address(this), from, to, value, code) + 99 : : ); + 100 : : } + 101 : : + 102 : 11 : function _transferredFrom(address spender, address from, address to, uint256 value) + 103 : : internal + 104 : : view + 105 : : virtual + 106 : : override + 107 : : { + 108 : 11 : uint8 code = _detectTransferRestrictionFrom(spender, from, to, value); + 109 [ + + ]: 11 : require( + 110 : : code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), + 111 : : RuleWhitelist_InvalidTransferFrom(address(this), spender, from, to, value, code) + 112 : : ); 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 : : } + 115 : : + 116 : : } diff --git a/doc/coverage/coverage/abstract/core/index-sort-b.html b/doc/coverage/coverage/abstract/core/index-sort-b.html new file mode 100644 index 0000000..226fe72 --- /dev/null +++ b/doc/coverage/coverage/abstract/core/index-sort-b.html @@ -0,0 +1,131 @@ + + + + + + + LCOV - lcov.info - abstract/core + + + + + +
Current view:top level - validation/abstract - RuleWhitelistCommon.sol (source / functions)top level - abstract/core - RuleWhitelistShared.sol (source / functions) Hit
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions: 6
+ + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/coreHitTotalCoverage
Test:lcov.infoLines:5151100.0 %
Date:2026-03-10 10:55:10Functions:1919100.0 %
Branches:1414100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleTransferValidation.sol +
100.0%
+
100.0 %10 / 10100.0 %5 / 5-0 / 0
RuleNFTAdapter.sol +
100.0%
+
100.0 %20 / 20100.0 %8 / 8100.0 %4 / 4
RuleWhitelistShared.sol +
100.0%
+
100.0 %21 / 21100.0 %6 / 6100.0 %10 / 10
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/core/index-sort-f.html b/doc/coverage/coverage/abstract/core/index-sort-f.html new file mode 100644 index 0000000..e680dc9 --- /dev/null +++ b/doc/coverage/coverage/abstract/core/index-sort-f.html @@ -0,0 +1,131 @@ + + + + + + + LCOV - lcov.info - abstract/core + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/coreHitTotalCoverage
Test:lcov.infoLines:5151100.0 %
Date:2026-03-10 10:55:10Functions:1919100.0 %
Branches:1414100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleTransferValidation.sol +
100.0%
+
100.0 %10 / 10100.0 %5 / 5-0 / 0
RuleWhitelistShared.sol +
100.0%
+
100.0 %21 / 21100.0 %6 / 6100.0 %10 / 10
RuleNFTAdapter.sol +
100.0%
+
100.0 %20 / 20100.0 %8 / 8100.0 %4 / 4
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/core/index-sort-l.html b/doc/coverage/coverage/abstract/core/index-sort-l.html new file mode 100644 index 0000000..e557c1e --- /dev/null +++ b/doc/coverage/coverage/abstract/core/index-sort-l.html @@ -0,0 +1,131 @@ + + + + + + + LCOV - lcov.info - abstract/core + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/coreHitTotalCoverage
Test:lcov.infoLines:5151100.0 %
Date:2026-03-10 10:55:10Functions:1919100.0 %
Branches:1414100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleTransferValidation.sol +
100.0%
+
100.0 %10 / 10100.0 %5 / 5-0 / 0
RuleNFTAdapter.sol +
100.0%
+
100.0 %20 / 20100.0 %8 / 8100.0 %4 / 4
RuleWhitelistShared.sol +
100.0%
+
100.0 %21 / 21100.0 %6 / 6100.0 %10 / 10
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/abstract/core/index.html b/doc/coverage/coverage/abstract/core/index.html new file mode 100644 index 0000000..be497f9 --- /dev/null +++ b/doc/coverage/coverage/abstract/core/index.html @@ -0,0 +1,131 @@ + + + + + + + LCOV - lcov.info - abstract/core + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - abstract/coreHitTotalCoverage
Test:lcov.infoLines:5151100.0 %
Date:2026-03-10 10:55:10Functions:1919100.0 %
Branches:1414100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleNFTAdapter.sol +
100.0%
+
100.0 %20 / 20100.0 %8 / 8100.0 %4 / 4
RuleTransferValidation.sol +
100.0%
+
100.0 %10 / 10100.0 %5 / 5-0 / 0
RuleWhitelistShared.sol +
100.0%
+
100.0 %21 / 21100.0 %6 / 6100.0 %10 / 10
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleBlacklist.sol.func-sort-c.html similarity index 61% rename from doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html rename to doc/coverage/coverage/deployment/RuleBlacklist.sol.func-sort-c.html index 09bb6da..7a9f3cd 100644 --- a/doc/coverage/coverage/validation/RuleBlacklist.sol.func-sort-c.html +++ b/doc/coverage/coverage/deployment/RuleBlacklist.sol.func-sort-c.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/RuleBlacklist.sol - functions + LCOV - lcov.info - deployment/RuleBlacklist.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - validation - RuleBlacklist.sol (source / functions)top level - deployment - RuleBlacklist.sol (source / functions) Hitlcov.info Lines:353794.6 %1010100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:101190.9 %66100.0 %
Branches:1616100.0 %00-
@@ -69,48 +69,28 @@ Hit count Sort by hit count - RuleBlacklist.supportsInterface - 0 - - - RuleBlacklist.transferred.1 - 2 - - - RuleBlacklist.transferred.2 - 2 - - - RuleBlacklist.transferred.3 - 3 - - - RuleBlacklist.canReturnTransferRestrictionCode - 4 - - - RuleBlacklist.detectTransferRestrictionFrom.1 - 4 + RuleBlacklist._authorizeAddressListRemove + 1 - RuleBlacklist.detectTransferRestriction.1 - 7 + RuleBlacklist._msgData + 1 - RuleBlacklist.messageForTransferRestriction - 8 + RuleBlacklist._authorizeAddressListAdd + 28 - RuleBlacklist.transferred.0 - 9 + RuleBlacklist._msgSender + 83 - RuleBlacklist.detectTransferRestrictionFrom.0 - 16 + RuleBlacklist._contextSuffixLength + 84 - RuleBlacklist.detectTransferRestriction.0 - 22 + RuleBlacklist.supportsInterface + 91
diff --git a/doc/coverage/coverage/validation/RuleBlacklist.sol.func.html b/doc/coverage/coverage/deployment/RuleBlacklist.sol.func.html similarity index 61% rename from doc/coverage/coverage/validation/RuleBlacklist.sol.func.html rename to doc/coverage/coverage/deployment/RuleBlacklist.sol.func.html index 7644183..a7a1b13 100644 --- a/doc/coverage/coverage/validation/RuleBlacklist.sol.func.html +++ b/doc/coverage/coverage/deployment/RuleBlacklist.sol.func.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/RuleBlacklist.sol - functions + LCOV - lcov.info - deployment/RuleBlacklist.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - - + + + - - - + + +
Current view:top level - validation - RuleBlacklist.sol (source / functions)top level - deployment - RuleBlacklist.sol (source / functions) Hitlcov.info Lines:353794.6 %1010100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:101190.9 %66100.0 %
Branches:1616100.0 %00-
@@ -69,48 +69,28 @@ Hit count Sort by hit count - RuleBlacklist.canReturnTransferRestrictionCode - 4 - - - RuleBlacklist.detectTransferRestriction.0 - 22 - - - RuleBlacklist.detectTransferRestriction.1 - 7 - - - RuleBlacklist.detectTransferRestrictionFrom.0 - 16 - - - RuleBlacklist.detectTransferRestrictionFrom.1 - 4 - - - RuleBlacklist.messageForTransferRestriction - 8 + RuleBlacklist._authorizeAddressListAdd + 28 - RuleBlacklist.supportsInterface - 0 + RuleBlacklist._authorizeAddressListRemove + 1 - RuleBlacklist.transferred.0 - 9 + RuleBlacklist._contextSuffixLength + 84 - RuleBlacklist.transferred.1 - 2 + RuleBlacklist._msgData + 1 - RuleBlacklist.transferred.2 - 2 + RuleBlacklist._msgSender + 83 - RuleBlacklist.transferred.3 - 3 + RuleBlacklist.supportsInterface + 91
diff --git a/doc/coverage/coverage/deployment/RuleBlacklist.sol.gcov.html b/doc/coverage/coverage/deployment/RuleBlacklist.sol.gcov.html new file mode 100644 index 0000000..1f3c2dd --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleBlacklist.sol.gcov.html @@ -0,0 +1,138 @@ + + + + + + + LCOV - lcov.info - deployment/RuleBlacklist.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleBlacklist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2026-03-10 10:55:10Functions:66100.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 {AccessControlEnumerable} from "OZ/access/extensions/AccessControlEnumerable.sol";
+       6                 :            : import {Context} from "OZ/utils/Context.sol";
+       7                 :            : import {AccessControlModuleStandalone} from "../../../modules/AccessControlModuleStandalone.sol";
+       8                 :            : /* ==== Abstract contracts === */
+       9                 :            : import {RuleBlacklistBase} from "../abstract/base/RuleBlacklistBase.sol";
+      10                 :            : import {RuleAddressSet} from "../abstract/RuleAddressSet/RuleAddressSet.sol";
+      11                 :            : 
+      12                 :            : /**
+      13                 :            :  * @title a blacklist manager
+      14                 :            :  */
+      15                 :            : contract RuleBlacklist is RuleBlacklistBase, AccessControlModuleStandalone {
+      16                 :            :     /*//////////////////////////////////////////////////////////////
+      17                 :            :                               CONSTRUCTOR
+      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(address admin, address forwarderIrrevocable)
+      24                 :            :         RuleBlacklistBase(forwarderIrrevocable)
+      25                 :            :         AccessControlModuleStandalone(admin)
+      26                 :            :     {}
+      27                 :            : 
+      28                 :         91 :     function supportsInterface(bytes4 interfaceId)
+      29                 :            :         public
+      30                 :            :         view
+      31                 :            :         virtual
+      32                 :            :         override(AccessControlEnumerable, RuleBlacklistBase)
+      33                 :            :         returns (bool)
+      34                 :            :     {
+      35                 :         91 :         return AccessControlEnumerable.supportsInterface(interfaceId) || RuleBlacklistBase.supportsInterface(interfaceId);
+      36                 :            :     }
+      37                 :            : 
+      38                 :         28 :     function _authorizeAddressListAdd() internal view virtual override onlyRole(ADDRESS_LIST_ADD_ROLE) {}
+      39                 :            : 
+      40                 :          1 :     function _authorizeAddressListRemove() internal view virtual override onlyRole(ADDRESS_LIST_REMOVE_ROLE) {}
+      41                 :            : 
+      42                 :         83 :     function _msgSender() internal view virtual override(Context, RuleAddressSet) returns (address sender) {
+      43                 :         83 :         return super._msgSender();
+      44                 :            :     }
+      45                 :            : 
+      46                 :          1 :     function _msgData() internal view virtual override(Context, RuleAddressSet) returns (bytes calldata) {
+      47                 :          1 :         return super._msgData();
+      48                 :            :     }
+      49                 :            : 
+      50                 :         84 :     function _contextSuffixLength() internal view virtual override(Context, RuleAddressSet) returns (uint256) {
+      51                 :         84 :         return super._contextSuffixLength();
+      52                 :            :     }
+      53                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.func-sort-c.html new file mode 100644 index 0000000..4f6c52b --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.func-sort-c.html @@ -0,0 +1,101 @@ + + + + + + + LCOV - lcov.info - deployment/RuleBlacklistOwnable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleBlacklistOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:88100.0 %
Date:2026-03-10 10:55:10Functions:55100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleBlacklistOwnable2Step._msgData1
RuleBlacklistOwnable2Step._authorizeAddressListAdd2
RuleBlacklistOwnable2Step._authorizeAddressListRemove2
RuleBlacklistOwnable2Step._msgSender12
RuleBlacklistOwnable2Step._contextSuffixLength13
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.func.html b/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.func.html new file mode 100644 index 0000000..3adf440 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.func.html @@ -0,0 +1,101 @@ + + + + + + + LCOV - lcov.info - deployment/RuleBlacklistOwnable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleBlacklistOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:88100.0 %
Date:2026-03-10 10:55:10Functions:55100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleBlacklistOwnable2Step._authorizeAddressListAdd2
RuleBlacklistOwnable2Step._authorizeAddressListRemove2
RuleBlacklistOwnable2Step._contextSuffixLength13
RuleBlacklistOwnable2Step._msgData1
RuleBlacklistOwnable2Step._msgSender12
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.gcov.html b/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.gcov.html new file mode 100644 index 0000000..1c015a0 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleBlacklistOwnable2Step.sol.gcov.html @@ -0,0 +1,120 @@ + + + + + + + LCOV - lcov.info - deployment/RuleBlacklistOwnable2Step.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleBlacklistOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:88100.0 %
Date:2026-03-10 10:55:10Functions:55100.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 {Ownable} from "OZ/access/Ownable.sol";
+       5                 :            : import {Ownable2Step} from "OZ/access/Ownable2Step.sol";
+       6                 :            : import {Context} from "OZ/utils/Context.sol";
+       7                 :            : import {RuleBlacklistBase} from "../abstract/base/RuleBlacklistBase.sol";
+       8                 :            : import {RuleAddressSet} from "../abstract/RuleAddressSet/RuleAddressSet.sol";
+       9                 :            : 
+      10                 :            : /**
+      11                 :            :  * @title RuleBlacklistOwnable2Step
+      12                 :            :  * @notice Ownable2Step variant of RuleBlacklist with owner-based authorization hooks.
+      13                 :            :  */
+      14                 :            : contract RuleBlacklistOwnable2Step is RuleBlacklistBase, Ownable2Step {
+      15                 :            :     constructor(address owner, address forwarderIrrevocable)
+      16                 :            :         RuleBlacklistBase(forwarderIrrevocable)
+      17                 :            :         Ownable(owner)
+      18                 :            :     {}
+      19                 :            : 
+      20                 :          2 :     function _authorizeAddressListAdd() internal view virtual override onlyOwner {}
+      21                 :            : 
+      22                 :          2 :     function _authorizeAddressListRemove() internal view virtual override onlyOwner {}
+      23                 :            : 
+      24                 :         12 :     function _msgSender() internal view virtual override(Context, RuleAddressSet) returns (address sender) {
+      25                 :         12 :         return super._msgSender();
+      26                 :            :     }
+      27                 :            : 
+      28                 :          1 :     function _msgData() internal view virtual override(Context, RuleAddressSet) returns (bytes calldata) {
+      29                 :          1 :         return super._msgData();
+      30                 :            :     }
+      31                 :            : 
+      32                 :         13 :     function _contextSuffixLength() internal view virtual override(Context, RuleAddressSet) returns (uint256) {
+      33                 :         13 :         return super._contextSuffixLength();
+      34                 :            :     }
+      35                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleERC2980.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleERC2980.sol.func-sort-c.html new file mode 100644 index 0000000..5982600 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleERC2980.sol.func-sort-c.html @@ -0,0 +1,113 @@ + + + + + + + LCOV - lcov.info - deployment/RuleERC2980.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleERC2980.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2026-03-10 10:55:10Functions:88100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleERC2980._msgData1
RuleERC2980.supportsInterface1
RuleERC2980._authorizeFrozenlistRemove7
RuleERC2980._authorizeWhitelistRemove8
RuleERC2980._authorizeFrozenlistAdd22
RuleERC2980._authorizeWhitelistAdd42
RuleERC2980._msgSender237
RuleERC2980._contextSuffixLength238
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleERC2980.sol.func.html b/doc/coverage/coverage/deployment/RuleERC2980.sol.func.html new file mode 100644 index 0000000..2fc8959 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleERC2980.sol.func.html @@ -0,0 +1,113 @@ + + + + + + + LCOV - lcov.info - deployment/RuleERC2980.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleERC2980.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2026-03-10 10:55:10Functions:88100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleERC2980._authorizeFrozenlistAdd22
RuleERC2980._authorizeFrozenlistRemove7
RuleERC2980._authorizeWhitelistAdd42
RuleERC2980._authorizeWhitelistRemove8
RuleERC2980._contextSuffixLength238
RuleERC2980._msgData1
RuleERC2980._msgSender237
RuleERC2980.supportsInterface1
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleERC2980.sol.gcov.html b/doc/coverage/coverage/deployment/RuleERC2980.sol.gcov.html new file mode 100644 index 0000000..44437e3 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleERC2980.sol.gcov.html @@ -0,0 +1,168 @@ + + + + + + + LCOV - lcov.info - deployment/RuleERC2980.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleERC2980.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2026-03-10 10:55:10Functions:88100.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 {AccessControlEnumerable} from "OZ/access/extensions/AccessControlEnumerable.sol";
+       5                 :            : import {Context} from "OZ/utils/Context.sol";
+       6                 :            : /* ==== Abstract contracts === */
+       7                 :            : import {AccessControlModuleStandalone} from "../../../modules/AccessControlModuleStandalone.sol";
+       8                 :            : import {RuleERC2980Base} from "../abstract/base/RuleERC2980Base.sol";
+       9                 :            : 
+      10                 :            : /**
+      11                 :            :  * @title RuleERC2980
+      12                 :            :  * @notice ERC-2980 Swiss Compliant transfer rule combining a whitelist and a frozenlist.
+      13                 :            :  * @dev
+      14                 :            :  * - Whitelist: only whitelisted addresses may receive tokens.
+      15                 :            :  *   Senders do not need to be whitelisted.
+      16                 :            :  * - Frozenlist: frozen addresses are blocked from both sending and receiving.
+      17                 :            :  *   Frozenlist check takes priority over the whitelist check.
+      18                 :            :  *
+      19                 :            :  * Access control uses {AccessControlModuleStandalone}:
+      20                 :            :  * - `WHITELIST_ADD_ROLE`    — may add addresses to the whitelist.
+      21                 :            :  * - `WHITELIST_REMOVE_ROLE` — may remove addresses from the whitelist.
+      22                 :            :  * - `FROZENLIST_ADD_ROLE`   — may add addresses to the frozenlist.
+      23                 :            :  * - `FROZENLIST_REMOVE_ROLE`— may remove addresses from the frozenlist.
+      24                 :            :  * - `DEFAULT_ADMIN_ROLE`    — implicitly holds all roles.
+      25                 :            :  *
+      26                 :            :  * Restriction codes:
+      27                 :            :  * - 60: sender is frozen
+      28                 :            :  * - 61: recipient is frozen
+      29                 :            :  * - 62: spender is frozen
+      30                 :            :  * - 63: recipient is not whitelisted
+      31                 :            :  */
+      32                 :            : contract RuleERC2980 is RuleERC2980Base, AccessControlModuleStandalone {
+      33                 :            :     /*//////////////////////////////////////////////////////////////
+      34                 :            :                               CONSTRUCTOR
+      35                 :            :     //////////////////////////////////////////////////////////////*/
+      36                 :            : 
+      37                 :            :     /**
+      38                 :            :      * @param admin Address that receives `DEFAULT_ADMIN_ROLE` (implicitly holds all roles).
+      39                 :            :      * @param forwarderIrrevocable Address of the ERC-2771 forwarder for meta-transactions.
+      40                 :            :      */
+      41                 :            :     constructor(address admin, address forwarderIrrevocable)
+      42                 :            :         RuleERC2980Base(forwarderIrrevocable)
+      43                 :            :         AccessControlModuleStandalone(admin)
+      44                 :            :     {}
+      45                 :            : 
+      46                 :            :     /*//////////////////////////////////////////////////////////////
+      47                 :            :                            INTERFACE SUPPORT
+      48                 :            :     //////////////////////////////////////////////////////////////*/
+      49                 :            : 
+      50                 :          1 :     function supportsInterface(bytes4 interfaceId)
+      51                 :            :         public
+      52                 :            :         view
+      53                 :            :         virtual
+      54                 :            :         override(AccessControlEnumerable, RuleERC2980Base)
+      55                 :            :         returns (bool)
+      56                 :            :     {
+      57                 :          1 :         return AccessControlEnumerable.supportsInterface(interfaceId) || RuleERC2980Base.supportsInterface(interfaceId);
+      58                 :            :     }
+      59                 :            : 
+      60                 :            :     /*//////////////////////////////////////////////////////////////
+      61                 :            :                             ACCESS CONTROL
+      62                 :            :     //////////////////////////////////////////////////////////////*/
+      63                 :            : 
+      64                 :         42 :     function _authorizeWhitelistAdd() internal view virtual override onlyRole(WHITELIST_ADD_ROLE) {}
+      65                 :            : 
+      66                 :          8 :     function _authorizeWhitelistRemove() internal view virtual override onlyRole(WHITELIST_REMOVE_ROLE) {}
+      67                 :            : 
+      68                 :         22 :     function _authorizeFrozenlistAdd() internal view virtual override onlyRole(FROZENLIST_ADD_ROLE) {}
+      69                 :            : 
+      70                 :          7 :     function _authorizeFrozenlistRemove() internal view virtual override onlyRole(FROZENLIST_REMOVE_ROLE) {}
+      71                 :            : 
+      72                 :        237 :     function _msgSender() internal view virtual override(Context, RuleERC2980Base) returns (address sender) {
+      73                 :        237 :         return super._msgSender();
+      74                 :            :     }
+      75                 :            : 
+      76                 :          1 :     function _msgData() internal view virtual override(Context, RuleERC2980Base) returns (bytes calldata) {
+      77                 :          1 :         return super._msgData();
+      78                 :            :     }
+      79                 :            : 
+      80                 :        238 :     function _contextSuffixLength() internal view virtual override(Context, RuleERC2980Base) returns (uint256) {
+      81                 :        238 :         return super._contextSuffixLength();
+      82                 :            :     }
+      83                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.func-sort-c.html new file mode 100644 index 0000000..6a57dc8 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.func-sort-c.html @@ -0,0 +1,109 @@ + + + + + + + LCOV - lcov.info - deployment/RuleERC2980Ownable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleERC2980Ownable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2026-03-10 10:55:10Functions:77100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleERC2980Ownable2Step._msgData1
RuleERC2980Ownable2Step._authorizeFrozenlistRemove2
RuleERC2980Ownable2Step._authorizeWhitelistRemove3
RuleERC2980Ownable2Step._authorizeFrozenlistAdd6
RuleERC2980Ownable2Step._authorizeWhitelistAdd7
RuleERC2980Ownable2Step._msgSender30
RuleERC2980Ownable2Step._contextSuffixLength31
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.func.html b/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.func.html new file mode 100644 index 0000000..06ea5a4 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.func.html @@ -0,0 +1,109 @@ + + + + + + + LCOV - lcov.info - deployment/RuleERC2980Ownable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleERC2980Ownable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2026-03-10 10:55:10Functions:77100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleERC2980Ownable2Step._authorizeFrozenlistAdd6
RuleERC2980Ownable2Step._authorizeFrozenlistRemove2
RuleERC2980Ownable2Step._authorizeWhitelistAdd7
RuleERC2980Ownable2Step._authorizeWhitelistRemove3
RuleERC2980Ownable2Step._contextSuffixLength31
RuleERC2980Ownable2Step._msgData1
RuleERC2980Ownable2Step._msgSender30
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.gcov.html b/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.gcov.html new file mode 100644 index 0000000..58cf267 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleERC2980Ownable2Step.sol.gcov.html @@ -0,0 +1,124 @@ + + + + + + + LCOV - lcov.info - deployment/RuleERC2980Ownable2Step.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleERC2980Ownable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2026-03-10 10:55:10Functions:77100.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 {Ownable} from "OZ/access/Ownable.sol";
+       5                 :            : import {Ownable2Step} from "OZ/access/Ownable2Step.sol";
+       6                 :            : import {Context} from "OZ/utils/Context.sol";
+       7                 :            : import {RuleERC2980Base} from "../abstract/base/RuleERC2980Base.sol";
+       8                 :            : 
+       9                 :            : /**
+      10                 :            :  * @title RuleERC2980Ownable2Step
+      11                 :            :  * @notice Ownable2Step variant of RuleERC2980 with owner-based authorization hooks.
+      12                 :            :  * @dev All whitelist and frozenlist management functions are restricted to the contract owner.
+      13                 :            :  */
+      14                 :            : contract RuleERC2980Ownable2Step is RuleERC2980Base, Ownable2Step {
+      15                 :            :     constructor(address owner, address forwarderIrrevocable)
+      16                 :            :         RuleERC2980Base(forwarderIrrevocable)
+      17                 :            :         Ownable(owner)
+      18                 :            :     {}
+      19                 :            : 
+      20                 :          7 :     function _authorizeWhitelistAdd() internal view virtual override onlyOwner {}
+      21                 :            : 
+      22                 :          3 :     function _authorizeWhitelistRemove() internal view virtual override onlyOwner {}
+      23                 :            : 
+      24                 :          6 :     function _authorizeFrozenlistAdd() internal view virtual override onlyOwner {}
+      25                 :            : 
+      26                 :          2 :     function _authorizeFrozenlistRemove() internal view virtual override onlyOwner {}
+      27                 :            : 
+      28                 :         30 :     function _msgSender() internal view virtual override(Context, RuleERC2980Base) returns (address sender) {
+      29                 :         30 :         return super._msgSender();
+      30                 :            :     }
+      31                 :            : 
+      32                 :          1 :     function _msgData() internal view virtual override(Context, RuleERC2980Base) returns (bytes calldata) {
+      33                 :          1 :         return super._msgData();
+      34                 :            :     }
+      35                 :            : 
+      36                 :         31 :     function _contextSuffixLength() internal view virtual override(Context, RuleERC2980Base) returns (uint256) {
+      37                 :         31 :         return super._contextSuffixLength();
+      38                 :            :     }
+      39                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.func-sort-c.html new file mode 100644 index 0000000..c671fdf --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.func-sort-c.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - deployment/RuleIdentityRegistry.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleIdentityRegistry.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:44100.0 %
Date:2026-03-10 10:55:10Functions:22100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleIdentityRegistry._authorizeIdentityRegistryManager5
RuleIdentityRegistry.supportsInterface15
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.func.html b/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.func.html new file mode 100644 index 0000000..03a6311 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.func.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - deployment/RuleIdentityRegistry.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleIdentityRegistry.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:44100.0 %
Date:2026-03-10 10:55:10Functions:22100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleIdentityRegistry._authorizeIdentityRegistryManager5
RuleIdentityRegistry.supportsInterface15
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.gcov.html b/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.gcov.html new file mode 100644 index 0000000..29c87c5 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleIdentityRegistry.sol.gcov.html @@ -0,0 +1,121 @@ + + + + + + + LCOV - lcov.info - deployment/RuleIdentityRegistry.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleIdentityRegistry.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:44100.0 %
Date:2026-03-10 10:55:10Functions:22100.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 {AccessControlEnumerable} from "OZ/access/extensions/AccessControlEnumerable.sol";
+       5                 :            : import {AccessControlModuleStandalone} from "../../../modules/AccessControlModuleStandalone.sol";
+       6                 :            : import {RuleIdentityRegistryBase} from "../abstract/base/RuleIdentityRegistryBase.sol";
+       7                 :            : import {RuleTransferValidation} from "../abstract/core/RuleTransferValidation.sol";
+       8                 :            : 
+       9                 :            : /**
+      10                 :            :  * @title RuleIdentityRegistry
+      11                 :            :  * @notice Checks the ERC-3643 Identity Registry for transfer participants when configured.
+      12                 :            :  * @dev Burns (to == address(0)) are allowed even if the sender is not verified.
+      13                 :            :  */
+      14                 :            : contract RuleIdentityRegistry is AccessControlModuleStandalone, RuleIdentityRegistryBase {
+      15                 :            :     constructor(address admin, address identityRegistry_)
+      16                 :            :         AccessControlModuleStandalone(admin)
+      17                 :            :         RuleIdentityRegistryBase(identityRegistry_)
+      18                 :            :     {}
+      19                 :            : 
+      20                 :         15 :     function supportsInterface(bytes4 interfaceId)
+      21                 :            :         public
+      22                 :            :         view
+      23                 :            :         virtual
+      24                 :            :         override(AccessControlEnumerable, RuleTransferValidation)
+      25                 :            :         returns (bool)
+      26                 :            :     {
+      27                 :         15 :         return AccessControlEnumerable.supportsInterface(interfaceId)
+      28                 :         10 :             || RuleTransferValidation.supportsInterface(interfaceId);
+      29                 :            :     }
+      30                 :            : 
+      31                 :            :     /*//////////////////////////////////////////////////////////////
+      32                 :            :                             ACCESS CONTROL
+      33                 :            :     //////////////////////////////////////////////////////////////*/
+      34                 :            : 
+      35                 :          5 :     function _authorizeIdentityRegistryManager() internal view virtual override onlyRole(DEFAULT_ADMIN_ROLE) {}
+      36                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.func-sort-c.html new file mode 100644 index 0000000..f0edaeb --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.func-sort-c.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - deployment/RuleIdentityRegistryOwnable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleIdentityRegistryOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11100.0 %
Date:2026-03-10 10:55:10Functions:11100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleIdentityRegistryOwnable2Step._authorizeIdentityRegistryManager4
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.func.html b/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.func.html new file mode 100644 index 0000000..f36b6a3 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.func.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - deployment/RuleIdentityRegistryOwnable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleIdentityRegistryOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11100.0 %
Date:2026-03-10 10:55:10Functions:11100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleIdentityRegistryOwnable2Step._authorizeIdentityRegistryManager4
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.gcov.html b/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.gcov.html new file mode 100644 index 0000000..c5464a5 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleIdentityRegistryOwnable2Step.sol.gcov.html @@ -0,0 +1,101 @@ + + + + + + + LCOV - lcov.info - deployment/RuleIdentityRegistryOwnable2Step.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleIdentityRegistryOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11100.0 %
Date:2026-03-10 10:55:10Functions: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 {Ownable} from "OZ/access/Ownable.sol";
+       5                 :            : import {Ownable2Step} from "OZ/access/Ownable2Step.sol";
+       6                 :            : import {RuleIdentityRegistryBase} from "../abstract/base/RuleIdentityRegistryBase.sol";
+       7                 :            : 
+       8                 :            : /**
+       9                 :            :  * @title RuleIdentityRegistryOwnable2Step
+      10                 :            :  * @notice Ownable2Step variant of RuleIdentityRegistry.
+      11                 :            :  */
+      12                 :            : contract RuleIdentityRegistryOwnable2Step is RuleIdentityRegistryBase, Ownable2Step {
+      13                 :            :     constructor(address owner, address identityRegistry_) RuleIdentityRegistryBase(identityRegistry_) Ownable(owner) {}
+      14                 :            : 
+      15                 :          4 :     function _authorizeIdentityRegistryManager() internal view virtual override onlyOwner {}
+      16                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.func-sort-c.html new file mode 100644 index 0000000..3d362ea --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.func-sort-c.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - deployment/RuleMaxTotalSupply.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleMaxTotalSupply.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:44100.0 %
Date:2026-03-10 10:55:10Functions:22100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleMaxTotalSupply.supportsInterface15
RuleMaxTotalSupply._authorizeMaxTotalSupplyManager260
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.func.html b/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.func.html new file mode 100644 index 0000000..461eca6 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.func.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - deployment/RuleMaxTotalSupply.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleMaxTotalSupply.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:44100.0 %
Date:2026-03-10 10:55:10Functions:22100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleMaxTotalSupply._authorizeMaxTotalSupplyManager260
RuleMaxTotalSupply.supportsInterface15
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.gcov.html b/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.gcov.html new file mode 100644 index 0000000..6933e67 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleMaxTotalSupply.sol.gcov.html @@ -0,0 +1,125 @@ + + + + + + + LCOV - lcov.info - deployment/RuleMaxTotalSupply.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleMaxTotalSupply.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:44100.0 %
Date:2026-03-10 10:55:10Functions:22100.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 {AccessControlEnumerable} from "OZ/access/extensions/AccessControlEnumerable.sol";
+       5                 :            : import {AccessControlModuleStandalone} from "../../../modules/AccessControlModuleStandalone.sol";
+       6                 :            : import {RuleMaxTotalSupplyBase} from "../abstract/base/RuleMaxTotalSupplyBase.sol";
+       7                 :            : import {RuleTransferValidation} from "../abstract/core/RuleTransferValidation.sol";
+       8                 :            : 
+       9                 :            : /**
+      10                 :            :  * @title RuleMaxTotalSupply
+      11                 :            :  * @notice Restricts minting so that total supply never exceeds a maximum value.
+      12                 :            :  */
+      13                 :            : contract RuleMaxTotalSupply is AccessControlModuleStandalone, RuleMaxTotalSupplyBase {
+      14                 :            :     /**
+      15                 :            :      * @param admin Address that receives the default admin role.
+      16                 :            :      * @param tokenContract_ Token contract that exposes totalSupply (must be non-zero).
+      17                 :            :      * @param maxTotalSupply_ Initial maximum supply.
+      18                 :            :      */
+      19                 :            :     constructor(address admin, address tokenContract_, uint256 maxTotalSupply_)
+      20                 :            :         AccessControlModuleStandalone(admin)
+      21                 :            :         RuleMaxTotalSupplyBase(tokenContract_, maxTotalSupply_)
+      22                 :            :     {}
+      23                 :            : 
+      24                 :         15 :     function supportsInterface(bytes4 interfaceId)
+      25                 :            :         public
+      26                 :            :         view
+      27                 :            :         virtual
+      28                 :            :         override(AccessControlEnumerable, RuleTransferValidation)
+      29                 :            :         returns (bool)
+      30                 :            :     {
+      31                 :         15 :         return AccessControlEnumerable.supportsInterface(interfaceId)
+      32                 :         10 :             || RuleTransferValidation.supportsInterface(interfaceId);
+      33                 :            :     }
+      34                 :            : 
+      35                 :            :     /*//////////////////////////////////////////////////////////////
+      36                 :            :                             ACCESS CONTROL
+      37                 :            :     //////////////////////////////////////////////////////////////*/
+      38                 :            : 
+      39                 :        260 :     function _authorizeMaxTotalSupplyManager() internal view virtual override onlyRole(DEFAULT_ADMIN_ROLE) {}
+      40                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.func-sort-c.html new file mode 100644 index 0000000..8f2bc94 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.func-sort-c.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - deployment/RuleMaxTotalSupplyOwnable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleMaxTotalSupplyOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11100.0 %
Date:2026-03-10 10:55:10Functions:11100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleMaxTotalSupplyOwnable2Step._authorizeMaxTotalSupplyManager4
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.func.html b/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.func.html new file mode 100644 index 0000000..9d21145 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.func.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - deployment/RuleMaxTotalSupplyOwnable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleMaxTotalSupplyOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11100.0 %
Date:2026-03-10 10:55:10Functions:11100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleMaxTotalSupplyOwnable2Step._authorizeMaxTotalSupplyManager4
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.gcov.html b/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.gcov.html new file mode 100644 index 0000000..e3cdd2f --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleMaxTotalSupplyOwnable2Step.sol.gcov.html @@ -0,0 +1,104 @@ + + + + + + + LCOV - lcov.info - deployment/RuleMaxTotalSupplyOwnable2Step.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleMaxTotalSupplyOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11100.0 %
Date:2026-03-10 10:55:10Functions: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 {Ownable} from "OZ/access/Ownable.sol";
+       5                 :            : import {Ownable2Step} from "OZ/access/Ownable2Step.sol";
+       6                 :            : import {RuleMaxTotalSupplyBase} from "../abstract/base/RuleMaxTotalSupplyBase.sol";
+       7                 :            : 
+       8                 :            : /**
+       9                 :            :  * @title RuleMaxTotalSupplyOwnable2Step
+      10                 :            :  * @notice Ownable2Step variant of RuleMaxTotalSupply.
+      11                 :            :  */
+      12                 :            : contract RuleMaxTotalSupplyOwnable2Step is RuleMaxTotalSupplyBase, Ownable2Step {
+      13                 :            :     constructor(address owner, address tokenContract_, uint256 maxTotalSupply_)
+      14                 :            :         RuleMaxTotalSupplyBase(tokenContract_, maxTotalSupply_)
+      15                 :            :         Ownable(owner)
+      16                 :            :     {}
+      17                 :            : 
+      18                 :          4 :     function _authorizeMaxTotalSupplyManager() internal view virtual override onlyOwner {}
+      19                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleSanctionsList.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleSanctionsList.sol.func-sort-c.html new file mode 100644 index 0000000..1594a91 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleSanctionsList.sol.func-sort-c.html @@ -0,0 +1,101 @@ + + + + + + + LCOV - lcov.info - deployment/RuleSanctionsList.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleSanctionsList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2026-03-10 10:55:10Functions:55100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleSanctionsList._msgData1
RuleSanctionsList._authorizeSanctionListManager17
RuleSanctionsList._msgSender57
RuleSanctionsList._contextSuffixLength58
RuleSanctionsList.supportsInterface58
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleSanctionsList.sol.func.html b/doc/coverage/coverage/deployment/RuleSanctionsList.sol.func.html new file mode 100644 index 0000000..dcf5ed0 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleSanctionsList.sol.func.html @@ -0,0 +1,101 @@ + + + + + + + LCOV - lcov.info - deployment/RuleSanctionsList.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleSanctionsList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2026-03-10 10:55:10Functions:55100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleSanctionsList._authorizeSanctionListManager17
RuleSanctionsList._contextSuffixLength58
RuleSanctionsList._msgData1
RuleSanctionsList._msgSender57
RuleSanctionsList.supportsInterface58
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleSanctionsList.sol.gcov.html b/doc/coverage/coverage/deployment/RuleSanctionsList.sol.gcov.html new file mode 100644 index 0000000..5b789dd --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleSanctionsList.sol.gcov.html @@ -0,0 +1,143 @@ + + + + + + + LCOV - lcov.info - deployment/RuleSanctionsList.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleSanctionsList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1010100.0 %
Date:2026-03-10 10:55:10Functions:55100.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 {AccessControlEnumerable} from "OZ/access/extensions/AccessControlEnumerable.sol";
+       5                 :            : import {Context} from "OZ/utils/Context.sol";
+       6                 :            : import {AccessControlModuleStandalone} from "../../../modules/AccessControlModuleStandalone.sol";
+       7                 :            : import {MetaTxModuleStandalone, ERC2771Context} from "../../../modules/MetaTxModuleStandalone.sol";
+       8                 :            : import {RuleSanctionsListBase} from "../abstract/base/RuleSanctionsListBase.sol";
+       9                 :            : import {RuleTransferValidation} from "../abstract/core/RuleTransferValidation.sol";
+      10                 :            : import {ISanctionsList} from "../../interfaces/ISanctionsList.sol";
+      11                 :            : 
+      12                 :            : /**
+      13                 :            :  * @title RuleSanctionsList
+      14                 :            :  * @notice Compliance rule enforcing sanctions-screening for token transfers.
+      15                 :            :  */
+      16                 :            : contract RuleSanctionsList is AccessControlModuleStandalone, RuleSanctionsListBase {
+      17                 :            :     /**
+      18                 :            :      * @param admin Address of the contract (Access Control)
+      19                 :            :      * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
+      20                 :            :      */
+      21                 :            :     constructor(address admin, address forwarderIrrevocable, ISanctionsList sanctionContractOracle_)
+      22                 :            :         AccessControlModuleStandalone(admin)
+      23                 :            :         RuleSanctionsListBase(forwarderIrrevocable, sanctionContractOracle_)
+      24                 :            :     {}
+      25                 :            : 
+      26                 :         58 :     function supportsInterface(bytes4 interfaceId)
+      27                 :            :         public
+      28                 :            :         view
+      29                 :            :         virtual
+      30                 :            :         override(AccessControlEnumerable, RuleTransferValidation)
+      31                 :            :         returns (bool)
+      32                 :            :     {
+      33                 :         58 :         return AccessControlEnumerable.supportsInterface(interfaceId)
+      34                 :         39 :             || RuleTransferValidation.supportsInterface(interfaceId);
+      35                 :            :     }
+      36                 :            : 
+      37                 :            :     /*//////////////////////////////////////////////////////////////
+      38                 :            :                             ACCESS CONTROL
+      39                 :            :     //////////////////////////////////////////////////////////////*/
+      40                 :            : 
+      41                 :         17 :     function _authorizeSanctionListManager() internal view virtual override onlyRole(SANCTIONLIST_ROLE) {}
+      42                 :            : 
+      43                 :            :     /*//////////////////////////////////////////////////////////////
+      44                 :            :                            ERC-2771
+      45                 :            :     //////////////////////////////////////////////////////////////*/
+      46                 :            : 
+      47                 :         57 :     function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) {
+      48                 :         57 :         return ERC2771Context._msgSender();
+      49                 :            :     }
+      50                 :            : 
+      51                 :          1 :     function _msgData() internal view virtual override(ERC2771Context, Context) returns (bytes calldata) {
+      52                 :          1 :         return ERC2771Context._msgData();
+      53                 :            :     }
+      54                 :            : 
+      55                 :         58 :     function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) {
+      56                 :         58 :         return ERC2771Context._contextSuffixLength();
+      57                 :            :     }
+      58                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.func-sort-c.html new file mode 100644 index 0000000..d9f05d7 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.func-sort-c.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - deployment/RuleSanctionsListOwnable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleSanctionsListOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:77100.0 %
Date:2026-03-10 10:55:10Functions:44100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleSanctionsListOwnable2Step._msgData1
RuleSanctionsListOwnable2Step._authorizeSanctionListManager3
RuleSanctionsListOwnable2Step._msgSender11
RuleSanctionsListOwnable2Step._contextSuffixLength13
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.func.html b/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.func.html new file mode 100644 index 0000000..62bd796 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.func.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - deployment/RuleSanctionsListOwnable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleSanctionsListOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:77100.0 %
Date:2026-03-10 10:55:10Functions:44100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleSanctionsListOwnable2Step._authorizeSanctionListManager3
RuleSanctionsListOwnable2Step._contextSuffixLength13
RuleSanctionsListOwnable2Step._msgData1
RuleSanctionsListOwnable2Step._msgSender11
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.gcov.html b/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.gcov.html new file mode 100644 index 0000000..9cba0d5 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleSanctionsListOwnable2Step.sol.gcov.html @@ -0,0 +1,119 @@ + + + + + + + LCOV - lcov.info - deployment/RuleSanctionsListOwnable2Step.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleSanctionsListOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:77100.0 %
Date:2026-03-10 10:55:10Functions:44100.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 {Ownable} from "OZ/access/Ownable.sol";
+       5                 :            : import {Ownable2Step} from "OZ/access/Ownable2Step.sol";
+       6                 :            : import {Context} from "OZ/utils/Context.sol";
+       7                 :            : import {MetaTxModuleStandalone, ERC2771Context} from "../../../modules/MetaTxModuleStandalone.sol";
+       8                 :            : import {RuleSanctionsListBase} from "../abstract/base/RuleSanctionsListBase.sol";
+       9                 :            : import {ISanctionsList} from "../../interfaces/ISanctionsList.sol";
+      10                 :            : 
+      11                 :            : /**
+      12                 :            :  * @title RuleSanctionsListOwnable2Step
+      13                 :            :  * @notice Ownable2Step variant of RuleSanctionsList.
+      14                 :            :  */
+      15                 :            : contract RuleSanctionsListOwnable2Step is RuleSanctionsListBase, Ownable2Step {
+      16                 :            :     constructor(address owner, address forwarderIrrevocable, ISanctionsList sanctionContractOracle_)
+      17                 :            :         RuleSanctionsListBase(forwarderIrrevocable, sanctionContractOracle_)
+      18                 :            :         Ownable(owner)
+      19                 :            :     {}
+      20                 :            : 
+      21                 :          3 :     function _authorizeSanctionListManager() internal view virtual override onlyOwner {}
+      22                 :            : 
+      23                 :         11 :     function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) {
+      24                 :         11 :         return ERC2771Context._msgSender();
+      25                 :            :     }
+      26                 :            : 
+      27                 :          1 :     function _msgData() internal view virtual override(ERC2771Context, Context) returns (bytes calldata) {
+      28                 :          1 :         return ERC2771Context._msgData();
+      29                 :            :     }
+      30                 :            : 
+      31                 :         13 :     function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) {
+      32                 :         13 :         return ERC2771Context._contextSuffixLength();
+      33                 :            :     }
+      34                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleWhitelist.sol.func-sort-c.html similarity index 73% rename from doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html rename to doc/coverage/coverage/deployment/RuleWhitelist.sol.func-sort-c.html index f9af8e7..86d6201 100644 --- a/doc/coverage/coverage/validation/RuleWhitelist.sol.func-sort-c.html +++ b/doc/coverage/coverage/deployment/RuleWhitelist.sol.func-sort-c.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/RuleWhitelist.sol - functions + LCOV - lcov.info - deployment/RuleWhitelist.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - + + - - - + + +
Current view:top level - validation - RuleWhitelist.sol (source / functions)top level - deployment - RuleWhitelist.sol (source / functions) Hitlcov.info Lines:162080.0 %1111100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:5 771.4 %7100.0 %
Branches:55100.0 %00-
@@ -69,32 +69,32 @@ Hit count Sort by hit count - RuleWhitelist.isVerified - 0 + RuleWhitelist._authorizeCheckSpenderManager + 1 - RuleWhitelist.supportsInterface - 0 + RuleWhitelist._msgData + 1 - RuleWhitelist.detectTransferRestrictionFrom.1 - 2 + RuleWhitelist.supportsInterface + 40 - RuleWhitelist.detectTransferRestriction.1 - 7 + RuleWhitelist._authorizeAddressListRemove + 263 - RuleWhitelist.detectTransferRestrictionFrom.0 - 10 + RuleWhitelist._authorizeAddressListAdd + 348 - RuleWhitelist.detectTransferRestriction.0 - 20 + RuleWhitelist._msgSender + 772 - RuleWhitelist.constructor - 102 + RuleWhitelist._contextSuffixLength + 773
diff --git a/doc/coverage/coverage/validation/RuleWhitelist.sol.func.html b/doc/coverage/coverage/deployment/RuleWhitelist.sol.func.html similarity index 73% rename from doc/coverage/coverage/validation/RuleWhitelist.sol.func.html rename to doc/coverage/coverage/deployment/RuleWhitelist.sol.func.html index e3f8fe0..b216e14 100644 --- a/doc/coverage/coverage/validation/RuleWhitelist.sol.func.html +++ b/doc/coverage/coverage/deployment/RuleWhitelist.sol.func.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/RuleWhitelist.sol - functions + LCOV - lcov.info - deployment/RuleWhitelist.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - + + - - - + + +
Current view:top level - validation - RuleWhitelist.sol (source / functions)top level - deployment - RuleWhitelist.sol (source / functions) Hitlcov.info Lines:162080.0 %1111100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:5 771.4 %7100.0 %
Branches:55100.0 %00-
@@ -69,32 +69,32 @@ Hit count Sort by hit count - RuleWhitelist.constructor - 102 + RuleWhitelist._authorizeAddressListAdd + 348 - RuleWhitelist.detectTransferRestriction.0 - 20 + RuleWhitelist._authorizeAddressListRemove + 263 - RuleWhitelist.detectTransferRestriction.1 - 7 + RuleWhitelist._authorizeCheckSpenderManager + 1 - RuleWhitelist.detectTransferRestrictionFrom.0 - 10 + RuleWhitelist._contextSuffixLength + 773 - RuleWhitelist.detectTransferRestrictionFrom.1 - 2 + RuleWhitelist._msgData + 1 - RuleWhitelist.isVerified - 0 + RuleWhitelist._msgSender + 772 - RuleWhitelist.supportsInterface - 0 + RuleWhitelist.supportsInterface + 40
diff --git a/doc/coverage/coverage/deployment/RuleWhitelist.sol.gcov.html b/doc/coverage/coverage/deployment/RuleWhitelist.sol.gcov.html new file mode 100644 index 0000000..ca176dc --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleWhitelist.sol.gcov.html @@ -0,0 +1,158 @@ + + + + + + + LCOV - lcov.info - deployment/RuleWhitelist.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleWhitelist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1111100.0 %
Date:2026-03-10 10:55:10Functions:77100.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 {AccessControlEnumerable} from "OZ/access/extensions/AccessControlEnumerable.sol";
+       5                 :            : import {Context} from "OZ/utils/Context.sol";
+       6                 :            : /* ==== Abstract contracts === */
+       7                 :            : import {AccessControlModuleStandalone} from "../../../modules/AccessControlModuleStandalone.sol";
+       8                 :            : import {RuleWhitelistBase} from "../abstract/base/RuleWhitelistBase.sol";
+       9                 :            : import {RuleAddressSet} from "../abstract/RuleAddressSet/RuleAddressSet.sol";
+      10                 :            : /* ==== CMTAT === */
+      11                 :            : 
+      12                 :            : /**
+      13                 :            :  * @title Rule Whitelist
+      14                 :            :  * @notice Manages a whitelist of authorized addresses and enforces whitelist-based transfer restrictions.
+      15                 :            :  * @dev
+      16                 :            :  * - Inherits core address management logic from {RuleAddressSet}.
+      17                 :            :  * - Integrates restriction code logic from {RuleWhitelistShared}.
+      18                 :            :  * - Implements {IERC1404} to return specific restriction codes for non-whitelisted transfers.
+      19                 :            :  */
+      20                 :            : contract RuleWhitelist is RuleWhitelistBase, AccessControlModuleStandalone {
+      21                 :            :     /*//////////////////////////////////////////////////////////////
+      22                 :            :                               CONSTRUCTOR
+      23                 :            :     //////////////////////////////////////////////////////////////*/
+      24                 :            :     /**
+      25                 :            :      * @param admin Address of the contract (Access Control)
+      26                 :            :      * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
+      27                 :            :      */
+      28                 :            :     constructor(address admin, address forwarderIrrevocable, bool checkSpender_)
+      29                 :            :         RuleWhitelistBase(forwarderIrrevocable, checkSpender_)
+      30                 :            :         AccessControlModuleStandalone(admin)
+      31                 :            :     {
+      32                 :            :         // no-op
+      33                 :            :     }
+      34                 :            : 
+      35                 :            :     /* ============  View Functions ============ */
+      36                 :            : 
+      37                 :            :     /**
+      38                 :            :      * @notice Indicates whether this contract supports a given interface.
+      39                 :            :      * @param interfaceId The interface identifier, as specified in ERC-165.
+      40                 :            :      * @return supported True if the interface is supported.
+      41                 :            :      */
+      42                 :         40 :     function supportsInterface(bytes4 interfaceId)
+      43                 :            :         public
+      44                 :            :         view
+      45                 :            :         virtual
+      46                 :            :         override(AccessControlEnumerable, RuleWhitelistBase)
+      47                 :            :         returns (bool)
+      48                 :            :     {
+      49                 :         40 :         return AccessControlEnumerable.supportsInterface(interfaceId) || RuleWhitelistBase.supportsInterface(interfaceId);
+      50                 :            :     }
+      51                 :            : 
+      52                 :            :     /*//////////////////////////////////////////////////////////////
+      53                 :            :                             ACCESS CONTROL
+      54                 :            :     //////////////////////////////////////////////////////////////*/
+      55                 :            : 
+      56                 :          1 :     function _authorizeCheckSpenderManager() internal view virtual override onlyRole(DEFAULT_ADMIN_ROLE) {}
+      57                 :            : 
+      58                 :        348 :     function _authorizeAddressListAdd() internal view virtual override onlyRole(ADDRESS_LIST_ADD_ROLE) {}
+      59                 :            : 
+      60                 :        263 :     function _authorizeAddressListRemove() internal view virtual override onlyRole(ADDRESS_LIST_REMOVE_ROLE) {}
+      61                 :            : 
+      62                 :        772 :     function _msgSender() internal view virtual override(Context, RuleAddressSet) returns (address sender) {
+      63                 :        772 :         return super._msgSender();
+      64                 :            :     }
+      65                 :            : 
+      66                 :          1 :     function _msgData() internal view virtual override(Context, RuleAddressSet) returns (bytes calldata) {
+      67                 :          1 :         return super._msgData();
+      68                 :            :     }
+      69                 :            : 
+      70                 :        773 :     function _contextSuffixLength() internal view virtual override(Context, RuleAddressSet) returns (uint256) {
+      71                 :        773 :         return super._contextSuffixLength();
+      72                 :            :     }
+      73                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.func-sort-c.html new file mode 100644 index 0000000..1d0cde2 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.func-sort-c.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - deployment/RuleWhitelistOwnable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleWhitelistOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:99100.0 %
Date:2026-03-10 10:55:10Functions:66100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistOwnable2Step._msgData1
RuleWhitelistOwnable2Step._authorizeAddressListAdd2
RuleWhitelistOwnable2Step._authorizeAddressListRemove2
RuleWhitelistOwnable2Step._authorizeCheckSpenderManager2
RuleWhitelistOwnable2Step._msgSender15
RuleWhitelistOwnable2Step._contextSuffixLength16
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.func.html b/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.func.html new file mode 100644 index 0000000..aaac14d --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.func.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - deployment/RuleWhitelistOwnable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleWhitelistOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:99100.0 %
Date:2026-03-10 10:55:10Functions:66100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistOwnable2Step._authorizeAddressListAdd2
RuleWhitelistOwnable2Step._authorizeAddressListRemove2
RuleWhitelistOwnable2Step._authorizeCheckSpenderManager2
RuleWhitelistOwnable2Step._contextSuffixLength16
RuleWhitelistOwnable2Step._msgData1
RuleWhitelistOwnable2Step._msgSender15
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.gcov.html b/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.gcov.html new file mode 100644 index 0000000..e0f2605 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleWhitelistOwnable2Step.sol.gcov.html @@ -0,0 +1,122 @@ + + + + + + + LCOV - lcov.info - deployment/RuleWhitelistOwnable2Step.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleWhitelistOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:99100.0 %
Date:2026-03-10 10:55:10Functions:66100.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 {Ownable} from "OZ/access/Ownable.sol";
+       5                 :            : import {Ownable2Step} from "OZ/access/Ownable2Step.sol";
+       6                 :            : import {Context} from "OZ/utils/Context.sol";
+       7                 :            : import {RuleWhitelistBase} from "../abstract/base/RuleWhitelistBase.sol";
+       8                 :            : import {RuleAddressSet} from "../abstract/RuleAddressSet/RuleAddressSet.sol";
+       9                 :            : 
+      10                 :            : /**
+      11                 :            :  * @title RuleWhitelistOwnable2Step
+      12                 :            :  * @notice Ownable2Step variant of RuleWhitelist with owner-based authorization hooks.
+      13                 :            :  */
+      14                 :            : contract RuleWhitelistOwnable2Step is RuleWhitelistBase, Ownable2Step {
+      15                 :            :     constructor(address owner, address forwarderIrrevocable, bool checkSpender_)
+      16                 :            :         RuleWhitelistBase(forwarderIrrevocable, checkSpender_)
+      17                 :            :         Ownable(owner)
+      18                 :            :     {}
+      19                 :            : 
+      20                 :          2 :     function _authorizeAddressListAdd() internal view virtual override onlyOwner {}
+      21                 :            : 
+      22                 :          2 :     function _authorizeAddressListRemove() internal view virtual override onlyOwner {}
+      23                 :            : 
+      24                 :          2 :     function _authorizeCheckSpenderManager() internal view virtual override onlyOwner {}
+      25                 :            : 
+      26                 :         15 :     function _msgSender() internal view virtual override(Context, RuleAddressSet) returns (address sender) {
+      27                 :         15 :         return super._msgSender();
+      28                 :            :     }
+      29                 :            : 
+      30                 :          1 :     function _msgData() internal view virtual override(Context, RuleAddressSet) returns (bytes calldata) {
+      31                 :          1 :         return super._msgData();
+      32                 :            :     }
+      33                 :            : 
+      34                 :         16 :     function _contextSuffixLength() internal view virtual override(Context, RuleAddressSet) returns (uint256) {
+      35                 :         16 :         return super._contextSuffixLength();
+      36                 :            :     }
+      37                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.func-sort-c.html similarity index 64% rename from doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html rename to doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.func-sort-c.html index 19a2bf6..b118fa8 100644 --- a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func-sort-c.html +++ b/doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.func-sort-c.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/RuleWhitelistWrapper.sol - functions + LCOV - lcov.info - deployment/RuleWhitelistWrapper.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - + + - - - + + +
Current view:top level - validation - RuleWhitelistWrapper.sol (source / functions)top level - deployment - RuleWhitelistWrapper.sol (source / functions) Hitlcov.info Lines:505787.7 %1717100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions: 91181.8 %9100.0 %
Branches:111478.6 %00-
@@ -69,48 +69,40 @@ Hit count Sort by hit count - RuleWhitelistWrapper._msgData - 0 + RuleWhitelistWrapper._msgData + 1 - RuleWhitelistWrapper.supportsInterface - 0 + RuleWhitelistWrapper._revokeRole + 1 - RuleWhitelistWrapper.detectTransferRestrictionFrom.1 + RuleWhitelistWrapper._authorizeCheckSpenderManager 2 - RuleWhitelistWrapper.detectTransferRestriction.1 - 4 - - - RuleWhitelistWrapper.detectTransferRestrictionFrom.0 - 10 - - - RuleWhitelistWrapper.hasRole - 20 + RuleWhitelistWrapper._grantRole + 38 - RuleWhitelistWrapper.detectTransferRestriction.0 - 21 + RuleWhitelistWrapper.hasRole + 38 - RuleWhitelistWrapper.constructor - 22 + RuleWhitelistWrapper.supportsInterface + 46 - RuleWhitelistWrapper._detectTransferRestriction - 37 + RuleWhitelistWrapper._onlyRulesManager + 90 - RuleWhitelistWrapper._contextSuffixLength - 80 + RuleWhitelistWrapper._msgSender + 133 - RuleWhitelistWrapper._msgSender - 80 + RuleWhitelistWrapper._contextSuffixLength + 134
diff --git a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html b/doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.func.html similarity index 64% rename from doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html rename to doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.func.html index 4994cad..c7034ec 100644 --- a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.func.html +++ b/doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.func.html @@ -4,7 +4,7 @@ - LCOV - lcov.info - validation/RuleWhitelistWrapper.sol - functions + LCOV - lcov.info - deployment/RuleWhitelistWrapper.sol - functions @@ -19,7 +19,7 @@ - + @@ -31,27 +31,27 @@ - - - + + + - + - - + + - - - + + +
Current view:top level - validation - RuleWhitelistWrapper.sol (source / functions)top level - deployment - RuleWhitelistWrapper.sol (source / functions) Hitlcov.info Lines:505787.7 %1717100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions: 91181.8 %9100.0 %
Branches:111478.6 %00-
@@ -69,48 +69,40 @@ Hit count Sort by hit count - RuleWhitelistWrapper._contextSuffixLength - 80 - - - RuleWhitelistWrapper._detectTransferRestriction - 37 - - - RuleWhitelistWrapper._msgData - 0 + RuleWhitelistWrapper._authorizeCheckSpenderManager + 2 - RuleWhitelistWrapper._msgSender - 80 + RuleWhitelistWrapper._contextSuffixLength + 134 - RuleWhitelistWrapper.constructor - 22 + RuleWhitelistWrapper._grantRole + 38 - RuleWhitelistWrapper.detectTransferRestriction.0 - 21 + RuleWhitelistWrapper._msgData + 1 - RuleWhitelistWrapper.detectTransferRestriction.1 - 4 + RuleWhitelistWrapper._msgSender + 133 - RuleWhitelistWrapper.detectTransferRestrictionFrom.0 - 10 + RuleWhitelistWrapper._onlyRulesManager + 90 - RuleWhitelistWrapper.detectTransferRestrictionFrom.1 - 2 + RuleWhitelistWrapper._revokeRole + 1 - RuleWhitelistWrapper.hasRole - 20 + RuleWhitelistWrapper.hasRole + 38 - RuleWhitelistWrapper.supportsInterface - 0 + RuleWhitelistWrapper.supportsInterface + 46
diff --git a/doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.gcov.html b/doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.gcov.html new file mode 100644 index 0000000..fee07c5 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleWhitelistWrapper.sol.gcov.html @@ -0,0 +1,183 @@ + + + + + + + LCOV - lcov.info - deployment/RuleWhitelistWrapper.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleWhitelistWrapper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1717100.0 %
Date:2026-03-10 10:55:10Functions:99100.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                 :            : /* ==== OpenZeppelin === */
+       6                 :            : import {AccessControl} from "OZ/access/AccessControl.sol";
+       7                 :            : import {AccessControlEnumerable} from "OZ/access/extensions/AccessControlEnumerable.sol";
+       8                 :            : import {Context} from "OZ/utils/Context.sol";
+       9                 :            : /* ==== Abstract contracts === */
+      10                 :            : import {AccessControlModuleStandalone} from "../../../modules/AccessControlModuleStandalone.sol";
+      11                 :            : import {RuleWhitelistWrapperBase} from "../abstract/base/RuleWhitelistWrapperBase.sol";
+      12                 :            : 
+      13                 :            : /**
+      14                 :            :  * @title Wrapper to call several different whitelist rules
+      15                 :            :  */
+      16                 :            : contract RuleWhitelistWrapper is
+      17                 :            :     RuleWhitelistWrapperBase,
+      18                 :            :     AccessControlModuleStandalone
+      19                 :            : {
+      20                 :            :     /*//////////////////////////////////////////////////////////////
+      21                 :            :                               CONSTRUCTOR
+      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(address admin, address forwarderIrrevocable, bool checkSpender_)
+      28                 :            :         RuleWhitelistWrapperBase(forwarderIrrevocable, checkSpender_)
+      29                 :            :         AccessControlModuleStandalone(admin)
+      30                 :            :     {}
+      31                 :            : 
+      32                 :            :     /* ============  Access control ============ */
+      33                 :            : 
+      34                 :            :     /**
+      35                 :            :      * @dev Returns `true` if `account` has been granted `role`.
+      36                 :            :      */
+      37                 :         38 :     function hasRole(bytes32 role, address account)
+      38                 :            :         public
+      39                 :            :         view
+      40                 :            :         virtual
+      41                 :            :         override(AccessControl, AccessControlModuleStandalone)
+      42                 :            :         returns (bool)
+      43                 :            :     {
+      44                 :        134 :         return AccessControlModuleStandalone.hasRole(role, account);
+      45                 :            :     }
+      46                 :            : 
+      47                 :          2 :     function _authorizeCheckSpenderManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {}
+      48                 :            : 
+      49                 :            :     /**
+      50                 :            :      * @dev Restrict rules management to the dedicated role.
+      51                 :            :      */
+      52                 :         90 :     function _onlyRulesManager() internal virtual override onlyRole(RULES_MANAGEMENT_ROLE) {}
+      53                 :            : 
+      54                 :            :     /*//////////////////////////////////////////////////////////////
+      55                 :            :                            ERC-2771
+      56                 :            :     //////////////////////////////////////////////////////////////*/
+      57                 :            : 
+      58                 :        133 :     function _msgSender() internal view virtual override(RuleWhitelistWrapperBase, Context) returns (address sender) {
+      59                 :        133 :         return RuleWhitelistWrapperBase._msgSender();
+      60                 :            :     }
+      61                 :            : 
+      62                 :          1 :     function _msgData() internal view virtual override(RuleWhitelistWrapperBase, Context) returns (bytes calldata) {
+      63                 :          1 :         return RuleWhitelistWrapperBase._msgData();
+      64                 :            :     }
+      65                 :            : 
+      66                 :        134 :     function _contextSuffixLength() internal view virtual override(RuleWhitelistWrapperBase, Context) returns (uint256) {
+      67                 :        134 :         return RuleWhitelistWrapperBase._contextSuffixLength();
+      68                 :            :     }
+      69                 :            : 
+      70                 :         46 :     function supportsInterface(bytes4 interfaceId)
+      71                 :            :         public
+      72                 :            :         view
+      73                 :            :         virtual
+      74                 :            :         override(AccessControlEnumerable, RuleWhitelistWrapperBase)
+      75                 :            :         returns (bool)
+      76                 :            :     {
+      77                 :         46 :         return RuleWhitelistWrapperBase.supportsInterface(interfaceId)
+      78                 :         16 :             || AccessControlEnumerable.supportsInterface(interfaceId);
+      79                 :            :     }
+      80                 :            : 
+      81                 :         38 :     function _grantRole(bytes32 role, address account)
+      82                 :            :         internal
+      83                 :            :         virtual
+      84                 :            :         override(AccessControl, AccessControlEnumerable)
+      85                 :            :         returns (bool)
+      86                 :            :     {
+      87                 :         38 :         return AccessControlEnumerable._grantRole(role, account);
+      88                 :            :     }
+      89                 :            : 
+      90                 :          1 :     function _revokeRole(bytes32 role, address account)
+      91                 :            :         internal
+      92                 :            :         virtual
+      93                 :            :         override(AccessControl, AccessControlEnumerable)
+      94                 :            :         returns (bool)
+      95                 :            :     {
+      96                 :          1 :         return AccessControlEnumerable._revokeRole(role, account);
+      97                 :            :     }
+      98                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.func-sort-c.html b/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.func-sort-c.html new file mode 100644 index 0000000..b67a8e6 --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.func-sort-c.html @@ -0,0 +1,101 @@ + + + + + + + LCOV - lcov.info - deployment/RuleWhitelistWrapperOwnable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleWhitelistWrapperOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:88100.0 %
Date:2026-03-10 10:55:10Functions:55100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistWrapperOwnable2Step._msgData1
RuleWhitelistWrapperOwnable2Step._authorizeCheckSpenderManager2
RuleWhitelistWrapperOwnable2Step._onlyRulesManager2
RuleWhitelistWrapperOwnable2Step._msgSender12
RuleWhitelistWrapperOwnable2Step._contextSuffixLength13
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.func.html b/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.func.html new file mode 100644 index 0000000..b704ccc --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.func.html @@ -0,0 +1,101 @@ + + + + + + + LCOV - lcov.info - deployment/RuleWhitelistWrapperOwnable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleWhitelistWrapperOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:88100.0 %
Date:2026-03-10 10:55:10Functions:55100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleWhitelistWrapperOwnable2Step._authorizeCheckSpenderManager2
RuleWhitelistWrapperOwnable2Step._contextSuffixLength13
RuleWhitelistWrapperOwnable2Step._msgData1
RuleWhitelistWrapperOwnable2Step._msgSender12
RuleWhitelistWrapperOwnable2Step._onlyRulesManager2
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.gcov.html b/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.gcov.html new file mode 100644 index 0000000..211abff --- /dev/null +++ b/doc/coverage/coverage/deployment/RuleWhitelistWrapperOwnable2Step.sol.gcov.html @@ -0,0 +1,136 @@ + + + + + + + LCOV - lcov.info - deployment/RuleWhitelistWrapperOwnable2Step.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deployment - RuleWhitelistWrapperOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:88100.0 %
Date:2026-03-10 10:55:10Functions:55100.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                 :            : /* ==== OpenZeppelin === */
+       6                 :            : import {Ownable} from "OZ/access/Ownable.sol";
+       7                 :            : import {Ownable2Step} from "OZ/access/Ownable2Step.sol";
+       8                 :            : import {Context} from "OZ/utils/Context.sol";
+       9                 :            : /* ==== Abstract contracts === */
+      10                 :            : import {RuleWhitelistWrapperBase} from "../abstract/base/RuleWhitelistWrapperBase.sol";
+      11                 :            : 
+      12                 :            : /**
+      13                 :            :  * @title Wrapper to call several different whitelist rules (Ownable2Step)
+      14                 :            :  */
+      15                 :            : contract RuleWhitelistWrapperOwnable2Step is RuleWhitelistWrapperBase, Ownable2Step {
+      16                 :            :     /*//////////////////////////////////////////////////////////////
+      17                 :            :                               CONSTRUCTOR
+      18                 :            :     //////////////////////////////////////////////////////////////*/
+      19                 :            :     /**
+      20                 :            :      * @param owner Address of the contract owner
+      21                 :            :      * @param forwarderIrrevocable Address of the forwarder, required for the gasless support
+      22                 :            :      */
+      23                 :            :     constructor(address owner, address forwarderIrrevocable, bool checkSpender_)
+      24                 :            :         RuleWhitelistWrapperBase(forwarderIrrevocable, checkSpender_)
+      25                 :            :         Ownable(owner)
+      26                 :            :     {}
+      27                 :            : 
+      28                 :          2 :     function _authorizeCheckSpenderManager() internal view virtual override onlyOwner {}
+      29                 :            : 
+      30                 :            :     /**
+      31                 :            :      * @dev Restrict rules management to the owner.
+      32                 :            :      */
+      33                 :          2 :     function _onlyRulesManager() internal view virtual override onlyOwner {}
+      34                 :            : 
+      35                 :            :     /*//////////////////////////////////////////////////////////////
+      36                 :            :                            ERC-2771
+      37                 :            :     //////////////////////////////////////////////////////////////*/
+      38                 :            : 
+      39                 :         12 :     function _msgSender() internal view virtual override(RuleWhitelistWrapperBase, Context) returns (address sender) {
+      40                 :         12 :         return RuleWhitelistWrapperBase._msgSender();
+      41                 :            :     }
+      42                 :            : 
+      43                 :          1 :     function _msgData() internal view virtual override(RuleWhitelistWrapperBase, Context) returns (bytes calldata) {
+      44                 :          1 :         return RuleWhitelistWrapperBase._msgData();
+      45                 :            :     }
+      46                 :            : 
+      47                 :         13 :     function _contextSuffixLength() internal view virtual override(RuleWhitelistWrapperBase, Context) returns (uint256) {
+      48                 :         13 :         return RuleWhitelistWrapperBase._contextSuffixLength();
+      49                 :            :     }
+      50                 :            : 
+      51                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/index-sort-b.html b/doc/coverage/coverage/deployment/index-sort-b.html new file mode 100644 index 0000000..ebfc836 --- /dev/null +++ b/doc/coverage/coverage/deployment/index-sort-b.html @@ -0,0 +1,263 @@ + + + + + + + LCOV - lcov.info - deployment + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deploymentHitTotalCoverage
Test:lcov.infoLines:112112100.0 %
Date:2026-03-10 10:55:10Functions:6868100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleSanctionsListOwnable2Step.sol +
100.0%
+
100.0 %7 / 7100.0 %4 / 4-0 / 0
RuleBlacklist.sol +
100.0%
+
100.0 %10 / 10100.0 %6 / 6-0 / 0
RuleMaxTotalSupply.sol +
100.0%
+
100.0 %4 / 4100.0 %2 / 2-0 / 0
RuleWhitelist.sol +
100.0%
+
100.0 %11 / 11100.0 %7 / 7-0 / 0
RuleBlacklistOwnable2Step.sol +
100.0%
+
100.0 %8 / 8100.0 %5 / 5-0 / 0
RuleMaxTotalSupplyOwnable2Step.sol +
100.0%
+
100.0 %1 / 1100.0 %1 / 1-0 / 0
RuleWhitelistWrapper.sol +
100.0%
+
100.0 %17 / 17100.0 %9 / 9-0 / 0
RuleSanctionsList.sol +
100.0%
+
100.0 %10 / 10100.0 %5 / 5-0 / 0
RuleWhitelistWrapperOwnable2Step.sol +
100.0%
+
100.0 %8 / 8100.0 %5 / 5-0 / 0
RuleERC2980Ownable2Step.sol +
100.0%
+
100.0 %10 / 10100.0 %7 / 7-0 / 0
RuleERC2980.sol +
100.0%
+
100.0 %12 / 12100.0 %8 / 8-0 / 0
RuleIdentityRegistry.sol +
100.0%
+
100.0 %4 / 4100.0 %2 / 2-0 / 0
RuleWhitelistOwnable2Step.sol +
100.0%
+
100.0 %9 / 9100.0 %6 / 6-0 / 0
RuleIdentityRegistryOwnable2Step.sol +
100.0%
+
100.0 %1 / 1100.0 %1 / 1-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/index-sort-f.html b/doc/coverage/coverage/deployment/index-sort-f.html new file mode 100644 index 0000000..a3d26c0 --- /dev/null +++ b/doc/coverage/coverage/deployment/index-sort-f.html @@ -0,0 +1,263 @@ + + + + + + + LCOV - lcov.info - deployment + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deploymentHitTotalCoverage
Test:lcov.infoLines:112112100.0 %
Date:2026-03-10 10:55:10Functions:6868100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleMaxTotalSupplyOwnable2Step.sol +
100.0%
+
100.0 %1 / 1100.0 %1 / 1-0 / 0
RuleIdentityRegistryOwnable2Step.sol +
100.0%
+
100.0 %1 / 1100.0 %1 / 1-0 / 0
RuleMaxTotalSupply.sol +
100.0%
+
100.0 %4 / 4100.0 %2 / 2-0 / 0
RuleIdentityRegistry.sol +
100.0%
+
100.0 %4 / 4100.0 %2 / 2-0 / 0
RuleSanctionsListOwnable2Step.sol +
100.0%
+
100.0 %7 / 7100.0 %4 / 4-0 / 0
RuleBlacklistOwnable2Step.sol +
100.0%
+
100.0 %8 / 8100.0 %5 / 5-0 / 0
RuleSanctionsList.sol +
100.0%
+
100.0 %10 / 10100.0 %5 / 5-0 / 0
RuleWhitelistWrapperOwnable2Step.sol +
100.0%
+
100.0 %8 / 8100.0 %5 / 5-0 / 0
RuleBlacklist.sol +
100.0%
+
100.0 %10 / 10100.0 %6 / 6-0 / 0
RuleWhitelistOwnable2Step.sol +
100.0%
+
100.0 %9 / 9100.0 %6 / 6-0 / 0
RuleWhitelist.sol +
100.0%
+
100.0 %11 / 11100.0 %7 / 7-0 / 0
RuleERC2980Ownable2Step.sol +
100.0%
+
100.0 %10 / 10100.0 %7 / 7-0 / 0
RuleERC2980.sol +
100.0%
+
100.0 %12 / 12100.0 %8 / 8-0 / 0
RuleWhitelistWrapper.sol +
100.0%
+
100.0 %17 / 17100.0 %9 / 9-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/index-sort-l.html b/doc/coverage/coverage/deployment/index-sort-l.html new file mode 100644 index 0000000..6ace07a --- /dev/null +++ b/doc/coverage/coverage/deployment/index-sort-l.html @@ -0,0 +1,263 @@ + + + + + + + LCOV - lcov.info - deployment + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deploymentHitTotalCoverage
Test:lcov.infoLines:112112100.0 %
Date:2026-03-10 10:55:10Functions:6868100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleMaxTotalSupplyOwnable2Step.sol +
100.0%
+
100.0 %1 / 1100.0 %1 / 1-0 / 0
RuleIdentityRegistryOwnable2Step.sol +
100.0%
+
100.0 %1 / 1100.0 %1 / 1-0 / 0
RuleMaxTotalSupply.sol +
100.0%
+
100.0 %4 / 4100.0 %2 / 2-0 / 0
RuleIdentityRegistry.sol +
100.0%
+
100.0 %4 / 4100.0 %2 / 2-0 / 0
RuleSanctionsListOwnable2Step.sol +
100.0%
+
100.0 %7 / 7100.0 %4 / 4-0 / 0
RuleBlacklistOwnable2Step.sol +
100.0%
+
100.0 %8 / 8100.0 %5 / 5-0 / 0
RuleWhitelistWrapperOwnable2Step.sol +
100.0%
+
100.0 %8 / 8100.0 %5 / 5-0 / 0
RuleWhitelistOwnable2Step.sol +
100.0%
+
100.0 %9 / 9100.0 %6 / 6-0 / 0
RuleBlacklist.sol +
100.0%
+
100.0 %10 / 10100.0 %6 / 6-0 / 0
RuleSanctionsList.sol +
100.0%
+
100.0 %10 / 10100.0 %5 / 5-0 / 0
RuleERC2980Ownable2Step.sol +
100.0%
+
100.0 %10 / 10100.0 %7 / 7-0 / 0
RuleWhitelist.sol +
100.0%
+
100.0 %11 / 11100.0 %7 / 7-0 / 0
RuleERC2980.sol +
100.0%
+
100.0 %12 / 12100.0 %8 / 8-0 / 0
RuleWhitelistWrapper.sol +
100.0%
+
100.0 %17 / 17100.0 %9 / 9-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/deployment/index.html b/doc/coverage/coverage/deployment/index.html new file mode 100644 index 0000000..e2cc395 --- /dev/null +++ b/doc/coverage/coverage/deployment/index.html @@ -0,0 +1,263 @@ + + + + + + + LCOV - lcov.info - deployment + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - deploymentHitTotalCoverage
Test:lcov.infoLines:112112100.0 %
Date:2026-03-10 10:55:10Functions:6868100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleBlacklist.sol +
100.0%
+
100.0 %10 / 10100.0 %6 / 6-0 / 0
RuleBlacklistOwnable2Step.sol +
100.0%
+
100.0 %8 / 8100.0 %5 / 5-0 / 0
RuleERC2980.sol +
100.0%
+
100.0 %12 / 12100.0 %8 / 8-0 / 0
RuleERC2980Ownable2Step.sol +
100.0%
+
100.0 %10 / 10100.0 %7 / 7-0 / 0
RuleIdentityRegistry.sol +
100.0%
+
100.0 %4 / 4100.0 %2 / 2-0 / 0
RuleIdentityRegistryOwnable2Step.sol +
100.0%
+
100.0 %1 / 1100.0 %1 / 1-0 / 0
RuleMaxTotalSupply.sol +
100.0%
+
100.0 %4 / 4100.0 %2 / 2-0 / 0
RuleMaxTotalSupplyOwnable2Step.sol +
100.0%
+
100.0 %1 / 1100.0 %1 / 1-0 / 0
RuleSanctionsList.sol +
100.0%
+
100.0 %10 / 10100.0 %5 / 5-0 / 0
RuleSanctionsListOwnable2Step.sol +
100.0%
+
100.0 %7 / 7100.0 %4 / 4-0 / 0
RuleWhitelist.sol +
100.0%
+
100.0 %11 / 11100.0 %7 / 7-0 / 0
RuleWhitelistOwnable2Step.sol +
100.0%
+
100.0 %9 / 9100.0 %6 / 6-0 / 0
RuleWhitelistWrapper.sol +
100.0%
+
100.0 %17 / 17100.0 %9 / 9-0 / 0
RuleWhitelistWrapperOwnable2Step.sol +
100.0%
+
100.0 %8 / 8100.0 %5 / 5-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + 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 5ee975a..6e237b7 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 @@ -31,13 +31,13 @@ lcov.info Lines: - 8 - 8 + 7 + 7 100.0 % Date: - 2025-12-03 15:05:37 + 2026-03-10 10:55:10 Functions: 2 @@ -49,8 +49,8 @@ Branches: - 3 - 3 + 4 + 4 100.0 % @@ -69,12 +69,12 @@ Hit count Sort by hit count - AccessControlModuleStandalone.constructor - 161 + AccessControlModuleStandalone.constructor + 396 AccessControlModuleStandalone.hasRole - 228 + 507
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 5e3e889..ce374e8 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 @@ -31,13 +31,13 @@ lcov.info Lines: - 8 - 8 + 7 + 7 100.0 % Date: - 2025-12-03 15:05:37 + 2026-03-10 10:55:10 Functions: 2 @@ -49,8 +49,8 @@ Branches: - 3 - 3 + 4 + 4 100.0 % @@ -69,12 +69,12 @@ Hit count Sort by hit count - AccessControlModuleStandalone.constructor - 161 + AccessControlModuleStandalone.constructor + 396 AccessControlModuleStandalone.hasRole - 228 + 507
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 001fd5e..0ff4430 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 @@ -31,13 +31,13 @@ lcov.info Lines: - 8 - 8 + 7 + 7 100.0 % Date: - 2025-12-03 15:05:37 + 2026-03-10 10:55:10 Functions: 2 @@ -49,8 +49,8 @@ Branches: - 3 - 3 + 4 + 4 100.0 % @@ -75,29 +75,29 @@ 4 : : 5 : : /* ==== OpenZeppelin === */ 6 : : import {AccessControl} from "OZ/access/AccessControl.sol"; - 7 : : - 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 : : } + 7 : : import {IAccessControl} from "OZ/access/IAccessControl.sol"; + 8 : : import {AccessControlEnumerable} from "OZ/access/extensions/AccessControlEnumerable.sol"; + 9 : : + 10 : : abstract contract AccessControlModuleStandalone is AccessControlEnumerable { + 11 : : error AccessControlModuleStandalone_AddressZeroNotAllowed(); + 12 : : /* ============ Constructor ============ */ + 13 : : /** + 14 : : * @notice Assigns the provided address as the default admin. + 15 : : * @dev + 16 : : * - Reverts if `admin` is the zero address. + 17 : : * - Grants `DEFAULT_ADMIN_ROLE` to `admin`. + 18 : : * The return value of `_grantRole` is intentionally ignored, as it returns `false` + 19 : : * only when the role was already granted. + 20 : : * + 21 : : * @param admin The address that will receive the `DEFAULT_ADMIN_ROLE`. + 22 : : */ + 23 : : + 24 : 396 : constructor(address admin) { + 25 [ + + ]: 396 : require(admin != address(0), AccessControlModuleStandalone_AddressZeroNotAllowed()); 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); + 29 : 391 : _grantRole(DEFAULT_ADMIN_ROLE, admin); 30 : : } 31 : : 32 : : /*////////////////////////////////////////////////////////////// @@ -106,15 +106,22 @@ 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 : : } + 38 : 507 : function hasRole(bytes32 role, address account) + 39 : : public + 40 : : view + 41 : : virtual + 42 : : override(AccessControl, IAccessControl) + 43 : : returns (bool) + 44 : : { + 45 : : // Dev note: default admin is treated as having all roles but may not appear in enumerable role members. + 46 : : // The Default Admin has all roles + 47 [ + + ]: 3597 : if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { + 48 : 3110 : return true; + 49 : : } else { + 50 : 487 : return AccessControl.hasRole(role, account); + 51 : : } + 52 : : } + 53 : : } diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.func-sort-c.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.func-sort-c.html new file mode 100644 index 0000000..9a3a841 --- /dev/null +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.func-sort-c.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - home/ryan/Pictures/dev/Rules/src/modules - VersionModule.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2026-03-10 10:55:10Functions:11100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
VersionModule.version7
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.func.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.func.html new file mode 100644 index 0000000..ba069d3 --- /dev/null +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.func.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - home/ryan/Pictures/dev/Rules/src/modules - VersionModule.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2026-03-10 10:55:10Functions:11100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
VersionModule.version7
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.gcov.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.gcov.html new file mode 100644 index 0000000..21cb955 --- /dev/null +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol.gcov.html @@ -0,0 +1,102 @@ + + + + + + + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/modules/VersionModule.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - home/ryan/Pictures/dev/Rules/src/modules - VersionModule.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2026-03-10 10:55:10Functions: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 {IERC3643Version} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+       5                 :            : 
+       6                 :            : /**
+       7                 :            :  * @title VersionModule
+       8                 :            :  * @notice Exposes the contract version as required by ERC-3643.
+       9                 :            :  */
+      10                 :            : abstract contract VersionModule is IERC3643Version {
+      11                 :            :     string private constant VERSION = "0.2.0";
+      12                 :            : 
+      13                 :            :     /// @inheritdoc IERC3643Version
+      14                 :          7 :     function version() public view virtual override returns (string memory version_) {
+      15                 :          7 :         return VERSION;
+      16                 :            :     }
+      17                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + 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 6514966..1c2b511 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 @@ -31,17 +31,17 @@ lcov.info Lines: - 8 - 8 + 9 + 9 100.0 % Date: - 2025-12-03 15:05:37 + 2026-03-10 10:55:10 Functions: - 2 - 2 + 3 + 3 100.0 % @@ -49,8 +49,8 @@ Branches: - 3 - 3 + 4 + 4 100.0 % @@ -81,17 +81,29 @@ Functions Sort by function coverage Branches Sort by branch coverage + + VersionModule.sol + +
100.0%
+ + 100.0 % + 2 / 2 + 100.0 % + 1 / 1 + - + 0 / 0 + AccessControlModuleStandalone.sol
100.0%
100.0 % - 8 / 8 + 7 / 7 100.0 % 2 / 2 100.0 % - 3 / 3 + 4 / 4 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 d593422..250be9c 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 @@ -31,17 +31,17 @@ lcov.info Lines: - 8 - 8 + 9 + 9 100.0 % Date: - 2025-12-03 15:05:37 + 2026-03-10 10:55:10 Functions: - 2 - 2 + 3 + 3 100.0 % @@ -49,8 +49,8 @@ Branches: - 3 - 3 + 4 + 4 100.0 % @@ -81,17 +81,29 @@ Functions Sort by function coverage Branches Sort by branch coverage + + VersionModule.sol + +
100.0%
+ + 100.0 % + 2 / 2 + 100.0 % + 1 / 1 + - + 0 / 0 + AccessControlModuleStandalone.sol
100.0%
100.0 % - 8 / 8 + 7 / 7 100.0 % 2 / 2 100.0 % - 3 / 3 + 4 / 4 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 42bb733..38d71c7 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 @@ -31,17 +31,17 @@ lcov.info Lines: - 8 - 8 + 9 + 9 100.0 % Date: - 2025-12-03 15:05:37 + 2026-03-10 10:55:10 Functions: - 2 - 2 + 3 + 3 100.0 % @@ -49,8 +49,8 @@ Branches: - 3 - 3 + 4 + 4 100.0 % @@ -81,17 +81,29 @@ Functions Sort by function coverage Branches Sort by branch coverage + + VersionModule.sol + +
100.0%
+ + 100.0 % + 2 / 2 + 100.0 % + 1 / 1 + - + 0 / 0 + AccessControlModuleStandalone.sol
100.0%
100.0 % - 8 / 8 + 7 / 7 100.0 % 2 / 2 100.0 % - 3 / 3 + 4 / 4 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 7bed3a1..e1ab118 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 @@ -31,17 +31,17 @@ lcov.info Lines: - 8 - 8 + 9 + 9 100.0 % Date: - 2025-12-03 15:05:37 + 2026-03-10 10:55:10 Functions: - 2 - 2 + 3 + 3 100.0 % @@ -49,8 +49,8 @@ Branches: - 3 - 3 + 4 + 4 100.0 % @@ -87,11 +87,23 @@
100.0%
100.0 % - 8 / 8 + 7 / 7 + 100.0 % + 2 / 2 + 100.0 % + 4 / 4 + + + VersionModule.sol + +
100.0%
+ 100.0 % 2 / 2 100.0 % - 3 / 3 + 1 / 1 + - + 0 / 0 diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.func-sort-c.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.func-sort-c.html new file mode 100644 index 0000000..79562b0 --- /dev/null +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.func-sort-c.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - home/ryan/Pictures/dev/Rules/src/rules/operation - RuleConditionalTransferLight.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1111100.0 %
Date:2026-03-10 10:55:10Functions:66100.0 %
Branches:22100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleConditionalTransferLight.created1
RuleConditionalTransferLight.destroyed1
RuleConditionalTransferLight.supportsInterface18
RuleConditionalTransferLight._onlyComplianceManager19
RuleConditionalTransferLight._authorizeTransferExecution857
RuleConditionalTransferLight._authorizeTransferApproval1947
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.func.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.func.html new file mode 100644 index 0000000..a785d77 --- /dev/null +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.func.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - home/ryan/Pictures/dev/Rules/src/rules/operation - RuleConditionalTransferLight.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1111100.0 %
Date:2026-03-10 10:55:10Functions:66100.0 %
Branches:22100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleConditionalTransferLight._authorizeTransferApproval1947
RuleConditionalTransferLight._authorizeTransferExecution857
RuleConditionalTransferLight._onlyComplianceManager19
RuleConditionalTransferLight.created1
RuleConditionalTransferLight.destroyed1
RuleConditionalTransferLight.supportsInterface18
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.gcov.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.gcov.html new file mode 100644 index 0000000..c7dd5c5 --- /dev/null +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol.gcov.html @@ -0,0 +1,141 @@ + + + + + + + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLight.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - home/ryan/Pictures/dev/Rules/src/rules/operation - RuleConditionalTransferLight.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1111100.0 %
Date:2026-03-10 10:55:10Functions:66100.0 %
Branches:22100.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MPL-2.0
+       2                 :            : pragma solidity ^0.8.20;
+       3                 :            : 
+       4                 :            : import {AccessControlEnumerable} from "OZ/access/extensions/AccessControlEnumerable.sol";
+       5                 :            : import {IERC165} from "OZ/utils/introspection/IERC165.sol";
+       6                 :            : import {IRule} from "RuleEngine/interfaces/IRule.sol";
+       7                 :            : import {RuleInterfaceId} from "RuleEngine/modules/library/RuleInterfaceId.sol";
+       8                 :            : import {AccessControlModuleStandalone} from "../../modules/AccessControlModuleStandalone.sol";
+       9                 :            : import {ERC3643ComplianceModule} from "RuleEngine/modules/ERC3643ComplianceModule.sol";
+      10                 :            : import {RuleConditionalTransferLightBase} from "./abstract/RuleConditionalTransferLightBase.sol";
+      11                 :            : 
+      12                 :            : /**
+      13                 :            :  * @title ConditionalTransferLight
+      14                 :            :  * @dev Requires operator approval for each transfer. Same transfer (from, to, value)
+      15                 :            :  *      can be approved multiple times to allow repeated transfers.
+      16                 :            :  */
+      17                 :            : contract RuleConditionalTransferLight is
+      18                 :            :     AccessControlModuleStandalone,
+      19                 :            :     ERC3643ComplianceModule,
+      20                 :            :     RuleConditionalTransferLightBase
+      21                 :            : {
+      22                 :            :     /**
+      23                 :            :      * @param admin Address of the contract admin.
+      24                 :            :      */
+      25                 :            :     constructor(address admin) AccessControlModuleStandalone(admin) {}
+      26                 :            : 
+      27                 :         18 :     function supportsInterface(bytes4 interfaceId)
+      28                 :            :         public
+      29                 :            :         view
+      30                 :            :         virtual
+      31                 :            :         override(AccessControlEnumerable, IERC165)
+      32                 :            :         returns (bool)
+      33                 :            :     {
+      34                 :         18 :         return interfaceId == RuleInterfaceId.IRULE_INTERFACE_ID || interfaceId == type(IRule).interfaceId
+      35                 :         11 :             || AccessControlEnumerable.supportsInterface(interfaceId);
+      36                 :            :     }
+      37                 :            : 
+      38                 :          1 :     function created(address to, uint256 value) external onlyBoundToken {
+      39                 :          1 :         _transferred(address(0), to, value);
+      40                 :            :     }
+      41                 :            : 
+      42                 :          1 :     function destroyed(address from, uint256 value) external onlyBoundToken {
+      43                 :          1 :         _transferred(from, address(0), value);
+      44                 :            :     }
+      45                 :            : 
+      46                 :       1947 :     function _authorizeTransferApproval() internal view virtual override onlyRole(OPERATOR_ROLE) {}
+      47                 :            : 
+      48                 :        857 :     function _authorizeTransferExecution() internal view virtual override {
+      49         [ +  + ]:        857 :         require(
+      50                 :            :             isTokenBound(_msgSender()),
+      51                 :            :             RuleConditionalTransferLight_TransferExecutorUnauthorized(_msgSender())
+      52                 :            :         );
+      53                 :            :     }
+      54                 :            : 
+      55                 :         19 :     function _onlyComplianceManager() internal virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) {}
+      56                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.func-sort-c.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.func-sort-c.html new file mode 100644 index 0000000..b181ee1 --- /dev/null +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.func-sort-c.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - home/ryan/Pictures/dev/Rules/src/rules/operation - RuleConditionalTransferLightOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:55100.0 %
Date:2026-03-10 10:55:10Functions:33100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleConditionalTransferLightOwnable2Step._authorizeTransferExecution3
RuleConditionalTransferLightOwnable2Step._authorizeTransferApproval4
RuleConditionalTransferLightOwnable2Step.supportsInterface4
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.func.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.func.html new file mode 100644 index 0000000..60b99de --- /dev/null +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.func.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - home/ryan/Pictures/dev/Rules/src/rules/operation - RuleConditionalTransferLightOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:55100.0 %
Date:2026-03-10 10:55:10Functions:33100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleConditionalTransferLightOwnable2Step._authorizeTransferApproval4
RuleConditionalTransferLightOwnable2Step._authorizeTransferExecution3
RuleConditionalTransferLightOwnable2Step.supportsInterface4
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.gcov.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.gcov.html new file mode 100644 index 0000000..b0a0b09 --- /dev/null +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol.gcov.html @@ -0,0 +1,114 @@ + + + + + + + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - home/ryan/Pictures/dev/Rules/src/rules/operation - RuleConditionalTransferLightOwnable2Step.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:55100.0 %
Date:2026-03-10 10:55:10Functions:33100.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 {Ownable} from "OZ/access/Ownable.sol";
+       5                 :            : import {Ownable2Step} from "OZ/access/Ownable2Step.sol";
+       6                 :            : import {IRule} from "RuleEngine/interfaces/IRule.sol";
+       7                 :            : import {RuleInterfaceId} from "RuleEngine/modules/library/RuleInterfaceId.sol";
+       8                 :            : import {IERC165} from "OZ/utils/introspection/IERC165.sol";
+       9                 :            : import {RuleConditionalTransferLightBase} from "./abstract/RuleConditionalTransferLightBase.sol";
+      10                 :            : 
+      11                 :            : /**
+      12                 :            :  * @title RuleConditionalTransferLightOwnable2Step
+      13                 :            :  * @notice Ownable2Step variant of RuleConditionalTransferLight.
+      14                 :            :  */
+      15                 :            : contract RuleConditionalTransferLightOwnable2Step is
+      16                 :            :     RuleConditionalTransferLightBase,
+      17                 :            :     Ownable2Step
+      18                 :            : {
+      19                 :            :     constructor(address owner) Ownable(owner) {}
+      20                 :            : 
+      21                 :          4 :     function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
+      22                 :          4 :         return interfaceId == type(IERC165).interfaceId || interfaceId == RuleInterfaceId.IRULE_INTERFACE_ID
+      23                 :          2 :             || interfaceId == type(IRule).interfaceId;
+      24                 :            :     }
+      25                 :            : 
+      26                 :          4 :     function _authorizeTransferApproval() internal view virtual override onlyOwner {}
+      27                 :            : 
+      28                 :          3 :     function _authorizeTransferExecution() internal view virtual override onlyOwner {}
+      29                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.func-sort-c.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.func-sort-c.html new file mode 100644 index 0000000..d8df2c5 --- /dev/null +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.func-sort-c.html @@ -0,0 +1,153 @@ + + + + + + + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - home/ryan/Pictures/dev/Rules/src/rules/operation/abstract - RuleConditionalTransferLightBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:6262100.0 %
Date:2026-03-10 10:55:10Functions:1818100.0 %
Branches:1414100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleConditionalTransferLightBase.canReturnTransferRestrictionCode1
RuleConditionalTransferLightBase.canTransferFrom1
RuleConditionalTransferLightBase.detectTransferRestrictionFrom1
RuleConditionalTransferLightBase.transferred.11
RuleConditionalTransferLightBase.messageForTransferRestriction2
RuleConditionalTransferLightBase._transferredFromContext3
RuleConditionalTransferLightBase.onlyTransferExecutor3
RuleConditionalTransferLightBase.transferred.23
RuleConditionalTransferLightBase.approveAndTransferIfAllowed4
RuleConditionalTransferLightBase.canTransfer4
RuleConditionalTransferLightBase.cancelTransferApproval4
RuleConditionalTransferLightBase.onlyTransferApprover4
RuleConditionalTransferLightBase.detectTransferRestriction7
RuleConditionalTransferLightBase.approvedCount264
RuleConditionalTransferLightBase.transferred.0856
RuleConditionalTransferLightBase._transferred860
RuleConditionalTransferLightBase.approveTransfer1940
RuleConditionalTransferLightBase._transferHash3063
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.func.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.func.html new file mode 100644 index 0000000..bd1a0a3 --- /dev/null +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.func.html @@ -0,0 +1,153 @@ + + + + + + + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - home/ryan/Pictures/dev/Rules/src/rules/operation/abstract - RuleConditionalTransferLightBase.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:6262100.0 %
Date:2026-03-10 10:55:10Functions:1818100.0 %
Branches:1414100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
RuleConditionalTransferLightBase._transferHash3063
RuleConditionalTransferLightBase._transferred860
RuleConditionalTransferLightBase._transferredFromContext3
RuleConditionalTransferLightBase.approveAndTransferIfAllowed4
RuleConditionalTransferLightBase.approveTransfer1940
RuleConditionalTransferLightBase.approvedCount264
RuleConditionalTransferLightBase.canReturnTransferRestrictionCode1
RuleConditionalTransferLightBase.canTransfer4
RuleConditionalTransferLightBase.canTransferFrom1
RuleConditionalTransferLightBase.cancelTransferApproval4
RuleConditionalTransferLightBase.detectTransferRestriction7
RuleConditionalTransferLightBase.detectTransferRestrictionFrom1
RuleConditionalTransferLightBase.messageForTransferRestriction2
RuleConditionalTransferLightBase.onlyTransferApprover4
RuleConditionalTransferLightBase.onlyTransferExecutor3
RuleConditionalTransferLightBase.transferred.0856
RuleConditionalTransferLightBase.transferred.11
RuleConditionalTransferLightBase.transferred.23
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.gcov.html similarity index 50% rename from doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.gcov.html index 9ee3de4..4dc44fd 100644 --- a/doc/coverage/coverage/validation/RuleBlacklist.sol.gcov.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol.gcov.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - validation/RuleBlacklist.sol - + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/RuleConditionalTransferLightBase.sol + - + - +
LCOV - code coverage report
- + @@ -31,34 +31,34 @@ - - - + + + - + - - - + + + - - + + - +
Current view:top level - validation - RuleBlacklist.sol (source / functions)top level - home/ryan/Pictures/dev/Rules/src/rules/operation/abstract - RuleConditionalTransferLightBase.sol (source / functions) Hitlcov.info Lines:353794.6 %6262100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:101190.9 %1818100.0 %
Branches:16161414 100.0 %
@@ -70,192 +70,193 @@
           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                 :         22 :     function detectTransferRestriction(address from, address to, uint256 /* value */ )
-      42                 :            :         public
-      43                 :            :         view
-      44                 :            :         override(IERC1404)
-      45                 :            :         returns (uint8)
-      46                 :            :     {
-      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                 :         16 :             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                 :         16 :     function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value)
-      72                 :            :         public
-      73                 :            :         view
-      74                 :            :         override(IERC1404Extend)
-      75                 :            :         returns (uint8)
-      76                 :            :     {
-      77         [ +  + ]:         20 :         if (isAddressListed(spender)) {
-      78                 :          6 :             return CODE_ADDRESS_SPENDER_IS_BLACKLISTED;
-      79                 :            :         } else {
-      80                 :         14 :             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)
+       2                 :            : pragma solidity ^0.8.20;
+       3                 :            : 
+       4                 :            : import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol";
+       5                 :            : import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
+       6                 :            : import {IERC3643ComplianceRead, IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol";
+       7                 :            : import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol";
+       8                 :            : import {IRule} from "RuleEngine/interfaces/IRule.sol";
+       9                 :            : import {ITransferContext} from "../../interfaces/ITransferContext.sol";
+      10                 :            : import {IERC20} from "OZ/token/ERC20/IERC20.sol";
+      11                 :            : import {
+      12                 :            :     RuleConditionalTransferLightInvariantStorage
+      13                 :            : } from "./RuleConditionalTransferLightInvariantStorage.sol";
+      14                 :            : import {VersionModule} from "../../../modules/VersionModule.sol";
+      15                 :            : 
+      16                 :            : /**
+      17                 :            :  * @title RuleConditionalTransferLightBase
+      18                 :            :  * @dev Requires operator approval for each transfer. Same transfer (from, to, value)
+      19                 :            :  *      can be approved multiple times to allow repeated transfers.
+      20                 :            :  */
+      21                 :            : abstract contract RuleConditionalTransferLightBase is VersionModule, RuleConditionalTransferLightInvariantStorage, IRule {
+      22                 :            :     // Mapping from transfer hash to approval count
+      23                 :            :     mapping(bytes32 => uint256) public approvalCounts;
+      24                 :            : 
+      25                 :       1940 :     function approveTransfer(address from, address to, uint256 value) public onlyTransferApprover {
+      26                 :       1941 :         bytes32 transferHash = _transferHash(from, to, value);
+      27                 :       1941 :         approvalCounts[transferHash] += 1;
+      28                 :       1941 :         emit TransferApproved(from, to, value, approvalCounts[transferHash]);
+      29                 :            :     }
+      30                 :            : 
+      31                 :          4 :     function cancelTransferApproval(address from, address to, uint256 value) public onlyTransferApprover {
+      32                 :          3 :         bytes32 transferHash = _transferHash(from, to, value);
+      33                 :          3 :         uint256 count = approvalCounts[transferHash];
+      34         [ +  + ]:          3 :         require(count != 0, TransferApprovalNotFound());
+      35                 :          2 :         approvalCounts[transferHash] = count - 1;
+      36                 :          2 :         emit TransferApprovalCancelled(from, to, value, approvalCounts[transferHash]);
+      37                 :            :     }
+      38                 :            : 
+      39                 :            :     /**
+      40                 :            :      * @notice Approves and performs a transferFrom using this rule as spender.
+      41                 :            :      * @dev Requires `from` to have approved this contract on the token.
+      42                 :            :      * @dev This function is only safe for tokens that call back `transferred()` during transfer.
+      43                 :            :      * @dev CEI is intentionally inverted so the approval exists for the callback.
+      44                 :            :      */
+      45                 :          4 :     function approveAndTransferIfAllowed(address token, address from, address to, uint256 value)
+      46                 :            :         public
+      47                 :            :         onlyTransferApprover
+      48                 :            :         returns (bool)
+      49                 :            :     {
+      50         [ +  + ]:          4 :         require(token != address(0), RuleConditionalTransferLight_TokenAddressZeroNotAllowed());
+      51                 :            : 
+      52                 :          3 :         approveTransfer(from, to, value);
+      53                 :            : 
+      54                 :          3 :         uint256 allowed = IERC20(token).allowance(from, address(this));
+      55         [ +  + ]:          3 :         require(
+      56                 :            :             allowed >= value,
+      57                 :            :             RuleConditionalTransferLight_InsufficientAllowance(token, from, allowed, value)
+      58                 :            :         );
+      59                 :            : 
+      60                 :          2 :         bool success = IERC20(token).transferFrom(from, to, value);
+      61         [ +  + ]:          2 :         require(success, RuleConditionalTransferLight_TransferFailed());
+      62                 :          1 :         return true;
+      63                 :            :     }
+      64                 :            : 
+      65                 :        264 :     function approvedCount(address from, address to, uint256 value) public view returns (uint256) {
+      66                 :        264 :         bytes32 transferHash = _transferHash(from, to, value);
+      67                 :        264 :         return approvalCounts[transferHash];
+      68                 :            :     }
+      69                 :            : 
+      70                 :        856 :     function transferred(address from, address to, uint256 value)
+      71                 :            :         public
+      72                 :            :         override(IERC3643IComplianceContract)
+      73                 :            :         onlyTransferExecutor
+      74                 :            :     {
+      75                 :        854 :         _transferred(from, to, value);
+      76                 :            :     }
+      77                 :            : 
+      78                 :          1 :     function transferred(address /* spender */, address from, address to, uint256 value)
+      79                 :            :         public
+      80                 :            :         override(IRuleEngine)
+      81                 :            :         onlyTransferExecutor
+      82                 :            :     {
+      83                 :          1 :         _transferred(from, to, value);
+      84                 :            :     }
+      85                 :            : 
+      86                 :          7 :     function detectTransferRestriction(address from, address to, uint256 value)
+      87                 :            :         public
+      88                 :            :         view
+      89                 :            :         override(IERC1404)
+      90                 :            :         returns (uint8)
+      91                 :            :     {
+      92            [ + ]:         13 :         if (from == address(0) || to == address(0)) {
+      93                 :          4 :             return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+      94                 :            :         }
+      95                 :          9 :         bytes32 transferHash = _transferHash(from, to, value);
+      96            [ + ]:          9 :         if (approvalCounts[transferHash] == 0) {
+      97                 :          6 :             return CODE_TRANSFER_REQUEST_NOT_APPROVED;
+      98                 :            :         }
+      99                 :          3 :         return uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+     100                 :            :     }
+     101                 :            : 
+     102                 :          1 :     function detectTransferRestrictionFrom(address /* spender */, address from, address to, uint256 value)
+     103                 :            :         public
+     104                 :            :         view
+     105                 :            :         override(IERC1404Extend)
+     106                 :            :         returns (uint8)
+     107                 :            :     {
+     108                 :          2 :         return detectTransferRestriction(from, to, value);
+     109                 :            :     }
+     110                 :            : 
+     111                 :          4 :     function canTransfer(address from, address to, uint256 value)
+     112                 :            :         public
+     113                 :            :         view
+     114                 :            :         override(IERC3643ComplianceRead)
+     115                 :            :         returns (bool)
+     116                 :            :     {
+     117                 :          4 :         return detectTransferRestriction(from, to, value) == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+     118                 :            :     }
+     119                 :            : 
+     120                 :          1 :     function canTransferFrom(address spender, address from, address to, uint256 value)
      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                 :          9 :     function transferred(address from, address to, uint256 value)
-     145                 :            :         public
-     146                 :            :         view
-     147                 :            :         virtual
-     148                 :            :         override(IERC3643IComplianceContract)
-     149                 :            :     {
-     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                 :          2 :     function transferred(address spender, address from, address to, uint256 value)
-     158                 :            :         public
-     159                 :            :         view
-     160                 :            :         virtual
-     161                 :            :         override(IRuleEngine)
-     162                 :            :     {
-     163                 :          4 :         uint8 code = this.detectTransferRestrictionFrom(spender, from, to, value);
-     164         [ +  + ]:          4 :         require(
-     165                 :            :             code == uint8(REJECTED_CODE_BASE.TRANSFER_OK),
-     166                 :            :             RuleBlacklist_InvalidTransferFrom(address(this), spender, from, to, value, code)
-     167                 :            :         );
-     168                 :            :     }
-     169                 :            : 
-     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                 :          2 :         transferred(spender, from, to, value);
-     177                 :            :     }
-     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                 :            : }
+     122                 :            :         view
+     123                 :            :         override(IERC7551Compliance)
+     124                 :            :         returns (bool)
+     125                 :            :     {
+     126                 :          1 :         return detectTransferRestrictionFrom(spender, from, to, value)
+     127                 :            :             == uint8(IERC1404Extend.REJECTED_CODE_BASE.TRANSFER_OK);
+     128                 :            :     }
+     129                 :            : 
+     130                 :          1 :     function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override(IRule) returns (bool) {
+     131                 :          1 :         return restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED;
+     132                 :            :     }
+     133                 :            : 
+     134                 :          2 :     function messageForTransferRestriction(uint8 restrictionCode)
+     135                 :            :         external
+     136                 :            :         pure
+     137                 :            :         override(IERC1404)
+     138                 :            :         returns (string memory)
+     139                 :            :     {
+     140            [ + ]:          2 :         if (restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED) {
+     141                 :          1 :             return TEXT_TRANSFER_REQUEST_NOT_APPROVED;
+     142                 :            :         }
+     143                 :          1 :         return TEXT_CODE_NOT_FOUND;
+     144                 :            :     }
+     145                 :            : 
+     146                 :          3 :     function transferred(ITransferContext.FungibleTransferContext calldata ctx) external onlyTransferExecutor {
+     147                 :          3 :         _transferredFromContext(ctx);
+     148                 :            :     }
+     149                 :            : 
+     150                 :          3 :     function _transferredFromContext(ITransferContext.FungibleTransferContext calldata ctx) internal virtual {
+     151                 :          3 :         _transferred(ctx.from, ctx.to, ctx.value);
+     152                 :            :     }
+     153                 :            : 
+     154                 :        860 :     function _transferred(address from, address to, uint256 value) internal virtual {
+     155            [ + ]:        860 :         if (from == address(0) || to == address(0)) {
+     156                 :        860 :             return;
+     157                 :            :         }
+     158                 :        846 :         bytes32 transferHash = _transferHash(from, to, value);
+     159                 :        846 :         uint256 count = approvalCounts[transferHash];
+     160                 :            : 
+     161         [ +  + ]:        846 :         require(count != 0, TransferNotApproved());
+     162                 :            : 
+     163                 :        843 :         approvalCounts[transferHash] = count - 1;
+     164                 :        843 :         emit TransferExecuted(from, to, value, approvalCounts[transferHash]);
+     165                 :            :     }
+     166                 :            : 
+     167                 :       3063 :     function _transferHash(address from, address to, uint256 value) internal pure virtual returns (bytes32 hash) {
+     168                 :       3063 :         return keccak256(abi.encodePacked(from, to, value));
+     169                 :            :     }
+     170                 :            : 
+     171                 :            :     /*//////////////////////////////////////////////////////////////
+     172                 :            :                             ACCESS CONTROL
+     173                 :            :     //////////////////////////////////////////////////////////////*/
+     174                 :            : 
+     175                 :          4 :     modifier onlyTransferApprover() {
+     176                 :          4 :         _authorizeTransferApproval();
+     177                 :            :         _;
+     178                 :            :     }
+     179                 :            : 
+     180                 :          3 :     modifier onlyTransferExecutor() {
+     181                 :          3 :         _authorizeTransferExecution();
+     182                 :            :         _;
+     183                 :            :     }
+     184                 :            : 
+     185                 :            :     function _authorizeTransferApproval() internal view virtual;
+     186                 :            : 
+     187                 :            :     function _authorizeTransferExecution() internal view virtual;
+     188                 :            : }
 
@@ -263,7 +264,7 @@
- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-b.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-b.html new file mode 100644 index 0000000..1481813 --- /dev/null +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-b.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstractHitTotalCoverage
Test:lcov.infoLines:6262100.0 %
Date:2026-03-10 10:55:10Functions:1818100.0 %
Branches:1414100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransferLightBase.sol +
100.0%
+
100.0 %62 / 62100.0 %18 / 18100.0 %14 / 14
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-f.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-f.html new file mode 100644 index 0000000..3d54907 --- /dev/null +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-f.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstractHitTotalCoverage
Test:lcov.infoLines:6262100.0 %
Date:2026-03-10 10:55:10Functions:1818100.0 %
Branches:1414100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransferLightBase.sol +
100.0%
+
100.0 %62 / 62100.0 %18 / 18100.0 %14 / 14
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-l.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-l.html new file mode 100644 index 0000000..90e3217 --- /dev/null +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index-sort-l.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstractHitTotalCoverage
Test:lcov.infoLines:6262100.0 %
Date:2026-03-10 10:55:10Functions:1818100.0 %
Branches:1414100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransferLightBase.sol +
100.0%
+
100.0 %62 / 62100.0 %18 / 18100.0 %14 / 14
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index.html new file mode 100644 index 0000000..1a454a5 --- /dev/null +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/abstract/index.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - /home/ryan/Pictures/dev/Rules/src/rules/operation/abstractHitTotalCoverage
Test:lcov.infoLines:6262100.0 %
Date:2026-03-10 10:55:10Functions:1818100.0 %
Branches:1414100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleConditionalTransferLightBase.sol +
100.0%
+
100.0 %62 / 62100.0 %18 / 18100.0 %14 / 14
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-b.html similarity index 54% rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-b.html index fe9d655..4c73cf0 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-b.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-b.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - validation/abstract/RuleAddressSet - + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation + - + - +
LCOV - code coverage report
- + @@ -31,18 +31,18 @@ - - - + + + - + - - - + + + @@ -53,12 +53,12 @@ - +
Current view:top level - validation/abstract/RuleAddressSettop level - /home/ryan/Pictures/dev/Rules/src/rules/operation Hitlcov.info Lines:424691.3 %1616100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:151788.2 %99100.0 %
2 100.0 %
@@ -76,32 +76,32 @@ - 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 - RuleAddressSetInternal.sol + RuleConditionalTransferLightOwnable2Step.sol -
100.0%
+
100.0%
100.0 % - 14 / 14 + 5 / 5 100.0 % - 6 / 6 + 3 / 3 - 0 / 0 - RuleAddressSet.sol + RuleConditionalTransferLight.sol -
87.5%87.5%
+
100.0%
- 87.5 % - 28 / 32 - 81.8 % - 9 / 11 + 100.0 % + 11 / 11 + 100.0 % + 6 / 6 100.0 % 2 / 2 @@ -110,7 +110,7 @@
- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-f.html similarity index 54% rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-f.html index b79046b..eba8d47 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-f.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-f.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - validation/abstract/RuleAddressSet - + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation + - + - +
LCOV - code coverage report
- + @@ -31,18 +31,18 @@ - - - + + + - + - - - + + + @@ -53,12 +53,12 @@ - +
Current view:top level - validation/abstract/RuleAddressSettop level - /home/ryan/Pictures/dev/Rules/src/rules/operation Hitlcov.info Lines:424691.3 %1616100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:151788.2 %99100.0 %
2 100.0 %
@@ -76,41 +76,41 @@ - 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 - RuleAddressSet.sol + RuleConditionalTransferLightOwnable2Step.sol -
87.5%87.5%
+
100.0%
- 87.5 % - 28 / 32 - 81.8 % - 9 / 11 100.0 % - 2 / 2 + 5 / 5 + 100.0 % + 3 / 3 + - + 0 / 0 - RuleAddressSetInternal.sol + RuleConditionalTransferLight.sol -
100.0%
+
100.0%
100.0 % - 14 / 14 + 11 / 11 100.0 % 6 / 6 - - - 0 / 0 + 100.0 % + 2 / 2

- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-l.html similarity index 54% rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-l.html index 7506cec..90bdb37 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index-sort-l.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index-sort-l.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - validation/abstract/RuleAddressSet - + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation + - + - +
LCOV - code coverage report
- + @@ -31,18 +31,18 @@ - - - + + + - + - - - + + + @@ -53,12 +53,12 @@ - +
Current view:top level - validation/abstract/RuleAddressSettop level - /home/ryan/Pictures/dev/Rules/src/rules/operation Hitlcov.info Lines:424691.3 %1616100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:151788.2 %99100.0 %
2 100.0 %
@@ -76,41 +76,41 @@ - 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 - RuleAddressSet.sol + RuleConditionalTransferLightOwnable2Step.sol -
87.5%87.5%
+
100.0%
- 87.5 % - 28 / 32 - 81.8 % - 9 / 11 100.0 % - 2 / 2 + 5 / 5 + 100.0 % + 3 / 3 + - + 0 / 0 - RuleAddressSetInternal.sol + RuleConditionalTransferLight.sol -
100.0%
+
100.0%
100.0 % - 14 / 14 + 11 / 11 100.0 % 6 / 6 - - - 0 / 0 + 100.0 % + 2 / 2

- +
Generated by: LCOV version 1.16

diff --git a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index.html similarity index 54% rename from doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html rename to doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index.html index 4c0f604..8abcc29 100644 --- a/doc/coverage/coverage/validation/abstract/RuleAddressSet/index.html +++ b/doc/coverage/coverage/home/ryan/Pictures/dev/Rules/src/rules/operation/index.html @@ -4,22 +4,22 @@ - LCOV - lcov.info - validation/abstract/RuleAddressSet - + LCOV - lcov.info - /home/ryan/Pictures/dev/Rules/src/rules/operation + - + - +
LCOV - code coverage report
- + @@ -31,18 +31,18 @@ - - - + + + - + - - - + + + @@ -53,12 +53,12 @@ - +
Current view:top level - validation/abstract/RuleAddressSettop level - /home/ryan/Pictures/dev/Rules/src/rules/operation Hitlcov.info Lines:424691.3 %1616100.0 %
Date:2025-12-03 15:05:372026-03-10 10:55:10 Functions:151788.2 %99100.0 %
2 100.0 %
@@ -76,32 +76,32 @@ - 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 - RuleAddressSet.sol + RuleConditionalTransferLight.sol -
87.5%87.5%
+
100.0%
- 87.5 % - 28 / 32 - 81.8 % - 9 / 11 + 100.0 % + 11 / 11 + 100.0 % + 6 / 6 100.0 % 2 / 2 - RuleAddressSetInternal.sol + RuleConditionalTransferLightOwnable2Step.sol -
100.0%
+
100.0%
100.0 % - 14 / 14 + 5 / 5 100.0 % - 6 / 6 + 3 / 3 - 0 / 0 @@ -110,7 +110,7 @@
- +
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 2c38638..c0fea9e 100644 --- a/doc/coverage/coverage/index-sort-b.html +++ b/doc/coverage/coverage/index-sort-b.html @@ -31,27 +31,27 @@ lcov.info Lines: - 230 - 253 - 90.9 % + 698 + 698 + 100.0 % Date: - 2025-12-03 15:05:37 + 2026-03-10 10:55:10 Functions: - 66 - 76 - 86.8 % + 249 + 249 + 100.0 % Branches: - 65 - 68 - 95.6 % + 155 + 155 + 100.0 % @@ -82,26 +82,26 @@ Branches Sort by branch coverage - validation + deployment -
89.9%89.9%
+
100.0%
- 89.9 % - 151 / 168 - 84.8 % - 39 / 46 - 94.3 % - 50 / 53 + 100.0 % + 112 / 112 + 100.0 % + 68 / 68 + - + 0 / 0 - validation/abstract/RuleAddressSet + /home/ryan/Pictures/dev/Rules/src/rules/operation -
91.3%91.3%
+
100.0%
- 91.3 % - 42 / 46 - 88.2 % - 15 / 17 + 100.0 % + 16 / 16 + 100.0 % + 9 / 9 100.0 % 2 / 2 @@ -111,23 +111,71 @@
100.0%
100.0 % + 9 / 9 + 100.0 % + 3 / 3 + 100.0 % + 4 / 4 + + + abstract/RuleERC2980 + +
100.0%
+ + 100.0 % + 36 / 36 + 100.0 % + 12 / 12 + 100.0 % 8 / 8 + + + abstract/RuleAddressSet + +
100.0%
+ 100.0 % - 2 / 2 + 52 / 52 100.0 % - 3 / 3 + 19 / 19 + 100.0 % + 8 / 8 + + + abstract/core + +
100.0%
+ + 100.0 % + 51 / 51 + 100.0 % + 19 / 19 + 100.0 % + 14 / 14 - validation/abstract + /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract -
93.5%93.5%
+
100.0%
- 93.5 % - 29 / 31 - 90.9 % - 10 / 11 100.0 % - 10 / 10 + 62 / 62 + 100.0 % + 18 / 18 + 100.0 % + 14 / 14 + + + abstract/base + +
100.0%
+ + 100.0 % + 360 / 360 + 100.0 % + 101 / 101 + 100.0 % + 105 / 105
diff --git a/doc/coverage/coverage/index-sort-f.html b/doc/coverage/coverage/index-sort-f.html index ddafc17..4733fa7 100644 --- a/doc/coverage/coverage/index-sort-f.html +++ b/doc/coverage/coverage/index-sort-f.html @@ -31,27 +31,27 @@ lcov.info Lines: - 230 - 253 - 90.9 % + 698 + 698 + 100.0 % Date: - 2025-12-03 15:05:37 + 2026-03-10 10:55:10 Functions: - 66 - 76 - 86.8 % + 249 + 249 + 100.0 % Branches: - 65 - 68 - 95.6 % + 155 + 155 + 100.0 % @@ -82,52 +82,100 @@ Branches Sort by branch coverage - validation + /home/ryan/Pictures/dev/Rules/src/modules -
89.9%89.9%
+
100.0%
- 89.9 % - 151 / 168 - 84.8 % - 39 / 46 - 94.3 % - 50 / 53 + 100.0 % + 9 / 9 + 100.0 % + 3 / 3 + 100.0 % + 4 / 4 - validation/abstract/RuleAddressSet + /home/ryan/Pictures/dev/Rules/src/rules/operation -
91.3%91.3%
+
100.0%
- 91.3 % - 42 / 46 - 88.2 % - 15 / 17 + 100.0 % + 16 / 16 + 100.0 % + 9 / 9 100.0 % 2 / 2 - validation/abstract + abstract/RuleERC2980 + +
100.0%
+ + 100.0 % + 36 / 36 + 100.0 % + 12 / 12 + 100.0 % + 8 / 8 + + + /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract -
93.5%93.5%
+
100.0%
- 93.5 % - 29 / 31 - 90.9 % - 10 / 11 100.0 % - 10 / 10 + 62 / 62 + 100.0 % + 18 / 18 + 100.0 % + 14 / 14 - /home/ryan/Pictures/dev/Rules/src/modules + abstract/core
100.0%
100.0 % + 51 / 51 + 100.0 % + 19 / 19 + 100.0 % + 14 / 14 + + + abstract/RuleAddressSet + +
100.0%
+ + 100.0 % + 52 / 52 + 100.0 % + 19 / 19 + 100.0 % 8 / 8 + + + deployment + +
100.0%
+ 100.0 % - 2 / 2 + 112 / 112 100.0 % - 3 / 3 + 68 / 68 + - + 0 / 0 + + + abstract/base + +
100.0%
+ + 100.0 % + 360 / 360 + 100.0 % + 101 / 101 + 100.0 % + 105 / 105
diff --git a/doc/coverage/coverage/index-sort-l.html b/doc/coverage/coverage/index-sort-l.html index 53eb3c2..73dd95c 100644 --- a/doc/coverage/coverage/index-sort-l.html +++ b/doc/coverage/coverage/index-sort-l.html @@ -31,27 +31,27 @@ lcov.info Lines: - 230 - 253 - 90.9 % + 698 + 698 + 100.0 % Date: - 2025-12-03 15:05:37 + 2026-03-10 10:55:10 Functions: - 66 - 76 - 86.8 % + 249 + 249 + 100.0 % Branches: - 65 - 68 - 95.6 % + 155 + 155 + 100.0 % @@ -82,52 +82,100 @@ Branches Sort by branch coverage - validation + /home/ryan/Pictures/dev/Rules/src/modules -
89.9%89.9%
+
100.0%
- 89.9 % - 151 / 168 - 84.8 % - 39 / 46 - 94.3 % - 50 / 53 + 100.0 % + 9 / 9 + 100.0 % + 3 / 3 + 100.0 % + 4 / 4 - validation/abstract/RuleAddressSet + /home/ryan/Pictures/dev/Rules/src/rules/operation -
91.3%91.3%
+
100.0%
- 91.3 % - 42 / 46 - 88.2 % - 15 / 17 + 100.0 % + 16 / 16 + 100.0 % + 9 / 9 100.0 % 2 / 2 - validation/abstract + abstract/RuleERC2980 + +
100.0%
+ + 100.0 % + 36 / 36 + 100.0 % + 12 / 12 + 100.0 % + 8 / 8 + + + abstract/core -
93.5%93.5%
+
100.0%
- 93.5 % - 29 / 31 - 90.9 % - 10 / 11 100.0 % - 10 / 10 + 51 / 51 + 100.0 % + 19 / 19 + 100.0 % + 14 / 14 - /home/ryan/Pictures/dev/Rules/src/modules + abstract/RuleAddressSet
100.0%
100.0 % + 52 / 52 + 100.0 % + 19 / 19 + 100.0 % 8 / 8 + + + /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract + +
100.0%
+ 100.0 % - 2 / 2 + 62 / 62 100.0 % - 3 / 3 + 18 / 18 + 100.0 % + 14 / 14 + + + deployment + +
100.0%
+ + 100.0 % + 112 / 112 + 100.0 % + 68 / 68 + - + 0 / 0 + + + abstract/base + +
100.0%
+ + 100.0 % + 360 / 360 + 100.0 % + 101 / 101 + 100.0 % + 105 / 105 diff --git a/doc/coverage/coverage/index.html b/doc/coverage/coverage/index.html index d70aabb..209f17b 100644 --- a/doc/coverage/coverage/index.html +++ b/doc/coverage/coverage/index.html @@ -31,27 +31,27 @@ lcov.info Lines: - 230 - 253 - 90.9 % + 698 + 698 + 100.0 % Date: - 2025-12-03 15:05:37 + 2026-03-10 10:55:10 Functions: - 66 - 76 - 86.8 % + 249 + 249 + 100.0 % Branches: - 65 - 68 - 95.6 % + 155 + 155 + 100.0 % @@ -87,47 +87,95 @@
100.0%
100.0 % - 8 / 8 + 9 / 9 + 100.0 % + 3 / 3 + 100.0 % + 4 / 4 + + + /home/ryan/Pictures/dev/Rules/src/rules/operation + +
100.0%
+ + 100.0 % + 16 / 16 + 100.0 % + 9 / 9 100.0 % 2 / 2 + + + /home/ryan/Pictures/dev/Rules/src/rules/operation/abstract + +
100.0%
+ 100.0 % - 3 / 3 + 62 / 62 + 100.0 % + 18 / 18 + 100.0 % + 14 / 14 - validation + abstract/RuleAddressSet -
89.9%89.9%
+
100.0%
- 89.9 % - 151 / 168 - 84.8 % - 39 / 46 - 94.3 % - 50 / 53 + 100.0 % + 52 / 52 + 100.0 % + 19 / 19 + 100.0 % + 8 / 8 - validation/abstract + abstract/RuleERC2980 -
93.5%93.5%
+
100.0%
- 93.5 % - 29 / 31 - 90.9 % - 10 / 11 100.0 % - 10 / 10 + 36 / 36 + 100.0 % + 12 / 12 + 100.0 % + 8 / 8 - validation/abstract/RuleAddressSet + abstract/base -
91.3%91.3%
+
100.0%
- 91.3 % - 42 / 46 - 88.2 % - 15 / 17 100.0 % - 2 / 2 + 360 / 360 + 100.0 % + 101 / 101 + 100.0 % + 105 / 105 + + + abstract/core + +
100.0%
+ + 100.0 % + 51 / 51 + 100.0 % + 19 / 19 + 100.0 % + 14 / 14 + + + deployment + +
100.0%
+ + 100.0 % + 112 / 112 + 100.0 % + 68 / 68 + - + 0 / 0 diff --git a/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html b/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html deleted file mode 100644 index 3e4edde..0000000 --- a/doc/coverage/coverage/validation/RuleSanctionsList.sol.func-sort-c.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - - LCOV - lcov.info - validation/RuleSanctionsList.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - validation - RuleSanctionsList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:505492.6 %
Date:2025-12-03 15:05:37Functions:151788.2 %
Branches:1818100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
RuleSanctionsList._msgData0
RuleSanctionsList.supportsInterface0
RuleSanctionsList.transferred.21
RuleSanctionsList.transferred.12
RuleSanctionsList.canReturnTransferRestrictionCode3
RuleSanctionsList.detectTransferRestrictionFrom.13
RuleSanctionsList.transferred.03
RuleSanctionsList.messageForTransferRestriction4
RuleSanctionsList.transferred.34
RuleSanctionsList.detectTransferRestriction.19
RuleSanctionsList.detectTransferRestrictionFrom.011
RuleSanctionsList._setSanctionListOracle14
RuleSanctionsList.setSanctionListOracle14
RuleSanctionsList.constructor17
RuleSanctionsList.detectTransferRestriction.017
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 deleted file mode 100644 index 03d8771..0000000 --- a/doc/coverage/coverage/validation/RuleSanctionsList.sol.func.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - - LCOV - lcov.info - validation/RuleSanctionsList.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - validation - RuleSanctionsList.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:505492.6 %
Date:2025-12-03 15:05:37Functions:151788.2 %
Branches:1818100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

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.017
RuleSanctionsList.detectTransferRestriction.19
RuleSanctionsList.detectTransferRestrictionFrom.011
RuleSanctionsList.detectTransferRestrictionFrom.13
RuleSanctionsList.messageForTransferRestriction4
RuleSanctionsList.setSanctionListOracle14
RuleSanctionsList.supportsInterface0
RuleSanctionsList.transferred.03
RuleSanctionsList.transferred.12
RuleSanctionsList.transferred.21
RuleSanctionsList.transferred.34
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html b/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html deleted file mode 100644 index 325f5a0..0000000 --- a/doc/coverage/coverage/validation/RuleWhitelistWrapper.sol.gcov.html +++ /dev/null @@ -1,285 +0,0 @@ - - - - - - - LCOV - lcov.info - validation/RuleWhitelistWrapper.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - validation - RuleWhitelistWrapper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:505787.7 %
Date:2025-12-03 15:05:37Functions:91181.8 %
Branches:111478.6 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MPL-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.20;
-       4                 :            : 
-       5                 :            : /* ==== OpenZeppelin === */
-       6                 :            : import {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                 :            : /* ==== 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         [ #  + ]:         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                 :            :     /**
-     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                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/validation/index-sort-b.html b/doc/coverage/coverage/validation/index-sort-b.html deleted file mode 100644 index 944c1e9..0000000 --- a/doc/coverage/coverage/validation/index-sort-b.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - LCOV - lcov.info - validation - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - validationHitTotalCoverage
Test:lcov.infoLines:15116889.9 %
Date:2025-12-03 15:05:37Functions:394684.8 %
Branches:505394.3 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleWhitelistWrapper.sol -
87.7%87.7%
-
87.7 %50 / 5781.8 %9 / 1178.6 %11 / 14
RuleWhitelist.sol -
80.0%80.0%
-
80.0 %16 / 2071.4 %5 / 7100.0 %5 / 5
RuleBlacklist.sol -
94.6%94.6%
-
94.6 %35 / 3790.9 %10 / 11100.0 %16 / 16
RuleSanctionsList.sol -
92.6%92.6%
-
92.6 %50 / 5488.2 %15 / 17100.0 %18 / 18
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/validation/index-sort-f.html b/doc/coverage/coverage/validation/index-sort-f.html deleted file mode 100644 index 803ea1c..0000000 --- a/doc/coverage/coverage/validation/index-sort-f.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - LCOV - lcov.info - validation - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - validationHitTotalCoverage
Test:lcov.infoLines:15116889.9 %
Date:2025-12-03 15:05:37Functions:394684.8 %
Branches:505394.3 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleWhitelist.sol -
80.0%80.0%
-
80.0 %16 / 2071.4 %5 / 7100.0 %5 / 5
RuleWhitelistWrapper.sol -
87.7%87.7%
-
87.7 %50 / 5781.8 %9 / 1178.6 %11 / 14
RuleSanctionsList.sol -
92.6%92.6%
-
92.6 %50 / 5488.2 %15 / 17100.0 %18 / 18
RuleBlacklist.sol -
94.6%94.6%
-
94.6 %35 / 3790.9 %10 / 11100.0 %16 / 16
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/validation/index-sort-l.html b/doc/coverage/coverage/validation/index-sort-l.html deleted file mode 100644 index b4d9395..0000000 --- a/doc/coverage/coverage/validation/index-sort-l.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - LCOV - lcov.info - validation - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - validationHitTotalCoverage
Test:lcov.infoLines:15116889.9 %
Date:2025-12-03 15:05:37Functions:394684.8 %
Branches:505394.3 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleWhitelist.sol -
80.0%80.0%
-
80.0 %16 / 2071.4 %5 / 7100.0 %5 / 5
RuleWhitelistWrapper.sol -
87.7%87.7%
-
87.7 %50 / 5781.8 %9 / 1178.6 %11 / 14
RuleSanctionsList.sol -
92.6%92.6%
-
92.6 %50 / 5488.2 %15 / 17100.0 %18 / 18
RuleBlacklist.sol -
94.6%94.6%
-
94.6 %35 / 3790.9 %10 / 11100.0 %16 / 16
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/coverage/validation/index.html b/doc/coverage/coverage/validation/index.html deleted file mode 100644 index bffbd19..0000000 --- a/doc/coverage/coverage/validation/index.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - LCOV - lcov.info - validation - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - validationHitTotalCoverage
Test:lcov.infoLines:15116889.9 %
Date:2025-12-03 15:05:37Functions:394684.8 %
Branches:505394.3 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
RuleBlacklist.sol -
94.6%94.6%
-
94.6 %35 / 3790.9 %10 / 11100.0 %16 / 16
RuleSanctionsList.sol -
92.6%92.6%
-
92.6 %50 / 5488.2 %15 / 17100.0 %18 / 18
RuleWhitelist.sol -
80.0%80.0%
-
80.0 %16 / 2071.4 %5 / 7100.0 %5 / 5
RuleWhitelistWrapper.sol -
87.7%87.7%
-
87.7 %50 / 5781.8 %9 / 1178.6 %11 / 14
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/doc/coverage/lcov.info b/doc/coverage/lcov.info index 3c88298..f8b64c2 100644 --- a/doc/coverage/lcov.info +++ b/doc/coverage/lcov.info @@ -1,550 +1,1261 @@ TN: 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 +DA:24,396 +FN:24,AccessControlModuleStandalone.constructor +FNDA:396,AccessControlModuleStandalone.constructor +DA:25,396 +BRDA:25,0,0,5 +BRDA:25,0,1,391 +DA:29,391 +DA:38,507 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 +FNDA:507,AccessControlModuleStandalone.hasRole +DA:47,3597 +BRDA:47,1,0,3110 +BRDA:47,1,1,487 +DA:48,3110 +DA:50,487 FNF:2 FNH:2 -LF:8 -LH:8 -BRF:3 -BRH:3 -end_of_record -TN: -SF:src/rules/validation/RuleBlacklist.sol -DA:41,22 -FN:41,RuleBlacklist.detectTransferRestriction.0 -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,16 -FN:71,RuleBlacklist.detectTransferRestrictionFrom.0 -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 -DA:94,4 -DA:103,4 -FN:103,RuleBlacklist.canReturnTransferRestrictionCode -FNDA:4,RuleBlacklist.canReturnTransferRestrictionCode -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 +LF:7 +LH:7 +BRF:4 +BRH:4 +end_of_record +TN: +SF:src/modules/VersionModule.sol +DA:14,7 +FN:14,VersionModule.version +FNDA:7,VersionModule.version +DA:15,7 +FNF:1 +FNH:1 +LF:2 +LH:2 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/operation/RuleConditionalTransferLight.sol +DA:27,18 +FN:27,RuleConditionalTransferLight.supportsInterface +FNDA:18,RuleConditionalTransferLight.supportsInterface +DA:34,18 +DA:35,11 +DA:38,1 +FN:38,RuleConditionalTransferLight.created +FNDA:1,RuleConditionalTransferLight.created +DA:39,1 +DA:42,1 +FN:42,RuleConditionalTransferLight.destroyed +FNDA:1,RuleConditionalTransferLight.destroyed +DA:43,1 +DA:46,1947 +FN:46,RuleConditionalTransferLight._authorizeTransferApproval +FNDA:1947,RuleConditionalTransferLight._authorizeTransferApproval +DA:48,857 +FN:48,RuleConditionalTransferLight._authorizeTransferExecution +FNDA:857,RuleConditionalTransferLight._authorizeTransferExecution +DA:49,857 +BRDA:49,0,0,1 +BRDA:49,0,1,856 +DA:55,19 +FN:55,RuleConditionalTransferLight._onlyComplianceManager +FNDA:19,RuleConditionalTransferLight._onlyComplianceManager +FNF:6 +FNH:6 +LF:11 +LH:11 +BRF:2 +BRH:2 +end_of_record +TN: +SF:src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol +DA:21,4 +FN:21,RuleConditionalTransferLightOwnable2Step.supportsInterface +FNDA:4,RuleConditionalTransferLightOwnable2Step.supportsInterface +DA:22,4 +DA:23,2 +DA:26,4 +FN:26,RuleConditionalTransferLightOwnable2Step._authorizeTransferApproval +FNDA:4,RuleConditionalTransferLightOwnable2Step._authorizeTransferApproval +DA:28,3 +FN:28,RuleConditionalTransferLightOwnable2Step._authorizeTransferExecution +FNDA:3,RuleConditionalTransferLightOwnable2Step._authorizeTransferExecution +FNF:3 +FNH:3 +LF:5 +LH:5 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/operation/abstract/RuleConditionalTransferLightBase.sol +DA:25,1940 +FN:25,RuleConditionalTransferLightBase.approveTransfer +FNDA:1940,RuleConditionalTransferLightBase.approveTransfer +DA:26,1941 +DA:27,1941 +DA:28,1941 +DA:31,4 +FN:31,RuleConditionalTransferLightBase.cancelTransferApproval +FNDA:4,RuleConditionalTransferLightBase.cancelTransferApproval +DA:32,3 +DA:33,3 +DA:34,3 +BRDA:34,0,0,1 +BRDA:34,0,1,2 +DA:35,2 +DA:36,2 +DA:45,4 +FN:45,RuleConditionalTransferLightBase.approveAndTransferIfAllowed +FNDA:4,RuleConditionalTransferLightBase.approveAndTransferIfAllowed +DA:50,4 +BRDA:50,1,0,1 +BRDA:50,1,1,3 +DA:52,3 +DA:54,3 +DA:55,3 +BRDA:55,2,0,1 +BRDA:55,2,1,2 +DA:60,2 +DA:61,2 +BRDA:61,3,0,1 +BRDA:61,3,1,1 +DA:62,1 +DA:65,264 +FN:65,RuleConditionalTransferLightBase.approvedCount +FNDA:264,RuleConditionalTransferLightBase.approvedCount +DA:66,264 +DA:67,264 +DA:70,856 +FN:70,RuleConditionalTransferLightBase.transferred.0 +FNDA:856,RuleConditionalTransferLightBase.transferred.0 +DA:75,854 +DA:78,1 +FN:78,RuleConditionalTransferLightBase.transferred.1 +FNDA:1,RuleConditionalTransferLightBase.transferred.1 +DA:83,1 +DA:86,7 +FN:86,RuleConditionalTransferLightBase.detectTransferRestriction +FNDA:7,RuleConditionalTransferLightBase.detectTransferRestriction +DA:92,13 +BRDA:92,4,0,4 +DA:93,4 +DA:95,9 +DA:96,9 +BRDA:96,5,0,6 +DA:97,6 +DA:99,3 +DA:102,1 +FN:102,RuleConditionalTransferLightBase.detectTransferRestrictionFrom +FNDA:1,RuleConditionalTransferLightBase.detectTransferRestrictionFrom +DA:108,2 +DA:111,4 +FN:111,RuleConditionalTransferLightBase.canTransfer +FNDA:4,RuleConditionalTransferLightBase.canTransfer +DA:117,4 +DA:120,1 +FN:120,RuleConditionalTransferLightBase.canTransferFrom +FNDA:1,RuleConditionalTransferLightBase.canTransferFrom +DA:126,1 +DA:130,1 +FN:130,RuleConditionalTransferLightBase.canReturnTransferRestrictionCode +FNDA:1,RuleConditionalTransferLightBase.canReturnTransferRestrictionCode +DA:131,1 DA:134,2 -DA:138,0 -FN:138,RuleBlacklist.supportsInterface -FNDA:0,RuleBlacklist.supportsInterface -DA:139,0 -DA:144,9 -FN:144,RuleBlacklist.transferred.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: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: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:16 -end_of_record -TN: -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,17 -FN:73,RuleSanctionsList.detectTransferRestriction.0 -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,11 -FN:105,RuleSanctionsList.detectTransferRestrictionFrom.0 -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 -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,3 -FN:184,RuleSanctionsList.transferred.0 -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:236,14 -DA:237,14 -DA:247,30 -FN:247,RuleSanctionsList._msgSender -FNDA:30,RuleSanctionsList._msgSender -DA:248,30 -DA:254,0 -FN:254,RuleSanctionsList._msgData -FNDA:0,RuleSanctionsList._msgData -DA:255,0 -DA:261,30 -FN:261,RuleSanctionsList._contextSuffixLength -FNDA:30,RuleSanctionsList._contextSuffixLength -DA:262,30 -FNF:17 -FNH:15 -LF:54 -LH:50 -BRF:18 -BRH:18 +FN:134,RuleConditionalTransferLightBase.messageForTransferRestriction +FNDA:2,RuleConditionalTransferLightBase.messageForTransferRestriction +DA:140,2 +BRDA:140,6,0,1 +DA:141,1 +DA:143,1 +DA:146,3 +FN:146,RuleConditionalTransferLightBase.transferred.2 +FNDA:3,RuleConditionalTransferLightBase.transferred.2 +DA:147,3 +DA:150,3 +FN:150,RuleConditionalTransferLightBase._transferredFromContext +FNDA:3,RuleConditionalTransferLightBase._transferredFromContext +DA:151,3 +DA:154,860 +FN:154,RuleConditionalTransferLightBase._transferred +FNDA:860,RuleConditionalTransferLightBase._transferred +DA:155,860 +BRDA:155,7,0,860 +DA:156,860 +DA:158,846 +DA:159,846 +DA:161,846 +BRDA:161,8,0,3 +BRDA:161,8,1,843 +DA:163,843 +DA:164,843 +DA:167,3063 +FN:167,RuleConditionalTransferLightBase._transferHash +FNDA:3063,RuleConditionalTransferLightBase._transferHash +DA:168,3063 +DA:175,4 +FN:175,RuleConditionalTransferLightBase.onlyTransferApprover +FNDA:4,RuleConditionalTransferLightBase.onlyTransferApprover +DA:176,4 +DA:180,3 +FN:180,RuleConditionalTransferLightBase.onlyTransferExecutor +FNDA:3,RuleConditionalTransferLightBase.onlyTransferExecutor +DA:181,3 +FNF:18 +FNH:18 +LF:62 +LH:62 +BRF:14 +BRH:14 end_of_record TN: -SF:src/rules/validation/RuleWhitelist.sol -DA:33,102 -FN:33,RuleWhitelist.constructor -FNDA:102,RuleWhitelist.constructor -DA:36,101 -DA:56,20 -FN:56,RuleWhitelist.detectTransferRestriction.0 -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,10 -FN:102,RuleWhitelist.detectTransferRestrictionFrom.0 -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 +SF:src/rules/validation/abstract/RuleAddressSet/RuleAddressSet.sol +DA:51,275 +FN:51,RuleAddressSet.addAddresses +FNDA:275,RuleAddressSet.addAddresses +DA:52,274 +DA:53,274 +DA:63,260 +FN:63,RuleAddressSet.removeAddresses +FNDA:260,RuleAddressSet.removeAddresses +DA:64,259 +DA:65,259 +DA:75,105 +FN:75,RuleAddressSet.addAddress +FNDA:105,RuleAddressSet.addAddress +DA:76,102 +BRDA:76,0,0,1 +BRDA:76,0,1,101 +DA:77,101 +DA:78,101 +DA:88,8 +FN:88,RuleAddressSet.removeAddress +FNDA:8,RuleAddressSet.removeAddress +DA:89,5 +BRDA:89,1,0,1 +BRDA:89,1,1,4 +DA:90,4 +DA:91,4 +DA:98,275 +FN:98,RuleAddressSet.onlyAddressListAdd +FNDA:275,RuleAddressSet.onlyAddressListAdd +DA:99,275 +DA:103,8 +FN:103,RuleAddressSet.onlyAddressListRemove +FNDA:8,RuleAddressSet.onlyAddressListRemove +DA:104,8 +DA:116,536 +FN:116,RuleAddressSet.listedAddressCount +FNDA:536,RuleAddressSet.listedAddressCount +DA:117,536 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 -DA:38,22 -FN:38,RuleWhitelistWrapper.constructor -FNDA:22,RuleWhitelistWrapper.constructor -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: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,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:123,2 -DA:131,20 -FN:131,RuleWhitelistWrapper.hasRole -FNDA:20,RuleWhitelistWrapper.hasRole -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:173,0 -DA:183,80 -FN:183,RuleWhitelistWrapper._msgSender -FNDA:80,RuleWhitelistWrapper._msgSender -DA:184,80 -DA:190,0 -FN:190,RuleWhitelistWrapper._msgData -FNDA:0,RuleWhitelistWrapper._msgData -DA:191,0 -DA:197,80 -FN:197,RuleWhitelistWrapper._contextSuffixLength -FNDA:80,RuleWhitelistWrapper._contextSuffixLength -DA:198,80 -FNF:11 +FN:125,RuleAddressSet.contains +FNDA:2,RuleAddressSet.contains +DA:126,2 +DA:134,67 +FN:134,RuleAddressSet.isAddressListed +FNDA:67,RuleAddressSet.isAddressListed +DA:135,383 +DA:143,108 +FN:143,RuleAddressSet.areAddressesListed +FNDA:108,RuleAddressSet.areAddressesListed +DA:144,108 +DA:145,108 +DA:146,244 +DA:154,882 +FN:154,RuleAddressSet._msgSender +FNDA:882,RuleAddressSet._msgSender +DA:155,882 +DA:159,4 +FN:159,RuleAddressSet._msgData +FNDA:4,RuleAddressSet._msgData +DA:160,4 +DA:164,886 +FN:164,RuleAddressSet._contextSuffixLength +FNDA:886,RuleAddressSet._contextSuffixLength +DA:165,886 +FNF:13 +FNH:13 +LF:34 +LH:34 +BRF:4 +BRH:4 +end_of_record +TN: +SF:src/rules/validation/abstract/RuleAddressSet/RuleAddressSetInternal.sol +DA:38,274 +FN:38,RuleAddressSetInternal._addAddresses +FNDA:274,RuleAddressSetInternal._addAddresses +DA:42,274 +DA:43,806 +BRDA:43,0,0,548 +BRDA:43,0,1,258 +DA:44,548 +DA:46,258 +DA:60,259 +FN:60,RuleAddressSetInternal._removeAddresses +FNDA:259,RuleAddressSetInternal._removeAddresses +DA:64,259 +DA:65,775 +BRDA:65,1,0,518 +BRDA:65,1,1,257 +DA:66,518 +DA:68,257 +DA:77,101 +FN:77,RuleAddressSetInternal._addAddress +FNDA:101,RuleAddressSetInternal._addAddress +DA:78,101 +DA:85,4 +FN:85,RuleAddressSetInternal._removeAddress +FNDA:4,RuleAddressSetInternal._removeAddress +DA:86,4 +DA:93,536 +FN:93,RuleAddressSetInternal._listedAddressCount +FNDA:536,RuleAddressSetInternal._listedAddressCount +DA:94,536 +DA:102,738 +FN:102,RuleAddressSetInternal._isAddressListed +FNDA:738,RuleAddressSetInternal._isAddressListed +DA:103,738 +FNF:6 +FNH:6 +LF:18 +LH:18 +BRF:4 +BRH:4 +end_of_record +TN: +SF:src/rules/validation/abstract/RuleERC2980/RuleERC2980Internal.sol +DA:33,4 +FN:33,RuleERC2980Internal._addWhitelistAddresses +FNDA:4,RuleERC2980Internal._addWhitelistAddresses +DA:37,4 +DA:38,6 +BRDA:38,0,0,5 +BRDA:38,0,1,1 +DA:39,5 +DA:41,1 +DA:46,3 +FN:46,RuleERC2980Internal._removeWhitelistAddresses +FNDA:3,RuleERC2980Internal._removeWhitelistAddresses +DA:50,3 +DA:51,3 +BRDA:51,1,0,2 +BRDA:51,1,1,1 +DA:52,2 +DA:54,1 +DA:59,39 +FN:59,RuleERC2980Internal._addWhitelistAddress +FNDA:39,RuleERC2980Internal._addWhitelistAddress +DA:60,39 +DA:63,4 +FN:63,RuleERC2980Internal._removeWhitelistAddress +FNDA:4,RuleERC2980Internal._removeWhitelistAddress +DA:64,4 +DA:67,82 +FN:67,RuleERC2980Internal._isWhitelisted +FNDA:82,RuleERC2980Internal._isWhitelisted +DA:68,82 +DA:71,5 +FN:71,RuleERC2980Internal._whitelistCount +FNDA:5,RuleERC2980Internal._whitelistCount +DA:72,5 +DA:79,4 +FN:79,RuleERC2980Internal._addFrozenlistAddresses +FNDA:4,RuleERC2980Internal._addFrozenlistAddresses +DA:83,4 +DA:84,6 +BRDA:84,2,0,5 +BRDA:84,2,1,1 +DA:85,5 +DA:87,1 +DA:92,2 +FN:92,RuleERC2980Internal._removeFrozenlistAddresses +FNDA:2,RuleERC2980Internal._removeFrozenlistAddresses +DA:96,2 +DA:97,2 +BRDA:97,3,0,1 +BRDA:97,3,1,1 +DA:98,1 +DA:100,1 +DA:105,18 +FN:105,RuleERC2980Internal._addFrozenlistAddress +FNDA:18,RuleERC2980Internal._addFrozenlistAddress +DA:106,18 +DA:109,4 +FN:109,RuleERC2980Internal._removeFrozenlistAddress +FNDA:4,RuleERC2980Internal._removeFrozenlistAddress +DA:110,4 +DA:113,90 +FN:113,RuleERC2980Internal._isFrozen +FNDA:90,RuleERC2980Internal._isFrozen +DA:114,90 +DA:117,4 +FN:117,RuleERC2980Internal._frozenlistCount +FNDA:4,RuleERC2980Internal._frozenlistCount +DA:118,4 +FNF:12 +FNH:12 +LF:36 +LH:36 +BRF:8 +BRH:8 +end_of_record +TN: +SF:src/rules/validation/abstract/base/RuleBlacklistBase.sol +DA:20,106 +FN:20,RuleBlacklistBase._detectTransferRestriction +FNDA:106,RuleBlacklistBase._detectTransferRestriction +DA:26,106 +BRDA:26,0,0,23 +BRDA:26,0,1,64 +DA:27,23 +DA:28,83 +BRDA:28,1,0,19 +DA:29,19 +DA:31,64 +DA:34,22 +FN:34,RuleBlacklistBase._detectTransferRestrictionFrom +FNDA:22,RuleBlacklistBase._detectTransferRestrictionFrom +DA:40,22 +BRDA:40,2,0,8 +DA:41,8 +DA:43,14 +DA:46,4 +FN:46,RuleBlacklistBase.canReturnTransferRestrictionCode +FNDA:4,RuleBlacklistBase.canReturnTransferRestrictionCode +DA:53,4 +DA:54,1 +DA:57,12 +FN:57,RuleBlacklistBase.messageForTransferRestriction +FNDA:12,RuleBlacklistBase.messageForTransferRestriction +DA:64,12 +BRDA:64,3,0,5 +BRDA:64,3,1,3 +DA:65,5 +DA:66,7 +BRDA:66,4,0,3 +BRDA:66,4,1,3 +DA:67,3 +DA:68,4 +BRDA:68,5,0,1 +BRDA:68,5,1,3 +DA:69,1 +DA:71,3 +DA:75,61 +FN:75,RuleBlacklistBase.supportsInterface +FNDA:61,RuleBlacklistBase.supportsInterface +DA:76,61 +DA:83,58 +FN:83,RuleBlacklistBase.transferred.0 +FNDA:58,RuleBlacklistBase.transferred.0 +DA:89,58 +DA:96,2 +FN:96,RuleBlacklistBase.transferred.1 +FNDA:2,RuleBlacklistBase.transferred.1 +DA:102,2 +DA:105,61 +FN:105,RuleBlacklistBase._transferred +FNDA:61,RuleBlacklistBase._transferred +DA:106,61 +DA:107,61 +BRDA:107,6,0,15 +BRDA:107,6,1,46 +DA:113,4 +FN:113,RuleBlacklistBase._transferredFrom +FNDA:4,RuleBlacklistBase._transferredFrom +DA:119,4 +DA:120,4 +BRDA:120,7,0,2 +BRDA:120,7,1,2 +FNF:9 FNH:9 -LF:57 -LH:50 +LF:33 +LH:33 BRF:14 -BRH:11 +BRH:14 end_of_record TN: -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 +SF:src/rules/validation/abstract/base/RuleERC2980Base.sol +DA:47,22 +FN:47,RuleERC2980Base._detectTransferRestriction +FNDA:22,RuleERC2980Base._detectTransferRestriction +DA:55,22 +BRDA:55,0,0,4 +BRDA:55,0,1,14 +DA:56,4 +DA:57,18 +BRDA:57,1,0,4 +DA:58,4 +DA:61,14 +BRDA:61,2,0,4 +DA:62,4 +DA:64,10 +DA:67,8 +FN:67,RuleERC2980Base._detectTransferRestrictionFrom +FNDA:8,RuleERC2980Base._detectTransferRestrictionFrom +DA:74,8 +BRDA:74,3,0,4 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:77,4 +DA:84,4 +FN:84,RuleERC2980Base.transferred.0 +FNDA:4,RuleERC2980Base.transferred.0 +DA:90,4 +DA:93,2 +FN:93,RuleERC2980Base.transferred.1 +FNDA:2,RuleERC2980Base.transferred.1 +DA:99,2 +DA:102,5 +FN:102,RuleERC2980Base._transferred +FNDA:5,RuleERC2980Base._transferred +DA:103,5 +DA:104,5 +BRDA:104,4,0,3 +BRDA:104,4,1,2 +DA:110,3 +FN:110,RuleERC2980Base._transferredFrom +FNDA:3,RuleERC2980Base._transferredFrom +DA:116,3 +DA:117,3 +BRDA:117,5,0,1 +BRDA:117,5,1,2 +DA:127,5 +FN:127,RuleERC2980Base.canReturnTransferRestrictionCode +FNDA:5,RuleERC2980Base.canReturnTransferRestrictionCode +DA:134,5 +DA:135,3 +DA:136,2 +DA:139,5 +FN:139,RuleERC2980Base.messageForTransferRestriction +FNDA:5,RuleERC2980Base.messageForTransferRestriction +DA:146,5 +BRDA:146,6,0,1 +BRDA:146,6,1,1 +DA:147,1 +DA:148,4 +BRDA:148,7,0,1 +BRDA:148,7,1,1 +DA:149,1 +DA:150,3 +BRDA:150,8,0,1 +BRDA:150,8,1,1 +DA:151,1 +DA:152,2 +BRDA:152,9,0,1 +BRDA:152,9,1,1 +DA:153,1 +DA:155,1 +DA:167,6 +FN:167,RuleERC2980Base.addWhitelistAddresses +FNDA:6,RuleERC2980Base.addWhitelistAddresses +DA:168,4 +DA:169,4 +DA:176,4 +FN:176,RuleERC2980Base.removeWhitelistAddresses +FNDA:4,RuleERC2980Base.removeWhitelistAddresses +DA:177,3 +DA:178,3 +DA:189,43 +FN:189,RuleERC2980Base.addWhitelistAddress +FNDA:43,RuleERC2980Base.addWhitelistAddress +DA:190,40 +BRDA:190,10,0,1 +BRDA:190,10,1,39 +DA:191,39 +DA:192,39 +DA:203,7 +FN:203,RuleERC2980Base.removeWhitelistAddress +FNDA:7,RuleERC2980Base.removeWhitelistAddress +DA:204,5 +BRDA:204,11,0,1 +BRDA:204,11,1,4 +DA:205,4 +DA:206,4 +DA:212,5 +FN:212,RuleERC2980Base.whitelistAddressCount +FNDA:5,RuleERC2980Base.whitelistAddressCount +DA:213,5 +DA:219,13 +FN:219,RuleERC2980Base.isWhitelisted +FNDA:13,RuleERC2980Base.isWhitelisted +DA:220,13 +DA:226,5 +FN:226,RuleERC2980Base.whitelist +FNDA:5,RuleERC2980Base.whitelist +DA:227,5 +DA:235,3 +FN:235,RuleERC2980Base.isVerified +FNDA:3,RuleERC2980Base.isVerified +DA:242,3 +DA:248,1 +FN:248,RuleERC2980Base.areWhitelisted +FNDA:1,RuleERC2980Base.areWhitelisted +DA:249,1 +DA:250,1 +DA:251,2 +DA:263,6 +FN:263,RuleERC2980Base.addFrozenlistAddresses +FNDA:6,RuleERC2980Base.addFrozenlistAddresses +DA:264,4 +DA:265,4 +DA:272,2 +FN:272,RuleERC2980Base.removeFrozenlistAddresses +FNDA:2,RuleERC2980Base.removeFrozenlistAddresses +DA:273,2 +DA:274,2 +DA:285,22 +FN:285,RuleERC2980Base.addFrozenlistAddress +FNDA:22,RuleERC2980Base.addFrozenlistAddress +DA:286,19 +BRDA:286,12,0,1 +BRDA:286,12,1,18 +DA:287,18 +DA:288,18 +DA:299,7 +FN:299,RuleERC2980Base.removeFrozenlistAddress +FNDA:7,RuleERC2980Base.removeFrozenlistAddress +DA:300,5 +BRDA:300,13,0,1 +BRDA:300,13,1,4 +DA:301,4 +DA:302,4 +DA:308,4 +FN:308,RuleERC2980Base.frozenlistAddressCount +FNDA:4,RuleERC2980Base.frozenlistAddressCount +DA:309,4 +DA:315,12 +FN:315,RuleERC2980Base.isFrozen +FNDA:12,RuleERC2980Base.isFrozen +DA:316,12 +DA:322,4 +FN:322,RuleERC2980Base.frozenlist +FNDA:4,RuleERC2980Base.frozenlist +DA:323,4 +DA:329,1 +FN:329,RuleERC2980Base.areFrozen +FNDA:1,RuleERC2980Base.areFrozen +DA:330,1 +DA:331,1 +DA:332,2 +DA:340,1 +FN:340,RuleERC2980Base.supportsInterface +FNDA:1,RuleERC2980Base.supportsInterface +DA:341,1 +DA:348,6 +FN:348,RuleERC2980Base.onlyWhitelistAdd +FNDA:6,RuleERC2980Base.onlyWhitelistAdd +DA:349,6 +DA:353,7 +FN:353,RuleERC2980Base.onlyWhitelistRemove +FNDA:7,RuleERC2980Base.onlyWhitelistRemove +DA:354,7 +DA:358,6 +FN:358,RuleERC2980Base.onlyFrozenlistAdd +FNDA:6,RuleERC2980Base.onlyFrozenlistAdd +DA:359,6 +DA:363,2 +FN:363,RuleERC2980Base.onlyFrozenlistRemove +FNDA:2,RuleERC2980Base.onlyFrozenlistRemove +DA:364,2 +DA:377,267 +FN:377,RuleERC2980Base._msgSender +FNDA:267,RuleERC2980Base._msgSender +DA:378,267 +DA:381,2 +FN:381,RuleERC2980Base._msgData +FNDA:2,RuleERC2980Base._msgData +DA:382,2 +DA:385,269 +FN:385,RuleERC2980Base._contextSuffixLength +FNDA:269,RuleERC2980Base._contextSuffixLength +DA:386,269 +FNF:33 +FNH:33 +LF:102 +LH:102 +BRF:25 +BRH:25 +end_of_record +TN: +SF:src/rules/validation/abstract/base/RuleIdentityRegistryBase.sol +DA:19,26 +FN:19,RuleIdentityRegistryBase.constructor +FNDA:26,RuleIdentityRegistryBase.constructor +DA:20,26 +BRDA:20,0,0,25 +DA:21,25 +DA:25,4 +FN:25,RuleIdentityRegistryBase.setIdentityRegistry +FNDA:4,RuleIdentityRegistryBase.setIdentityRegistry +DA:26,2 +BRDA:26,1,0,1 +BRDA:26,1,1,1 +DA:27,1 +DA:28,1 +DA:31,5 +FN:31,RuleIdentityRegistryBase.clearIdentityRegistry +FNDA:5,RuleIdentityRegistryBase.clearIdentityRegistry +DA:32,3 +DA:33,3 +DA:36,16 +FN:36,RuleIdentityRegistryBase._detectTransferRestriction +FNDA:16,RuleIdentityRegistryBase._detectTransferRestriction +DA:42,16 +BRDA:42,2,0,3 +DA:43,3 +DA:45,13 +BRDA:45,3,0,2 +DA:46,2 +DA:49,11 +BRDA:49,4,0,4 +DA:50,4 +DA:52,7 +BRDA:52,5,0,1 +DA:53,1 +DA:55,6 +DA:58,9 +FN:58,RuleIdentityRegistryBase._detectTransferRestrictionFrom +FNDA:9,RuleIdentityRegistryBase._detectTransferRestrictionFrom +DA:64,9 +BRDA:64,6,0,1 +DA:65,1 +DA:67,8 +BRDA:67,7,0,1 +DA:68,1 +DA:70,7 +BRDA:70,8,0,4 +DA:71,4 +DA:73,3 +DA:76,2 +FN:76,RuleIdentityRegistryBase.transferred.0 +FNDA:2,RuleIdentityRegistryBase.transferred.0 +DA:81,2 +DA:84,2 +FN:84,RuleIdentityRegistryBase.transferred.1 +FNDA:2,RuleIdentityRegistryBase.transferred.1 +DA:89,2 +DA:92,2 +FN:92,RuleIdentityRegistryBase._transferred +FNDA:2,RuleIdentityRegistryBase._transferred +DA:93,2 +DA:94,2 +BRDA:94,9,0,1 +BRDA:94,9,1,1 +DA:100,2 +FN:100,RuleIdentityRegistryBase._transferredFrom +FNDA:2,RuleIdentityRegistryBase._transferredFrom +DA:106,2 +DA:107,2 +BRDA:107,10,0,1 +BRDA:107,10,1,1 +DA:113,4 +FN:113,RuleIdentityRegistryBase.canReturnTransferRestrictionCode +FNDA:4,RuleIdentityRegistryBase.canReturnTransferRestrictionCode +DA:114,4 +DA:115,2 +DA:118,4 +FN:118,RuleIdentityRegistryBase.messageForTransferRestriction +FNDA:4,RuleIdentityRegistryBase.messageForTransferRestriction +DA:124,4 +BRDA:124,11,0,1 +BRDA:124,11,1,1 +DA:125,1 +DA:126,3 +BRDA:126,12,0,1 +BRDA:126,12,1,1 +DA:127,1 +DA:128,2 +BRDA:128,13,0,1 +DA:129,1 +DA:131,1 +DA:138,5 +FN:138,RuleIdentityRegistryBase.onlyIdentityRegistryManager +FNDA:5,RuleIdentityRegistryBase.onlyIdentityRegistryManager +DA:139,5 +FNF:12 +FNH:12 +LF:51 +LH:51 +BRF:19 +BRH:19 +end_of_record +TN: +SF:src/rules/validation/abstract/base/RuleMaxTotalSupplyBase.sol +DA:20,25 +FN:20,RuleMaxTotalSupplyBase.constructor +FNDA:25,RuleMaxTotalSupplyBase.constructor +DA:21,25 +BRDA:21,0,0,1 +BRDA:21,0,1,24 +DA:22,24 +DA:23,24 +DA:26,260 +FN:26,RuleMaxTotalSupplyBase.setMaxTotalSupply +FNDA:260,RuleMaxTotalSupplyBase.setMaxTotalSupply +DA:27,258 +DA:28,258 +DA:31,4 +FN:31,RuleMaxTotalSupplyBase.setTokenContract +FNDA:4,RuleMaxTotalSupplyBase.setTokenContract +DA:32,2 +BRDA:32,1,0,1 +BRDA:32,1,1,1 +DA:33,1 +DA:34,1 +DA:37,271 +FN:37,RuleMaxTotalSupplyBase._detectTransferRestriction +FNDA:271,RuleMaxTotalSupplyBase._detectTransferRestriction +DA:43,271 +BRDA:43,2,0,268 +DA:44,268 +DA:45,268 +BRDA:45,3,0,179 +DA:46,179 +DA:49,92 +DA:52,2 +FN:52,RuleMaxTotalSupplyBase._detectTransferRestrictionFrom +FNDA:2,RuleMaxTotalSupplyBase._detectTransferRestrictionFrom +DA:58,2 +DA:61,2 +FN:61,RuleMaxTotalSupplyBase.transferred.0 +FNDA:2,RuleMaxTotalSupplyBase.transferred.0 +DA:66,2 +DA:69,2 +FN:69,RuleMaxTotalSupplyBase.transferred.1 +FNDA:2,RuleMaxTotalSupplyBase.transferred.1 +DA:74,2 +DA:77,2 +FN:77,RuleMaxTotalSupplyBase._transferred +FNDA:2,RuleMaxTotalSupplyBase._transferred +DA:78,2 +DA:79,2 +BRDA:79,4,0,1 +BRDA:79,4,1,1 +DA:85,2 +FN:85,RuleMaxTotalSupplyBase._transferredFrom +FNDA:2,RuleMaxTotalSupplyBase._transferredFrom +DA:86,2 +DA:87,2 +BRDA:87,5,0,1 +BRDA:87,5,1,1 +DA:93,2 +FN:93,RuleMaxTotalSupplyBase.canReturnTransferRestrictionCode +FNDA:2,RuleMaxTotalSupplyBase.canReturnTransferRestrictionCode +DA:94,2 +DA:97,2 +FN:97,RuleMaxTotalSupplyBase.messageForTransferRestriction +FNDA:2,RuleMaxTotalSupplyBase.messageForTransferRestriction DA:103,2 -BRDA:103,1,0,1 +BRDA:103,6,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,219 -DA:141,84 -FN:141,RuleAddressSet.areAddressesListed -FNDA:84,RuleAddressSet.areAddressesListed -DA:142,84 -DA:143,84 -DA:144,191 -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 +DA:113,260 +FN:113,RuleMaxTotalSupplyBase.onlyMaxTotalSupplyManager +FNDA:260,RuleMaxTotalSupplyBase.onlyMaxTotalSupplyManager +DA:114,260 +FNF:12 +FNH:12 +LF:37 +LH:37 +BRF:11 +BRH:11 end_of_record TN: -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,463 -FN:84,RuleAddressSetInternal._isAddressListed -FNDA:463,RuleAddressSetInternal._isAddressListed -DA:85,463 -FNF:6 -FNH:6 -LF:14 -LH:14 -BRF:0 -BRH:0 +SF:src/rules/validation/abstract/base/RuleSanctionsListBase.sol +DA:20,46 +FN:20,RuleSanctionsListBase.constructor +FNDA:46,RuleSanctionsListBase.constructor +DA:23,45 +BRDA:23,0,0,20 +DA:24,20 +DA:28,84 +FN:28,RuleSanctionsListBase._detectTransferRestriction +FNDA:84,RuleSanctionsListBase._detectTransferRestriction +DA:34,84 +BRDA:34,1,0,77 +DA:35,77 +BRDA:35,2,0,10 +BRDA:35,2,1,55 +DA:36,10 +DA:37,67 +BRDA:37,3,0,12 +DA:38,12 +DA:41,62 +DA:44,16 +FN:44,RuleSanctionsListBase._detectTransferRestrictionFrom +FNDA:16,RuleSanctionsListBase._detectTransferRestrictionFrom +DA:51,16 +BRDA:51,4,0,15 +DA:52,15 +BRDA:52,5,0,6 +DA:53,6 +DA:55,9 +DA:57,1 +DA:60,3 +FN:60,RuleSanctionsListBase.canReturnTransferRestrictionCode +FNDA:3,RuleSanctionsListBase.canReturnTransferRestrictionCode +DA:61,3 +DA:62,1 +DA:65,4 +FN:65,RuleSanctionsListBase.messageForTransferRestriction +FNDA:4,RuleSanctionsListBase.messageForTransferRestriction +DA:71,4 +BRDA:71,6,0,1 +BRDA:71,6,1,1 +DA:72,1 +DA:73,3 +BRDA:73,7,0,1 +BRDA:73,7,1,1 +DA:74,1 +DA:75,2 +BRDA:75,8,0,1 +DA:76,1 +DA:78,1 +DA:81,17 +FN:81,RuleSanctionsListBase.setSanctionListOracle +FNDA:17,RuleSanctionsListBase.setSanctionListOracle +DA:82,15 +BRDA:82,9,0,1 +BRDA:82,9,1,14 +DA:83,14 +DA:86,3 +FN:86,RuleSanctionsListBase.clearSanctionListOracle +FNDA:3,RuleSanctionsListBase.clearSanctionListOracle +DA:87,3 +DA:90,43 +FN:90,RuleSanctionsListBase.transferred.0 +FNDA:43,RuleSanctionsListBase.transferred.0 +DA:95,43 +DA:98,2 +FN:98,RuleSanctionsListBase.transferred.1 +FNDA:2,RuleSanctionsListBase.transferred.1 +DA:103,2 +DA:106,47 +FN:106,RuleSanctionsListBase._transferred +FNDA:47,RuleSanctionsListBase._transferred +DA:107,47 +DA:108,47 +BRDA:108,10,0,6 +BRDA:108,10,1,41 +DA:114,3 +FN:114,RuleSanctionsListBase._transferredFrom +FNDA:3,RuleSanctionsListBase._transferredFrom +DA:120,3 +DA:121,3 +BRDA:121,11,0,2 +BRDA:121,11,1,1 +DA:127,37 +FN:127,RuleSanctionsListBase._setSanctionListOracle +FNDA:37,RuleSanctionsListBase._setSanctionListOracle +DA:128,37 +DA:129,37 +DA:136,3 +FN:136,RuleSanctionsListBase.onlySanctionListManager +FNDA:3,RuleSanctionsListBase.onlySanctionListManager +DA:137,3 +FNF:13 +FNH:13 +LF:47 +LH:47 +BRF:18 +BRH:18 end_of_record TN: -SF:src/rules/validation/abstract/RuleValidateTransfer.sol -DA:26,14 -FN:26,RuleValidateTransfer.canTransfer.0 -FNDA:14,RuleValidateTransfer.canTransfer.0 -DA:33,14 -DA:45,14 -FN:45,RuleValidateTransfer.canTransfer.1 -FNDA:14,RuleValidateTransfer.canTransfer.1 -DA:52,14 -DA:58,10 -FN:58,RuleValidateTransfer.canTransferFrom.0 -FNDA:10,RuleValidateTransfer.canTransferFrom.0 -DA:65,20 -DA:72,10 -FN:72,RuleValidateTransfer.canTransferFrom.1 -FNDA:10,RuleValidateTransfer.canTransferFrom.1 -DA:79,10 -DA:82,0 -FN:82,RuleValidateTransfer.supportsInterface -FNDA:0,RuleValidateTransfer.supportsInterface -DA:83,0 +SF:src/rules/validation/abstract/base/RuleWhitelistBase.sol +DA:15,157 +FN:15,RuleWhitelistBase.constructor +FNDA:157,RuleWhitelistBase.constructor +DA:16,157 +DA:19,51 +FN:19,RuleWhitelistBase._detectTransferRestriction +FNDA:51,RuleWhitelistBase._detectTransferRestriction +DA:26,51 +BRDA:26,0,0,13 +BRDA:26,0,1,28 +DA:27,13 +DA:28,38 +BRDA:28,1,0,10 +DA:29,10 +DA:31,28 +DA:34,18 +FN:34,RuleWhitelistBase._detectTransferRestrictionFrom +FNDA:18,RuleWhitelistBase._detectTransferRestrictionFrom +DA:41,18 +BRDA:41,2,0,8 +DA:42,8 +DA:44,10 +DA:48,2 +FN:48,RuleWhitelistBase.isVerified +FNDA:2,RuleWhitelistBase.isVerified +DA:55,2 +DA:58,3 +FN:58,RuleWhitelistBase.setCheckSpender +FNDA:3,RuleWhitelistBase.setCheckSpender +DA:59,2 +DA:60,2 +DA:63,2 +FN:63,RuleWhitelistBase._setCheckSpender +FNDA:2,RuleWhitelistBase._setCheckSpender +DA:64,2 +DA:67,27 +FN:67,RuleWhitelistBase.supportsInterface +FNDA:27,RuleWhitelistBase.supportsInterface +DA:68,27 +DA:75,3 +FN:75,RuleWhitelistBase.onlyCheckSpenderManager +FNDA:3,RuleWhitelistBase.onlyCheckSpenderManager +DA:76,3 +FNF:8 +FNH:8 +LF:23 +LH:23 +BRF:4 +BRH:4 +end_of_record +TN: +SF:src/rules/validation/abstract/base/RuleWhitelistWrapperBase.sol +DA:36,44 +FN:36,RuleWhitelistWrapperBase.constructor +FNDA:44,RuleWhitelistWrapperBase.constructor +DA:39,44 +DA:50,34 +FN:50,RuleWhitelistWrapperBase._detectTransferRestriction +FNDA:34,RuleWhitelistWrapperBase._detectTransferRestriction +DA:57,34 +DA:58,34 +DA:59,34 +DA:61,34 +DA:62,34 +BRDA:62,0,0,13 +BRDA:62,0,1,13 +DA:63,13 +DA:64,21 +BRDA:64,1,0,8 +BRDA:64,1,1,13 +DA:65,8 +DA:67,13 +DA:71,20 +FN:71,RuleWhitelistWrapperBase._detectTransferRestrictionFrom +FNDA:20,RuleWhitelistWrapperBase._detectTransferRestrictionFrom +DA:78,20 +BRDA:78,2,0,1 +DA:79,1 +DA:82,19 +DA:83,19 +DA:84,19 +DA:85,19 +DA:87,19 +DA:89,19 +BRDA:89,3,0,1 +BRDA:89,3,1,9 +DA:90,1 +DA:91,18 +BRDA:91,4,0,1 +BRDA:91,4,1,9 +DA:92,1 +DA:93,17 +BRDA:93,5,0,8 +BRDA:93,5,1,9 +DA:94,8 +DA:96,9 +DA:102,62 +FN:102,RuleWhitelistWrapperBase.supportsInterface +FNDA:62,RuleWhitelistWrapperBase.supportsInterface +DA:109,62 +DA:116,4 +FN:116,RuleWhitelistWrapperBase.isVerified +FNDA:4,RuleWhitelistWrapperBase.isVerified +DA:123,4 +DA:124,4 +DA:125,4 +DA:126,4 +DA:139,4 +FN:139,RuleWhitelistWrapperBase.setCheckSpender +FNDA:4,RuleWhitelistWrapperBase.setCheckSpender +DA:140,3 +DA:141,3 +DA:144,13 +FN:144,RuleWhitelistWrapperBase._transferred.0 +FNDA:13,RuleWhitelistWrapperBase._transferred.0 +DA:150,13 +DA:153,1 +FN:153,RuleWhitelistWrapperBase._transferred.1 +FNDA:1,RuleWhitelistWrapperBase._transferred.1 +DA:159,1 +DA:171,57 +FN:171,RuleWhitelistWrapperBase._detectTransferRestrictionForTargets +FNDA:57,RuleWhitelistWrapperBase._detectTransferRestrictionForTargets +DA:177,57 +DA:178,57 +DA:179,57 +DA:182,105 +DA:183,105 +DA:184,85 +BRDA:184,6,0,85 +DA:185,85 +DA:190,105 +DA:191,105 +DA:192,201 +BRDA:192,7,0,81 +DA:193,81 +DA:194,81 +DA:197,24 +BRDA:197,8,0,24 +DA:198,24 +DA:201,57 +DA:208,3 +FN:208,RuleWhitelistWrapperBase._setCheckSpender +FNDA:3,RuleWhitelistWrapperBase._setCheckSpender +DA:209,3 +DA:216,4 +FN:216,RuleWhitelistWrapperBase.onlyCheckSpenderManager +FNDA:4,RuleWhitelistWrapperBase.onlyCheckSpenderManager +DA:217,4 +DA:230,145 +FN:230,RuleWhitelistWrapperBase._msgSender +FNDA:145,RuleWhitelistWrapperBase._msgSender +DA:231,145 +DA:237,2 +FN:237,RuleWhitelistWrapperBase._msgData +FNDA:2,RuleWhitelistWrapperBase._msgData +DA:238,2 +DA:244,147 +FN:244,RuleWhitelistWrapperBase._contextSuffixLength +FNDA:147,RuleWhitelistWrapperBase._contextSuffixLength +DA:245,147 +FNF:14 +FNH:14 +LF:67 +LH:67 +BRF:14 +BRH:14 +end_of_record +TN: +SF:src/rules/validation/abstract/core/RuleNFTAdapter.sol +DA:40,16 +FN:40,RuleNFTAdapter.detectTransferRestriction +FNDA:16,RuleNFTAdapter.detectTransferRestriction +DA:47,16 +DA:53,12 +FN:53,RuleNFTAdapter.detectTransferRestrictionFrom +FNDA:12,RuleNFTAdapter.detectTransferRestrictionFrom +DA:60,12 +DA:66,14 +FN:66,RuleNFTAdapter.canTransfer +FNDA:14,RuleNFTAdapter.canTransfer +DA:72,14 +DA:78,10 +FN:78,RuleNFTAdapter.canTransferFrom +FNDA:10,RuleNFTAdapter.canTransferFrom +DA:85,10 +DA:92,13 +FN:92,RuleNFTAdapter.transferred.0 +FNDA:13,RuleNFTAdapter.transferred.0 +DA:97,13 +DA:103,8 +FN:103,RuleNFTAdapter.transferred.1 +FNDA:8,RuleNFTAdapter.transferred.1 +DA:108,8 +DA:114,2 +FN:114,RuleNFTAdapter.transferred.2 +FNDA:2,RuleNFTAdapter.transferred.2 +DA:115,2 +BRDA:115,0,0,1 +BRDA:115,0,1,1 +DA:116,1 +DA:118,1 +DA:125,2 +FN:125,RuleNFTAdapter.transferred.3 +FNDA:2,RuleNFTAdapter.transferred.3 +DA:126,2 +BRDA:126,1,0,1 +BRDA:126,1,1,1 +DA:127,1 +DA:129,1 +FNF:8 +FNH:8 +LF:20 +LH:20 +BRF:4 +BRH:4 +end_of_record +TN: +SF:src/rules/validation/abstract/core/RuleTransferValidation.sol +DA:46,348 +FN:46,RuleTransferValidation.detectTransferRestriction +FNDA:348,RuleTransferValidation.detectTransferRestriction +DA:53,348 +DA:59,36 +FN:59,RuleTransferValidation.detectTransferRestrictionFrom +FNDA:36,RuleTransferValidation.detectTransferRestrictionFrom +DA:66,36 +DA:77,20 +FN:77,RuleTransferValidation.canTransfer +FNDA:20,RuleTransferValidation.canTransfer +DA:83,20 +DA:89,12 +FN:89,RuleTransferValidation.canTransferFrom +FNDA:12,RuleTransferValidation.canTransferFrom +DA:96,12 +DA:100,195 +FN:100,RuleTransferValidation.supportsInterface +FNDA:195,RuleTransferValidation.supportsInterface +DA:101,195 FNF:5 -FNH:4 +FNH:5 LF:10 -LH:8 +LH:10 BRF:0 BRH:0 end_of_record TN: -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,17 -FN:79,RuleWhitelistCommon.transferred.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: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 +SF:src/rules/validation/abstract/core/RuleWhitelistShared.sol +DA:33,10 +FN:33,RuleWhitelistShared.canReturnTransferRestrictionCode +FNDA:10,RuleWhitelistShared.canReturnTransferRestrictionCode +DA:34,10 +DA:35,5 +DA:45,14 +FN:45,RuleWhitelistShared.messageForTransferRestriction +FNDA:14,RuleWhitelistShared.messageForTransferRestriction +DA:51,14 +BRDA:51,0,0,6 +BRDA:51,0,1,2 +DA:52,6 +DA:53,8 +BRDA:53,1,0,4 +BRDA:53,1,1,2 +DA:54,4 +DA:55,4 +BRDA:55,2,0,2 +BRDA:55,2,1,2 +DA:56,2 +DA:58,2 +DA:75,19 +FN:75,RuleWhitelistShared.transferred.0 +FNDA:19,RuleWhitelistShared.transferred.0 +DA:76,19 +DA:90,4 +FN:90,RuleWhitelistShared.transferred.1 +FNDA:4,RuleWhitelistShared.transferred.1 +DA:91,4 +DA:94,26 +FN:94,RuleWhitelistShared._transferred +FNDA:26,RuleWhitelistShared._transferred +DA:95,26 +DA:96,26 +BRDA:96,3,0,14 +BRDA:96,3,1,12 +DA:102,11 +FN:102,RuleWhitelistShared._transferredFrom +FNDA:11,RuleWhitelistShared._transferredFrom +DA:108,11 +DA:109,11 +BRDA:109,4,0,4 +BRDA:109,4,1,7 FNF:6 FNH:6 LF:21 @@ -552,3 +1263,377 @@ LH:21 BRF:10 BRH:10 end_of_record +TN: +SF:src/rules/validation/deployment/RuleBlacklist.sol +DA:28,91 +FN:28,RuleBlacklist.supportsInterface +FNDA:91,RuleBlacklist.supportsInterface +DA:35,91 +DA:38,28 +FN:38,RuleBlacklist._authorizeAddressListAdd +FNDA:28,RuleBlacklist._authorizeAddressListAdd +DA:40,1 +FN:40,RuleBlacklist._authorizeAddressListRemove +FNDA:1,RuleBlacklist._authorizeAddressListRemove +DA:42,83 +FN:42,RuleBlacklist._msgSender +FNDA:83,RuleBlacklist._msgSender +DA:43,83 +DA:46,1 +FN:46,RuleBlacklist._msgData +FNDA:1,RuleBlacklist._msgData +DA:47,1 +DA:50,84 +FN:50,RuleBlacklist._contextSuffixLength +FNDA:84,RuleBlacklist._contextSuffixLength +DA:51,84 +FNF:6 +FNH:6 +LF:10 +LH:10 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/validation/deployment/RuleBlacklistOwnable2Step.sol +DA:20,2 +FN:20,RuleBlacklistOwnable2Step._authorizeAddressListAdd +FNDA:2,RuleBlacklistOwnable2Step._authorizeAddressListAdd +DA:22,2 +FN:22,RuleBlacklistOwnable2Step._authorizeAddressListRemove +FNDA:2,RuleBlacklistOwnable2Step._authorizeAddressListRemove +DA:24,12 +FN:24,RuleBlacklistOwnable2Step._msgSender +FNDA:12,RuleBlacklistOwnable2Step._msgSender +DA:25,12 +DA:28,1 +FN:28,RuleBlacklistOwnable2Step._msgData +FNDA:1,RuleBlacklistOwnable2Step._msgData +DA:29,1 +DA:32,13 +FN:32,RuleBlacklistOwnable2Step._contextSuffixLength +FNDA:13,RuleBlacklistOwnable2Step._contextSuffixLength +DA:33,13 +FNF:5 +FNH:5 +LF:8 +LH:8 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/validation/deployment/RuleERC2980.sol +DA:50,1 +FN:50,RuleERC2980.supportsInterface +FNDA:1,RuleERC2980.supportsInterface +DA:57,1 +DA:64,42 +FN:64,RuleERC2980._authorizeWhitelistAdd +FNDA:42,RuleERC2980._authorizeWhitelistAdd +DA:66,8 +FN:66,RuleERC2980._authorizeWhitelistRemove +FNDA:8,RuleERC2980._authorizeWhitelistRemove +DA:68,22 +FN:68,RuleERC2980._authorizeFrozenlistAdd +FNDA:22,RuleERC2980._authorizeFrozenlistAdd +DA:70,7 +FN:70,RuleERC2980._authorizeFrozenlistRemove +FNDA:7,RuleERC2980._authorizeFrozenlistRemove +DA:72,237 +FN:72,RuleERC2980._msgSender +FNDA:237,RuleERC2980._msgSender +DA:73,237 +DA:76,1 +FN:76,RuleERC2980._msgData +FNDA:1,RuleERC2980._msgData +DA:77,1 +DA:80,238 +FN:80,RuleERC2980._contextSuffixLength +FNDA:238,RuleERC2980._contextSuffixLength +DA:81,238 +FNF:8 +FNH:8 +LF:12 +LH:12 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/validation/deployment/RuleERC2980Ownable2Step.sol +DA:20,7 +FN:20,RuleERC2980Ownable2Step._authorizeWhitelistAdd +FNDA:7,RuleERC2980Ownable2Step._authorizeWhitelistAdd +DA:22,3 +FN:22,RuleERC2980Ownable2Step._authorizeWhitelistRemove +FNDA:3,RuleERC2980Ownable2Step._authorizeWhitelistRemove +DA:24,6 +FN:24,RuleERC2980Ownable2Step._authorizeFrozenlistAdd +FNDA:6,RuleERC2980Ownable2Step._authorizeFrozenlistAdd +DA:26,2 +FN:26,RuleERC2980Ownable2Step._authorizeFrozenlistRemove +FNDA:2,RuleERC2980Ownable2Step._authorizeFrozenlistRemove +DA:28,30 +FN:28,RuleERC2980Ownable2Step._msgSender +FNDA:30,RuleERC2980Ownable2Step._msgSender +DA:29,30 +DA:32,1 +FN:32,RuleERC2980Ownable2Step._msgData +FNDA:1,RuleERC2980Ownable2Step._msgData +DA:33,1 +DA:36,31 +FN:36,RuleERC2980Ownable2Step._contextSuffixLength +FNDA:31,RuleERC2980Ownable2Step._contextSuffixLength +DA:37,31 +FNF:7 +FNH:7 +LF:10 +LH:10 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/validation/deployment/RuleIdentityRegistry.sol +DA:20,15 +FN:20,RuleIdentityRegistry.supportsInterface +FNDA:15,RuleIdentityRegistry.supportsInterface +DA:27,15 +DA:28,10 +DA:35,5 +FN:35,RuleIdentityRegistry._authorizeIdentityRegistryManager +FNDA:5,RuleIdentityRegistry._authorizeIdentityRegistryManager +FNF:2 +FNH:2 +LF:4 +LH:4 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/validation/deployment/RuleIdentityRegistryOwnable2Step.sol +DA:15,4 +FN:15,RuleIdentityRegistryOwnable2Step._authorizeIdentityRegistryManager +FNDA:4,RuleIdentityRegistryOwnable2Step._authorizeIdentityRegistryManager +FNF:1 +FNH:1 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/validation/deployment/RuleMaxTotalSupply.sol +DA:24,15 +FN:24,RuleMaxTotalSupply.supportsInterface +FNDA:15,RuleMaxTotalSupply.supportsInterface +DA:31,15 +DA:32,10 +DA:39,260 +FN:39,RuleMaxTotalSupply._authorizeMaxTotalSupplyManager +FNDA:260,RuleMaxTotalSupply._authorizeMaxTotalSupplyManager +FNF:2 +FNH:2 +LF:4 +LH:4 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/validation/deployment/RuleMaxTotalSupplyOwnable2Step.sol +DA:18,4 +FN:18,RuleMaxTotalSupplyOwnable2Step._authorizeMaxTotalSupplyManager +FNDA:4,RuleMaxTotalSupplyOwnable2Step._authorizeMaxTotalSupplyManager +FNF:1 +FNH:1 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/validation/deployment/RuleSanctionsList.sol +DA:26,58 +FN:26,RuleSanctionsList.supportsInterface +FNDA:58,RuleSanctionsList.supportsInterface +DA:33,58 +DA:34,39 +DA:41,17 +FN:41,RuleSanctionsList._authorizeSanctionListManager +FNDA:17,RuleSanctionsList._authorizeSanctionListManager +DA:47,57 +FN:47,RuleSanctionsList._msgSender +FNDA:57,RuleSanctionsList._msgSender +DA:48,57 +DA:51,1 +FN:51,RuleSanctionsList._msgData +FNDA:1,RuleSanctionsList._msgData +DA:52,1 +DA:55,58 +FN:55,RuleSanctionsList._contextSuffixLength +FNDA:58,RuleSanctionsList._contextSuffixLength +DA:56,58 +FNF:5 +FNH:5 +LF:10 +LH:10 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/validation/deployment/RuleSanctionsListOwnable2Step.sol +DA:21,3 +FN:21,RuleSanctionsListOwnable2Step._authorizeSanctionListManager +FNDA:3,RuleSanctionsListOwnable2Step._authorizeSanctionListManager +DA:23,11 +FN:23,RuleSanctionsListOwnable2Step._msgSender +FNDA:11,RuleSanctionsListOwnable2Step._msgSender +DA:24,11 +DA:27,1 +FN:27,RuleSanctionsListOwnable2Step._msgData +FNDA:1,RuleSanctionsListOwnable2Step._msgData +DA:28,1 +DA:31,13 +FN:31,RuleSanctionsListOwnable2Step._contextSuffixLength +FNDA:13,RuleSanctionsListOwnable2Step._contextSuffixLength +DA:32,13 +FNF:4 +FNH:4 +LF:7 +LH:7 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/validation/deployment/RuleWhitelist.sol +DA:42,40 +FN:42,RuleWhitelist.supportsInterface +FNDA:40,RuleWhitelist.supportsInterface +DA:49,40 +DA:56,1 +FN:56,RuleWhitelist._authorizeCheckSpenderManager +FNDA:1,RuleWhitelist._authorizeCheckSpenderManager +DA:58,348 +FN:58,RuleWhitelist._authorizeAddressListAdd +FNDA:348,RuleWhitelist._authorizeAddressListAdd +DA:60,263 +FN:60,RuleWhitelist._authorizeAddressListRemove +FNDA:263,RuleWhitelist._authorizeAddressListRemove +DA:62,772 +FN:62,RuleWhitelist._msgSender +FNDA:772,RuleWhitelist._msgSender +DA:63,772 +DA:66,1 +FN:66,RuleWhitelist._msgData +FNDA:1,RuleWhitelist._msgData +DA:67,1 +DA:70,773 +FN:70,RuleWhitelist._contextSuffixLength +FNDA:773,RuleWhitelist._contextSuffixLength +DA:71,773 +FNF:7 +FNH:7 +LF:11 +LH:11 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/validation/deployment/RuleWhitelistOwnable2Step.sol +DA:20,2 +FN:20,RuleWhitelistOwnable2Step._authorizeAddressListAdd +FNDA:2,RuleWhitelistOwnable2Step._authorizeAddressListAdd +DA:22,2 +FN:22,RuleWhitelistOwnable2Step._authorizeAddressListRemove +FNDA:2,RuleWhitelistOwnable2Step._authorizeAddressListRemove +DA:24,2 +FN:24,RuleWhitelistOwnable2Step._authorizeCheckSpenderManager +FNDA:2,RuleWhitelistOwnable2Step._authorizeCheckSpenderManager +DA:26,15 +FN:26,RuleWhitelistOwnable2Step._msgSender +FNDA:15,RuleWhitelistOwnable2Step._msgSender +DA:27,15 +DA:30,1 +FN:30,RuleWhitelistOwnable2Step._msgData +FNDA:1,RuleWhitelistOwnable2Step._msgData +DA:31,1 +DA:34,16 +FN:34,RuleWhitelistOwnable2Step._contextSuffixLength +FNDA:16,RuleWhitelistOwnable2Step._contextSuffixLength +DA:35,16 +FNF:6 +FNH:6 +LF:9 +LH:9 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/validation/deployment/RuleWhitelistWrapper.sol +DA:37,38 +FN:37,RuleWhitelistWrapper.hasRole +FNDA:38,RuleWhitelistWrapper.hasRole +DA:44,134 +DA:47,2 +FN:47,RuleWhitelistWrapper._authorizeCheckSpenderManager +FNDA:2,RuleWhitelistWrapper._authorizeCheckSpenderManager +DA:52,90 +FN:52,RuleWhitelistWrapper._onlyRulesManager +FNDA:90,RuleWhitelistWrapper._onlyRulesManager +DA:58,133 +FN:58,RuleWhitelistWrapper._msgSender +FNDA:133,RuleWhitelistWrapper._msgSender +DA:59,133 +DA:62,1 +FN:62,RuleWhitelistWrapper._msgData +FNDA:1,RuleWhitelistWrapper._msgData +DA:63,1 +DA:66,134 +FN:66,RuleWhitelistWrapper._contextSuffixLength +FNDA:134,RuleWhitelistWrapper._contextSuffixLength +DA:67,134 +DA:70,46 +FN:70,RuleWhitelistWrapper.supportsInterface +FNDA:46,RuleWhitelistWrapper.supportsInterface +DA:77,46 +DA:78,16 +DA:81,38 +FN:81,RuleWhitelistWrapper._grantRole +FNDA:38,RuleWhitelistWrapper._grantRole +DA:87,38 +DA:90,1 +FN:90,RuleWhitelistWrapper._revokeRole +FNDA:1,RuleWhitelistWrapper._revokeRole +DA:96,1 +FNF:9 +FNH:9 +LF:17 +LH:17 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/rules/validation/deployment/RuleWhitelistWrapperOwnable2Step.sol +DA:28,2 +FN:28,RuleWhitelistWrapperOwnable2Step._authorizeCheckSpenderManager +FNDA:2,RuleWhitelistWrapperOwnable2Step._authorizeCheckSpenderManager +DA:33,2 +FN:33,RuleWhitelistWrapperOwnable2Step._onlyRulesManager +FNDA:2,RuleWhitelistWrapperOwnable2Step._onlyRulesManager +DA:39,12 +FN:39,RuleWhitelistWrapperOwnable2Step._msgSender +FNDA:12,RuleWhitelistWrapperOwnable2Step._msgSender +DA:40,12 +DA:43,1 +FN:43,RuleWhitelistWrapperOwnable2Step._msgData +FNDA:1,RuleWhitelistWrapperOwnable2Step._msgData +DA:44,1 +DA:47,13 +FN:47,RuleWhitelistWrapperOwnable2Step._contextSuffixLength +FNDA:13,RuleWhitelistWrapperOwnable2Step._contextSuffixLength +DA:48,13 +FNF:5 +FNH:5 +LF:8 +LH:8 +BRF:0 +BRH:0 +end_of_record diff --git a/doc/schema/RuleEngine b/doc/schema/RuleEngine.drawio similarity index 100% rename from doc/schema/RuleEngine rename to doc/schema/RuleEngine.drawio diff --git a/doc/schema/rule/IncomeVault-claimDividend.drawio.png b/doc/schema/rule/IncomeVault-claimDividend.drawio.png deleted file mode 100644 index 3056bfe4aa200c30a237a45cadcbc8974e60fc2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100066 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 avPDm9iYQbss7?WyqtnwmN`9zeAMsx`uF;?X diff --git a/doc/schema/rule/conditionalTransfer-Storage.drawio.png b/doc/schema/rule/conditionalTransfer-Storage.drawio.png deleted file mode 100644 index 6fa3d10732f85082dad8f67d8c3bb32325cf9610..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89794 zcmd?RdAQS5zc$PyZV+{Y11Kt+EeIlDI=2c+(>6_$&TWQ91(POilO|1@rcGK!0RcCP z3eJk+qwuJJ6N3W|s0a#9I17phIDw+#gbIT13ZC=6-#OR!z1R8wyRNc#nq*DC@&4Uw zZRRE8;o}FMKCoA>UdKn!V7gbYzFe~O|9NJI?9K_0Yl6*{ zwb@2H{4OW>0XZi6oDSxn_t~OQ`HzlV6Cu#SSlW6M23JwB(lEhq)9aq*cAg8a{MD)~ zPy&aG`e-}ia(E^>+*T7D&Bmgm?E!Eti)8`)3JdwNYBk|C)|e=&;B`AR(LK?cVxXj{ z3U~>zLGFprM3>#^n`ra-z?1*86vS?u=$PmL_cCmO)x`hDa8?(B&KCb!AxXPn)Gl~E zT7H^ctl$%ZDea$?H3h9M0dhnyh-^}}|ym~=>TjWWV<7>kCJqTt1; zFlg)XI-p`MPK9~!#dPDD5}%R$$y(d1g(E3fFpj5W1*%7Yu@&NV4A=n7I@`R{APk=) z6(qA-5!?c*NQ+#src{9mAzpvQ<#Z}eol4+AH`5TbkdcOyw9)b+Ay2z*1U;}4U{DAm z3NUYaY9#0)<8jz>UaDd@j3Ul5P!n{N6fwaDe*ZH<15dUDh%9Ozj~lBtBHW;14{ zk_BfgPsH>@NJyz^FQ2T&ngl91RVL{&lSNOgWU{GX+vQEGSx?)J@Qz|6!lB6uVYb2^ zCgQJ}d@=x20-OXRol`2y8s1lF@@wy9X7d)|` zvk=i8elKBJJd#jY0XF4!$)v$3j;2`B!)m0I3bmnFQpjU`)Jzmqt-&Nf$C*M?gX_^~ z!wFNMZNQ;0O?QPw624{|vt_**(z>nkevi}J_P13Q4ns6(S5LHRbs1bR1+Ua9Gd?Iz z+LFNncsT^?_7+i3B5FnQnH=Wi)kLK2awkhP9A%IMEx{-+SvoJvL@6eb#Zp9JkQ5T( zQaJ?pJR;;LKA_Ar5s1XDWOiE$aq-+2n?YD0`F}_DW$|Jt!k^G2r?OOK_qUkv55fT z0?TkaOdKv~nja&DVp)&^Q6j^DF}yYv&igc15z7YHq@DG)RK5YaR3Wiq^O>S2CGlmE zuSo7hw$6IN6Q4s1!Y!H$*95%CDCez zB%&fD+*%nXAX#e}X`ZqK-(nje3d2PNa_~yb8RnUY>6gH4_ zHJHTla#7Us9x-oZsu7u~;v{hBR0Z;jv1(jK1-k*0QKpzt+@ThiO0g}SM)j^%8!)U=)#izt+7R|#)g zmlR3y%2qt2qj|SUaA-7G^5I&}M(d%dQ9$ajY)6H(*VD+#o@OHp#%j?-CE|@J(O@Xf z)uKTMk#-Rb-n2X@OA??jvk_N)1%iRN3RZF0BAQP~dN>g2z#BUF2R;rEYTz7rx83&f zH0_29?i|i4Nw{4uQwcbV)~c{xXH#4VP3iWS6=*Y>7oo}?+E%oTF;t;xtssQ0#Dz3$ zY!l>M*p;CO#9k|+?N$MbUogPojpJdC5;7rIxv}7-%@n*(db1_va0|kodvf1FG zb-pH|wU`lAB`>eFoslXRHQjj}r7Ad+D3gwYvqom5B*awPRkmiiq&E@=YjycKFnoz- z3Q1?oK?P_`FDkBb3r_peUOXjLTOjylywP&fj>TNSIHQ*g3e+(Y`3kw7q*_1nsIqvW)NV#}BY$2jwWLR*%qSfK5pOI9%Db%sXM zzH+XpGjhi70v!us$R=hJRk@BvJrYr8jCwTZmonfHXpl*WaL^}HPy_ZiG^NqhZGu5I zwW!j}_!2TwEtodQMpr4?+j0bBmeu6)io4~&SR7?3m11anGt#KGU^_umB z2Q;7GlhNu;StB7tqIArUv&jZdR>-QZYknr9 z!DwAmNWag=rIL+gK?@4OR9RtDsW=zZ848ICaia;5L5@RU&6cp@1znG2yog4)8)=#H zXA=p^0)CR_jK?)AthgzJ@z^ar+k>Vf6#}==B1b!gXiX&|2p#v<3@VXO1swFW< zWig%B{E52SN+v6gLW1D&wrS`96~f-CSOQtiigZC#%6j>{H}7i&0C=c4OCGo$Q}s%i zkxT!;H;{33C!I9JN?d{{$P!jiOeZ8PkScMZdIiDNVkxOm>7a~7=my`2m6BLC*Uq9! z18pM_%I%|?#X3Yb;2dj$F$FA%#ta(t!^V7;CHh1$rzIL0go$9*^vF=-ng&fPEp<}tp-bC)r454Y?-R+ z2w1ZQpGG>F2uBo?%R`K$a9*dqlx?^|cFb&$wXn?=53`^F>=p7X0Rs?LaK|u^dm=}(NYi&%T*#_vxf}C<~2fJ$+-3x~XCRjmvjby-ISk3z5tc-QqASP}PDfk_YAxRH zaHq507);o)nw841s>wk~DdU5E(G>27Od29v90FCTvZYg>1I;%@XRy?6hgnha0cZ-x za0|`SP{U@c8k)TUTLMXPo~o&_d6%51Go}miMqQ1t&gR4nhDo@m8uztnTR86Xg>rVk zpMXL9fU5>qOhm|16ZhCrE1cD|6d$vk%!;ptsKWc3Y7EL+PC{|se2y1s1xXalyb9T~ zRGW+!fpS98iUKACYfJ+)L;U3=mIyTKq*b%%MI%GHDxMPFR*^*BK^EkAIG@kA8gXY! z5*f;qHi?o*MtzV#acnpm^r!0OoSAEiX;l=NTtNj^gxI7~34u&Vje*?Ppioft1x+x+ za5a;tQgF!;2~_AvK8I*QE!On=yhJVzK#q}Vu+>BiOUGzYC*!C+nD+@jL&$lF03j(w zBpLLo3>LOkkYL5_O|YSOwN+F@Iz$psj*caL6BpwtXv85oa|u~-b?x;S2u2}{Z8nqlS&CX%A>12Re&nNPV>sM$oTrh*pj)jAi)I4vd>+f6(q88oc2qEsj1em$Mb^NFxgabt|$ zQn5xHRLOZ?PATHCX4G;ehh|E$C!K*noo>l4EX5ElT&`Hi27Hyoj26lTGHIpiWK*h_ zazf>3iiT-I$Y@2j#*t>p6;Y}wq>?P)`KZ$wsblVDIbY7E38G3fT)ifio$)Au^s1hS zs5jGZ)q1vu0+ znr%6%oSX>wGHyHjeh(-v+9SU{mUB03wg zYY|VniicT`smOtxy+~JrT)AWm2RVN<1=?pyxhfF}$8urN8)S^!qk zOt@qN^>&!f5UD!O)DnWdUR5G7ML(G^KyXcx9oZt{Za1vhU-mPpW+uP{W2FQVN`ZvUk^$1rz~MkmacK=d&!$_M8d7bG zb+5Bz5DD2+2L(`FjAudcP1zE#z3s-SLd33=qjEcD_lN9^QK(8-w3G=OP#D&zWI5+H zS|QmUOg9^?R=CLJ5~(IhWP}(W5a?W^!ZdWHkpXODtzkH8CEe62-S;{~$gWsq4I31@xxVR?&eIz~xXfa1^(v?MP#cwxzxDr0IuDGQ~Hn8jo~mNRQ|T?+a$xkv!7%idHo z;7Nw$D z2bj>EfmBM?NsTr<)q26@#eksTpbbvP4Wp7KDJCfh-g?{{YUTqXh^CE73BVC9*0!>X z*Pqjx`81af1bECW;)=bV289$-_7`GCL?R+_XC+WhG@Oxu7%eoFU?b}k@D@mv zh{scwE0G43_sAX}oHn(v2Z>ccr+Atr2$JIwyE_NxFf^Yr%sN(M%GE4OAVRPd3&qet z3UeU2s8G#G&Sbc0S(u{eTDXA=HAlNeDZ1L0<*d&{ASW;xfX%$|wA1phGQrZ2R|~al zvYe0jB4*f)b3PkeX~T3Gmg#nu1-)x8CQK#*O8eX?+U^PmXcr=9;|(W{!gW-R)!SSs?uU~BJ>{14s=uZLAe>cQc*zjL zF$zy>c^rfRBrYl`HPUDShNi)y5fGR?kygUu0!%NFaYosi1v;x%2@SJFlIP-H1y>|m z4+6-nsAU~9r4*@{)l4l7MSVWEWUG24GcK1yRotgiS|S9vtb!a)RV#Sg5h1gfh~`l` zhBqooiKY~eN;Df~p^aDFl^E`iFr1e4i0N`UOtp&+(X6H`nx3{$9m**RZJ}Lz!OrBJ z9(zP}aGJNCPMDg>wasQwM|eU`8>O_%UQ6ku=#VQZgN=sW(E?wz#T8DI<$9cvJu+?c z+x)CrcU!2NM=CC>4hR^gwE<@3l@gmpDis}5g|@B~JbB6OK}uk8q(7c^xjcZNVj~PM z`(335;m^>4fE+Gn)VeKOC|Q9tPAD#}92W6#N&#WPPGEXYi^NK5$W`<>%YcBcC#VGE zHX;Qzk_{I|g+L*!WF@~Jfm{LEE}K4kPBC~qVZ~Uc63M$0hPO#J z{R(BzT3oD|S5kBX3ALK08#r;fl5rP!U!WFA6(iwL3O0GQ09Xne9$*5ZAya`05tU7j zMQwJ8%z#c4@lY;p!(0I+4TnMDCeO5tmdEJUSF`99L5&+hG$&yqLIAb6;19P?|qC}}owd%M~t<|IPYARf3+fEOpt0^sI zsD{8R7JTr-h||lYm{eGDx0G5m7t<{k%XF4n8pGD(EM{x@3tl%(n`xbCWs>EBDL{3l zZKQn-hb!*20#Vd(yOd~}AP~TMF_Ue33r(m6XM3 zJeCTp?h=#~{Yk^Xb%w^XjNHlwPsxgytWtA(HpAWb)D5g_J$NTUlJ|AV{u{*vdRnYh}%L)w3bUoa?)n`W%df5h`JO zvt5njB+8~6L4;WBPzieLs((xG(3D6~RR zvz3Z@nGzN&r>az5uZ7HL1ni8YkZ>bVYKL$>QFb`&i8d9k2HfG4BdJ(nAyIBnykclg zDUOPO)t13P0+r!IUL+0sTmamZym5>5&N~Bv7Ohwz76v@L1#{d=!X0xmVZ!=?W};>j zs;bT;0_$ki7p|BU&XpI*ia zTH96jRO$e~zz(2bkVh%-qei8WEL;&>p|n^wy{1CN!@A8x98n^c%ld(b2cq6=we1gy zu|&PeI7&ndLk-X}%N7z^EYbv&EZ|vipo+4NR5RXO&KITK39wI3DIy%MgIbX=D=$sT`xk|ih;0EJ~a?Uc|*21R4 zo=j%SA>M)zWlz{iD?xjjNE<~L@O=a;lF4$wg9gw7>XPJy!)|i`cD0OPNHXMUB?Q1b z<&}KNL<((4j+Aq815xbdl!wJL%|h12qJGGdBiFD3yc=ABkCbEMr7A7y0eihs1?+RN zSm5MVvqt2F~5xo8w>F|eVCif#wR1?z61B*`Hn zDhfGIqnNk!20P6xrdT^FDZmsavfjD@Tci3tKChGZ#cFM|sL*&aP|2mztW>lnhQMYh zFKBHYk2JZu>1#WiN*D=veU^ilY(ASe#5yU6ZZ@OgP%_bEt^IdYh01a%m~wV#cnz!6EYCO8`6)G)N1xnd&r=HMT8LUDg4zf&&Q90wRx>Ygc#Q{BQiBc#vNY(F! z_;!HevV@R?{2Xi{XuW8`NDEFCa95BJL7m;MqA6z*&{v4NAd^+vR)-8tw5ec4jGpw= zp;DbPe5men=eSl#MZt-MMv0XjxZQ<`aNR~UYg&nkl5wRd*SxHRhd|A)f@?%_J~A!YRVUybS_zPYjZD%Pa50hq zb{{-cxmv9wjNvJxK{uf`8d5~_b3DkZY{e$f$uyTVm71$giw>HP<y$4#%MVdfILx~!d8534pwOpN$NV`&sQ;6t_I6(5O|PA z#tXs{V$fbdq=c$W8_@$5;Ae>2`T;&pUnL7UV^&eByL_17(LD))E{a}T)Z{!N6K|#C zDDG-gMZ#vyp`I`tM7bYMk{s#=ke`aSkNanqv0)-Ta zoI8vc#X&1Uz|3K=_nD8^bx1PZO(+00{0Ys?d0+$L(RLx_ z4q5DsE3MG>su$Q23ugq(C#f~8k#ev&rRgaW%Y`9lpw6n1fSwI=F>lFM%q8kz^VL;t z)e@Hvgluw=s={zZYN?!60mw=MxK%x+ z5LJT|Qdlii$cMO6q|pRgg-a6btL0h77xZEV14*8YuBIWT2#&_dLe^mv_G=;h@T4n-i4H*dKpWsnq{xf(~lrkW`L;zhqn2iRRB<+MUg(MN;IKQHcRN9pb z`r?3^R!DCEt`;LPXRzqWvbF-M>z+m?NQ}K zYm_BxACor9loUzhwKNiIk>EzXgtHk$%!UL)NE2qYU9M1wpRi@oWFQd?B4OEPwvaYPNuDRs zSQMw6^|%~!xFbr~-}L)qkx;l=%w@9m1Xjgq70#k~-o&6hCHvzcG8u`XRMSpYT=6V# zt&7X~SS?F|eN{vV=`kPT0W@k9oNX&7JY-xai9FjxQ(kA@85C`~BH{&kj;|LBGHB~d zv@Nu)KrSd=5t}wGoR1hzL694~OHbNTS^-aoP&*$)!*rqQhr&rjCrp_nJX%G~HVBs^ z(g@nHTGfC8xf;&pz}b>;y=ZD$LBWJNl6DvUl{ADRHD4|Oj2Fp5L0eX)D{+<0Rr6}P zruh9>k#|6G>Ba04tFxo3%dPfwtTlk}RbGXcb#*JK|_rxZOy5no-z6 zYk)NCRVq&6W+E298$J zf@0$gDw)Yu!D-`W($mz!_C|!ug*~Q3*BcIBx*X0jNTm&qlQrwHdWCViRa=Y8_##od zRMwhw%u~+#SZm7`3R7T)VnvcA9Jmdls-``k1qK5fo+#ZQ+f6JCAO+{QFX1lqQ&WS>wJ!g2{y4&R#b5C`a`0fL9mSrBgF}J3)u=Uk# z)SEqn&wg`}x=!prXxQbSJXxl|dHf}y`ThQ0-RJc6ICm!l>8`HHw@DqnM|OcRg~1)i z4<3HemCx+`=+Q-|U7$ZKe!gz{>qq8~xOj*D!}e{1&hWmYfBV6*Rfj*S!&5qDpV9lY zXGRWPaCdR=g2mY2qZ5PwwW?$Gte&?PPyWqvLL0w)4zS>suzjb;XY_ z6i;_ax9)8oo(L9lZO5jUeoK~Y@~U5*b7AU^Io8sSfxAu)?t6I2jjQ_Yn|0j8P0wC( z_~37=cU_l%b^hjqr+sD#;9{#?n5Qi#A?A z^qcLsfF&<7cC=pmU{JbcfgcUI=Zi`E3L*r?5opV%?;owK|8dVcLr_YG}W+83-Gv{`U$A7Kpl@ny!n zxs}|UU0W{2@4IMv^uy)E@mDVgk2@#y3vPH|^p=MYAnntM&C91*t!C~%yQ`bLa{h1q zfwafXoH1xSHsirCcH@j+*L=C)yE#W++0+G=@!&ffHto6jg6@6;uLCd5TEFb|>t=(O z(3h4oNA)zQbL@qKGplYKR=VrivH#be`rnLA8*$q7ba?iZmpd2CyaXCcqy__ZojUkZ zVuEE$J>EX|cX1cI51++W7v6evz?ge3XV#QhU`_c`Couff)>o%ExD6e@e7#7$ zyLaFITYq^aYt3$AAA5Dld7qB`E!sYPw7C5IqcVE0yK`Lk*Uw&L?!Vko+3t1JzmBfv zHxJ3IASb-PM$FXz*mdoq$1Z#B_ESf`5Cc+QWvyxa6W{&Y*WESwt-;V|mhFLMozgM; z=AL7|S`vwWGOpk5c{5(UYSLFfT=Mw8A6gfQet$|IFx2d0dk%i2GjO^$i0Ix#Rl0_x=OxSG<1I*%l&Gg5%%YO?)$Z#*3CSQq7vQ z_E%^8J#yO7=W{|+f{#35E_Vav4+Kl!-lz96>ALHH4L`hpxpvfsmk#b6eEk~pL*K}q z=Yug0-*(wO%*4qz+_L6F>gaP8JU?&z;^meG`v7q~J!Q)ByB`1=oG|YB<(FDZ?G(XM zyC+O-#5?}D9*Fn<-=gS_ZHQm6chu@vPPp*SsV}tWq-6#?3s)|NKimK6aP`jojlNg^+W*RlUvD0BpYza(ZYO+7Y<+1lL30KKA$zpFQ{VHfhD9 zZ!UXiv2@j6KZSq!>z6HymfU#3@(p8K(K zPV8>p{Yh!b^WVPyHGA4K+y1rmiq~%d_OX4)JBN;%(2?%WTzB*PCqKUXyvLqdzuo-e zhWkfzpQIzq&y7=mKGw+=9 z)v|(kLL$%pWnH6ZYRj4$ItBipr2*HGal*)-qO$f8>MT`QZ56p}6m>lfOIV3>!E5(JQ{V!SmGj zd*5Ah?V~qAFP#+kzC8cT3qQJY|I5er=gdRjKfUOM-*pRN(#zj=tQU#grcvZuIW%a9sXUuWN36Qu=T?e9pA1{`~jo!;9oq z^ICr&{#_~UCaBAVPls&iIb?neP*Rb+L~*USZ%+zX zu!&#&mV5R0$m8#A_U##re|_d9#d{m$&oO;JJv(ITyl=ky@x{O0VDa~Tc!mDjDSF}k zn8!8!(1Ew4=!4JAd*>sNy_vflHx4`Qu}v?%HGC?O>;tS}bg$gwAjgBeaPrLLNh|+8 z^81S)^*X#~$xUxwqP}q3>JH%kkKfZXY{&5jZf$(`(Odf7_cliFyXdnc(?5D7_tDPp zKUj8)>*t#;K4RiiN<;a*>kj?kh%ItIIs5Co%a5)6`=*71#6Q2e@9Ob?GWEAykJfG+ zvkOF@r~5zt%i<|_ZvA}Yk>QJ9nKA7t`L5B!4((fglk3PeqfZ%(%b%Zp( zZ+LiUe)#z(Y#8uf@4?rM-#z_-&jH|ly5BKr#5{BA`6x8^qF`<3OEYip^$z(-!ySM0OlKfHMG+w)fMXn(iu67$4^GvEB|?|;9iKEH6& z@vY=L*Y`bf(mR(nw+UqN{ms5hy60YW;m_B)c*pmLnaLqG^0l?I zrb5r>i}%##zOZV-+99^*&l}Za?woln**a#f=d5u(cb>QJw%oJ&UToVyP}v#ZMP42r zDh(Yqd%tJWm|;&0`)v06toPV?!`K-goS4#%Is4@IkkaY=rrWZ?@hhiq-!j!V=&EmD zT7B))rN938>GobzHgv81=3Zm*qo2%qY1iTV&)oO!tfl)_y)p4Y;Jt475s=Ui?C2W& z#s|$Ei?+IZhD{yW(cio4w7&WM5BwlQ=e&6nl)QG#mMeeWJm&VXLSRFw@0aHcJ2-F5 zaSz<^jk^7r+U+ttf8^Fp9|}{Vqqqg*7mr@L<+iTDue{Os2X)<_g^fRsx^$+#|LQ%) zv+&qGw_j2b=bbq90=Vx0LO-+y#FFU(o;h&S>E@pMuYF9vkiT*I`NMvk{noB! z>)+2TL5_d_Ddp3p!TCwYq)g_a_+?*xwy!?$<~c`Yx$pe^h!e%Xe)?g-IU{!4wJ$df z>_+Hevqz#Ey3k*b??#_Oo*%hjNKfCX7xcsz^a#?0XD!tu?yyp zd~&t{&%HN1;DK4jG2O5JIGgYPd(XmQv(|Oa8nA5rHGw}ad!lpJv3u|Dd^WPEp)5-5A4!~|#zXz_JvZsf>U<+kWD-6fBXjO`h*bo`y`j%+L5_vEfwodX7O z1NmF|6NbGt@zRBVZ@ImPos?g?n%cZ@;PYl;@^82PR(Nn@w{rKYi)gVfof1Gyq2Pbz& zXF@BFJ>lms)*nQl*mdCIUB_?y;+moTZ$AE`w};O=^3$N8%Qk)T-#6`;^3kOO9(?@R z`puV)IxaSQ-^vl^W!Rg}`t9;RcFlWs|N7&;Kl`pP<sRx^csV1^B=L!Ts8*p*KB| z>6kEe@~J0|HD96s^$Z{w6#MA|`7_o|ne@}!UtO|))2s={*yqL{D30m?e+9K}&$oYa zR@E)fCSE*R%0AmM`??-s_0aK)uDIu!n_C;YTxPHRn?{{Vem!6<_u`4Kj=AeFG-Tu` zQyj9nAFB*|gum?-s4$}Q)eGLGA&wcogQ74#> zdT+Y^AcT(Wy3fP~A6j z=?goL+gv+l?ad<>MsGD&pYEy1kux`6(DC<|FYNTnTcJZ8n=kHKxXeEL=DTh=GQ%_S zP7^!#sHpc`%ny2eZ1C7V^VZFBTo4`cj_1p_>7B+Te$O=*etbhR``FH@ufKj(_fOxt z)E(RB25xp9v;E$0V*M*Z>cjfKgHynN5wPaBi5C2wvZfPoNpEcY^tSJ>TFD0oEjcZ4 z{!f368$%8%&cDLGk$vK%^s7^s@%*gf4rmCgr`Ul4kp9QM<^d1tH|%`LsGsGho^-;&|oX#1-5J3C&( z!yERm+PQa$Ix6#08D{F6`i@37{9!!%)Hm>k{WEqdGrhZ)&5Hi}m0^z$8gf)$Ie+u|VZR+9Y?mp)E1CDP5AGx)|{|Nfh ztf9;7U%h;HEAFAE<{K2D?)us_MR}EeXfB(z4?BqWK%TBjwicuC#G4H`|$DImj3U1_z zHmD&%4jR?_i%s`^^~N2G0OsB}b>EZ5&=;S(e$SZ`hb*iud~^Qyr;NI!KJ@dDQJcEr zxt@cyp_{ipgVL{t4)DgxX^XF4%B`*ZHujXloOWVc4?S{nZqEKkP8pc|&|+syAybZr&;*&#*pTbMKCNCIq zrOduT*rt3 zFP|}Z_Au?IsjIm9%4^q=k1_`aKB-N&5y^_zF)zkd7P@|Ky0zq}=}&$ska^Y+u7rOW5_`{p^# zKe220rJW~EB5UWHJG%bene7=jw76UI^J~YR@k(Hp>+OSIjo+y}{nU`x`P)c2dMwFBLd=;MY#Iqky zz2dFsK@I-(Tb|FIXFUDN)D@RCw{4ty!*I`2b1&Y2|NHrlDQ|bZ+WDnLPrrG$>y018 z@<)%{CGL2B?KZHoeH+(3c_qHNhd%fB>TN$?_UFJUTdab;`=4Sxh(k1NvXyagWF2H>B`Qi~B|GEbkgQZhc1960BH{Zu zulMJ3{XW(6(c%H}evG2EaZ~$F87v%loVjMsxJpU9;2Yoc-5lX*0YkeoLoB=>n z%ui0Pb6CwKh?hi;k#VfxNPz$nav3k2CYLA}Ua=qao$~R@9|e!mIRC}od-_x(0GdgC+I`yM@E?`SyB{qq9;RAiq-L5Q&oIV}pyrZe_^zJ$RGo>Kiz{{x zUwiTtASy~byptV~NGz!Pb2Qg4q+z6PMOj>c8>aGJ58wOoofEcLz2M-})I&z=l-8>O zqvQcF5ZV4e2D00%G0HQc-P3oEHiAp$dbqE7HHU1rTZvO8DqFHHuq^L{H zpXzteXZPo1VCb#=Luvu=(vbu1d7h&xCGXNY+w(kZ5~Y6U_$X;=m{Wr zs!KD+!}dPeP8}IdnLYIVHUDi`V<$y3ufeS^Z5coh7p^?NZ2Z+mY5ZEysJ_w;58c%7 zKLC~Kn_(P9=2P;Fs_^G(3YJ#}#|I{ML`Mk~PGU-Z0asL$zX{P>AWW079}Q6H?MK`1 zCy=?f%P(v`%xDL%+nFk;1pNVcyBW8{%8R~?bE zX$g8gA!~+X4Go zgPEQuBuZbf&|iOICYpkZiS`^liz9^)%Z#)k(o~RDL`))Ju%E2><%bq6AbybwR({k9_npCGk{C zapNC$rR@-B2okNgK&|+O_AglXx0ASzI*>G>vjAyr$2#^UEKLIn*NsVS+7o10iOtGy-_O!*P{@V%t?{j6KO zzx5m8OG!uDuWEd$PzFZ!rzgkWMfLYmFMO`35OYBFszZ*-qi}*~^bOg~z7a}srC+mQ zD@7gvoKa$8jSSdOAI>;K*@`eBobkiiiF@3N!;gC6IjEti_ibzLG5noT2V3(Agcf!S zjnPQZpZ2gCfZWU!*HG)u3lQY-LI>#P2}!+&`v9RF`oZ+4FknD}HVU)K3SfTT z9~hjnYHaBgP_TY`4%W$7Fw}s)7$+S2@;c-3&2god~&NXL?QDOF>h{i=}Lu2$_wt z?Gkv+Q))-x(75IS`unO)JH>`=NqNwurEgPtEE)RV=A&o1ceI2~$uA{Rq#KTLVsI`-c0ubV?86bc^e6-MZLb7YP z|9t(feb0ra&7_qP6+G?VHyPYG=nZ<9j%{;hckQDzPpJ+G;WimcB!~`Y+Vyba#foj0 zXz6FcNg}-#zmDQ=&6|Vej9?&KNlFBE#xuF#;4+yp7&<|H*Esfv$M2VwC&UX?-W8eb+?pHLIFWKarD_{m9MFH2Rb<@*#@EM`RG zj{D>?0HAz#=6%(`(A-!IQ@VhlH2$IF`X^UwjbWdbjRwgJ^k~dekFP%& z%4sZMuA$@1Yd94#$w@Z(AJN212(8c;2p7$W{dyiYdffn;*X)9dxfkT8+COTe=N!|~ z_x`UIU^QaI)Oa={NnQO@8(jdEO?_W>P%WaI;AiO<1Gk2JiX#IpTYkF5amdFh^hR@F z&$wMj@@J*yMWy|75*w_B)&QDdBwP;JxEtq{_O1C&9ga6Ycy**R(+kpmA9|LW5<>^& z61aux{c+!+hyGPP2j!VhNN|m81k4xX+sN_eQ{-G$@lzBwv?^9&;q8=`-b$?M9r)OAzXjX96M9^3#|UR*LOuri)=j24pbko`1R>;#6ORE`J(B3;(Zo zaMyM7&aSt0O{_e!Lf6E`%V~FQZ3WDUKAPJ`j;B|-5MCf)!u-q%0f4%?d|6L{W&esU z9zh3XTM6s7>kHf&x3-wnbm-*xg*$_ORn6##rrS51-|jN^o4@}{zcq1|U5|acz2>GC zJM3saQAnzD!8w;0$1zT*0*|F&*mykWhDOcsAnZa|?B0(^#i#CR6 zrJIT(+8LK}e;maX>uMk!=8RROkuAH4Cvo(G8u4N|CaBSS!(cMHzI%HL_|(I9k&hga zcOQO&)iPN6h3z2OV9D)P6^UrXMe<>iK(GAfN&Wxn%A=Ysm3d}F1}(jo(Qr|fAL~)N z(NMH4onCCp-F`HCSg}_Ojw3T%&`p3fiSdd^6U`mhExm;;v9^PSWF-yQ7#VNpdyF3) za+Ycpg|el1aG7mC)E#qFal%FztDvVQPN@JIpYb6*GYRj{8dZJ|1Y8)zdQ)4{v&rMR zj_M~IFk(7JT<&p{PeYeU1`rtN&aT7=a2Vt8ewGl%dxqxF2?21S<&+l{#^$?s&S)CZ z*)w&rk1}Pd=V$vu(lB~b2UWF(De2Tgf;Nw9C4S?t$7TK^ zODb%sBY^^Yqu^IM3n<%HNea2eje$fX#^K`Tifk2qhU4GwWuJ!aEGuzv9Vy$p7V7zB zw`<*c==}GjIxp@|URyPW!(E>^@yL{4>4l}2RQCo;RvC2?ToTzhVz1x%q3G8c^dDH6 zPe=o`E8(B|q)8z-SrE0&29f8fC~a%rlODV(>Kws14p)7KvYJgRQl(#!eEU1=)wfEP zmr`wK_Y9CwZ)*2B1BZ6YwW8hg=Q0Oh3Zbw~^WTrY`4s-t@thU4Z{M%Gp=TsNN+AM^ zm9@9{`R<^HQgl?<08c4G^F{rrLNIbm_a}?EOcOxxIWZ|8p1W&wU0|(wT&^BXsDEA_ z+0$mOp_1=6K{OF)tYT-xr1%+69}xxE1$E(~bhK>m3oDCsQ3kC_eD}k0CPEhm{fpF5 zIj_Fq3`GR5_M6-%Yej(8g4V}%`?7bBE`WIW9YLvyx0?{XJh4yHr|O|NL|@2;yTT@8 zssb)TMhRz*OeepXR4ACALzjP(=dg##Yq%7aoH_K5zi8rBs1Mu5>k<-}`8<@bE|flY zSBoZ4Bcbvk&XD2VpI?T1#X-e4#kslgNQYs=MNb?-) zC({k?2Ne;spm(@7Uc4Zz(uHd^+fwqVh6^6y_vF{t6vsXYhp?mo>Ox#;y z@bdz~h3U){UZ2ZBYoP&jNL1nIb?>DPgH~6suR%RE2CW{%%}o1#PLAT#Y%kiOadShW zQOW%;(s>CSAxJ)FBsTQxm_Q-P!wGMwgx}uRbQA16h+0 z0VLUwOD)U7dDZP=DlVS0>#Tuv+yP3)&B1|e4dB9j>uE&1&Ua|VAknr-c})U&DGUHN z*?r~~3>4R(XNfA}s{9EW{e0EBs;Fqi6&3Z=MQ568VO5MTLJ+lOV+h0Z0nypJOW|N2oJ#8zqtt@t^GpI zOPmuQdp?TIi;y+_y6WV~$O(_6?mTV}d)YJ-Pvzl9>^&iH39eVaN(Kf$f zl?O>+0OH6XJqSi9#wslk^%_A9rGijmD7rfK{>v4g3L6!-O1~B+ZTC?qb}IKa&Ni=FrDfah&}r z006Yh3^7*bk=eH%39?bDdM$9+gTZYyA+!o=!fKkvc3Xk6yI;2 z@s|!?e(AdLLAedJ{WJPAFl@L_{xF{2hQeyD%%zOA!Vz;Bw#RcHfWk1Njr4S=M^Fa! z2k$6sK~w&KG1kPH0U~J&RHf1xPWO)Y-p^c@#pkITt`A7QmQr`QMV1CW(L+eFUt0^W zQa%K8cigbD@&g*7OdZL)LSTc?6Nwod5Pojz1V)8LJhMn5=1yn~NoPp)h9k5YC_L;l zd#^k(;r!{ni1p>`Gw`3czv}(wlb45aNX>Su(Ave>gOm>A4Ed8ZZ0IJUmpL6 z0TW`39tn-2eylZw#1I5Y>B4BJaL9H`3&P4V%}%!#;qX6LS%UOX*oUAZgD+}9ME(lE zK&>FEOT`sj|GoL(G0zp(3bI7CDn(~pT&rK57sw9EkcN9`NV%TQqT^pnChArMwr92R z2M0K||3PjnFuqF}?^ZJV z;}^+-S>Bbf=x2u3D1c*rC#y>9$ALEC3lqAa^a7l6uJS#f^60<7&$X_suC$}uo87j|f zJgSQQehJoQ4SB#yVHWwl+u3(W5HKA81vN*`NrJYuo5)OW?8oBQ_-p(mGp>qL-;a+L zYbVnUj7eaNBiwi{gM^xc)^$s8&pLdkf$a#mzafK&1IR~7uLBy_D#yqIM(LUG0_a(C ze|*=`{JY5k?vE*-^pJDXpwC)4ovL_&4l=v((_|hBG|#$|yJ-rA{Xd#5uv?wqz9Oiu zX|D#x{z>;$UpC6`Xr0AYN0Q-D8wxv`^EzCdy4663z2wV6vf1L3XEm@lYP@csO>R>E zP{B@^D*W8@TcBfq>w%8Fd$6`P22^X(%tPVH(6i#?CSkOjH~;sJtLGkti&2k(wp;xD z{|S0y{y|4nhFP^Wi})#I@pfeBfvmmDk+R1gw2&_(p!37@;B%6u63 zii-=>6!yE0(N`g+hPLt(xP7z!y z6&Q71b5n|f8PQ6O=-c8%VdXiRo295DbwMY|X5J4`fAVZQ=UuoEE9j&}wQm>QgGlQ+YTgXc&^6aAy8gv#$aVf^UXhC;~lV_jE%Y%k1;k?%- zU#x8Fg4w54D|6if%szLsLZB~P15&+Ou^cP)T^Zyh5AgYH`!nHDHei|6#TqNqQ@jQ} z^yg}1sdpMQ2qz>DS%@m&s@QP{kGgO>sir?ea4tU$c;kJUZaqu zv}kV3#TEQ_89UI4kE20*&l<`9jUp5qTK%`Aa5Iux^oQ!_}Tw-`@aprx;TM9PXIOmO=+#(@HpsMW%7#4(K$aWi{dhC zdTxtGuz^*OjDri$(y!fI(ywA+peXZ~5j{%_^fWy>SMC5k{Us=95hu05|0Cv%fs*^4 z5{ap%2Rm7jFqiHJ>s*`;7kJitN|A3?!C&3BbZ1-aY=CZ(rw;4^GB>GVMfG zxOx11`Sw*%(VAc+_{T-EA;9T9Ci7WRPR&72 zX77*Xoxa$u|7flVPVQW?@D&JPEeC8j0DijsB-i@(DKWNS+(!+cdq`f5Gi@#T@@@&0&TY+WBc*XoYflT-XZuok+`@NPUE6`^w|4i( zX9wRm-l0H%TpNB0RLeg5GZDT=-bn%Uchw(H4-f2`Ew(CDtmR*Xgz6GOZ0kEf&_T_p z70e>j@UE9GcukDNZUHH^gYdhM%^9*7Qob#GZvbN6j#&qi>+@vUzbeq}4N}nYyCjWn zyq)#Y`nRQbd-Vbk)w=Nov;qB6=zjChS9J*+e}BIA?UyKDBr^-%^d~t#BLbRcVKwT% z8oOITTRGE%e~kB&X{lwP+H5$rt@AM3nLRyG&V9bq46bXZZ+h>&_4)Q6>*gE*n82tc zR?o4IvF(Fd11Bd(zGThsL%<#J^!6?EB%9^RI1R?o3EmiCEx}K8#WQ{|;PZBGKUiQS z@71BGn1Kt52OAZR%%f2ziyFQ zxfkC6`s%Z_O8I z0Q4hr|7Ih1%yvMBPi;K|%x$Eo-Z}Wg2S!A)KP3>b5>rs^R(tMik^UxDaVr~uYEc9# z;bCK6%?UUoweKcIosw8Zgr-ky~d_4CiJSnO~CmK{LSNnEm|xQn4YGV5H#;KX~`=cQUhZ_f9RCRBdRrmrsLs1vA|P(rKj!`R{~+Ms#~O`a)(|{t7)q8>xnFe{0(v zGqpv!^RD=hC5-J|!Bhp={WJqNge5$=5QoX9gyEUvFSQzHiA~C#WqJW1Uk!0oLQMT9 z8wdN}@&33`+&12la?MC8kv{5U2)^-a{cNynfrXJ2wQVw$;aq%d=tyNj0^#eNu#*Ojuv z&22(qGkR@=AS2BqC1eCnrUV!wKC7Fo%DGW@^@O?(Hu>uwNG)c_lO|lNYFF5Q6XDk{ zmRYnW%H7z%@%VibO>OrCTA9b1AlM84;~cg3$woU&c7spOC0f9C+%!~CB;|B*6N>Y~ z!)M!)*u}s4GKYdnbg#jia0#*oqy(-LJG5e}s7X- zjR*kZF*N=B&5L*vDKJ-r1h zP1!3zARA}hq3%wO?N^iALR8GvkVVentF|q{8-tJalLvwS;O1=Hm(Xbjt)Z$QarqAGgKZQ4qyUu2_n<#X*ac{|rp!%267#(7+v5hfRLacH0#!Pi5(J}jeA{#>bAv95U0rx2tX2E3U z_33%GXtoqb;{u7ZIol4N{x7Z6VqU$g(RHvimt!|o4H-|M=%q=9aNsHK@P{pB@Fc;# z^-g){LL1M9k|xye=WYPIK!e@fVH|#&ZzG0!AvHPh2Fgy?(Y~ToE`*w%XV#62W8v}^ zfQXsC`0nE38M%(^NbjGPKjf8#iFg)PZWj7N{iHkIR}L96%Wyw7Q(&WKAqu2gST z)h&w>)_psE+OhLR$`?B913NHkw&1ujnK{n|k>fxrx2DHa+ir0&3#iqj&S&^{zzs@x z999LB#i4x|RBxkujPR;Fsw(f|OJI5;o%8n8SlC7d<#gpO%;NZ(DV?QMw#?i#_j8U{kEQ#GPCPQP{X1#;yqaOM{m&L@VJX8kpOsq$^@twVj+57h}I{l5vDo9We{N zT21V_Q`gT7r}IMXO!TUB;14OD($!doSXKx2yKfH?S1b{IDB&`Ci|Rc)vMI zeKDxJEu1|?V0VBsNN6k}SE@#*Vrznyy|emtiv0RM-pRj*QwjHlQ^S|Q+iQk`b>l_q zp>3WNI6qgL!%^jSA%aq`sRAk?B#Ce#Wyhs+YI)z4=2R%4n-bQ0Hh!BJnh)$!=Z>8& z!iXn-j#qAQFF$qBP0YK8|Bd)9Vhw|trV_X@DcO87t*(Hzu?hjU?Z*}aQD=oZBM6mypFqeord(7_-jm>A?ub?>fcdCdvsx zw6ZM8@J@FDpY3b)=C=P=3qT{w^{y_{qJqbjAVq47XX3iGMX7j#G>|$gCo`RwsDoZW zx+ksuw8yy&vfo-`D6Ju=a>3Y4Q7~b7=F+4>ht>TDqrT_|$cH#|-D=F+PEHc?cxft! zg^?uV+J}>AX_#Xc=7)vJ<%Du?Jek|@j7f^RKF+tYyN63#ICh;kh#;Ok3j@sTyC!PY zlqUE5#Qe=h@qBLOTzBR8L*Dqe0LHTmowt5ZR>F!=W&^q*qN74QiPqJJBZV0c>xIyA z9m(0rTZmxcZdFWmiNvrfxdp@}e)EE=YAoqF;>BiR7V!r%;>A{`>w3*tnr*aQ1Pd3K zS1Q%#(n{&_jSYzi9r(-f_|k-J;)xu|Kmlc-oqxtYzHcP3U(K#l#E~&JcHUThP28Pu zi9NSUIQvV|_z*lXv;Y#-<>&rMkc!1kNeD&zYmVAyHx(*>B4SC2d6=1o*UjwYiaTQg zpJC~mmz$7(1xyB6Df-0ULZ5I1w!gIVF*?+Y^lFI9BHyDUfWAe@uG;qt(RBFQjz={4v4D_whb z+w62<>}t8B)US-Wc&U<5o5{C@V9VJS0b@4*`QbkYaa4|W!gDfHfhc!4q+RT=Lv*JduPe!A}Un=m!%Y87BSd%yy*8 zX*Rhf*Wr}}<=jYNc37NWO&_%^jFx|6akd{Y>j@lK5wub4+RruZ1l|PhUQx;K@MoR7 zdtf>t9id&ImKoJb)@9bhUCln7n3YjkB2O*q%wF3u)@QbI%fV;)Z5D_HE<&McF}vY0hHsb_drZo`El@x-Gm z)|YaY?r-<3{f$n)ghy5#@eO*8+q?@jSltA+f5CD&3zvh^>;h0Zc~x;OkX%ouX1^&% zyxpsQpU1D_P*}^{YH(N3FhH=wb{cQr3dcbK^mQ#S)Yon>8e>>P-QD_lLR;uBN1uP1 zVah6uOB&)N9vgSBMYGe~rwK?tvc4TW;ybJd^3DIu`A|xIeMB1jHA{*s-}TAFEQej- zbKqAJZwv|)h2j@gEE)`%#(M7FV6$wJ>c9=NQNC|CwB5SQo=<2rl=|YXoDI#kO~>QI zL}f16K!}VnD&~>fnSSTPB{ikr@#_-@WaBE{BGMK$z)swCqB@3)O5}&3;Xm^|i|zes z`Ix!+M!;`W+3M|C0Le0FT1il+Hh_gr`Y%cYdJ_fh^DhQ0 zTS!I^E8EqK3mL@A>xp7F*<9=0_1)hg=ev?HDb(ssA}#$_%-g?h#v206@$jk5t=G`A zOqBkG2MlqAwyGEtflJtPqmD@nF70yLqFn_SP{FLT_=5jDM5 zVp?19+o&bTcP|#-GtVz?rJbb^0*ZX4MQ-~cBVW@75gQJmjO2&m7m3`4sz)=PYn7X9 zmyhCg0Dd~8=vJ;CVA#Qk%87XUFANJj)cam2me{3M0*I3!TZbp~WQ^rwyxa&wr68!XKGx8dG^M z3wcW#!$GM<1{XcodY)|ne3W!mGgX$1k7h^7N64UTE(TeTw*i-U1nC<5PlD zSG<=5cBY7LU{*~SmlMw%{m{Cwk#guY1{mfZR@Q3Z$+55RM9P|l#B z-~CTOE&Y(3jwAWHb?iLAg4rHnPzIFgU>$s#4tOuksX+GXz6@C>*Sf$o$#wMJ5qUY| z9y`_uz655VD>)Nq^Bp;XVZ74%0}#Gm_CFdVa_Tksj~K`B9Mo zx0?B3iR}jG!da93`(&R!lYrWIv!695t>Ma0(T9#0s_cgLl;2}7Ow)B9h_{cGRVs5a z0&JjzJ`@)DhF+Zx>K{65<&LJfb1mKZcZc?%+i+p^EWd^Z@x-_%Xg9CxEwr8wE^^M z0qFL-Pn0qp-QP>UWlF~`O|r@2;r31l$-SRn(x=5VhuD7tbUw93H2y|1m-NLVwL9zg zDF%|P7Jdr=oafHwb4ZK|68a=b);u8D;To`oWi|fgGbGRCZ6#NS#Z=UtHc6bs!aT~$ zzdut{^2uxQHCoSf(F8HJb4Iag7}P$vKRPTJpjp`bFBzl@dZ%gb+c{{@RLeLu=K(i# zFWDb(GNg|1gv#%yrh-U`OX=^|4?3t=^8kG6#Tl?%rxmVC#It$>pyTFb?RS%!$68b+ z6TwzVwY55hG6U&9-vGTSN&2x+1hkg~utRi?SJ{93B{1b#5_NHNrtRgisRB#pok)<15WG17 zpgy<$tLcK8UN;uE`-FV;xcyx)PXJotvf+Lm8DTm;W+P@@ewKN^f{A0VOapR5>H%Fy z+XZECMQECT(h?t?4#9XA4g;%_7_mdrpaM}&&lU`z?5_kJhEuU|LX@k>7$Rsp(^RI$ zS>~5G5%wEnEQ0+vOHMV=W9F81_A=)F6DV}l3sMEnn4S!&EHddiY!z<+>Zn0eW}YtM z6X_u-s(fKh^?D z3R$ASjlpw?MXBk|t)x@c#z|n4n!y@Kr zV9CE#vHiH`oz6^GY>Tu|k80-1#uvVLtlj+Q{z|Zq6*T6czm-E1aP{E&RP(6%!h~t* z-|$3MFmwk9(KnXi=LDeO)B{}fUj-RMR&YG}s~cAF-+vSWNJIo+YrX>$qmAnH?gQu+ zJw<9@N%?mR2k@zrj>??>^NDHj2`=TN7w`Nr;4x`dvUf}LiTCl_DLjhn^h>~>(QfuW ztdoX25AYc+cweb|p9}@=JO~3kgtgKVaGPHM8~(k1-eyobknaZ*)>9FGetEMp4n83R z?k`AH0Hoi?92RRv*c6^EF)e!1&K$nU~QDs25ge5WpzV7aZ+c{mL~j6-FX+ioeQG*8;JOhI(O;tq(9C zeowId9Kvqi1Wap_J5Vxox&tUh`^Aveky0{IH`FXR>r)8)i1r{I$6Lu@7cdcn2iuF1 z&7&a1%o@PJnRkAI>>h=XY5&A9;HLTj{@k1XvJ4H1Hl{!;D!j)Hqd|d-&2;F=S;Ach5M3&AU?p`iOiXhgOZxSt!@xp{jhg>i-dlIp)CL@ zPI&-m=l!~1?b`VrZ2K<|&Hz>Y+y9pGF(cBNUYk;3gse5V1X)T3>#iO0nU=XHVN zQvb>S@{zc`w2pVJ>%QK45%%S@@q!)g)$pV`zn-Rtk?AaIs|d1>YI4)G$rOy*daMLv zaK6doT=kE~TBpArpY1}F$<0^z3yR&uJd*}Wp3LvI*P^a-fgKT43y#~g=1eQ6Ss9cX z+&CF?;HqTHC0ko}H)m(-eZGCojAmAv=$MY&`H(Yh>06-W?UiQ>VuTbwNNvBxBAnzOsnv2LCC^<=f~A9 z4f^?onRKncB(nZ4p?zCjkWYi~ikx%wxx(zzzPrjX@FE!}!S5)msjUmN1Yk4t573LxET+a`AeX@b3hRY3Jd)fXtWY_)+xpg?g* zrL0SmnnGiL!cBSzkm0YGGyZ`^_3;PFJMsKbiT3Od-Y5?#*U))y$`+SKL}|vH(K`bB zgxvB-9FRi~53nAWmyfl~x&GRvQ^;P09nHnDNBe`2bHhp}T9h`q1m%2&h+tAL>7qX%bQL{^>PvA@$`r>L{T8K3clO)UixgkM zuFPzJk}Sln&99N~5re?JXft*Ygh^48OF(9lt!a|wQ28G{(B9DA=qKs$zhtI)Z$jrU zf}@pvk=LqM|7bFuoZ|RZ3+&;a!tKblVarOwB^8Jnh`Q*e$1>>#9F?ukjXg2-h6pXO z3sX^U1HxpgLH8W}J7OIuBEHxK7?rFF?QNw=znvZ{3|r368Hv6F;?kU2keVb|S2a11 zj$HGwHG=#85SIE7^^f&9F0|_HOn5?DIJj))idKWd^jWs_yN}|3DJbT7{>uAIH!`4T zRmpK_qR!9@ce?}igjQwUIGy+u-0{r)AL8-I6|y?R5X2V~GEFui62u$b!o3IXOf*UG(_u8D zTY~?=n5ire*G#bikYr!Nt4t!aGB~>{31N zaU@6$kIJU#k`M(?q_(2N7SWH@9v6EmfyGi zIiknS+;|vLzFAbR<-ycM( zLtTut)xNiekJCR*+w#m5Z-nwPjXtY>q$6M`80Kz(GB~}doEOVY!`2L}$PTQ?-xr^S ztN|a6;3CJSFfqTYSPp$74wx`3gA@+#aSl9rhhw1Nxl!4pOQZ?pNDkvz*;tt(YUtHd zF?wKJwnEy4q*~=q*i4&A6z!aAD8p&T?vR*O2-o^S77dik!>-(fGe2YSeNn%gpjSlg zjbvca)b!@)0gKg(oBz;x%lo>Zt30QaJptPuj9h7z%-c%5_wM(AWUyr#iDLO7u+TT6 z7Erlo8Mr<#SlLCom2w|5ioFUr{sO{g#2z%10IgTaFl^C{A*oZYH)27o3?t9}7dP6| z$Ii;)OhIB9u8SR_W_Q%Zscic%3!7G4Zl0x&TZkJ{odK|cdD`X#i5k+s_}T&dfGa9v`A6n z(Dmc)Ky<~Nv3SvC7#my!oBwqvB2HzLwYZeUNb=ZyljYQ7j8V+$k!I+Cql(}#_Ogy2 z@cdnpuD=TOr-|eh^MQ3GaMvu1r+V}Um$k!IzS{q|2)zr*tcq} zayToJv@p`_ui-kLd0DMiI z0|T79d{kmthD@?3V`GAYTr0cgvumN}Kdw2cp@M;V;OcAH<|T$Z3-XXmnINh#Ij+lH zsb|z;J$b0|w@L5f?s@#x{u9v{k$>;!$aVBX9$P82<-uL(n(lduWY0+3q^~Ze(lzdS zL@WJ-IizQrTTEOSrCR}swpV_Zs`vVH5>q=*lJl=1!5v~$QU7CUJ3kX{{Z2}5OC+6{ z!H8d@>C@u3+1kdrlAfVltHuL`gq$=K;P2qI7rB5}XuV-d<7n^8wJCzK5!Y!Vvgk*M zRu@5X|Cwds+f+^>FfHCK`J>n=Cy%ZFEx4cR$}uLWH3x6l6|a%Ar)i4<1CEJKibbpN zX9-g?SWuNZt>?$URe+SG+kKgVnAp&`I~U5nRi!%vvB3S~2UwJ37*XL((Mp_(s++dF zJsrES_je~3bf`B3h&}dO);IC@FOV5FDky&H9jpU&lG@`%n!=fP;?!N zf-9|4xZmTxBkW0vl(VPX?5Sh0JQHYRKg!DB&K+Q6Bs_CgZiOl%2`@@^$mmk8@ri=4 zw`rvI9QB&G#@L$Fo(_?aF5Hp7v}VLT<6+yu{jGDWORh7N0em}9MB&+5zn-4WyoJ232wyDa^sNAV-ef;fP-{u;`vB6!2 zlR~O*XI&zgCbPSX-azJb_-&@X0ebQ9vpOp^ee6NPe36ONB(&yohHzxx;b$7nr75qv z)FQnDLHGNEkhGgzlVf3n+ZA+-fwtIs{pPa_=-&K~Ne0N>qOMjdp7#m(ZKoCc$4QPc zH)D^pv#QasvK=&QV*k^_F$Wz1ixxps%n2?1(UoNlbK;_Z2vQhcda|`qPPu^iCGqj> zYPBDUXKDZJZ}WRE3+^Ul8W9zqynf9Da}#B=XJa7Y6079KSKmn{0k%*>UPG>VYrUxp zOSR_~S|gh*Xa2>a>w#U+BW4ogYecc?l3^!b0upBk^9@pKGtF%m%r7gG3V>owJNZbI zXaaupF6n~%CDCaJ$AHfJgesaOhwCI~i4uRt>%UsMOCodasa*?ew&K1#Y^zFXyC}+s z$~hN+^Hra{(fd+zum-o$RF$-bQjEom#yltuDME)hj zfb={Di#HbCX`pYHqWli5~E%L zt2R(PFfpMa>{<6sKWF?15sSgZc4A27ac|?(6_HHvtt$8e=OdR2EWUY*{)APJ;x(s` zXC`FJx0R`JyGZxv--psLw}8XVd#AU%F{`o$613;pmDt17PzjdI?YNdLei4@L{1e@- zSaKd**8GEWQJU;LS!$BG?q=>|i)}9Gf*b0B3TU&n0>yS?mDoP^R^;8Z&}d|WN-+%0 zkMzgAl3S~dEo2EK2{aS$OBBm#NUjPIW3?8Y^xtklu?Ls(mbRb%z9`34Oi({bXG%}w z5Mz`7t2a9;!IbH!iLDB%qcqq3V^3k2j;!+$Wh?4sr=eY?6U_ibzc~AI#^Fx&UKABw zc*`Y`U3P(I(xJ@TMkrbLB&JdEAl`h-bki!`lKhm9YXTE<_9Ci~a+$oUZcznA0riZY)auk z#Na4h`=>~~Jmtx&b6h8m>IkL5PY=Ax&LZNPz^~F9@7HbXh&!|zeShQOOdRTR_{rd& z*TmTbHiBR3j~<>R0w^itJTh-t{eZ#h%A)Q9RazqTYlbYUg!Akag6G8wl4Y7n3F-5P zs8<50-UQb!b-5*yU0))%Y_>4A@~(vv{oFPpg1=Z9FR&KBouVSk?H%k*EHey`utnhE zmGFlIB@KCavQHNX8J(|jc>_h^b(!dU7^&@DP(Ton=QpvFF#q0=Z7gOql{@|TDmZ&u z#@=XhqYRwJnLA@z(QFfeIuN8Y7m3OsSne_`fV#8OC7Nj~B=?+v9uCLslJ*Z7f-`E| z-CO&b`i~&G#Of>VEY!6;>aG8o9p&n)h^gJOXg_p!2IRMf) zztDb-q082X7||KnkCgp?RK0mT)a~~_9*qpbjD2UuzV9O0#@LCGt|@`v z6&g#CWGPVy*_T9wR!fPJElE-R&a3;rKi~K7@$k?6=r&$+y{_wA=RD8z`8nw!& zEJ!3b-d`jH1`Bp^D|Pv3c&~G7CJRG+GW6%t=}UjN$UF61EaKy;h>lC$74|UGgRR0l z5-#_vt2Ul?ZGKz+R^pG*35rM2BrC)BTkfE76)<-_0$!O_!>r)MIKF3Y*vnGsoteGE zklx+?djnJRuRa|58DlfA=!q4}+fDF#Zos7eH$KEFay;UCP*ZD}U)P&A!j_NSJU7p8 z`BCvBFQ3dm8zQFm>q$?lk(A4APnK8bj-xb84}Hv76%mQ@M<*G|;1$Im8e=)K5zd(A z&5iFTC=wfd0*+cwDK|B}vRadY9r0q|yVLw@Y0{EI;s-JZE34sg*Z$2%v?r52 zSfjn{x>>I5zaAIk+>VKIxRq)4@Dri6LFrp9ro)vXi8bJ*j1zZt=UVdqd*jy5k!c1@ z9MKLXuDJML*JbQ5^urXU&|LNQ>&6Tm5^KAdqU#Q0|9m&47!ily8{Q0~RKZ<1Q5jR< zz8iRoTxxzEG87$pcS&Cfe^oLus#}$iwf?lkDR^~TK(`C6(bYh6L)3<6gMQQl%Z%@N zd+g_vIRO$cDDoNBMaOO^k=R_gyt@6O2d^a`$msS)b8$VQ1UUNAbu~l)wT0~|cF?F* z346!<@yD-zTE`E;9XRGT_|}+1Kz(~6R(wI4(Fp?V$rdzMxzsGEjF0(n&%O~QL@M|% zNF8F@eZ_x)x$a6(le>9v8qPm>;BUfigdAEc&ZL7e;aOY^cMrtGr7QnEx=sLPyTsm@u^cFv3i%>dzS`!zgZ!Y zmzLopfAG~=qe-iO?VHh&VAZwvPT16=1JI*#+DGz_>fE?h3D7x~W9johrn$Z^CgXmkqfLe- z5E-B;v`-!AppTHV$07|)H3FKX@8-@$D)vMfRMaJCU7bm^G3NT1+?@I8kNz`vRXubz z3Zy=wkw@kGS)oN$wC7U*ZU)gG384F*h$WI^bx$oFa_T?ifjd=S047OM@KrL~t8?Fj z2v5aw&$lMb+8)5OnPc9&u(kpl(kc9Y>~~OiZekY3EuMPHJE(mp(zBg6MDGg1lQ8-_Ly+i>Nzm8V)3b1wb~`K(A6C9}T`Y zuLTMaH#K{eyl8Xi4lU;#Y;T1&)&a1WQGwRtC3Q{CC_C>t2JnQBNd~Q#GNFt&=E`?y z1%%3XT3u-8#b21PwLiM&P4Nw)a=hV(hkv9ecLGl(`rQ$sMtW$?;DI`fnCgQo+1anq zD=YvGYd!*X9@>1Sk2r}ndXgQW)r0gZrQd>~o02lPdj^6h(5vXs?^AARrj7WQX`mKu z3@aVeT=KRNsf<8Jjw8JYP3T1&AXal-mk0EF{p^Q1J!!9Zb89QjfgcMHw|@Z3o91p& zO|A~gJsR52qtb_{3lPk_{x1+47w8v7v$_IJbPvQk{^!;gUfQX1E2Uy>*Kp7GdO*+p z*uH1qOmSAOh+J-eu(_i+-fo}X$A*v6#a@HYCi>dy0i#4r?iT=>SCsR8aefP0;Rm2~ zd4Go+D&*a4V)70y@XV{m`?D!hw}E?M`9D)d{#S&Etz$WDh-*2PvtE(YRG4x3Bq$n& z5#T`pM(UJ>$DX*;@busUG_CIlxq`IrWH+RNa;kf2nN*;meJ2EZSavUuaD=R#TPzW4 z<7*$gxD@Wb=GN@e|+F9EGRNhaJMzTTI~j2TnlAchn41g(;kF& z*<=D{XBpo%yhe)*hQ6m0gk6k)GD<-FVWvr3RSG#S{H*jjvh>Rav! zWvxrNq8h}ErsA#+!VrM{eQyTQoU`?FMyQHJiX~*GsSI(FP*73!teaO2W*63S<}xb3Zka0I;C1T=WOFIO8(= zXXx)DHa|na_24u~-dM^eJ7_O1O*#EP@8zD_J_|@LN07zjKu}{%rEv&{gee zp@F4(6`4k3Q=|@RAJj&Uw2S5Oe=Q@A#k|b2HworrZF^;DU(fm3fKXzLc2_!^w0X={ z8g&jRU0T0jaim(@8F|(2l_e|F+5#zdO)wJiffVrm3hyajpGl*OFQ5y%00^UnPw>vW z`9yFLjO9_1Fx8 z$aOWl6}Tbnj`e^v;neafO9?_%Xk@0B`Tv+?uHb~jGQJw+*s5N#7Ef9LLW=JcF0>sP zP7*3Zf_{y1v~%I z#oFH185xJCmqc%Wt3KMW{0(j}o()Bn(=UcHPqEwswu17iBakV=w2Wl@mu^wxFm5P% zkC`4W!ueJdn(de+Z2LF#^4zzp)9cMc_nSVmXeA(gS)nyBAL8jb#2NPoT7mu?G7ipY z+XaV0q;JO302Y)lYZbC&ruDG}>`7A7&%Z$Kn(S(?a2WE zu`J(*)5%W535h1@QjIAhkyfRSRXeNy=BVn^pGl@EjAe2h}Y=|DNbC@9{YLx7FYmIsF-Q zKedx^ANx=BenXU$h^#2nS`ID6;DE8K`T6bhar_{6nu`S9)g?XZr4Y(BZcn_+xmzv| zt?Bn3@T|T4$UwIw`%+@SEK{N*^yEd|uUW8iL{rdfRi^ON=ZJf(sd15c>Y3D$^HJ?* z^*s6NBHtsrzZVSmfE70t_^e4N2zr4HA}P0lBJko>Pxo6jrduC78}301b~^mc%G|Tl z7fA<-S`Z2p7(0WR#y8jtykw3^L`h7?=5;n;J>`j}@tbr5BR*V4x`|v{`2X2yKVs#a?l zJM|8G1*3OKNGBDom;AbWbtTF;K*N=$KgyS;-#$HCuT1E4YLnhvlhB2gsI}%nte!FM zeR?S6gsWZ`V%ix9?8UnxMyMp*RD+jgAdDgL5_LP=W4P{+QEfgu4TIDQkk)mr9xLa% z9xcCnP179xXE9lOob>+awCpMXgxJt$`(~jn|An4Y+5uCa%CA|o`RN>YQ~BcKw^)AE zz@3}bzMAsf`jW+V#rm$9x=M4jlN5g6zH6+{8qXX*y~`-5{hCGX?FUn&>92L*O;8pPp3-mg z`ZaZ2Y7{~YW*XvKM5UJ#rXe%BLn~Kzwp~!58Hf}wljVGs%CwLvQg3XgD=c`GVUiuM zju}pxscZ%KU3If5F+nFGms3l<0P6M^gNB!$)3J(iW#ZF4K7(bhLYBB?V@%rSwO>2m z4=9jEWhQH1nHFD)sQrD?9HA7?I9&6+4abLyty$rgJ$t7Qf89n z`$8RwR57|!*tIC~2L_6;tNDeRblJFH$1r(d{n>#Kel)Ok2p5y31X}ka$T&>oB960# zTi8g=!n4*nnUJ~C{88XJ5E5-4K8Z0nq~rb(I5dsKWV&3FoMn}CJ#vn4fVoObG~G1} zOy1P!U4}Hpv;7LyRf)QQLWQS@xUnehERY|LMRRR*?=xZQTX4Tfz~?ui6Ws6eg)%54 zS zbUU0_Qh#ZnC2%H^_T{gWGVf<;Dr(#9xbcR0^6{yM!6-Z8yI}YxiT9kq2?rU`HowRK zNEg{@ODis2zCq^t)^Mf&b$@3Sa<3AEmeE~tWKprtx(drCk=ae`Pfi?ib-(EY0`l;; z>~<+q2L-lT4*G?go} zwU!p5X_*_B9)nHHgYLWAE%P5-6!_Cex-x`~cqm6zw3UsId~ArXPKGwJ`t8;(;*Y-C zvne+HaM~Vqvi-2Z8Qx3hRB_L1pF=zo3~Elf2UvwA^>NP6ii$36L;7rf=q{Ly9~+Y9G_?O7h!5(o#44;@THPE51!s4t$HG&Y4Vl9a4aS8LgyGOhtD{&htmg(^0VGb3858y?N zr>N*_Pn{y`YWrfXi1o%Nag3RYH(6bmE#~h?xelwM#79+^-|K5mJr?wnlMWY2U!|Vx ztsC&XOvlz~X~OE2CMQ2-EL*m2y#lTF`#TqY@DB-iN8E)^C`%W1*#0%-g?{|~$D#Sa zv|RrdG;w^Clba>12xi*$C*Dqs;ga7g=^49?XB1R4EI1gx2?~laI(?x!%cNU^otbQ* zN*Yq88O-!`z@(cdb9m>pOueTO^4sHLO@xG8s>=f6I0ozg=y0SIk% z-PQs{)J0Lug&GOTCbQ9zPUFN(^8Spgy%AN;DhbSZ?furVT%Cz{f#scZDGzd%zYx~S z)U?^AAH=rfes!s8*Ba{)+1B+49!4=-g053W!Uf%}VQB|qcXgJ;{N#DQ*F8>VE{0oK z+e8BK-B_X8fp!|B$0zS=@47S&w*(ku(+p0gaVz(%sVScH!Ox{9^XY~*NzTu?)AbH?%cS%*0O710FRwvitwp&Jv%o&*d5;uQ`DRhLCm}5 z47KgMmwydbke^+{l%mm-8;xlvLW?Y8HFyN&-VbF}7!R0?6ls0=t@M_og4Og;+Nbmu zk8#_0dXd_HB;Xx?8{1b8}C^QeEX_OcAR> z(J$R}H(FCl&pnM+-1@jNCMzKa%i@?>=RZ(h78rgIXV^7l%NiuP+A&Vl_JZko8ijF( z#f-mwn)s5`?=1W)jT7R$71_fy!;;-~(}IImp7TwS$CjfoF~sEu;32PUhMeci@x_%Y z+D;+)Xy&cN%7iOuvaStXFs`fWQmTW^?9GNjI>omU`27<^p&Ar@b9;)keu`!o^^c#D zk_$GEK6sRzb{AhemmGeyOw2m&x+|Ls)Be;7GlpHEBIK`E^59qN|VWEU472 zIi+dtR?NfA1K-C?IL6rjV(49gkoQ>LGp6ibOA@rP4i#)6sGCV--0!~MGc=WI! zCsZ8OS*U`J?;*#n*RNIGuBqQ?_AYa-55GcvY=y>iyQoB*j6C%Uss-cP%siN;+1DUW z6U{71A6DBtbY0l4hL9YKVn|FpR_l9N(KBPfgO=~?l{;$vydPkM^7~DPr?<@R#F$7i zOR5r?!qt}xemD!7t_e-gbksKU4HdAq?C1RWs9m;<@sk-!35(o76tjiBSScl`KJ${y zMW_K!m1?*XtZqedW|W~atq+%pU&qYT2w?Hr2NshIxkI<8S-FMB3}5J5k=Fw)+!@y6 z$v0kWQqrsGVz@>{e&SWHZ-ysE2$64959WIj$Bf^747?4M_i1N(`Z{yT4QcxtbF?D< zI9Z8^%jaIUFbrCM#J01ogThnNH}z4%Sfw$JHySa!jtdMKm15Ko7)WA5I6KPpjj4S* z^%DJquMW}stwr|IDhld;km{01?WC1X>DJzPZLAfL^2>iod;Cd(n00{qtpep>hbuxQ z=e)zFglDGaKl1DxG-h|r=nU8k-17eNL5kzx39B12c}3Zm6ny1q8#uwrixxSh>Fc~QL;q#B(608UQVbAJ` zEx98OQW9NFaqo^VM~V$}b6i2Za8@iX!2hH@B6?o%hLKH5>oXO5d~xdwG-dqiL!;_? zwverGn(t&1h#!u&l!<5+QCru}HgWZ&S)k2-KmF~|$d=x?_>yGA?{PWTi?w-B@`vBxz-v<){p&^&nK8mzjOe%b#~E-Wu}b9|{E*?@O*!RjMJ^ZEUpUxN{X?O8vFLxkJ8Auh&cV3xkLgu?Z3<5rhCStvS1ykS8t9^kd#G7lMK|_Zt4b8<#S$hFfkz=z=3%z< z0s@J7VCD#4SGiKA5<&Q(;rU7g$u+!YEQ!$CztCp9x@hQO+$A{TahZDbfa%W0tc81G z6t1knioRF{qdoOQvs#s#&f#5nQP7m?$kdaVf}0>-326`b-r>QIPfGAFGW6B6g{kRar<_tX6i;6 z`_6w{0L%8s^}t3Z_7RC^gaVPaCxt;wKILdeZ!(cek{(li$dE1VKz~QH%X9uA(^(Gd zqBZ8X<6j%EN%@p%lXT<4`O8>lHQ9n^n|H5ws%-P6WSJEq-=kEy7TJZB^`3yfbY#s zWw-q=dm@-nEcjv7;3xFB7&LL){U9Iv)6HlJ!$U{n@|#7@DD&dtEVgO9{-pEtZ)@yk zhf9zJ$1*Xq%Qtj)g=R1o3O+C>>AL-H+Sjls+9ws7c{yxCyE(rxhldy`iGPgDtxW$GZ3DCSwp9ZMI#WVQrT8v;6$=D*>|*t@F-d*$qWKx@k+;x_$scx2w1v0nAFXeY zeaIcT;x0PMNB*>QxsLF9XZ)4#Hn+(m!ADdavXa}MG+ae*UhCMy(JgcAsBTuF;GqZI zZxV0eS%^;`pGM>9Wif9EVF53=M(KG9i?L3xjYK7X3&_NDycMkqz#6#LrPa=^Uc>6U zxeQbCQl@L_9KeUVRjtefF2Ounu=u8Ta-bRvStDd}65L#oL`)BiD=w-7I+ApU&M`A-UG z5)RTYC6#Sr*KzpXr~;dV6lr2^y~bJPER5Ug357FR!|!Fbr$@T?`L(5Km94<%?b~-- zk%dN>Cpxcs@vN0E8g8HXSS3qzUC9}=;!nimPv!to_)m|VcxUk83J3rbXWiva>JMS- zhS;$41~gxd1Z!LvLPfb)E2Gf-3xX~K>c#=Y{pIv^L9qK+T@R%N8S%Kjx&CdwC~c9j zN&1%3sp7jKo@gj+o0&OQ=JSvsmW;)&I*J&R4Sqbh>dU~Ajv0I-7_8Ulg)R=+m79~^ z-qHRpa6TS6$lE6E3^=}_mAptCS=P|#LLcSa2N};Kt+TTrWsPT z9>z#R6Fa$8y@uGVImC*M<6;mP8^RYE9PErATd8Sg=^@(H=Ci5cNiszy{=(J^Pm}tC zW<14k9MxUjZ3mWx=6a_Uu4`Uwlst>p7VmO+pY`G+59Bz9ti`;Sm}q0oAjzt~E+I^i zId%M@EB~^WTMNENfecXu- z&8dq#c%Dd$cf>KW15MKTGEFYE>zF4_*Pe+;C7_EAg`AsPFY{ta=sLXh7I*dJPgqLg z5_w=$q-%F~PsT*zYrAgR;EdjnnoebEUw2YAgH@pf#gZAQj>_77@PrGRqZQm~8w#&#WX1iS*3qTsP1!uS6@zmQ*5qb$ z4HK-3Z)d0wt3S2y8Cr7<;hQl1sX}4H-;`T8o!sdjIO8ct7)s!xk80`(Jlb+ZH^v~s zfUv*r7=$$Ra0zD6U2{$j;#A66PkCOfB=HPvoCKS?+@YM~p2h5)ufJg3TCyuH?9gJ( z$y%rvT?wpTzLF2sStc76h;`=CJgs$kvb;Mlu0mfl!-}@tm2zm)e$!E#AH$_>9I_Nt znXp|cogs^}OMTq0B4*Go5$-fNhMh|_7Nz8AxsflRgu4%(OCUE# zyVeyhRu`a&`LHl9Uhy)FoTBp=(T@kC48rJlRKESqB+Er1lf?h_dw2ZPe1a5qSm=Hl znvTTIv5CfReZUOs?#B${SqNS6G}4nz+S8hb_fkwl$RhS_MRQo2kEQi&{=AjWy^hy| z2>TylG>MPMJ_v|VVd$E5n!JYyR#&G^uKiKwZ^}=?xc%YWQgS5jr7^=Wlr?sg!zvly zfmO1>*-g9L@YAua7$^2dwqe!FBCKa9kbX4N2E?S_Xy3Q4;R;G_%_rZXmcq)2^a2nird%zxNlOhr~=^0E6{O`gNS z>WC>PVBG4=NHOCJF+6)rP8^GC_q7l$X+g;Tepn5D z5lE#AAk`y2uk`iKE~T$8J)eN96OZACe;>_Hk~)gV*@=c_v^3igs;3}$c3!0I#uG%l z@Jj_sQo6c?>fjY!wRl$dve%CiliVY2A!XZ@G^7Cf5RvMD<1->uW7tY3j4ETe*b+k& ze5KA`w30EBfWSH^?lD||66rFXXD_SJBpK2lq{sw6_4KYDJA&LtLI;rh=$y8Z%!8$| z2|PxS`q)g5S53G;*EC< zMc=>u(n;gpT^c`)5x*bF77;vOn%{3T4$SC4IiC& zUn*u#75yB6Uh!$L=FFA7Lx^B^w%>=H^%=GO+u6NTKPs6U+=n0yzfR61d5jwLSJ~fP z>D}XA4&~-ixSga2y=Bw%0>oYpq*10`##7(!v(OaeQ*@I9n!J2J`+;ULHznka8z~@aS09V;r5!ki}dba2hXQ?zHJGK zt6v8nT_ps}s65(G(b`)sR*{rSGdL9Zbl4;Jr00PoWFVR+i0c1(pu!*om$_!dH)Qto z#{2#c8X+`1IUG$i)Rle&c#(|k{t<%_1(?fJ0n-fCPR263g?$FZQx$AKZ|AF?zRDi5847M5??t*`WF(8S-)nV5 zC0LN6_OcH#P54WVLWn8w ztpbv4c>mLeT`)(|59u*WZ@p&Ni+3l>TDxp(r|2gpP>=+g-sJu!>Rx+}*S4;1#HS}R z9{$4ePfuj~!mzf6sAUiVkF@PQDT$=m8W=#au-N&e?mKu_jiH*4x%*s?H=1Otm3%RD5sF>}a(DB*tx(bb+#!;n2@AQ2kUxyEP z$#%iiTR&t-s6@ul+|YgCR1F*U9oG6b-t{L#%H&=$x$y6fc0zXa)01L@#ldrQ(gVgR z7rV8P@exaE;Z6vCTaQ4JgO^ku)>flYv0NFFc;k+6+reD<1JLig@t4Gts=1OEunfKZ zW(!unL&3F6)jJt{{S}nAZI_b#(PWyu<7!iUe|oJX+*TG!U*$kKoV>&CDbXP zYASpHjFAz7!2$?c5qghFrWUaqlTrhGuD%uj((Km%ebUCOS&Fk1_vIafY<{q-oqk*M z`R~>xz!y1}+Q)*vdRGus@a(cn)~r~Y<=%mD&!^YCktw!_k8vS*R7|6JQvwGhToAuX z@rTYjJl@gzar;dY$)u@y;B_b>cEPPzsqsh-wL}Ipi~HVbY@eLdxKmC|!6rUa^YD|@ zBk>eNpSgpdtKA%fXK5OMf8wE}+4ydf`at86)rs~GHythPbCS;+6kgQ z421H{piyQSy@hCfTcGv3ug>TgE~5%Oi6-ohw19Ru6F~Cz-9OK6=${eolCEj$Tu}|& zX+@lNq{k3It^qnfuU1)cg`j6Y3JuOX*LV3fw}nOwbvbA*pady2ekgGRu{(OY5j>VR zg;=9mw!_5IEg~geflhs%PQR1`60SnXE8Z>!xlN%E%kJaJ(GSwe99sdnpegw#AY{EV zX7!G%3Der4HDNAe3pYslj6Jt$)Up31_%of!sYZ-xBY-vPUwCXAqQ$XD4w)Bv>x?mo zQ2Wb$wzL~Vzra`BS@;y6ZuojP=d0DP7h~p-@nhf1nzw+mG)flm0~<#~_NLUuh8Q1!+dp+WfTR@B`!y=9lr;W#N8#b(1W$P}+NW{t zK)msj#%K0$P4pb~%4u`NQ8*r)-A#7{DL#=ORwUz z>^<=tC+OL*riNIutC^~SVqCh9oS9Ky^Y@BIg2fV_qQ-4>7m@?-F1+r=&fg@?dkq(O zsJ}|zyO2PxEzbUQt3~J~49FWkeYbUCe$72F5?#wVozwnNot0BG>F3}RYDT9wP7GxW^KEjE!@yDbcyKgqi)D`WV3i#YdHTST8#TT)PeXFdo;= zAjl*}2Tt93VPFbe97004g>IGZx5giD@~!Ov?Rd(VE5*1MEY_67%>rKOLpp7i^oIYIO+JSd660g|9*=Q-Knd0HyJhJuMyjc59txocvcR(UIQ-Du8 z-BzG>hUfTUp5PCtDSg9iU%1v1?sd=9iO-2sD!fOzRe&CXZ4uQ=_ZO<>Zt+SNmK<0!@exUT?WvRXCfPN>875)73{%v*-wn!4Z zwYB0aoCL&`ZuJyTB>KH6tf#%}!!|aQ)W-9>kAJ@e*JSll6SPtrcxh)5v#TMXaj!n7 zSr>+^qly^7Jmz>ZyBhAf_2?VeB;EXfHdmd}x*DTC>YPwJwY>!@OsE!o@}&wjLbsOT z6JXvhEYj+`#{<8rqBlfzNz4y&tAVfExc@hdShg>Up14IUNk&=@19^|*{%%>g<4jO- z%z}Of)7g?oSpH^B>RU-V< zq7c6$gK6-W${=T+fiVsgVd~QuhqkZ~yeZ^o_u(r+Q;Z@C`&kk8Gqw_oO&fvmC{A$)Uw#f1tV47=oGDL(X=t{d5q4+WF0n?iNL>{qv2_!0k44}N_<2v9 z0Y|P{iZ3+76C|d=K_v5t;6rr*6wHjtgeR%(*k_lH8}fNk&CR@rryNbphBujf;L7_$ z{*BX~Tei!jK2EjC45SqIDZY>!(&<%1F>YiBp;1Zpd+<63rmy~iL6Nr{R20!b-H^?MLOU#-wpp}GO=P_i-Z za2cKNv$XvV%LY$ik@fE?kaZ(aeIfysNeH2df(&^XzN`Gk_615^se_*_1>>e^40+wa zr6Hbc=!s7^gDP=2)w$CVm!CRzppMT;yN@`?M|SEOP>5@90BuI2;;DW@b(`NI&g?wumxlQyR$ScM2ZlRztF zB`MK|BSqSKBRFq5ehB8cT_^T6Ks(GE5c6*HbvN&SB z@0*?6SB2~sKP20RStJikCjJ(Su;bF@sj6fiN=ySOr~pEV_j9p#a_61$S)jG8!$NBy z@6>h(EBeYk%VHp?i{~nu?dm^gpZ&tvMB%^d?XK?(Zj!Ly0NgokkYBavp)VIPi6jjP z5=VhXc1PkBs8#1_3Bnwad}uhN;10^9TxIs}R~JH216BdMbt7n(0jTer%f1{AutBkzLh09fVKc3-=D6^OE(y2No0gr??$l-|k2hst35@ zO9Q9G`KUYEZf;A^n7sHRP2we-DN4xA4 zE=4@94?K!EOpbflETM;rb#zG7kD;__d^ra`Tt^Q^Z@OdA`TxBA*kzhej{kiFT@;=; z1NT!S#TO`!2@?5C>}k(X{n=6f2KK0-`vubek{F-Gq}nv6#v=183GG$9=(qdu}JY9;7iF|hWo0md` z)cFF$Y;bL?rRobDPFMz)F*UZO8L#wQD)#%pnN)y{ z3#)NQ;xo)%w~f0IYEU8q*@JpcqUTAf|Ha8RrT`|!LzX% zZ|rX+C435q<7U``Yx2W{EQ#~!gP*`QIHOXH319Fqra6F6LQh;;D)$iW;`#(+%;iBW zB|QJ-pWojf6Y0Y69W|)mAWSM)vV)=$uLoz2<++eB5@>Z%i3ZLE=&>tO}N0qo>6C$NY|=G&N_#*f~-{OhxmCtP3)NM=WTg$aTxO<9J?BwS=7 z@m>{T2Dtnf$Xh$e`1voZknhz|KIGUtD)OGWm!UC779K*JBq1JoIQYJU=`a<*`nJRT z+Ija!jg~(sT?4ikV-6Y-1?f{oBh{7m#hLa<&u1lijqe~;;I4XR`$8w&c?4myf3Y|N z`?vW1JR(Cl5ghS-<;^h6A@QxUz3q7k?B2czKjiWS5)pLu$QVv&!vq+j<=fy|nhjkdF8;82fnS2&zq05Cj`?!t|+?M4!Of}^E zM`Yz@#HDgt!D#J`&+R+axB4p%ifZ@rxfY%#+PNGqACx>&F}3*WeSa3Cj?U0t^8?`8 z6q;scA#y#pxKzGvyR#{~16FeSDR$}ly@7?u)%gZkn)@Dz(`fZ&Sxkl~{Sc>jGg*n^ z;e*F`z&%VV;-CH}@54w@;f-WiroEp0mS7TCcvm)FM}CCN3EC-k7;0z_th}IC`t$p$ zKRDm{tUUe`@#w63#{fR_)c(%>I77&!j==jpL(iUciDOuWLXx3itq`j-jbEG3EhcMD z4kPoUV!4t+t>-1?Q<_{ypSp6b8o9X+1S=&7j=^rnU4a_>;2FXsqJ5XU!^ zs4j;>SpJd}qY=1J#y;KgTcej@wjMCB&&r!=Q?be<5{lD6X>Ay4hNtzy6Ps`+^qY`J zFME8Q@$I~f$@szcVH>t3q$zk$Inzcku#5Zohz^bmAMIP;FLq(w zuyd;i(vOrgYSpX%N7R!LgcJ#EK&>sa@aq3A#l7S8>(yJ(>r}1E=)PG!nl}CVF z{nESlY$~h!{)t}7b@Dg@rIFLuJ&U^!j@Cf1DuhvJ)2H7MSa8vKuUwO4eJ_(4IaVPL zFZ?2$SD^0F8DqL*q=MJwKK?MSkFbqfyQXW9-lU(Ou;@&iwBUT(m<(e$ls!e{?)b_O zo1Np019mQBuAtKa-fT}~`Wd=Zo?D%#x2xn;t4r>5g}h~-UTmMowT>T;0F^jngEdrO zco|os{~FtU!&*@GzU8i{`hn@6)LV1@Dk#=p!ojByrR;rL#r(?h3NaQc{ibK}r&}DR zAZ(t=uC6zHDXPPOq(rWqc4eQHD%hp%9O_ae47Q(>*X9bh9pylM53Am_kN64ji*!2u z@^@ZsA(2rIfTRWY1E@~I{euCJ0yw8}NOJnYU=Jx0O_A7(<>crMdwC3FTP6e?^=zz1No~w&wpd*oY`?DYTKGyp z%BD6)M_DkI5qC0K5kps^>k4ZBsZ~BuqQo6 zxGBktIJa*5D4mP3!KptnktdLf@~XU(-|YkIJxLETef}#FjHzY9rrn4(Gy%kif|3a} zb&H~RWL0BF3`)t4G{BbRqKKBM;KeWp5s&LHD*zcaR)&;qkt#FBb?`owDYsrC(mn>q zChMPN$r(~T+B`p3VLD#Q;krCa@h%K0=UZB^5Wk#+dej9>vx}a&4Lz>MQ7zHFsi*TH zY;C)0n&Z$QJ?tlFT~Viw>*@TPr-jCFjhqYAe~-jryHi4hV7b632S&rLDdm{HCSc2E zExQ-<(j3RQ>b;r@>@LzE?yn5G7X;D-*qVg1htP_YaJDxkwn)d(WLBi$JOpNC>9@+ zWq31{lpqwil!sQrPx|1k=#h?)^_5ZOf3l!~tUccL%U|@u)-GJ@A^ZmZdtGP};%>In zbFGhg$K#aWDsxhkvs*DUA!hu^IMA^d9Zm^%EoQM1d9b*xu=T3~xUN50QEBR>bxoo< z$=&#*H#4s9u1|ggzg_Xf6wJh@R}b#q=O=NXEU9M2DKVe7bIIny|2 zd)7!-EVPC=ytRz}ro%!kC~}xDOuO?0`_%{COyr34bG?sE2G51wa8RkgC90a57$Xyg z6(e@5Pvs_t%gjie&?TmXnw%Ft7bh{JT@>q}yI4Cjk8vEU!Gtg0#!GckKZMLmtu^iP z*SI1H#?DCN6ISFpE-|GJN69X}O4nVJoI@NPWI~PjSkD|U&f(}EbF{Z7v3trAMO$x) zA!9iM{45eLGr}th|B;y?Ot>RfH;+c~_F7@WK*-=tj zUOTS}$m34@_z9`kj>#hfb(RdVH}!cb1EsJ#pS}0WS!^yq#~_ugO#LVOe|G2=>KcYY zuFZ|Pn|04Jvv7S^o8HBR<8>A{QChAdZ|dlNOc4rv)ONZzmL6GsU(2M@>zXo~#%z<7 ztYc3CJkeNyW<#JDoOhM{f7LA}9rN`SzwxN>C!&vI9q*`k(ePWXF@xJL$;;Rdd?MF` zVRqIj8Is!XWWu~?qNYSawi)s0jhFzo9&uh%vvyvb;Q%Tn2>Z8XjG#%80Mjxz*wm#E zpWGt!X&;(N^qZ2K`fJi4yZ?168qoIadx4k}WD!zI)Z|o%r_eje!6y zvQ&vTtn|{ewG*rPz|Czdi6H2M-$O+|*96^VrxAmG^?kY)sCwK?3TDt#;i2Kbg)mes z^cGjn{XU%i4QMm;N*Co$+$b*py(^+y8Nn%9x~xq}{`zd3SfT`3@CNgLfCiuI`~?f`HO zG#I_H^FvMfFH+p0*aZkaG2HolbAW98x-mKDiHy(w|NB#-;%m_86{EPruz?14kAs0# z@1L_s?(Inv^f#CWOoo-#;3A+R)@lQJbJ#UQ1k0Y&h%FNN7j(m0sZzs}Mz;IO9|d_} z)r-m%IbQ02Ks0192RW1d)9a>sD%*v<>wkY)={u3}KagP{y&YgWz|H_8IZk@<`0^hm zzRI|4`A9@9msk&3nks-G&=>x3;pWaEJiHm`tO$hUnExO41jsCOlK?kT@-PM5=!QOR z1`Cy$b4L_S!kmEY@y2_U{j)W8ZKxKk>jzC5p8WsTO!pdksPKS1R@ANIi!~>}f&$|E zc}|O>0BH6w;GWQUqc?iouem%g2f+`N3auFbxd@f_y>Vo2Fwqz#~|~lcTaJ+h3~ulm;T#NkxIh4>-&h)Fn5wQ$`_dq+d%SB|G|={ z5$Flu`~GQr=>aB<_vvAeo`;Ky0JcfkzI5-uFAFUn;tbStCd7Up0A?^A;61{wf>pR} zcgHll-3g#h3Mv8w;>2EZbu*>y*4o}s8e_Zz%HMn=15&OyHro<#h9u`@#A88eqDoMhRWScCbqj$!Kiq*vBgZ zZ3UkRmg{(geuDSaGW~y%CegzA(|9G|jvo(WMK!_tCh1IE5hsZnYH|v@$F9l195T`1 zAQ*FyP7e;s(A8}eSf>0>q#9!>8KAr}+X6TcPBhH2z`|lPaLU2M6aWi@oJnU9jGP6D zZ_q;+Lt3L1ppc!#l1Bb#*%naHK+lJE1<)1%NC)qZA)`C99%jzS*kSnl2W%XJNcBL5 zJNW9=`IA?X&jU>CQ9f`;LjFJU-aDM?|NkE^sSYLQ*eh|&kUc6{$FT`zXOGO1l9W9= z_DnWeAtj-Z3LzQE%4ngeM4=LezW2w`cz-^h@8|dX=l9?5x?WdT*Q@7wj>ot^?&Eg5 z-9cz{XOJm^R{i;}^kB#p)r%H}vhX&L#LYT!yX?ZFnPxu<;$hfi7zv`eY-j-RUD|Ut z&nkptx5FlXNQIORb}K`J0|kQB-+^sS{+DMKAZ9QPR(W5P*`@$GK@1O*vbv68NL79g`6el$O99ovh7Wy(7bldxhEa}H3Z&Hss-1hq_sluH zrn9#`oD~aY|KC#=(oc`{Ypx4A=qJ)ULIza$p53kd_muM?_XB>i3GtWQhHp*>gwrF? zo!O;!N4S&rE7`&e-c9oOy8-~iYHS$WrR$zuM%f?LU2d>QzNTEa`qN({jtyzSDw7y5 zs93Oc4eIQrLX>FrM(7FR31BU2?W2VAJ}iNs$;SW6a_Yar12!ZZ6JEvD^LUe$2n8P( zHuAL}Ppfv*u>^*{AF&yy$&GCfHA+Fj=&q>DeRW-g_}k3A5Hl8?wj{e!8?3Q3iF6(4iR6q zCWu%o7WGB{vj&&YJ6=y#X)vdZR)!~hCl3JLH=UE58`zjOR&)`gH;!}=?(vFjMGHRV z0vvB6XG-MSMcHDO*dCJA{$B3y6{|kh=6|i00Vld5Z98jRK{i$R#P?T#0n9avBZKBP zZsLzdV(@ZR*OO&B%)`%ot&<=1+3Nq8Tks-u(WgF9f4>bUC`ta5ijI`hNB=Pzz334? zx>avK3R7kY6ys*1ecdPcyNra2Xk6&unOeoq;wiW{9znFgbFBS&$=<_V>CeW%K`brHGtSgTFV6)W@BRBOhD+$X z3U(>e(uW+vkjL)4ZurUnc-1;Ow9ib_*zPEi_n}14v`yN7?2^Z57wucgcMQfjqMfWm zdOY`g?UP657C%h2^v8=I2{=LA-yNX+_UwgAy z#NdyPaQKYa9q&klu-@5CUvZ_V9yHc_LbvXav~q*~F5G9J7uVH$H=wn|@%7ae)}I~T z&44{|zrVJ0Ov-#Ajl(o+4_R3`j<0|_LyQQ5uS_-1Wm0IfW&(j+uP;c4D@^#=!?hH{~hf?Pk-^QjSU&G!-I)RH*T~bTec0`lkR0ywb z|M&gg@hM6apLUp(1I-nVcc$*02F$D+v;vUS%aWC`@n48=1%B1sDiS*+_P_G` ztdJtq3g8CEC-R>UNkQMWfdaK1XP^v|MQ$^o;bzazeH+9F2l7?6kej+dS%-c79wc-} zg5&_axTH#qb9sqsMc}U5WF0oYZXt69Dv24kZumD`o!_Balny;8WB= z=+*cG>&tI?^yFST0-`1(1H~(CX5D`qacfZ!{%va!MxmBvWR6t8WS-L^!=EN>xe(%Cr zCWV!tD0=((e6#I)NkugH!&qrzflGZ6Kb;kR#tecn%6ug9`vX^( zWi}HC>g2h;YJMp2Aw%*(Nk+*CgqQ0I51j?9^ z+S0YH*Hn``HHSJNZd*}$Y#tBkA{~PU-GA$d$fZP4^n~1(Z14xUaw|ZJM_S4yciZ$x zz|h6H;^#g?9aa+hg%nPGf#B!4^u2LTiTzdj!eQ z0FKaVcK5@(ysd|_r859p|L4p#yFFmGnjp@7-(|KJ zfv79?cNLpys1atf&pfI6qOm|TeDe$xczexBhLqvaNl?`aDyRha{`JyOrOgAuyFMx> zVrsE(u6IM6eo`*Jp!R91&X?FwG@k+2urCm5#y@@8515>n9{^qt6`+mh?5XK!FXzcs|3Sq+ zyZz^zWl7K{2{Z#_k`%0wZX=^6iJfgNN!`rQL5cZitq{Hai=W+6y(6kuwX%q@Rqran z4x`>@y->?!HfF?48x0YO_?aU|8Dk{&6#J`_eZ)7Ho1x>^@!sPG#ER6DrOtmNLSn`y z<1dz(+(Ady#90>XC9KVVf;QTm!Xu6|xC=@fa%Q6ew zd*o`G{Du#aCNKK(Kiu#s{a}Ww{Q1e*tNHV%x9@yM2o zsbtgky(wai^Py{Uej}D%3ElVJM{|)KW?jWU;73@%x!7e`JSjwGir9!+dTS&3qDiat zeeg=@OYK#jBVK%m1um_~CIlRLoU< z4bwO#BHmBxKgkn1zQaMqLigu45nRVbvNxL6tNWhw-(+G!Huc5WW=;S)4c?*Un$O%A z_n`wnMIV|a9{=SHG=ySqvY&P7xac>de?Plv{64fL=3%H+QCBhhX^dy81x&kOoc?W+ z^1%%k8xl1iE)xFO5um@qIjWXCZ*j{}>xdmqXPd^oh$^nQAL&kc$P*+dluGt&`ul{} zm{Yrq#V3)9od8uOltETxi_CVvpMCkZWBe(m)dFQ0pRQ`}{yWPIq)qSS4otLhcgnaw z)1|Y9#GF$|u2I8Da9Pt%N?*8zaU{C}{P?upc&q>L*V}l+!ExZ7Fb23G?*xEOu1&HY zEfRpY+n4;|LM-O(hA-RYchI}=&salZ@RaOP@t#By^TnxcwE8Cjk1@(a1w*~`R9gA- zMqKdfZp5}f1`3be7II10lwa*G)(*~Zct6N-Vczs5eUgHyF4`{ghS-#Du%xa{dR+U@ zR5YiMLPf?KK#ODrY`!CO>8pUobh0OuJE}@^=hGtQw@Xd_nfck7feg zw|ybn|0S&T3{QW8i)rxd{NuBeWJ3@EiCS#QXW<>d7l*OdeVi)N6|iR5;*uUy<4V&v z9DPWr{^}Ifbe}6m-~FLlv>_j8*@J;T>U3puv%@DaAW<3LHNj zI%`N4JuWnTnH+`U3fnOa$6Pzbog?lKgg z#W$wf?nydG-uzy?9nnpYH%k`eOL#x&4riMtoi${xy2{0@7(`KkG+|NkN-h6)qM^Ju z=EA>$O=?0Q3EoD4y=3w>fPjx2YJAAyH#F78g@RZXpO36~14cADrUVawAEmtpxLtXR z;rG8m5;3?5aEzBhJ+l%r>l#f$8HxXWcq+qLHn~7HTlAad`<1_EC?2bWzRQ8?NZ3*| zn)XXr6jbMkf4^#4E#LqFJb~{fbgul;8?-)vgq=!M!nVnt4g|th_>b-*XBEK_ei)bu zhsgnV`u#Rk{GN>qkx1rK7e1kz)j8V^7(sOvKhmMcBQ#1rA=Kyt8R{z6<82N7SSbu6aU|&1Pn$4h!8?&8La?K70YoIbtHGts1hz?E_Jx_U5&&3FL*}5S0(Hqn z9=j9qE5HWWv@hQE`7Z#!2mb}&m&n?@eg!#@UuQ=LO72Vz#4G-ALF6FwT@f=1bRg-76GlnGj;>#z7NNR(`G~z-igPcti+C?3rYcnD3i)lH+%7GW z#2|{v2H8g+)53Pj~C!;f-y$|9oP*5QUTWKP=yf-`Dqc5hJJ#u13$Xfc`5; zYU$_*fZLpqqTx{ho5UIg0>ttQl3v;gJ8l&~&XMogDJspYj~@ppsVrmi{a;`5ex?66 zRG;5pOk6MOc@J^qe(r(|IN#DQ91*#$JxD|JiPA6sFNtXphY1LK-z}zmK2la3{03NtTIC#zaJ{xZi+oyw1 zU(E`;fJ-7a-i#q}v~eI&)MHOKTi-aa>jg~Yu({n3!i#|f^@t$XzMK=7qazdSq?|!T z)-yA{*xLUU;TNdUntcA$9H2KP^)jWaJkoiVPlB+o$)NYgXZs3i-_XZye{RWhiFukw zJy!f^iEdTjoyREx?18!I+x^{vb65SnZm`w6Pa^Qy?N=AvQEuAt>p9VMpv&CjToTgA z^P0h*R{^7|xywjBN_ivC#m@|;T2L63HEMR8TN=8#ryL?O+2Z)N88G&4M@N87-~?K^ z&dlFNXL&xpe(>N*%@X*Bp3Lzg;EK}4sicEAMFrN5Fj6J%WY}A99)y);EiNwGOT@Cs z150HN&n!X0^7JGO)*+r$4KQj%$IN%~+z0&+F?1(6;whNrU!(Udhz0RV>%MpE_{ZAt zIi0uu2RLx+D1dQYz8e&~i_E}W9}ja0J_dq`6#*ocrAtY-AMLlKF8El8=WegN$?m7g z%G+Z3YbsvGt=E#!neZK5Z~Ek^-aRE;2Mw5gsu@obA-}_JXoZh zZ<~+k?SVKuJKT&vi1r69ei2A=`>wrK@?zD639Gv~uzw9@0d+_#A8Btvk%EgRL{E0K zRa7?WE7$1}+HVl;j<`@J(GQd8sx+S%NeAC2%@|NRqQ2aB=)d8|mXK#o+CkXK9qe+Y zN+8C)epgZ$7jMf1S@Vv^n0Wgp&ak5v@j&lU{)YC=KESbyybAg`C&%st8Wa879VT@7 znM2OBq`0sZB)yYb_ohjTnCJNs?yG!?Tl1MsP=Mb7-0oT1J`N8?Dv4YL0N=M3Uy6$m zWS+(DjlCSXi5M*IO!|lM!wcGlj2~}A{W$x?3N$eJwh{uA+lHaI2RJIMH%UI)`;?3L zzS`bFKftEVw*7L!@c+=5e~P`>&1x@sR7X#bmm>1i7209nzNW6NlxLmdYIFi+BS9a( zO;l0khp2-^m3;)`bJCG;rMSEpz%Cwp-NlFB_OWyIM&XB@7M~q_tk=Kyl^Xta4NyQ=wTIx zzc|SS^T9s$100XHT`vLJ<_gUxT26nRJ}M%65?w1ki4Sl6fi333{e(5BrLp#&juWJR zqa8PH#M}CQ`}1nn9W58{PrMb9l;kAtFw`mk$nEkW1+%AR^DA*pMm^HhRM%yJVgtM) zkO9QAs7a;NfScr@W_V$meweiN^W$gCH**H%+3-=Npp@Mr9!~OyO;_`MBkd`@G65iX05_Sfab-&JuTlGhPzp@n# zIKIn*7#zJ`pdi7T3aZXba+imF)wqHvM7&3j5*fBGw6QNE3Hwh0c6qz}qDsfov`F}cZhkzc+9}N>&}z2KBkGEg zXb(3l!PP@U<7`GY5;nIho695&C*gr;949EnMzFm|j~`TI*!^ydNL?gxpG}4IBY7x8 z->8sqbA|7>T^Azk+}znk=|5Tv#GK*ivjwLz*vhIK4>c*V${UKWMl(|oKVeH&*V4ng0Alz5i4Od;h+nRUULQD^cIte{#bOLXkjLmwO{V zarfpUS4Ny8Mr_4s;v(c*Vlb>fo6I>f^ z>|{Mdmhx(!*`btjXe^vCx~5EYuDhtI_CL^m#0p!}By1S{>qoL|5hj9`ga@;CsHr6= zW#2gJXSf&1;>EEwWrWy!KE%CRrn~`3FyBrecSO+Hmw_6{&&X1+FZS{_9BPSW+}5Ma z+b;is`gO%nS#R6FhtEE8o|w3m#~!0nP|}PMB`|G{#HtnzoCn)e9U)8j^Bjm7KKiN99QV=ele!B;|qpUDA;w-r;%lGUQG))8lx&YDNI~3=*ipw6GTqM-=I0lhE-2*Hyp?%m z%>=WLNW(}KrCi?`M4UA@qjQ}w7tyww*n;;V$%V7`sxffUxs>4~))OLRhjv9BG!P7n zkokTS`^bms{w&Su&@D-k`L^6oe51H<+*b^u+>0u!dehuN(yFOyM4hX_gbYHRt-hv9 zYG(UH5-Kn(dcd8JOD*dY&TaFe#L)K};vNu>S(e)$Fh$I_Y6=rI{zgT252@DG}apyA82}hkEZ=XhM}n zJcAlY?0hU6)NE!ot1B-o(raj8zqBI%J;f*Hl%p8_`+v8Puu{L^(MrwFrz9i&cKq0M zmWgfi(nXv(p{_nU<%&W@X#8H41Qsm?PA(gH&7(cXADG==W1dvBmORC<#liGT3R?S0 zS{*a{(b|Xd?^_kNYY;Cr1Femb!_`opS1qCR=)6mqJ*)E9DCZOttp*ok_9O+o84*`F zMmkLw$Jg1O_rC-!;2-V>AWbOGKDUd%@qN@;40pM8Evem&^Q=1Vm%HhxeLt!jq3KxS zR&1wWv&IyOV*3`e5^EyYp^dl~GD{KfEN9IBoK%xyCJ532xwnGYF7Q>I(;ivNsaLbZDliiyW}Y}Rhr z9>Kib9{w=q93nP3Q!toLSRS~Kg3_PB>}^eIf(U!ZK@SKjRWxq=N%3;gQXnsl&Kj5u z$CBqKE#+iz^OrVhoZ4SC)yf>BziSubuG0sl+3Ocq>N?#4*p)It_x_*!;w9|3!JKXD zH3&?#TqDcZ1->t2C^xv68k|}%djsF0Yo=mazKCW1 zrtk6B{qzPk!cVFzt2B}TugT!7Cc9C_Wr*0c*Hopi?R6H&fJ88>$t+hxokgumjTRR| zfZtquN*u~V{85mKI$thF&S->S=*{X+PqDRJ1HhVA%QXo5ahxH#^dVm<8Rn9mNx?ys zjdV~g?pE5K(uUs2K$}7sXrZdUTe~{Gdoj zf;jdPZzG_9Zbr^`-tl}XKv9eyQP%OX9&cbtVNF#vS8u&X4CpuKVFbsf z20R{{;4qhAeCqs%?ryBET}b%iA@4*jkbwB9Dj}+T`!q|GF{Gc4YYZ`tvVgkQyZ)G2 zgMSt@JotTGPDAlh$GtRH6vm1UP@R0uH!f}@aFoXpT@X_Vm5fYS0en$;RLc_hM>^^~O9(pXXJXu(UtX>alii5C8$bovd zR)q2fPX%mHFZuJ({j3MNT&JE3GOkaOZbpPDL>W8|DIJMQa8@H;?z5=rKs-Z#D2y6g zgeBh4bOYUu`!2FCy$8zEEBzp$bVy+Q681Te+j_#O=(~Z2VYhsDgWRs{je#Mhg&hF6 zPCYuS?1{EqF_|DtBQ(r74w02aBW4aTlyF#{saU9NT-3G>LtJQGXld0ARWM!1D|RCq zKGG3-Shc0tW%lJve{l@!LGRMh3m>mTfy{%x0sCh2ua(}QouOZWaU#-o^BbTULr7Q{ zwgr_Yv5!#9y`k+{h;OkzPA+i|Qvy`aBZ7Hv!4pRnGCPs zrruV_P6wvw$x0NBLL)XO*_MZW6ad@1SPvXkJvF~IO+5wFwm@hSO2V$7PL#W;ec}a@ z%U?r!8Yk7b?1={*#dpu63OA2Ne9a|{Dk6^j(gx%2A6wNda_^}qqQ@P(94CJKLV?FR>=8}XQac17y^ zT3^$9(;kOvvZ;@akf2b$E}SlxKD4@-k?n^u*@BL}`GyeCRAP7@w*~H|6;s50EVH_M zTW?=cl1azwQMucF>g*Yyx$umdo{~MO#umC|e6FxnF(O0zAd~Oo`3y*&uG3F)+@C=W z^30g))eN9AcSPqw^*$Yv>E>R>Nmw4qJAfcPws5u;r(q`1o-6j_Js8vCl(2D!JSIb> za6Z1bsL1Ee+-n2H@9w6MEhh$}t3bmVa#bG0n1wwEPJvJZs0QcP-QY8q$;cc&4t&>c zX!A7rhR9Y1+m#N`*ayPN1|yhH90FS22{j8l@k!KfDauHfimT?Z(weuhiFz!H-L8Z0 zxgG{q(#Vc9H9~znD&RRW6an3GVe1vSFprQVcVBpaMYjKILeT2NWL-Ty(6uevd|y-N z@-CKGk|8lX;0Fzf6ybAgmHq^_*YiomE3wT2RrQ3X=G z2&I;Uw~djwcZ)kPr3YSJ^5ANJ%hpOkgHvy%T2N~(2UQVS!gM&}FqZ}PBy<#Wqubrj z92E!^TJeQnK!P752-m9@(O@Zqx z&ce?^jiHl8l8L7G=cX;R(on#QRVd2PJS}U9I>WN}@N7-NWFZNKRgm0h^L!#>4;z|= zE?@VYf%n3>_{~(*VocB6@QG1PsBwqdLBE1hNs?I7X%-J+8!2royWhvf@w|SzpzU=S?s>qpD4v)sZwnCXbW8a+@lER`4ceq2h{Z?WJy&m#;*w(8; ze&tn6g=PI|nu($N0e-@bB%cLmMdQzl)#~R~w1X9nB9Or)8ms5fiNnJ%1~F<%CU74J zbx%o=Rqvud8-7w8LAd;*Y*#0EHJo2xJE3dh9-xIqV&Bu0BvORoq< z0^m9i&uaMrE@Nk3iIG>@$z8w-QpBc_gz*+Nh}8LY?)fm1#JYW}0LitFygm!bNZ#Bo zPKk4(7P6L_&2MKVj~p6JDA~~c*@)4VwhxiOaNXi*!b`|ZGRFEWAUD8qIO7Ig$Sbb( zY$w$iu89k_lHSsd5>~lCjZ{YnI?{qNi3?po&Z!ov+o9Ya!Z8Jq_Z-VTug*IMq=nm; zumig}IT`G~s%3Id&Oq#0`*UzPWl)8ZTTCt+%QN}tH7-Kj43x{y;eC7vQuluB4A0`A$+mf(V)JHzYU?$B*27 zUl8LFG|SGT&GdptedWgvvBszBZ#3!dMc11qqp$N&B0I!rwK6d^(wuQiCI<;UNeAdnG8CU@d^^%z&qtR zs9yU>uoeKyPt|`2234Ykg7oDUa{S^@{*gc_sEB2-P95JxEk=E!G)nmZb{y-p>-4nn zthyWD5O(hk+@*GN_u2D2`))zQS3?OMA2^RwgTV)*%Kw;zP7LL$Fn9|Qe$yW8W_51L zKV%|o$Rg4;y?^Ff61Yr6(x&3_uom|LJvk`mWq&9J4lZ7KuMf4oLD|zat?;N&4u+TG zF%O2J5uf()E+#Zc^N|}n^ZXlANh3;oz2KUb!6S>rI!j~KbtITm!Rk8S$D>?!PM|J( znVMR3J-3JZaUXkz2=c;0T1;oEld z2(qC?+NaDfj64T*TYv>=wYUQ+#2q8H%gdNPL=X$n0FuKbn{6owAG%|`L5@hd8*|F+ zR*bJ6G-mRLO$p9DWb7q)3ML}8f*&?OBht+8JVy$xi1*=$yGWFvnVaimzkZVJKpMb_ z9T9Ds1Dj%5IT*tn+7(p^YJ&T;d=Vo+ai^;61x@Gz#VO8g<(-rP+QudtOq7LIqC*Ck zb}D51ZlHJCS*RrHL*PYbF-XB`?@(e*i>+N8s7VU>=t_@I(v$rLq@IAZ83MuStl1_w zX1sd7j~@9&AWR9&88wSuSlpoDQ9#o?$z~+Jle!X$VvUZsKQx1ymH*1=GacL)S*$Vh z-=Wz;2AntSYIi5!?O>~d=QdLL^0mJ5|Dq>l*FrgP{g|BUUO)2c(d1Lk1nD1ZjBeO5>-Z2L(lX?B=;<(6(ERK-;dsciIbP7f&B-K_2*G=}f(x;Sd z)24^7$ts$`Z64+GZlJW2JnsgIR?1PzkE!PC&-Ta+r^CU==V1=c#ZED5gutu@QH~5m z#dvX;6;?O=XTSmBj0E1^A4hYPSh0Us!Bvv-Al2%dJ-8*G@LxL;OBuN4k|K-u;5@pwz*hK1C%2~go>+GQ^N?B2mPtQPQ{zxx^)G{ zL1&y#^iUN0=8-uGGF2|9#34wldi!_$mgC_~{xsKv-vW^A z9|)?-y;F=g3!HgV@%T9T(6|iG5V2&Ku>y{p1`N=T{q76Z=7DSv4h*9cpU6cI)QsAFawPGX)5@8B`lZo3ISCT)`4tUWzUq!k9Yt5 z3EvuL2sjcAJOW10n${?A=J&e6VSW!&#N-xORgL`lTW<^xFtfjzx>}XtMnhg_pl%9I z!vTBq-fN-^AtP9L580!0-;_bWQ$H^jCK!tZuJ~FB-1&#$ssGD8xVY0~gseb!466nM zrS4_ocvJ|KhW$5Y%Qmhz62gp1rj2vv60Df}Pb?c}Va2%Lm$5+K+7TIyw;wg=mw}N< z;>+K9(($T#wU$6XuCF`D#vJFNW9X!x;{OpcR0%Zlsh;p^MT@Urvt^Fnx}lluiC z<1C1HyE#BO=RB>29Bj5!S{RuwXVI?nyo&>;bFDTQAd5Wk-G%-EK;P4Y5a16->;Jyh z)QPj8bR^Z2C1*;ks0%E(8l~(=1uD;@Wl46MVO!USZDdD;!0Gs{81-zKZz&;&g)!)o z4Y@zZptI%@IhV13c79%cE)14|GTQmrk_PHH*!j{mGiGRWH^MnSJvaFH6pRZ-0v3={bip5RipAP;asN7tBsih&KX&J z3(zGD85>)Vaa8{6e%yR8yaK0gvaXRK>+f4Mk&oz1B{Z!DL|w&kp3V2f=e?deR->PX zqui6_eYB~#9O3gLcbdIq4i8?f;bIwzLKmbm!nU}Td6-6>a#917x5;XpX?d{uZjsZV zEigPxqBh?kp@fx$nN{6Z@o5J^InV+dJ3~a{2TLT}%v|s4HXhJTgq1`V2kp`i`2XHG zpzQ3&o$x9Cys)zps+p9srmk*ifx>%8q65f@Ef%#90hLhD9QS+@z)`h2_{cn^2Tdhb z6u$J-O8Gh1V~J=vN!p&Z!GdUbsI8Fzd9F?1%OGpmp0W4i~C=rI;8U zeaPjJ*kFbVWqEE1>;`kN`rCM43O+~BJxW$7RDp5n+~d#1rS#1%&5;Z`WI!25uk#;W z;a#?Z$vPPlQhwI}Oo3{1IWj@SCU^L%-_{94%@xNtM9q2G(Ld(bAwQ|>m_B{Tui;mB zn}QTx{rWYml-jp>Uw62pyZIA;xrZFG?Ws8X_=w0W70E}7h*KgGM9D60XP&F=9*5}% z63;Nih(wH<^nbnkvU1HP54evjjrx@z&(>KFziD{sb4>B`@W+EM@_L6q1}MDh{dmC| zKb{`UUl$)z-av%cq;D?Q{`Z<$`Z-`kpHlvLO_L*g&_8lnQM^LuZ`zHpQsC&zZ`M2Y zD1Nx=DKT$>KF1B%oty<**U?^sps7!B}SHXDFX6ow1m^Bai*h#~{a`KK( z&xUQEp9%xKxP1={Z@|suALOO;fo}dVia5M?6R$@pzk-Kko!e0s1iHwbw6Oh3y}k&7BHH^ zv3q5(I7|w>yxrK#JBDC|s?&c6BMcbtrJ+_!wG7eLeG92j^@EY8%BO5jC@9zX$6qa2yd9$;;v)Y zVHxb_&!@WKkY6r}1G7ZDSx(lcoX-S*c6j>eJ9x5mGx%Ph?Vd?1tOx1UY=D%JNhZK* z&LDHGkOZgv9mEiN5EKNoCC6$IM@$C|@~Ogs85EbA)qOkyVWH+9VL(} zj>3umF}beyMQTq?5Tro*TFR-D;meqNWyb9j&r!SOOb8QSAc{^6^ezBwn2=45i6<;% zY7MaGP!6Pi7si%|X~n~`7V&R5z(-LW*lEqTp7l#&RP5Ke;s?cpF9~vC^JCrvdUGtj z(5~&SC64_NuneAB5v1Ii*A(KYc)`; z@GtG)$3+BM zpFl06f%5dd09Rr-b5&fwgt1@b*Ln;Cs^8(RL(NB788#<{ta&>9jPL`XY+i^4wN+U?jDjTbsE@5rz;A5ts5daaiBJVuX zuWt~g_y+OYwY-c^u&p|9n@#CoaL{O3?d5`_a!Fm`bK@7lc^z^9@xAquCp)2aD=P0S zeYVIVfo_GXgecaT^jUga}ueiFgq@o2g%OH4?`B6bHbkNjv(m z^cXC+S~x83$R2JGItE+LV@2b-)Q3ILq5V97rgSfhT6KfIeGg89!%is;tJAB#FG@73 z>Z?b7+M>$F)Gto#hi&yX0@nTcs_-9%Q4o$mP4O3>fu4u)PfHH9d`)yL0O3{h6Ep-= z_J>v6?p(^2EWo9tms@4gp%h}FW^#RaDyVhl3dV?kJO@Pwr(I$GkHDqB&+2CF8HZ%b z8Aj7@)_IPvjqhN1)!^}I445G>ZsP(lB5O6rT<)diMIQHxyOXM1SWw>glW0Tf4|3nr zF~x)WaJ%DRv4tOzo!jlgWeHkXl5ol7tGw29qpO%YJX{xDGy}e0bm^Y zK{qtZfeaF&i-CiJ%16dR0A@d@$-91-GMP?KYv`kl$Jtlz8>jMg?Srx}_;F-Bo+OpG zP@+>kxLoLr7ME*Ps`pxbc==(*G~~p*1JlJUBaU++!KE~I1A2R55tQt->~SJ+?Mq5E zk_4F;coySf209be+@{n~f$5huzPZPAGpTAR8J zyxXTDFpN_yROdYzVYY4}-{JOJ0PDTgL1vw@yi1s6{AvFW zR~z+^iX#wb6-k%}*j zCQa`&Ia^RTH2Cfa#r-Ju*FS_kccdtPiWmWUu`W_VMV&I@56%cmfkgYm)&Nl5E&)`5 z@pa%j+{rkquP_v4TRLVox)pO3Y395D8fpnh$R7tt^0hnEeru4=KN$#VuPg)rc07<< z6h0EP{$&qpW03{yf`?-kYLqkFVB!^Oyib^b>t&u~dRG*)Eac`tcV|ad*)Ao_TWb=c zeI6eyHJpZdknm3m0F*B3NOQa;oN5}xTuQZ9Kx$D2m~s~U1agBL&?uKcc;2DF+uobs zyn=jScjNgl-9pzY>~C@CA0fnE0PPj~Fa0`Vqb_;Tm_b!Iv@f`P7^{FyQjM?lc|$jE z)xG@cSKZRU+6sT7ANOqla7vx~WH|tuJUYo!f#j2MHa~1vx#s0oPDr`A56A%Y;C`Hl z*B*)l5?jhIW*h%L^&X@dE&SC?U2`zbDUs+Z+Bi=*M*AHhp;5awOOV7p4rGYi0S=>Y zU@)Cffdw)9&cIs80y)=o04&PX20#Wp13ZrIXI{|zl}$Q3yHcIs@-V($eejOWLq1mtzSUi)!zWs-L;q{(&VvjPoy`LB&9Dc+=x>)J-sr8Ew4;i^{+%{`@Z-|d%VHg7 zDew0N19v=Mm-s*e`2@R+V+Eu_O=@p^{1S}8N~{5-+cWQ~&HCbH;aE%h7s1)hZ?1Ie zE67?mS&2oH_IB>4@M&w=rSP3lk-7>brXC~_-ht$(E4Z#1VU1^d?ZpNVw!p;dtg)~U zmhHhxk7u{G@O4Ku=1}3xw>^1EuRnbpg9SJzso6?txNkkuB@;)(9He)A%()A8B&mnT_TrL|s$L>>0p0>@^{A*R3xk1f>HhaI_bR(tf$_8PFBIjS?W9u-0q)_~@c* zTnF0ye?EULORMlTk&zSWY~M>LWlJjW_el5}Ve|7brTMEnAT*N!1l^bFm)1Z3TJL>k zsK|-8#V}J^8I4@N4LFN2LG$880F|agt@+U>J08{!M4k;?s?IaFYd_toZ8?LpkBw`H zdavdL@jiPm-lYr3C{Zp6f1vN&c~skE@ks`Y`ELpImZb_-mkY1 zJB^84ySF!9PplhVyf1f*=BeI!y#{}>fY=)$w zUg21I52`)a^)^@6Dr+s~egIBUp=w#VlE`p4(X zpznbj0bvC?pPLLfEnE+iXjmnS_U0%Mg82e4oUJ>5-bNjaQ2Q-eDv30es>Yi}qyP}v zmIEL1P7uDlT~d|vWGiz^TyJLt%Xe%KPl1U=x{w81+N=rn^e9 z_l{2yV)AkgBKR4=h z+4!M@W_Z(m@gE4gD(&Q4(Ozssl6VIC1`jUo312Rw(KqxG{4;7r zl}6b(!|<)H>#B^qjcJ(PZzZ;vWya1=W;A)8|Kz)l{Sr;uI>W+AbBxf<t~c^U+j=*#rox9sffvBvfK-=N9N6{OoUF5#5+M0>{K+<&Y3#zsKuL1Oh%PA zxB60g9XcEhF%qjq^y=Wyq@ zzfpX;g-T%LEuSGCcjFp)9H@>yJJwI^9Fb$jiyWVp`rqwT)z(lRlk zluJtksl2^V+CO94Kv^L5l@z$};>!!7p}pRzf!YWQ_gHY}Bu+L6@20pCoow(ZC*HK| zk_9^U)h5HbFN*ZV9Ld|`)r!-5qlCHSa?h9l8kdz%`jWf$~)|hC>e{e+|1`jQ3Ya!K*)i!bxvx32T4%{VR=xN4Ed9bd#l#D0UiXrDs}S;3 zppJLnPyF?_MOA# z4!;-oqg%!HInxS8OuZ1fda~@Mej3J~#OJL<(>Hy7Pj%~~MJBq0Mn4aUp90*|Ay!e5 zRomlhesDBe>f7}*j}M-RtLafI4()5ViL8lg1q< zRlOHc31@j6w0~z7Ut4j+o(s@T&;I)Mnu_AxKqY{8=( z7o}`KNyr_idwc;r%!vHK1U^*mrLi_mFx=vwK;w6!Oxec zofAzy3Vf!JG}Uk}Ho5z1>K*S^M6iRp`z`KUPjZ)vqFc?5I2wDNfgHkHW{9Y*=`m+R zV@e4`?%aZ%x01NEZmVuHlWg+=B@F5+sF6RfDCYgdoq>%ACphNtC9Btzn{Y=q@r+{o zsA|>oVP_~WcQ9%Aq;f95N>0Msa~x<+R@;@G5dYBDKEjNk zImFY75OFu||8Tp@n-uou0OkGqHD@||I{W$nFUpas{rH`hj`G%xzFz!<*qzUaT+y*|AN?9T$wc z5YD1;ViuYzESlq@hY*=B zua3E>ACIaEJ+$cnXJoipd|crTNJ|-!zcSxv$@Lz(?1_CH(Ii10l}CWA zp36lZgcpKi)!nV1n_smMb+k;9V)a)L7P#2oR$#u@!5L z;R|Q^*^X5ezFw2e=&-6B_8tij&B;dwRAgW89IXUG*(h{#rqK$;8u2pXCwc*2>-<`k zmzn1P_SfsWiblc9(j`UHB#veEj&fAG4GkBOi zYHgmdKEaZ&9@A=8_}1HIA1qt9D@E>*&O5Ec1)P;|m+Q69Zqc(RyQMPiy86!c?5=R< zQCkKa>PvWHahD|Lt(q!8RrvHDO~A?{UtFw5x3PfW9Vh!4z+G9C$^?(LM|?&~J##TU ziShMVJ6!o?-3LnI)~-aYRbZ<1mDUE;hn6QuPJNB<1c}q;tW6S}yn6^Fm~<=I^63K2 z*!uj^gPG7Wj{gB<-R3iuJLoNwy>H6JOhp!((*t2%UHFMLa7h7)a%U=>#r2cc*XD4N zO;N_`pinE;5^*X=U9aZMiuD&0Vr!O^RwrnCfSu0G{j8gw@mAi2wa|sSFQRHJESbczmxoQDZ=7>W27bpQ;`D!p|mi8KlTbx-=8+_y=#-1EL- zYOHKJ5iFl&TA4mKzONt(tpcAGnwg2H5lJ$4JZ0h!@U>4q9k{m-l+RN&FTG(O}?sirO5e2-J;#^u9>N~TZ z+(V4f+^q(&qK2TO(zhR5-?+ZBin$5ymd4SWl`)GD7rn|oul+WsgGnbHT7&uvX96cT zS#>E%E#llW=$w*8IjpfKz>$`8^%qGjdB?)}GHlGQ_;;t4A&_uBumi{FP`imxkw#Si zmT78VVGRxN*dSfw77m$JlJX6zaK+{vkR#Aj>8(GQ=f4>BQnOdAH@p5}|HISV?d?AN zV#EPx&vvUJoW+lbb(j?v7W*1@+q{Gbs$^aC)GzhVtkLZ?dzXy0;}X)h>FsYl!re}L zP{jN`lCmP5R-8c1CFxh@tzERBjVq5UHp#zWITZnxKhg4V8S@BNU5uQlCg^#FWaXjQ$DcH3Q60ihzKBb9pdJm&( z$yn9aIfy@)a7xpOHDP>lyi_XTm#8If9QaU_;_)`Nbq`sV$Aj2mb{jPe5fEx6FglFv z&bs+7VJ)~gDucI`EvSL7mCgC8JQO@mD?`46gGI%vR2yo}j7g#-EiNsb`fx}37-Wfs z<2!WCL|e_$bkkJv{BvWq)h*HQ<#jS}E<;d3FdaRkKA6*?@Vz=H_Pt3x_KocafH93Z z#jj=+_oHALG3Jl{_`#dTpOz_D)4@WBolTwR1ZCE^cr`Ub#ll7C;O*tpa1?TB+aU+l z6M`FzD2G_j7+34t4DvCaDXodN{MxFATQZQ7eF$u;?8MH!L!$}A3upKv9JfuCZqwFz zck~i}oonN{l{zU`Tv~$RbR{!)ltehW+ishWw`G&ugB3mZ)YIIN^ZXA*sgC*{UXjBe zb5cVoM+8i%gq+-;lw)q07F{*;?HMhiWmwuS!TOd%p+CJ^$qCX+CaG19aW=CDOrur1 zjvdUK0en{ca9Q??-BIGZ+yu-cwHqi2I0rbN%r=KJ|NOPzF%c(Gy$Pn4G;;Xv^l?9G! z=mk6Gk-I7{RHWowKSsjw2<7TCR+^5!-iJ%ONAn&WOc6T!*@rwoMV;#u7CU%+s9ar% zu?it1iL`X}2wqOdAvp9eDDF%vwALg|b+F7t!vuVe zN?K8%W9r2uv1U0|XBu%qtuesO&+UI_c1&w&av_++&qzGl-dj4F8h+}L9 zX`f2GlPRj3n@;LQ6mgJ=9P~o>v>lQ4)rVbg5QS0<$kY0)rGYB-^h8}46Cu!3nQTyX zP7g}t3aRb*Lp}lsMg1CMyC4tS`JFS$6j`0{*h@0DV^&KB^jFR+>cyUO3&RrmNrtHs zI@EWr?@G61PWeJcWWbAhbsmxYc_|V}i&q+BcK}lXw!X5U;O=UO_c7>UBUAo>8RRYF z;?uMOY?Aa`y(qe5W z%MehyM7;JU6)6s;q``(=3I6Lo?@mC;JZ-mZ(r)n|A1I^@$@=8(x!4Iuv>2fr?D!Vbe=gG1WCi!D zboQM|7&m?Lj33wK1pY{w2N-!aeHAEKZ9WTblKuDhknR3K(NU=$?C`BaS* z-DBQvL+4YY&7$&KCps2|42_vr3 zc6YS?$d8;YK-!(u`AblW$}%wV2D7}5JuVKI%GnMsli&t;ap`KK0#I$GhbGLt0zmPJ z*O*ZMnRx8pUw+b+_goI|)UMHoFKKRXH)M|zeCC!>Yedd4l*zM`oY%rl)Yftg80?g;F3<%T>_Cli@D@e%w0 zXFHpXk`+WuFndV+hKy0p+UJ1Vq!g+xVMyXnR9e&7ft=36Wg=tQewMc+*W#kIFrK?3 z*SQX#-62MZlH~WP1a`uN9fkkN^Y7`t&qc34ti`nFCpg@~*yNG z+c{h7Kg~9CI2HS-$Iu(xe>I+9ptWr&3|(pIkPdOH>l)D>={ZzOq4G0Elz*~*uS<`DC1OV-=@d5JqmTtQ_8hL>@2{j=Inx5_W|bd&{PRD>CZEsjB6BuNgsYtbELX}GE6RY?;<M{wDV7dsYpli zqPF-sTrBn{oh$h_#iG6tqRMkyk{74IHa7^mM_(bUF01)c( zml`8a5i6s`AI$a#vn6D!6dW-daNO&my;Srw__HXFaBz*wY z~Qv5_8mQi}87|;8uUkY8Jy6Wv>$aVKC2;J>&|w)~6w7rv36_g+vPV!o*i30{GbY zZ>p#L*XGg8eH5ub!#t#3$Tzuj2OWcY+tJTad3!c#gT+qbnhsNp(z^@2Pi&70cxpAJ z2;OVCF4|?i)?{E(R8 zZV*GfEpYu&6$P8^#ainBir533v$1Hj0i52Uai;)C1WzT7fs942+uN^#Nzg2zW=(c1SDJN>)8Q(JHj4v8#idL4cJK+2T9rk-9InUSu2vAq;`5Bn%Q z=9FQ6r70s`ZJf)|e+%4nUrIoP2He7!`>!p!sMNq$AwWu zkF_ImTn~D7fP0C?QJ_#LQOs~8Lx&U|Ys8m#VL92T*pBfnhN61vCf4Y#?L(GOI( z%LHL6UlsS|LNN;$%K|epT6?@P$l6^0$WNE-0K65`iZDB~0?A_sMAO3q~EydJ(hV zG+M33|Kgo0H!bw&Ki|VA(FbjdqSC{x$2T4dzs}l0g@*V~?=Q68JNay~!o#kZ6NRPu zk#eCu%t=KYW~RZGo8LBB8a4Ynw)X1E&gU;K+{?Q#>Oy^Rt#%KJx6HI%!5RWw#9(|* z?f)tSoC%c-6py$eTb>!yWKRWGUHe~K(UWHzj&^VGI-u1Q=>=UlCAK@mS8AX6B8X4E z=AZh_pMfuw(PLYbWi1eMpCU?s?3e$2tmpK+Max3}^t1Utb8Bc=h=SV2RybS@095_re`l*J|&$$xx(>>^?FON=(?3rHma*4Uu&5PDcO9k0a zSBb)M=#aJfpeH^;8s?l13`P6g;5FW(*M6qDt!Y1&rGM}FLq(oZ8p5clEROwzZDtUG zOcVhwzj33#V~^GKkN&Rop@2srDao*q0nwTMV|;;y9X36;UqEWn7}M=Yg`Y3Jy->SO>G>6 z&OaS640HJ5PLEdjueqJIn5(F*RpSy{%a&onIP<}T>8w7w&l6ZKE}mN}?ttLE7n#_B zwQM8%u0tKfcF4rrUqY^MNECkX>hCXv(L}8D(`$-{aFS{aMjg=}qav}!(3xn|nRLHB z`;wBLs2f?{t(t?2c*f1$N7F&m+*bsN8fRbwIs*=N00FKb+^Sd~g!1Bqvq}H==k@#T z5vL>-D!Z$>PG4t2=YOwv;;FaA4Jit%rBLt(m9%w+3rx7KINtIqx7!U7V<4#H@D9{y z@3;dWkU091Wq$eYOF!L{%FJEyT!i7C*Fjudh=7 z1nIuIS2#2^tLi`ZWG6##;6zVx_H&T^hV}|b;4NE45nyzK5AM5jb;sWLnFgP%-Aby7 zsttBrti5mPX))!qDCGH4@XwI(UL^)?YP7q3+;Jv0Xx`_#jAz)*$=OQIjS0##$~rRZ zeiqy|-D>UYn87*Y>1}>8v)0`6DcI)w=eqX5@|Mo}Bc{;Vyjo5RR-nc&kuRfaWZI7EbB@~%lsXhUahceS&?GypCd{JIF0tooU8^cSEx5OW9)=nk% zM*DsYsOPl5^fZ;rF)ryNQZ7Bm=g1a*zD?Mjh&80L5C*B)n3hb7ol(VK>mxHzB^y9Y zhG}5WczEiZ@8E}jr+jH2FW3-dw!L=+b9rGC#-)1(JjGIe#Mc$suH3bv^<&S{&oxuN zJ@flj9l?(zsVyLU7pr?;QXTB^tUTTI3eyf;|UPL!c1coGoA$h*y^BEriLn2wCMHgR6LlyiIV7B+^}xC#ykPA4?%&HDy4 zRP&E-^l=H}t)0%~G_2qomNHv$eW}CvWVOpDNRdM; zHIJw;QIlU*72#1KB>;`g(3VL}pN&3t>*h#z zib44FkJh@s!oSp17Eb00faAY#A;NLYh%zo`Kx8bVPp()yoO>|gvYl; z_o=d$-rnQ`-YXjOXk=b(>k6CP=wo5LhE=XUgzuJb@PJgbP#`R}-x~!ykW;|1V2AS^ z2U$zma~|o#QLKt7`j7TEO0;XUz($W>&ak~wFZ1{z_M*8 zwJD=!1}{y(jbbqlV6(Ne$W_>@f!FG`N8qS{Gn7-EUze@^A>su@i?r-j+WGH@rBu86 z)1wtG@U6%&q`%VLjm{$Lwy^38rUAdj=*pu2de`EqOu!M}!=)1{u&~!lS z%@lbq6DVah-U7BU=RiNq;st4tG-NaZ420d^!4BoAyYYE2YB@GN^veA@paS2Vryh09 z`_;_u_Uh1N>8tLq^6)?$k&n;4#(5i;yUb3cnH@jefCxE?0HRj{5$gJ);eeoT2(oT( z$vo`Uf{aGt78b+1B!Yi14(jsP0gUM-S3T;4x6r?IJ`zr4XD)3jv6PGEY8ZTjJo)Ky z2Fho(A|d`7)Y&+N129d%8b1$-k3m!d+cFSY)?3ETO%D%8^D%J|*b^0iyturGN=i)Y zDinck*77eZ{`I}5cCBIpmG(Og6p?g#LTeCHIt{+U&cN;X?q&3P>Q2l1v~*N2U)o#ZbKQhepCeBd8{e1avSla%i_5D zx(l-va+?quZ_oC4i|UQ{uZdEzcUQK_D}xpDENFv!*$RNccA0s~+)V&K5B$7SxM~Ep zFj%PBHNFId+GeIhcMT2&-u{~Ek23i7nEk_)V;#5w-`2GrQ9e>%9=oikZr zBw=|GG2bp0X6L2WuCGqJleqA7b#YbSAxxs> zT$lo@BisE3#N=sUugXDfm}WK&t>-X$^w$1NG?E>HRm37K#u z4~H$|^j(v`gLwy;b_%Q2xJ$<{SPq?MeJ0IctV>A|%iC1{otCCz6=WWr)pu}lSnq;K zeG&LV(^$Pc!o`(^nJxG-Z~?bTtb*c}GJfhNr42EBr|_u8dEd8q9uZCT)rk{y1FC-> zc+=kX@Eo_}WRrGeBQ9!{cMkXzRX(ZPnM9j6*%mGjdO1EJhX#%4= zMa;;uY|91YllV3%Fn6*5Cn}oYUJ`TogglT^Fw~XM%UE0EoE%TgbPG zDV&?C|6gP;ZS-;Ouh1LbiXA~WZWFpn*$?jAij$_pO=O@!6js>AVDA@`Uqhl=X4NU` z0a%%zh()(;y*n^21)^4A+pzRa)9s92wYVm1nxU6f3#*~gY50Jg;Dvgjep8$vd-Sn@cMrRFp6V^|O3E37ZE342ZEl{BAY z?LvbryA2b{pufmX6b}$9JR{3Xn1lp!RT?Jhb)w$pH{>sl6T*&h;&H?#^6x~_{ih{j ziLcH($r4}Uu8F)5T_s%jBu%xxX;bj?B&qkzmXueUHf@X7Cu*9*s(AK((BB;)?}Ozi zx@E<&H3sBse-jEG!KOQdxlqRypZ)82B~9t^ zl&y=pev5b(>ajZmFWTL}&ZOEr{#%%n;>ySDH79Oo8steUjhNUN<5cZd;+XizkAWoj z-r3!$PsBu(DB8TQIaR9D>c9aJ_KB?pQ#SK@S2*UgOF3iyF3%CE`Q@eq6&U$R4gMtC zBvntD46!uKw01Pd;;+Xz^m*_2 z>bucw`jy=uxE2RP0#b9+$`4(2*XnD?g8jK*^QifXa86NFaIgL=(5mG_GIsm(NY0HT z(WFC@Y)9rmeeq`-o?v$g2aW9nna8E)U4~^Y7Aj@z=|~c~Jj7=>+j};gUn?0EOO4=} z%iBBFpg0UioPUuYg$xO&Zx-2fSFZSRy>n&8xLZ=h=OBBd? zs$_N!5Ajj{z8<}x)+@sEp57Ck4Zmi;e9kdtplX)Dy`uIoNPpb>Cy*o9arQpGy5JPa zQGUY&JuZz&x1~BkuC~djvh-4FWb3Mo^1b+{^=mu_YE!m%`s$9e`#{3rCB#OlSz!6Z zAvbb)f^~Gmm3@<9t%}WQ)`WKqk7V$UCs==aWnup%Y|8PQ9`enUE`C{-cGT}l>+Qy* z!cUJ+4b+tUI|~r9@1lh{|IyH7)gxj`XIOb%9vAF+zw+ty@P+#)3*OdrPj-&4apjM( zsCcM6q*>Js_r@#2HT|1u+w##ra{d54MBGs{z)31F7+JHq57n`^(PKi0%{#Vh?0qec z!$e1s$gr%AT&$%pAL2=gbrNIH2o$Cs5{R@P=%dwwX<48Ba9_^NCPMyij|1eHsg;v% zkIykVe5y0}N;y{3o>nJ!?4YLPN=4OU$VJpw_L6Xc@fHp7tvC{oifGUAZuq77hrP|uPPn8hy#U8@wvf&hoycy#=gwD}=ODj2P zckc%EYkDVH-ykGyD(gseMUL8)jyH=uFcw_w*xh1D)<=9fa%|7WDYhW*cd*IhJJp^f zZb)0y&h#X%H!oXGX_-KWADi_o0!;TMyLED+lw=J;lE={D{iwsK&L$7v|JPx1X`(vU zVQ+WX+N*GQ5}S#r>2clgmK&J@#6nlf!pz|jDXBb1l9#v0hlu=WHk%I|s(+0IjI_v! z@8Xp9g3T4r2MIQl{Y#okiXsj?rYE`IL{rc1ZTn8*585SnM&si-vPx1^$9|j?MY8O# z{E9o#grb)o6)L;t zdaEc)-f`JXV=Te_k3ZQNlDiEIdXRjP0@uhZZaaO7NU)qfey9fImS@&C`FQWC)80C+ z^DI}T8)}{~kIC#Mq^S6|uq9eY5{#pIAi)mWl#@C31SiN07iXzk> zqRZ8iGWBC;tSNiSgyL#0|CTl>)FWFM`WczWm6p@6GvWD;>Zb~@qwJywbdnBanh)lM z=ktFk`(xf)p~eGk{dC0V&UI+(T3=C?AhcD>um=>$V@as3F57(yW9eww(8o^kmJSoKuZ<$q7bDAc6 z8L7VLYdjh70)KuoZJsFL~5@0$aQGnDHX3INea|EdE`5t2nEQyq811~Vdlyf}%_ZauiPayS$gQvc7~NEF`e&=67t(vPxx zj1B~c6FhxeaCq2A@lNJqBE+(rkYrf48PPK*7m;Y9qr$z)!+{^2Wu1i5-0(Wr1p{dE zUO*M^%N6B1cp|zRn<=zvps? zOr{ODfhO zrn9FO(nXf}#v}WU#01W^XQ@6uBx0lYycZv*GJ1C!=+6-)>KvL4bGZ}6PZbjNcH$J~ zYfbp-Xz!(qpN5v5CVQ4B)ZMCFP{zIX9Bs6DW0;7YowjK;i=VpIHrwSfm!|~enhMWO z3pfHCmH^0Mmw>LVn+V+FrV1dd`CIs1c(f4HWNERGsHv;~P$Djn($)Xzkr&TO&w-6g z4l@7`Np1@o^gSz^bemJKEKq2wwD|gcvv@b)OXa5|XZPrn7hRO+pu%eo3F0!wp@xo7 zb6vnK4vU0GozEK!INk1*73k3wiX0Z6L={5uq>wJO8u*O4mN0DGh_I5Jx<&Fm1O6piZ8Aa`j%2O&)+IyaR#|{SrLBxjtb@ayi1uJ*YO^ z)t$A}cwez+j7A8YMofjzZoeu?$D){ZroVMK*~_+mfBEsx=5akQ3z$+*TJE+%GZhHX z%sAtZsxBMYoMA>}|D$6X^C^)adpEwQ4l4i3AjKm%Oeh33RIdDAm^Xs(W(6<5*&@8W zy(MQG2a7sDr6KDcP|>A1T9pWJDKV#sNx@-nnNQ3?B|6YHlCZx~&uQ4P*W^An#1+mX zg}Bafm<-QBfN%Ju^?uvx`hNk<-v}t@oDNeGsAMTTHb`@uzy@2i>6;=Q#|^9|=CI1( zuiH0hQ~ddb+##8uh;J@%=-LP4*^jy|u*WuK-v&N&aUy^23S(I@c=gl?gSE=Wjt|;X zYc@AXVYJZEOXHHQa{PT&n{>Lc=!nGSsHo8?4$WH>hvo&l-_Kf&r=M4|FQ&-CVZ4TR zcZjTE3f)K&dE^h*YEyKrmb%@ocWh%4$wxjM*bUd}-J30ZL=w#4frk}itD#bvu>ic- zbu{-;nK*s?QupnyusaUXK0(&thv(ImluAy{1kI6Y(&13YnX!_bg|-{~`#?~Kx? z1DUele|x_;3o!xbgX2tBz{N@CVT4H)z=5u!@M8B&Z;Q%}(J0Hi|EU>ZNs!`V!r*!Q zzMmwub4t+I7P)Lyl%tO=;m!WnXPkx^`AxL2Av?iVqZ`hbFtf%|;VuJkqyN16MpViy zY5*Z#EQ|CPWz+}OsbO@{B)ao}m|LdcjHReNx~5H zdOZhFKmTOlCDx`BUa;rU3tJul0xo5TzarRTeF+6=FMzQ(bKwWKB#M?`T!^pLA@*y1 z$5bK3CJBS|YL+>6Erf)1+zBf(p)p zpn^DpC=P5zzyZ{as5s(?8@Gb!Mifw-1wG&_&kCM>&hxzQm*@TTemTEi?%ui6thKIn zt!wyS|F!Px67k4UN1S{_pFVw#ic;ZJpFW4K>eHvM(f=>tN$DDK8TfUGm5ShfR&E^n zMV~%UzC~nPnp0Bi#Xcjwp+E0N!ce7QwMKfwBVm}R7nPRT(7`Qut~Cm3Ni7!s{0@d- zWE|uh=kaAco{`?5&ksHj&-eg_Nq@edFBkRy?8rAB0v(LXx^Lp(E~e_X1AaTG|6)Hf z8r%g9qh1t?GNZOe!lcg|81MDFO&BV}#zw*+a9>wzMer+9RB8>kNx{r_#;XnRIt-2X zk9S23Rm_G4ULrk^e>^na2P4>c4~Btn{(CAU>>2MJ?*-4&`BL6g|F_}XE{d&u`Og`4 zbgw7i%UXn9?ld^B&Ry(9{+wC6Xj&>z%RwdmdvLdLt7{bhd|D{BRRu`mJ~e66JJ9oBQU?bU8)mIkZ*>0b zCLpwB#f~CG0?IedXrdwZ=(vMqYNl>w!g+~~CFq`I^PMEEu&G>C?PN5+r`YvLty%{U z%4tf<@I3*}!5O7gG9jLC+nt0DLZt{|p)~=khm%36>GiXrShyVW2l)^M)P-@VBsTGk z7L^DL&9quh$LBtdbed(_kM+DfnfBKrQH7^4F<$mL5hhxR73xZ|jf1ts^2h^j^Dz7zxY4B0NzwOB_XIuwDRdE7=m{*rpSPynHD^(QY@q6e#3E z2v{T>2MbF!q>w~gPDYKYrHoND5?CeEOH?Z*ys3oKHI2$v!K>9^)uXv9i`!+E_j2K= z(L*>m&4)7~tw^c}0&JD+0P7}^uo{u$oIji@)4fK(q1ZfV7NVL`kK#2dLL|Fpr-8Sv zEafd?Y_W$FB5DqgB|uw;sxW!F)=m591mvkk3pf(8vc9wv$a}&`1CR6Rc)b|ROWnAh zuw^Q#W@XSh34R(eASYR{5Hy_0Xd&0Y;fB*zh+dIRRm4h^Di@1ZITO&Ez*BKNQ|J{s z74R0g(xfCNBq!}b2=G@9E_ygGgY_icoq7eSfzKxRDZ`|IR>WRb^(9UMnsx=xo(qhd6l zV|W*yHs-+-c!27;E=U%N9SRLN)od#jf-r-x63Lf^>w3Y zJ0TSzOJx;1CHPx}&?>S*P(>qBqyZzIOe#XaO;OA^NKy+Y5=jfytI>vK86BaRq2gJ~ z2u4_=gVhkR+6h*>ku)!)5+qFfNU2;+I%*&Z<>``&<4wGl$prFIv{hysVusb?EL{_G zO^CoSypSNdrh!Yzf}o3W%#+|fDZy#OCJ-}_2sFH0p}}jYQclKs22WQN8*y|-ck?A# ziPDXFDc3}LDIich&~)9gB^p?@p#?=fgNm@Dw*1kITI}V+Cd*+}x>wM9zLJs%=(a>; za+Q#%b$AbC(^ew}nO!W$pv8t+>J?>&@f*EzFVWNMO@~53x+FPoCJlapOU5uOfr7Y8 zYI+m3+9-?hNfEN(uucbSB~`@5ZcLJ(Ai~&qw(ZLT$uw`0Z5wditYrK#+iquzwM3h0 zXH8GZUEVa&G-9NLC%}CTZRCoI8!d@~O~m+6DFA`sO0ss065(LUfiU6P;K;;}{P(9w~k9gp0RBxsOnM@r>DfEK1B$5xr$c|=MgjovU zT`FKh9VAzvLoA#QU`-1S(T$44cfwYvST%czO1|6;s5sY&71*YQ!{JO)z+hd-hjcQZ zZ+r0zG68_L}02x``Y1->1&Xt1!tm21W4c|K{Afj01hEJ5cY60 z-Lc^o5;ek7CU1u`ia$cwMqEYKy|5ysVX5f1pYcpM=(iLMD55Ch3T+Gu15E6+r-d?GEHu$~IU za(K5c;%zzwJjxdUW>Nr++etzZTTzydN|w(H2dk1rw)AoZaXri%EJ(1{O&V@S=^}X^FY1}FWmZ$^F5In} z0D_Wu4x|q$%d_<=X@W&0^Cr)>A_c;Xw(?F`);-`E<*m2|RM!GQv*~jxrsIU-xYA8r94RI`Ei&8_0<7MI1t6Y_ zm;*vfR3scn$T2N30>xPI*Sw|`X++rIoJtEaB znKBDrVUb7+$tF6g9tE^l&r{vrISpfTuEqRDqN?dS-W7fl?0v1^)i%Z zQ#~>&`Z2LxwjjaAa|ai^NGB+^;~Hk3#azW>s+u!78{n`g?TRN5JxvBO@jRU?n1WLE z1{*qALMpO1-4oL;N@Ku}mUY1?+3;ds49@!61{%j~e^Nw^Y$IGz4F}3gHFpLLZ^)Gz zTy`qKMWUJ`E09#xWE6ob8QVv|v||g+h{qF;{rEr-!s)5%4M6e19@Aj0M(RVZ^b9PSlrtnOoxbPvs# zp>nEg1bUPdtx4We(Dpk~22Ml14hy4TT$v`*zzzi}top)v9`VMDVY6EZdi|*k%Hljs zH+e80+HhnjQB7kw7E3Zg$jL%NS0*7tthsB7c`2o>BH>D}7s;y{1|Ss9GQf<+~~+< zE-F;oOaP{U8RJbeSztlUMuK#SmttBW*lw^;2Gq~ED5FZQpk_6aD>+I7f-_=Ih?l|Q z5HVdl7?>s7&9cE-g62YPOK@GTRqmt(pB|_%y#|10UZGTvM-)Zr+Hs^?RV6Wya`=iW z#4xBR%K1nv986lZoRe#-sfMabxl#jI5$UN`DkS7U4YrCFY>^^NE9?LXBSxA72(RLe zhV*Py$&n_&4(%X@^0~N^)H`VazBranv01ex#3?weU`4D`%%OaUuWDs75k?yl9r5U7 zSofn`o`@UWa)W3=0uSY~tW*ZjgU(~wVhW{Tj;Y`Qpow53W^|KQ+y=o3@8!yVPdcNC zP)otPPPNdhw@XGLFLoiJ%EP+lE+UZv0X16N|3dxC!cC`@K&T3 zFhWK;L?=mKgeWlXLZ)=35o~~pNhES+*^`z4=Egf%H6C~9VAE3JXsW>_O;a_bs!%5Y zh>)p##Uxu)uUL;0jjp5D!irLk(gl=n%At7D$&f`?d|#s64I?sNtdhZspX!w>1woZ$ z4eQ2CoJYDXvlr6*4HATPPKh%OT#2PBXvuWbM5*G=TYwv_jNo+~w{GZ34L;$a;&no& zb4m+OabWprJq!w}Qaxewb(Q9t$)>E44)QTO3UD9x|6oaRIex)cu$b zAP&k8_iCsr>9MMh*32wOZEnm^oouKrbwD#c;HrXj*Rbx5Gj1GWc}rHhzD|qnK%ELL zC`o^ka@v&PXjB$EZ z>8!(rBDm&8Sg_(T(#|!*i9)%fnrr~|V@0aerF25|bdr?Nkzk<%EWq1HQJJpSkO6wa z(taiv_S8LSxhJYdpeXq(5u#csVFqsD9Xn4ZjJjGxY>+{5pjN!nX~>0APlbC#EkJv% zLbQpvD5LBnGL3l07c6;fsNi^$@ftuYqy!>Bf@dSOUdvLmJ}S#gnp@z8Re+Vuj&0+L z9|R)5TUz3gQn?DLgbNB?tyzV5sZl}M-a(XLH#2Qdq#eow0?iAOJ^`E2K+0eu`GBL< zLpivd)x&bF;)#UiU@QsRrz<&wk4D&B#4Qt&(O#J58!ae|lS)oVq4i`@jk0;D+U7hq zPDXjf1dV)Fs}>NudR?}vOiM~)rD!vQ1`3sSybP7~cB92cyN{8p_0ShZ+ zEj6A2!8hsQaJc7Z#8MR2YO#8cg@XhvbxKB+b{VP;6v0g~QOo%|U7`+$Q*FE3jg;ja zmjoa%lHJnmG~gPWb_Z!vG9JJhcB*Cy)v&vK!E~&caSIPJ1!U#|GE5yr zDA{%|ToyWHDeF-T!u1TNz0zsMAl75>`gT#!9fxHaY3r!25Vj9*4ZxN{NcWn(^a?k8x z;f_m1y4U{|(97GchL&%sO2*9VR;dWA00{hFh;N(}uL+HD9UJq63MNt!3qAHv#OM3p z$<1ms!P64j$#l{+tE)+MM#{)BI$$D_h~Q?G6H~sVOKz4zXiZFqGKH`P5V-)NaYGZl zEy(Akd^QK@!givq0q&=Lkwhbce7)h;I0ds1ZuCm1ZZMKzOuP ziRP1%776lNO$7v@noCDxrBsjVGR1T+#1d^(&(I(Y2@s4jg(y)CAX$Hb0TfTL7fp&0 zUh*PAB%9HMYQCk2v@H}^vOz<>auzYuxvtr3Yia~%QGddhYa~_K^oC+hj%ou|9YB>h z#8p7@trPs?x6qR^#XyM>Q9MVhaMRaB3Z85XZ4&JgE?1)}l9L-22)1^j7@^=y z$Mye8Is@kFQ_JPJCb>pa)L6cx#Emq;Dpt2%bqP#QH^(--VJ71VDJ-Y4Jr$TZ*GWpf zB$MkUn+Xx^Aju3R5XqDkuOnTrm5tl9*{EgXC>j-YCsK?;O;L_E5YEAiWR@!6d^Xsw z3#nY$OqqDD1Xy2RRQ2lyp!+e~32GEd2|hK?I7nC0eGN8Y5g_E^aX*wwIEbD}BRKdo zWc4b+vK+3!-EPevrkoNLfUBa%f{T8gH3?Em*|OabaTpG(2&U&C&0!0It#Wv!i-54} zRztCLJdvuSs0JsjZjPbD$#kz!?+FrI_ScvQA4#Rqcs5ev^1V<&1fxc!a6#AV1`?_V zf|3lN4+9Jok5S=oQwCW-5g)8`e_yG zb<31fXZ*=5NoC4S13*JEjUZv4R2FQjZDB#tMHosisD?9TZy4c%{y@3L1YI;(v^gPB zL7E}g9b5G@WpxoB)&kW7*&!nlD_|wNDq@fZpAlLF7f6+{V5DnAVZs;fg4oQ2+QAy6 zG1W>m+^aT}HjgIJY}Ez>wgDdX=mnA#+`bVG`~_rfL^`UIbIV%EDq*loYU4E}pG|w3 z1TaioY$=2{MbI$s?V0g*ldyA9%NCn3mvoXLD%Pr&*;rD}2J>dxs$$7{K?lk(fpPSD z6a>m3N78FrI95&(U9nISZBCK+bhXd`sfM=6hShyb1Q%eFeTD(Qz}u@*pzcsggcg^DQ3$#@etSTY&Pl32)2lpIqD*+|_Yfpf;KFi$sN zm5BNR0hkfxa;~Ht)TvU(V<=U~a$L+GbBqMcDqe+XvB5;BmGon+X2h?BAUWTVnypST zlH?i8EO3o(E3fg*DA$c335_H>Nj4Xc#<+4jlksYvSWpc?IWr2xbUmAji$u7KxnPu0T1k#<8OeO0%7|99 zREB$Y(~xpfT+&cg?i3UMFZ8DDB&ZDMVe{TmA2&bA%c%9P)<$H zyG2Z#4?J4HS=gY zFExWCo$&xT4P5kKDQb3nBo>5N*$RU^gva7KC&XLr0`MAA36umafhQH+Op4`R)muuy z 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

5^ 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 diff --git a/doc/schema/rule/conditionalTransfer.drawio b/doc/schema/rule/conditionalTransfer.drawio deleted file mode 100644 index 9f632cc..0000000 --- a/doc/schema/rule/conditionalTransfer.drawio +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/doc/schema/rule/conditionalTransferCMTAT.drawio.png b/doc/schema/rule/conditionalTransferCMTAT.drawio.png deleted file mode 100644 index 83cf65889f028dc201c25ea81ac742ed430337ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84882 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%0DGO>BM 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 A`Tzg` diff --git a/doc/schema/rule/conditionalTransferTime.png b/doc/schema/rule/conditionalTransferTime.png deleted file mode 100644 index 52eefdc978079f395f9b343229a2957d3ad92278..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29921 zcma&N3E0!r_AiX0qA!Rbs2~WuC<-E&q_c|JG()E}9nv-ph^9%Krc=_iX_5+p%A}}( zA_96GaRLQ|1E_!qBD^X`jt5adj}r)@A~>Na%H2Kw|M!0Pd%ov>_j&TXO?LLMvi90* z{nqf_6^)SRc3j-ity{Nq1AZ(Het+oJ?eqm_p9Svf_ix<{eom{$NwnMYcLyKt)(!GD zaJEq~^Kv=YZG_GD*WCyNDk$~F2pcv6LGW@;XlP0m+=BLsBFcF=C;s&gfe`x`2wWZp z@{F)~ZFcYnLB_%m#QoKumvYtrn#eI00uzj6VR(cM1$SY&s+-`~bUSZ$+DCyqud0@F z>0CA>H%1_Y!{!=mbGCAx3m4{lg$?ypuc*OUc7NxM}AoT&fR4892&VZ#Bt zMVXg0z5-s$|HaWbm1{b6H*14iWuCX?s2b$`Yl12dKI%Vf~51gil3vYAS&TJ#QCX!kpPS?bCqblJOV-8JYAqmB<&!J zH4pD^SuCTZQm~708*;wH@L3twGKFy65*lILh!au2nQ#-ht5r9=ezfA_{B?H{a0eAl zS1kp86E+*15tx*V3Iu#Iz_Vn9s2o<7nE;HSSwQww^$3cVlAuMEaapZ!;@r@riG-J@Hb;Q8qVhMTOIn=%rEWPh~|dJ!cq8&ef07YHky?v)zuc+ROvsdzo1kU=aNSFvW21`|12 z{&GsP7+nZZ9#1{)V9|0pMi&zlF4~zA7XXum3V~#*eM4zJFN}j5nW&}nBD3VpcI^ zRcdmUlg+HNRHRduty;<3YcMN_0X=9W^KFt-QK2T9o{-4rZDFJ3cmOuiA?~kqC!5#T{hw2`UD;t3`XgURR}b4kIa6DEpkX zLe=Fc)wA9dS;F0FE#V7AT2{E_3zg(_rBq9jT7>XPc-#y^ZT=umZ%7d-vSdSLCY>gY zvVeO;)D|rfA=Q_P7s_gi^1xIy#j~cJ)&QZds7qlZc_v5(98w{mB*RrQla3eZVpK08 z-b^7`DFkYcRy^d#+DFqg?Yfc-nMhj-2{oyax?3s8KCnDmqIAin*Ns9TTX*HcE}&rv zNOzQ&h)e}@S+vMn_KIaRaJKaAb%^DPe^wT$Z5~k1woLT(k(fsOcQ4HW0W$h4N+u zhAEpP8kYSwC&Ie(88uuBInpuA<%v2;yej1F{uUqxEktVGCTx#_33L`N7PH=_;bO87 z(zI$mOt+j~GMG)4vZ;JCrlo=$Dm2ptxvcA!VYu81oh^kpd&J=(P`8GcwVc7HQbDo? zp6j3w%KHVCIw3fYxbAnVSx!br%>`z;F!W-1KN<&wZuqs@}STHz4nNI5kNJh!#7 zfMb<3&@F^F>#JrR{)j`VCNLJ&3uK|xii=i^;)SLeN`fx9vlT3{W;j>aQFh`q({k4k9_0b)(Nco;Hp`A! zGFP)l@~*NKvg_eSQ}ETqbdqcqplVv;GjO0OIoNF0Y=v+%ixV}>#1h_kFfXYHoCy(x z*Omh34Q-~ahCKsrQXZC5^hQ>WH4 -=`?kzty}Y84?9o?smJFgV=`(M=b@Q+f(U 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 jHel7`4osP6?};0 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 MC~7E_BP>Jz7vt_aIRF3v diff --git a/doc/script/convert_links_for_pdf.sh b/doc/script/convert_links_for_pdf.sh new file mode 100755 index 0000000..2f4d392 --- /dev/null +++ b/doc/script/convert_links_for_pdf.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Script to replace relative markdown links with GitHub links for PDF generation +# Preserves image links (they render in PDF) and external links + +set -e + +if [ -z "$1" ]; then + echo "Usage: $0 [input-file] [output-file]" + echo "" + echo "Example:" + echo " $0 https://github.com/CMTA/CMTAT/blob/v3.0.0" + echo " $0 https://github.com/CMTA/CMTAT/blob/v3.0.0 README.md README_UPDATE.md" + exit 1 +fi + +GITHUB_LINK="${1%/}" # Remove trailing slash if present +INPUT_FILE="${2:-../../README.md}" +OUTPUT_FILE="${3:-README_UPDATE.md}" + +if [ ! -f "$INPUT_FILE" ]; then + echo "Error: Input file '$INPUT_FILE' not found" + exit 1 +fi + +# Create a temporary file +TMP_FILE=$(mktemp) +cp "$INPUT_FILE" "$TMP_FILE" + +# Use a placeholder to avoid sed escaping issues +PLACEHOLDER="__GITHUB_LINK__" + +# Step 1: Convert ALL relative links [text](./...) to placeholder +sed -i -E "s|\[([^]]+)\]\(\./([^)]+)\)|[\1]($PLACEHOLDER/\2)|g" "$TMP_FILE" + +# Step 2: Restore image links back to relative (images render inline in PDF) +for ext in png jpg jpeg gif svg ico webp bmp tiff; do + sed -i -E "s|\[([^]]+)\]\($PLACEHOLDER/([^)]+\.$ext)\)|[\1](./\2)|gi" "$TMP_FILE" +done + +# Step 3: Replace placeholder with actual GitHub link +sed -i "s|$PLACEHOLDER|$GITHUB_LINK|g" "$TMP_FILE" + +mv "$TMP_FILE" "$OUTPUT_FILE" + +echo "Created '$OUTPUT_FILE' with GitHub links pointing to:" +echo " $GITHUB_LINK" diff --git a/doc/security/accessControl/access-control-RuleEngine.png b/doc/security/accessControl/access-control-RuleEngine.png deleted file mode 100644 index a7113974a111e7ca79da98024774bdd908f70f4e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30462 zcmZ^~2UJtdyEP6mY7mhG1oX8)LX#rW2_gs~A#_3yO$ZP|AcTY#iXdQ+CWwdvQfwe9 zMG&QT=_)8HB2B7F7Zp^R|H=Ei_q+F7>-(=2O*lE3b7s!Wex7IVJ&6Q!Jm0>5_Hl7> z@fjInt+=>$A-TA?`C)s&5!(+ha={ySpcNj&Rn~WOj*E+Te-MrsEI(c?&t4G^`eqJ|MQ))qO!_KMYWSknl?%*k}7&? zn&3YrH3fAIO~?P7Poj|N|J9J1f+A?(1W`#zQUwD(nNsP&q2N6ft?sI>Dg!?0F&H$m zJ=xua8YHP~pr)dsprX$CiHV_&nW?0*KKM+d`jWvLp6uc4&-saG0EwkQ^#`XbD=Mff zaBflGJHX!$oMfP+sIH)>pr)*E^2HYOaCi4yF!hrm`|MB*g1KJqsZR1X97U{5weheR0l@gTff({~YxshfqDh zop6paz(@rC*U6kCDmXCQo>USgfaC|hrvBH6T4<^ps^gVUnqjC`-gLZ~kAX7&KMl}H zpi}=|%qo~h#?dKM`oB%9;8Yxa+&vh9ESwR^%R4a0*8)RjnT9I6GmL4WzWy4XHpamL zK6)l$ik2*jRUkDq%+s8xA8bUSdOBL*!pVwu%8o=uN&pxkOsHRwBbFNOX{c#niP7*< z)uZ@%`zhhcXbVTYhGS5$vIP+g6%j+QC;A2|ss-87DM}b$FMTB+Z##7g(auoSQ<_r^{oh=;IdYscykl* z4%&7ww+jJp2C5Wg4;$rhM+c_8fw{G(H_5`t(!ol_(9y#NZ>DbMfC~#?s91tCDJ&W> zK$Aqn)4kNFn(ls~mOf_cSR6JyFkFd5u_rr*P=bRralv86p5dy-;3CE*W@w7CgTFzz zD#29UON9y^55`>4i*C*t0SzkJo@GPTw5K_e(56(g5I;u`cf2Xi!9Kvy$QteF;bG}u zs_wv`_=TGiNUEXUzIG<=wrI!T;1Hr2nxOAM)bQ~Q3{D%~_6S z^l$@ZcRv=%GuSwoNcLt~67XT9FcT$T4IJKIlj2}trN-0`13d~dKx2G7h%^;1Od!F= zUER`1-6Bxmo?!-VPtQZiMxX4>)bl1;ng)1q`lCq>V0q)w;nt=`6g59DJvFos6&#}n zDf`gr9!#`NsCfuhA4Aa#wFzP1)XWJqw2h6brIlS6nq^O?2m69+Fhdzu%K9c?kz;Ta zH7_$mZ%s9vFIcYzUd9^6{$aj>4vzk|#wL3HwqZU2#{NFWq1FUHESQ=Y&tP{OHAT)C zI%WrQj7Q1h8Zb47`nv?a1U{RrO$^frc%OprMar=~;Pb zhOs;Fq9b@n1 z7(@eY+R&^#HC0$1wp4$ThmoegcR0q6;NT5V#lVzKqlSjiEHrRvf`dERAB$BaP#9PZ z4YN=sGqkNS+7wJ43(_< zeYmYzs478U(ZIr#=tX3aZLIOuK{R?W5$$NH?B#&R`CA70f=gp8jNFyNJr%vNI5L(M zq(?T?^fvZUS2d#%1F;%ltd%f6Oq!Av=ze-sGZw`<$jn#OUq3wD z7prGTQ1SD|>08+-I_gtREQ~@;DU?7(y&zSxzlx!s2VKpNrbbk^Q+3b?3G+vz-8suf zF@WjE>5Cfp7iu4l4^jzGa#s)cH>3rFBV+<+zOX0^GRupi>CV)1N3$qqnt>XsCJYU- z8Zj7yMPmRgfrkDYnf`xZN)M~(r$NVKtj$ll64kvi7%Lk3{{>U_-qav6jS6DPzmTWm z=mh9P#=wtlu6dd8ua%y4U>hNiK; zt&w$55EDxaQVan1@2TobL{r_ZR7_YQ1an0XMLNbTKoyLXy*&wSVXo$&7^tLTiw#19 zU}9?>?4!nT*Qel(N!GTkARBPl$l8~L3sUm7HZ-9*FwK08Y`huP47{;fkYy;w z(%cpoU{4CLRkQZABGZ)hF<3l~MDeh)bq_c2^&ruez1&0W141$6Py-^thpJ?1OT*aF ze2vI@iaz#O4_|kCO;t5x2WvZUDezZZZX`sW< z`i`0mk3dTh-wdpcj0pZ55W?Ub>AtuyTYn2O)*AecC#XAwTc{iQtAzw`PW18$QPjYr zL+l)FiFAFmim3*fsITnfV}Ml*vp2Fb^CRKV`bvH#w#Gi8;o$cc`W}wHN(82+p?6>i z-PDetZe-?e#k4jwGol$$Y1AMKjGd!}pD{@>SkKr%9}{Hg=^2hzwWkMA)XX$((Rw&K z&VdoEVeZd?1Z#6mvZ}oy0ZqUvtJD3J>9kOSqoztY=SnK>RJyV^$q^k+G9?fQ3@gnL zKb#lEP|wK7)=teQ#K_UlgXnJ;M732lW;xo?Ou|%YG#oi3Sk==vK!ac!Xh6{LG5}K< zgR#`4*yFvdtZ8Z(gCIlqFp9B-vY&UTy*0s#Xl&;TZbZ{T#h(=7kMXrr#oIF6)issT z;r0aZg%2j&f`g=3ybm318Rkjw!YcX%)BRb7SX(0AD9i$5tzj6dW}xrk9d2j>n!+$i zj$t0kKB2ZOYr2;=k!3G968=Rg}YNj*6B(K}26OM}NH#oF@no`ua=_b2=dy zPbb)D2HX3a8~Iza2>L$3L7oAAoJ%{h!pUGEVLYhHBtst(4LmH(P#;<_-abGrNX^V9 z+{zLc?&nQoQWQgdeH4AnG?kU{Xgbr^6s@X;wN|v%a}UQbacHu)MUXdvU~Y$|nwYB_ ztC4Y`SS-`P!3$%B*CToPkPOrevA&kxfndoS=-~|=Of0c=u!>a>*4>%_Rw@SPg;%r)RQ9GYapsO@ zUOs*XO6u+&rYt3Ox|z9kh`mFYou>sj&l8|7O)~U~2;-H9a#&TfB*pm8DvEh&KZVl1vQ7o6{Vc!tkTv z%?aTq1jX<$4vGhPda9{{uQ-_I3!;;OpRy8~6lSLmhEOv|*&x7*KzG*z$H^G9x0QV$ z){FuEpsO3(hKHFEI9&~(1`;`;LLVec7!W}X{vY@Tj{aBTtAevUR;S9vCB|ih)w2mb zx0JW{>A{Y{Dh*lZj-&8OsO7=R6R17#w?gn;s0Ue!QK-++S&~_;M=c-obYPV)Ch%Y_ z_dm$ey_^-ub^U^Nu>Y+K=-j~j^+gfkb(^Knyb$;6+pN`W*9OOJZT)w){`@dQ20$)s zuVqH={Q0szo9Q~7s~Nbs@VGhT)=JZ6Uu4wp$-SGaU7|~0Ze6Hyjr!9OwYj9Rx&7G-0%&T5C%F_moi6!Wji#fv;VcEB$HhLoAXjqdp(#pQm%NDy4aPI$kC0vWf zCh*sRF)M5Q^EpR7aw8~WbE$eMk2PL#SjDR*u|b1LLG`oq6Se1OT8V9etLb1C4^*Rsl&V%VO zOtTbQBl9EI9ehWsN^^8ou6kioV3yzTT!>hPeoJfcK!H)!_WFoZ{DEVmd&~asnb9=c<)@JU+NG1k-drIC>XT8k6vv2s}b=#=k*(&kSo`C*;; zQ5)2VzuUk3GF?I{Tv%i8Lq_~GoPyum-ZL_+NQj30pI5<6T`3&wNLSb8!yX=8sli8j zvbj_cUYM6gw)M^a)m0oh?@20!1u%;M4zrI<1FxB{Ld}RG2MbwEk7A&V&-JAYD zx00ai47ECmY5KbpaYW~Q%^2%bvk^16P z^LaAGxmNIhO~w=1y0SRfvNmfxtVsJ?%P#uV@I5^L7kXiuIpp0JaPOZb6}b zI#p{l`ux{B@s2CwjpSoJ25XNFqSAOFu>A*SCm=&tbT+yj=Ke4ci$%Ah=B56cZXmd} zj_E}!x;g8g5IY1v0E4li9!J|CF)^=o8DeJ|qQ&&G#0YR%nDB-bbU$W~-oQ3T7#sd)cEz`(;!?f0$P3k5UaxLC{P_H8jHDnSQ|nzPTL8<*)9px3``~(EjNY(n zP`@_lw3McQpyK%ft(R59KE+QiTE)&vDw2B-+JCA36jfjR<6i3NUiFWj*S>pU9wvg> zrh5{a)zZA$d1QUi$-kC=@7-^Dii%7Mq#xTveS5!Zeb{%z(YJI~Y9m>p&bvctdvm2Z zPxq#FL{;S0YL|N8XH)6ha4VQBn=d}`+egN8zA?&lipHScDIxo7y=kz5WZjM=cxq_l z=bOHxyTkCJkx!3>&0KXvSlEvwNmLVC=yh{a^^=#5jCNd&-1y1F%gb@*ziut;HGhR- zn`Ei;U~gfm>C5bdh-(4<>G>Uzei@$x9rC|oqLDQ`}+D$pXW=qVCK=?h-j{|P?)u|h&g%^IuiM7Y_|ai1yIt_Y7@0z@>LGJ zo=~=PewgJ3X5VmRR;b5VcSN*c>>>bdrYQR#1sCU?7u-q!M)J_JjaMIRp$L0pk`PFm zdDG7UlRVLdMCp9*v3iz$N1|>D)Zp?VlK!Rr%$$xU9GSPZ5 z@9aFaDDQKsk1d@0EEIk7Pr8W$Giq>qW395ZdVILwH~ilojp`hbUvVx-%6V_DwKOBu zW18jk%tsP~KxFAe)(M8d8kp0an$;&2;GO9yayhYJoTGRoq%iPfBF>DMg^a#4KTNf@ zzCHip#48(S1O<^$_=u`^S`Ichuus!GWA7k@tA1Sw7jLu|a9u%wr zUC*;!8V&4!_SWL8c88?pAWj#07Zu&HOT>Kny1RJrhccHj%3Cvy6j`1Q!St4=)VH*E z4=k6T8(dgUY!h-4PEXTay9q0}tm}Y-ZR(VV)5=@-bh58jb_-#}j3K#QSIQ$nyvqy5 zW)cmI?3szWr(q0@PJmxaI-@bI?IE8cf4v`1-B+fwo<4fv@3y&Oz=dA!y+MzimN zP@iT7AtR8^xk0@$Md)UN-6MxMD|if=r~JvKLcYJtFBIxcGaWm5oS4bFad0;k)uOLs zf&JQp0M;}T$+zM$b+GaaQ0}mm#$Urbn=32kJu}fj5LSF0boxL2JBnSB@2``3e{+YSPCnCSR?e?}j7ABz={hYtX9{QmKfby9{ z`4eW~1`>GONMFWpFO=2yjg7R%RRuI(J`}JU*X10W>|2{T^LJ%KNboQO`YO7P`#v?JyMCzsYczOiKse?bbZ8}p ze68bTY7j;FQOe87u=`792maALAAr?LHVJj~{$x1pWBErY=C444GkfdH*}u%({-k!$(YLT#u{W#$>eZjW#Gd2C%k9lytYlNpbC?r@C&EZ^N!ErS zO;Pf==mwVETg&iS->1B z($`EZE~Y-xoK<@P_3F!=!*&7aoKdKHf9Z$(hmfaak6l_KgX+G6FB8-6o8=hfM7x7X zn{Zjz2*oyQ%IdnJwT#x<`8_TEA_FB56ChCYy;p8&zW8y-=ktEVQ_^9Dk`P|OiC>|E z4iwE*=75nj&s7*3#pn>SM=L42wQ#+%z#!h4px|d?UZXs}&-5%0=qbc5yf3!j(zM-& zf{Vv!tu(xKdC(&n4>}oqSw_YO%&D8OhRx;r<$`;c_>Rw;4xM(H>2sY2cM!g zU*$a*d_sOqY-NS43M;|#=(-9P-H;KB+(Bq*K+^oZc;#bbN zkI*X3l(PwsP-*&*%aTNG;=9xH5AFpR>f%zbwWMf_e-+LyPkr6R2^ltfVp>o$0I@5^ zLPlP>{L_B&>poPPBxJO#uaLsY&z{l8PMhGY9k92jU|{u}UH;XXq}Ju-TUa;s=!DAQ zwt>zyZsJf@v;328RJKgcJ`{v12{&Xn{N33ctnk3s|DH-NrS#`hPgZ_E2?-WB1k#|q zsEs-GsI5@nH+SQ_K`d?8jedK%#w1DKjL{5WA^_f^o&4OeM#Z?O^!mk`0eH+X&u?Mm zs8v0P&S-1R>N|1?x;Jaj&1N$V}UX45E6YY||F7wKmzi zf`@p!$L%=K;Ryq6xYPwzfO4iSuenqV5++at*ivg=_80UUpfVM zBMf(OZ~R)S8tGfEU(sQmy2**^=b=6ak-49mICWcd)b^B#gHp2YKA!!@&kT)6ZThjA z8aQXYf_{FPJ-xM{nObdKWZotLd5HSfEqd>qXvpT2NvWEj z4|!PEfnToQKUTaOiZ-BC)t7n z=MK)gLS@riAgGy#Mfm~M@l7BX70PxX8$)H|TD)@nKGP$|!@lInNt*P=!z9e3Bdw44 zH&k%y+^W9Q3ljOFWL>B+@*4;wLk36uJpCJ1FRgdofLN_0ft*(uj?8+kDd$v#dC-`k zI|fCs#cT0VCsD>I%MwZ9;cuRB$bc@YLDa6CEJi zq&#BCUWT=sxq;$eJvHDRvypktZtJ?K8_4KX*AE^)|E=|UuGy>^6eBocgI(uJJ*uf3 zbTr%&ignY2n6q=k=O0!rK6x?hK*^KT0gsm(w*Qb~OVrjXz8)mYyBZ4dI591#&c;`9 z{mU2D-rIka$uLGi)ZoOh+3REOewALY+VN1V7zDIM1MENu$o*=q%{YLyB{=ae14M-Z z5b!?#mDHAj97aV;eoH>pR9;+GC#zp*Wr=koK_WNTpV`{G*k&>wF%xvL(D_%{DwLh@ zg;L6=3x6ZAma_jKx|II%sDH2^MJe?j~lT4K~HAegvjXBl4HE_&w z8)TP>iLja2mVI(1ZqC&5UfJTAyA7aLYd5+*4xag!zdzqv#9TQ{{%bhNY+9RtUs-s= zu{Wq?cJr%Xi!F=*JI(5`*|tb0tR59Nk*h@ZFddp%&rv zC_XP_xF_n*Z00{2V}YZ`i&>*os*xM6POH3APiPt*j{kuZP1~Q*2K|gK}7B-1)P$?iz{-w`KK& z^e^)J#CQ*_iHjSVw~@P?W=@4P81y_vY|E?;pEfi1AjaUsUc22bFkJ zvT*|ikUfz82tO}?Zmd~14`0&l#?kXXUIFH#y4L)bdV3|{&}xnabR(;}QOP#i<3$#t z^&mH01cx7}S*Xq4`8LT3cjv-pg+7tLAD38pAzyjf326Ea zJToooVY}wx2AD+hm-%&2j~w3C*wm;Vp=)U^J$)-2a7SUW%P6|>^yvC4zID*7tC-nF z-O1|F0pi$~&{=S;@eU{Z-yjl9 zhm%HB@3i)F({T|zWZG2L!NEU_~rK$U_$}~=Q*@xb2CW9 zc(p~Z!$<;KfRnQ80JY7p`W~G>KOs5q*M~f==<=ns#_?xj$HBrFtfchs9{+{y28sN_ zX=lhTpGv`>40(YjRVCOH7pCCM*x0JL>6y@DhM}7)!FdY;BxCZ zA^8;04zt&#;b-u7W2NB-^F=NjobxLRcA78i}8)Q_aoBnqE2nsA^zK#C-+hj-!_g=K` z%MKCO#e9Ag#-~?bCb)Z_A3ifZ?Fg=fMN zABjHjy)5H7l?dOkbq@P#&wKLIdmPNpyVJsM)M4U;Gdf#~Rkl>OP__>0o+0U5=dC37 z`v@TA`^&BgrWKqFkB3cqojdI&HCi*r zs1p(V(MIS&vALlaeD+9Zk#>{b-!E5~7eHnR25RjLf!aG?P94Rzm51(;W0au7VtRC> zBXT2_YeV`pzZ?`o)@X|DgNv1nDzzZ)f^sanv}P))uRZcPp9WfZ=12MS1H}T8?=MsU zVle=++m~OkKmrGYq=$6g`nSHQA-l(TT5_?T&%3h|#gZZK$9(4937N2m<01!-Xc;rR zjE&iDV-sFsCHOeI*m+a|{>pK>Ws(y2q?Psrvn7V>=NtJcI2bGr$u}9G9XxL%?bxtO zHT@tme?i1AKH$>ak81+Rnkpr`W;nZvTSQ4s zAid$2K8}49Faox6>v7B<$Bs$1R*h*$&o+OW zCCT2!TW+u_KgFdI`4Hs^G!NV23#RmL(Hln5jzQk&EwCoEdLABL{hj3^-6X0H zrngq?*}oqiX+9rzU}dlHhVfb~Ed74IP)v!ygKChh^>xkOmlFL`x6j3tJ)!U%d$p%R zBkf(4QXbFIT>^K?Qs!U>PM?AZ`bgymc?Ml3ViV$R?|7tY-j`jtE{i$zuIJSKuX1HI zZL^ttAF|p&9qC7#5I-o0q>XmEKq|WKZ~-jqE{|tN3WJ(ACD|8f1I*2U@~6LrkcwW< zwO7keT@tFcl1HjNlR>As4)5n)y(p@BWA{4G`-9%6&UZ;9QZ6Q>4G#wgvvxP14PO_p zkd8kqbXQXMLQ4VcgVq6cx2xQ|qJO()_OOt4mP}ESzvU!qcjUn`LE2}s-bJ26oA0tr znU7y^vTCWbrb&M^B4WR~qUT=nnx+#gyebuQ0#{yT9}U0p-oHCzdBLhcqgP6LiO+K{uCebfkKCM6xt^a?bIG&nCVY zu@(vP2=|N6dp8*6JB>Nc)bBLzzeU|wn^PFea7_m*$X zV?~BM2@BhGimv*8SCN*Io>VBHN0QaDcN$-P1PNT}LMT9o@kd|3wkuV5gsis#^jehS zU$l65yy0y{gAnViba5y%qfWYj;2bK=B;8#eC`|sLHfw<)A|N7DWHDV;#YDGsHIQ;w zZwO=AVo7jxIY${V2H=yDlCr;m_?RP1va(|AA7^AYih-=7LC|CWfZFa7{CN=r_C&n% z+t0=&c%bCjO?-l!3LU&pIJHpd$RqX-G4T_~O~wj#-{~@N-jKHoK_H**R$m(MIwOZF zg1;He{)Wo^vprpR@pj9r*Mi9N_@gxesIL{hOm4}dJ(F!umg^Qyv)ZqjpYHK1APXJ- zd;Y-12~Tad=3Q^VhqCtSl=qs{-|xSZhs2bxuR6{Aia#Q8O#~{GEN!ZrsNom$iU00_ z%jm?~_1iN)8({K= zV(KQai^>;kSl5CwA}~bcpGz3zLCvOq zMKVe?m9YzWwxZjF{pD`AXCErrVwm3->@J_(`le6WptSXQ88-2vF#F=TcS*0tY2U4W z&7afCxMrr#EVF!<{l%bbh8^w^mmOkbJ)u={dM2JPRZkvi`6o8wPr9T;6aBqYh8w9h zhilT}iW5@sXunAQ`pbExyT`a&R&J_0hCbl_8~>HO+A4@NO>3}DDK~%e=p{R|M_?P$ zc4@tvoz|lA)Hw+c$Z#{yO7^0U2>7zU}$__@mX7-VtMUGzv~3t*B(MO$F* z2J)*;l2|Iw>RXXCsRqsO$I9OC5xy5VxM|_c%R@xc+lf07Z%ttO+^%-(CQva6EM9Yz%RoJ#oBsCOW0#cay-~gUJ0mziXz9 zCu>h$-IE6qX1DRZs*!#3G3=r@X?D7E~)PhwbPh<6fnekJS9h*1u$sg^hb5`5=B2jqL z9qqH{xB4}^+XRuYbj)9tum&;j{)JTtRlEUlz;x>O0TErhhfLAC{i_?ABG$Cn<;&l4_D%f|6`i~3;WZh1?Gq7qCEUVrtt0y81|%R(t+(>1O~2%F39*dm zZF~=Qr*z^*9QhU@)B?7YcI}sUgj$~Y=dmvbvFx-xQ%CJ}OZb20ykFr-v}UL2*x}m$ zYX2IwR@;gDH}a3?!wxhXTub>A$ z1+GY_Iai)R#ER*4N5nMkW}R|A#8X38BHe48Ht+Df+DIpQc;70qo2FcuZRa%|np*+q zj)+Y)-f!{$0Vs|Xez!!W%*~(@Fuv=(Zzz_OIC>6@f5X`SZ^|c~hID!4%*VhAccr-1 zf%=lPw~vSV<9Arm%jHQ(Cqe11m?^I3#o!2pZ%|c@=cHKJM}{*!~vOiN-n))nP)Y1-Gk7^ z-w^)ow3pOI0>5cdR&K??iGN~5HR(r)mRYym!oHOt@+H|lymHxb+?i0*>9}k8<-gdW zO;3Jb`EW2Rp;EbhpF+<3P_pIr6U?DX$nyf&ov9_}0|iW0c}2hr>hb);XG>tn$NLY$ zBrrB8=z)@b*1~(RkYynl--^N^^H->rUG{1#p7JXha#)yLubPY4Zb9ejh910MW(MM{ z0zxe>*Vg{j9nSREf1Uu3TBxBTUsE5OIy-bw$cIG~no(@0QU}7FEBCJGvf)FQUm0CU zfJ<5b-ir7&@=crf2r(ASbkB!?2k46|4tJaCF}_fEDd3Z!m9=ZjImofh2iw5@vN)JF7Bi+xUX{eHQdS)1AH^6zcupf3kXu;HyoT6}yYYSe`C zd5;esOaA$BqH88$I@ovLxQrAnD(*0k^Q1U|fB$Lcx(;YN@A#(LDz;@(!TQ6) zGvg7ota$&l+ehABe7$d-b_mh7BRveG%a7-2mFy_Xw92*?yuTvJj&w4GWq%8Ajo@F{ zd*rH7{3jXSJ>xtV$9t=!F<<4%L&_0DPHP=PiH)YFk1CSxt7Qa$Bq^fOXPy@>{WJ6D zoO}opnqB_3h_u8v5RV_@Kd5yqc_%%@ItPYa$+!}SE(wT3u~)usqLtv2Ex%*d_*V7m zNyxHt(VuddgbyQ`L>KnE_rjW&YQ9}sugfnrVZW}nJ_nT=gs&v*h(+q4p#3p7V}Eg2 z4e(^t#xB{5hK8jIAP9JEGl<>vEDM_hA!wXn}0IJkb+6( z*AP}#??AaTi@u3tzGZjKUcqt8Q%(0coN0NskMyD)u9PaoZ*t82qLGkX{m+N_w+;4R z6_qlhS#=Fu3f}E2wRw1-^qV&W$!FDt=?tMZ$iI3>H0+-LYU-!;UU_7C{ILDudr}1d z#i5EHhfN&{EdetRGmqAit#QJ1sqLZIFQzD>*yxH&6YAZ)N_)?QE+4LOe4@eLhL*Gs zK9gqi&7HY23qKoDB75|9bf|7xXwC!^F{8P|@5?J}XC8RhqQfsOdSSn`=44%b2m3nh zdzTT8df=#J^4dr}Ug8zmavayf&#hqgxq3M-$o_XKJ3%xSsP!OZh66?=`^s6rHQqF+ z44PZ&P~5W1vyK+%3BJsXKS$BN&+Yqzica1yVoR?c z3$fje&j@Y$8nyl9t!av26WnGrC;fU_SJSBf*!!71F55089#LaeTlbxK`X}oyb>ws; z567|%CEsOyPZNf$)jUj#gywo(U$?C-xKrsGd%e{?MjIIy)zFducxFY$f3gRsHY;Q= zX?NwxAx04?xZ!?;_Y>l|>r_2RO+|nx|E7L9j4^P0^YKu5pJZ+rtfsEwu;{O6CG0cn zvr!9lP!r-r$$Fh5e{FtF9@K7mGfK4k$ZKn#1~;-Slr2saV4$GCxE0t_5|SM4mjokI?pRYC9WTFTn z+~#^SLFHociruKY>XMLPK?aJAulbYdA)%>lz!6!{+^O+1D5aIE&r|+ic@W)F-1Lv1 zZ4^__0!33^!29j}6yNEn^+@3xt{92rQay4~5@6#evn&-Zwx#I)R|CGY$3>3$yX0Qa z@7Cc?Rr;LzV0o;b(p)Y}DuZ1*rM3tUuq8WH+yk( zz9}fjJjaSTbR-?nGb_;YON;=xNP#Sn3}K914e6HM&tkh#>4kQ;pS0`UHfF;$bsBSv z`cJlSM3rZPhtz3VDaW)1|G+rvC>Q~a(7@iQ9_d^15~wsD$k9{%G6}!NSgt*@S8)ZN z>?AP{jwDhtpC2+zb?oUSN*1Hv2)dCMIYyH~ea;R26$k|+;uzoeQRDs&AQ7f{K{&2Q zzo%~umY-Orj-{du6R>)gOwTwV*|0Ip&A|SA?ciP`J0Id~LM~TP0YgGg!<}W`f9w%9tzVL5ZO--K+~|`em-!pt-DNiqOSQaNs3CRC2FM}PCp+)m{UcSL z2Ah0!t}(p!RTXd`1irhdiEL?UM;_qVR?Lk{+>>+}5DvA8VhhHd4xT@F2GWRx@CfLN zF$RvH3IH`(F^k1Ws6S0YOLA1T(dhb}jfD{)dkbZYdK!nG$Uzb0xVOeMMj84MU-DSz z$Fk%yP-zrMjc0}BHgFdOPA39gKZa|26R_Q1)bCCw39-`Pi845g3Y+~Dt5ZpOoYOSH%Y0M+xE_V&-WRc-s^exEnF!jZ|FHkY+V zfC8~pGo328Aah3m)$^{}$}C^E6vZxC0y1Y6kfMmUbRyIH9|nkl9@PMROhfo%`=T)4r(TN;mJ7_xc8yJ?F7#`mV zARnijN@YBPc}BMYU5R{6$}B*k2}l5@dyETEo-r*JXSZh*eCWW!$#+OmY!zjcAaQPY zukK+UK<~}W7F;ub!l6uSMD_Hb-?0-D7x}A%?493~0iy4WkP}%bh6vk#6#W`7=j8vA zyW7(*p@g`bp}=oP2F|YPGM9SCzdPI8O~RXj0;mdcJBSbl$mht%&cl@*!cIegw6;e& z*sEj3&Ox58J+v;GA9xn3B)6W6m>3#2QK)U_aM8X%jPEmkJY}~pM&w**>jCrx7e`$f zWj0(FmcYuE8f4r;bHx2DdDakVuNH7REPlOrB~|=Xk~LKJQVXBPsGG)k=smMsv}KvN zkhNT|p&iVPZ&F9rysvHe0g%llqV4xeyD>ir+NBxu381b!s`T31K+h+`1!nT0eXoG! z`Ckiz<*eRnf-Vm6-xh{W?Y$=*pFVidAOl!;A;_qHFvr}uxxTbCU~=k}afMClK554M z!=ho8{xcpR?Bvw{dN^>AZCLmr?YsTH7+n;b%@Jl;>@hGyJb|H!B|}|sK|DZ1IG$6E z-EZ0O&0wjMz4J~6645QdeIRP$SLg298tUB7TKV^M^7Xj4I?Q^X!IJEp=7PD~$9S&x z`k3^Z1wkRn@bu5!ek}(C?!?#T>@xIB|YNtpyOx*vRPj(?D|yW?k^4Mxl@b_tn1U8A}q$ho4gad2;N;6#-NXV{USv6yXW%4vn+kzxbU3*7y)0Ef9gVNv@{5 z_a-chBc2^N{Z(ue=zpV;yZQc6g$r}8Bd!?!)0?I79tcNYutxuwt2|O<*Y+GJDn*_K zg6ib(OJJ_JI`_mR!Lu$r(7MJDn}A;chOBaqJrEd!ymIJuRJz!s+jA&I;Nn;qtFK;a z_|X^g1}9P|_oKHIHj~z(_Q82tDy!yiKy7Zx4NV&K*}=p9`%`TwRyy9V#TMQcSP@^cQV}ly%+aEIm2;~8jbs$ahgqWW=F^KEsQ?ulltWQ zxN%U}CFl*!(wb_8pIB-BTjg;@d+?bVUH`+LpYLq%D9b}q|Aim()9#SoD6Fv1%>C=P zI%7tJl5-cQ^%DZ_4lBQq_el9iO}S(gU}boe+t%X(0aR`A_m>CJ!icFi9J5}EnfrcW zfCbiGw;zgufuWD0HHa0pYu{g-vatVr-3g5QKRjE2_n|8%*#-hX3@h`v&#s7&BfNn; z3Wv`F89lFh_f%k_F-R}aiEdY*b z91roNLH$g+NnP?DX5%9n#pd5YqjJ&e_DzHL_`WKt9<4}*zb<$0z%c}+Oc`Cj1A6Yn z0_8i}WUppawSN48Wz4HKp-S{y+fk6G%t}YcUE^CQN&O4dyAWV8AYM7HJ^BzNE+O(4 zE@ikIK|8OAu9%-}_%$Ap7kqKMaB28iu}U9@GTvBU@_h`Ha3gBbHks$@(+_S<-(A6g zB0F-!KW9^h_Z*?Q0hqm`MjeoFeQG;A^sjfRPiK?H*#R+TBook|aI97U9@7phKO4=< z_mR~-8wBQh(+l2BgRJ)Ne}LSdo7@M&Y;mJo;(MD__Q%I8kN}M&AjE02*X=_f>HM48 zTYH3a$}gR)Uwjhf+A{-ULw3oasqmu`RJ(ZSYKKTY?*rmPuQmYAmT=u6ck1+A*;JYh zs6e_ExcfI+Z!P|LbW+SFYe)y+Srve1Et4~%$HZ@)A8`}cwDZ-uu(cWwG~!o0o#lJ^ z%6}cStOL5Pv}+AJPz;&Q*nJ|*6)J#0&g}p6idUhgWk~gM@C@)({kl%lmVmtH84Y-G zvTweXD+uUZL;v`eAPvEYAC@HKtUb427MW(di{n#+B7`)RuJp_Uzx(Iq{Z=RVxl;!? z#%_+SBv@E}eZJ!1dEnxb)!Zeo%j7=E>OGNFuT=;@Lp@}X$nox_CFph_3{Bag5>giV zi*}C@lD~fj%-oHI{YJJRQbrF)e{FeG1(0p%13@|E1#X#~&J z^X~#3O|olXt1T6-?6)U}Y`UqAVcK4&O8Fk<{^@)c`?d^yGVbl;rz`hze_p=<%ebX0 zGsu6oc6%~jbW|dnU(l=b4#zd+cj@!Jh`24n){4sF60nMijDF!HZQH7C2V%M?wX-*V zh&r@LUjQtAwJ7^J12{k{qWvkqm^@b(2mOXk?37ULyLx&L{z^IzX4P_m;8gKh_VR`8-fm`kptJa)wQQMnj558_#Zu{fauj7S{ySLYG`ryxsy@1h$# zM2g2fi76eB#r$zd-VMK8s zzl-DL>}pa29@m@de)A>VKqR>_(%k8_Xv|9+ptycs{8*V6>;X#Xbud>yayDTBcy1DO z&hP$?6@iq1%>BCE!HD0J@hQ)Zvlw#nrn(qx>0RI=Y=Eu0RS2j6!I>2(TYPl%W;od5 zF)vVO>|-YRdH30IP?)`_+5QcRj=-`|pz52SCzrOn&jo`j^%hjNXJb<31+Vrx(9vrW zwFE<@zK^=J@6A+@+8B+gn157U$8+X_|GNiQ1C_|m9?j5*e`=0+fDL8=n=&<<5YpS* zdb^5Uo0~=!$~jJ#!c9(&D|iR^h$);%92?V=5y^RU$@MC;KrK>TZ+!iDYJLk8JoTH_ zaI2ZjX7Mye;na?T4(tT`U~JOXeM!QN;14bzuG`=7f(W2|4qwNJsi6wshjNC1YtWpv z9097Zu~#+2xy~|XvY|Q;Ea;ubfOl0(y6NA2HWP=|F2M?Jat-nyxH&Ps;1 zT5yXW63wF$%SDRTb(^~Eri&I6gA2g+v3Emu-HDmd4Grbii&fOSEoK9khl%{3Z7X6y z@G~$`C>#Texhi#avS>$R*jt=}>oPOd!(jbx2k;bFu|v@nsfx_m2X=NhIlGNUK*Bh7 z2_4rf)pDsn{&;vdu$bvp&v(9g3F|G`PL#{J86XX;@M*gj@U_0P3F4^?h^olU)Zmp9zBjf5F8eQzv`pP8SL8k;S#$f!ZsWK* z9>atOaS}#iDqvhuN1)k@13Zl&DO+}z7<~rz6J;ii8fJR#N>K3|W%Oyz*^r{F$$PbUn|EKXh@zlR17**&ur+hT?Zhh$u@f#m=6Tj(mp`ewYSx5QQI#7^5 zD6s|n?+q_z>4m>L%Qgz&o*A--J^q3uP1;5WW|;6hx&V)oP76a=toM?X}5!(d-xSLW6nN!cRB;1Zm1IDg?h#Q2hmn&lKZGt($qPv z8o2-P_%nq{|88BFGE|tGdZM7Pgkg(~!Wpmw2cQ!f!hmG}M4<%e%G^?n_`GHUd9;RE zh`(|1P+9X%I4fCe^xzg4t<`>GiyP)*A5aBS=NFMOK&J(nZPmtn@e%yaGoSapk-(ff zr*kwu>sgCZ8fWX{rs*x6vB>fBKg@t_v!4bmg)S2z&g-H7+0fz#_1sP<^JDn$74#{2 zxvzsqkd7E}4WN7DaDS2F~AEM?34>CngPhRM? ztQ<{x@%J&lc(koEuaE8@oF2b`oaDW>0?}|1Pz> z)q~CF(H4x5`tFSR|JwV`ps1JTU4c~>FzhZMAfW7$Bqt?^2rP?|BuSJY5=12<*#x-i zk`&2GmLOSz1OWxff|5m&5)=glR1P3|1aA+Xx9b1pR-L!%R^2cEDnB|q^P8UO>3+JO zhZ{Hx$2gOGw^r-(*>QWSITLiU>XJOU-RuWG{>NvkAxj)OR;rtE+ zkb@X(f-x}`r;8QBu#!7ij0Jdm3t%mZLI&s7RcY;Zr%qjOScp6N69}O#!7Njp&tzESgUIlFvs4N;gJY`(k`+HNE0 zAiD}Zx)jmo4;Sl+#&gj}bu#Y-A|Lq^NZ(3LUY;coh0krp;jMcXVqz~f@$yVETaM%K=R7{-o)LH``w@9K0e5T=D<0I%pqt3wA#6I#G z-ro3@7Z{=vryp>h2#pa^Wcm$sh@KZw_`y=DCROSpcN|6Yw&-aMcDUuic5oRE96K=b z=l^MraqgEulSs;X$}W8T8Q*+gKk+)=)KPbsj9AY=R0s(EX%6)u>&n&_O&d~rz2rdfCNY?2NL%hbD z$c=Kw4Z}--5KqB&Y11|!W1k0pZw18mlC8$96=I|d3~F%WF&WuTK!>C7@?nmA-hM6B ze=3wy*yLx}b1icqCshF!#CPSMzTxds8DJgwuFgJ8%Q^67_Eo+ZX||}=>!TGZEBP@* zzHo;4b>R$AMbl3$jh*pqWE2{Lt`sv1&Q4pmp|#)84QkODFD`3d(;*s7)tr8R8P75l)w>ILu{U?`cLPp5Gv{?1W^y`25Q8IH^z8rX1ppcoB=mk! zZgV(8+eg8po&P>|QNKZc#owI% z>*8Qh(yK&iJ{Q(NNq#!UyHOJ|8_>tlDr(*W#He;5Itvw%s&~+kl#cBLrLilKmPqr|+{nCV}6~1HDc*;V`F*%3! zD6HK{RyFKA(BKf&j|YRpoT7GX(N{Pql{_UGV5_Nzp@XTpPm4DO0aMZSv`FRx{3@Ru+c-%yz7dn z_kgBq;F2C-wQYexGYCD>Nr!zd^q8$&rourZQSVLV@{^6M0y=7t&D($8O_h^6(}+Qg z&IPyxy81b?iTwb!H)i#}kRKQBJ9u`k^}p zJLO1`Azkfy^edW?9}HU>#es*j{0@vg8t_tJsg2sQe zz_|^AddZ0yM%lFo2&CEK`jRIJSVkSaFPqe5PIRJ<4dI1av~+>VUS*hhOoO}p0kitV z_wj30NYVi~aJwO8YiXop_}TID5(x|gOm~b(S&gEa!*DQga4z~rw>i04p6{lMx0Q z85tfeQv_o8X9$hY?6j~86}ViNalGS1P||02V81&9+WI8MH1H@yziXJdzBVxPDbJ2d zu$V6v1yp*6XZicz-I*UiB(oxLV94#wvx?XYD1J<|FLdmT_XQxqsnB6qbr9f4@VdkF@&+oS{vOs$!jzPYqKbN4OzY`OzCM+s!~BM{ie2lqMDV+o|; z0{hUY`PX^c`~VP7!l>M@Od`Zfp!rb_1f)^mIBC-~9>s^N0_|iTAs%iPOmX_E^$pob094oZkNOOkhYL$49=o`?d9U4C+xR^}XmtWyOK`X??*n6@M_ z`ay?CvB)se9)7n8kp}9F)!UfuA(}| z=og*YoXa`%d2y2?iV80GE|X78Shdk^=9B#31kqnsK!cB4QdkL?5{zo<>n= z>t0X6%xe2T*Fxr)Fy83ckhV5#@P4$x$CWQ-XFVHzeBM5}5;)hHm)VXoWWNPObWH0k zDPho@>Vn}y{N!Pv4#5I8?6hYfG3A53TW)#9t{1;FM(a_YG&ODOzWs4SU%iuDJU{GvlPC@CCB+ahByhe+^x4z*Xq<4_b{jwm--S}|eD`Cmkn z8<5{~d-7%M$;BI=jE6-bE6C!===fnn%JP~cE5akGiANX8*h1RT2lynF!3^6^B}iD? zX{+_dhc^H##QoaFkB5Mu=UQorq;SB6YR1Yp<_eHW)Vy2>VaoKu;m*G)O(T?r2K-w4 z2G7I+l{=sBF$p0gxE4tAu2apSY^f(5yCoqQsn3eOq(|acT-CM!TRDQQG%aql#J&Z7 z)7$$8&)eCzMwAv+j)>$Kv$`rW8a#yO?(sJ#utev*$9-XU!5Kt&@X=0@_~~h3WcYDy7WPyn%nR0tR0F*hU*VxF^_>{mjO!^8~$taL*>{T|_>?@ga`ivnO&ns-@ z#T!|yWQ?I`NE5ajGx?Br7M1ndZu1nmk3SP`FDm1>xus2F95G^Qd_GG(`kcZFXEZNa zI~tppTw|aImLj0!H00~asAX_lMW^epu6|5%&*81=ursG`x;gxHvMG{zfwk;JP=EJGg)?}) zRf|gI{60lAN)8hmuiUhVSvkDE@1zfD1j<+lX5MEf~M%iKla(iQp7S)cz z;AW_rUOr;@XzokdVsIU{z=0+NrB3m0htza67^+jsXv{vU>LZ({V>fO9EVgUue(DKn zI1mmZ`XqkNMQsxZT3%vGt|kMSR>EXq{ebMRSi$e`4puWWo(`N9SYXpW&vWy|Dk5&r zC7&!~T~dde^vg#aZ*=veHaK<|4Iz*0*9d;UsZgO2kby!f9-P8=!zOPv0G8+o>H8gs z@|wEe2MVggyU<~Ik3gKBE*b#SbRetBGZrR4&x_>x zd_RGBoUne24mI{xxe?s@11zvf9hk#SptB+M+*Nx6sjCvjKjn7px4_~8{}>_t&EnD%2jLG1V2(N;NjyRF zbc+PMA=^+cN9Uy%T@84~*s*13&700@7CGyRiMR67`Wq@Rt^lR8XK@2O68dNfqDcFK zM2HbOQ1U3F+GR*U)YzR+hi}a<#NZ{XcX&B00*!NZdX%viIEyu;ek5?f!Hf+5`iLRbSuv` zC`N3c2n;xCBQw33u24bfAkwitIUEeA?C@50E8Fg)e-}>Bf*`6PxT?bo5dUyfz~C;t zcG8Wn0tTE?eByz)+2#haSIIF3-<0Xi)rQy`(}3a4&H)!Xw0fr|m9oRQ7t!w38_KVG zcz@IqN@3L}g&j)39EGdz+?N$vn;50SMrq(H0V${U&_fhI$w zxYUd;R$_z5hzLFMM4sxaL39ih4a^?i&9XO?QJf&*V&}x02Z3E?calk2-Z#Ub&xcnK z?9z-e?KQd!O-)OF!bP6guMf+6ozgw zF&xxPhsFRTG2q8q5P~%p`U*G397KK=0RLs>#^)l3y>^p`C#0slgIAIk+yLajvDDoQ z>omIJ2UbB1|HBo9MPLWCgKF&|pfH61uHrx_45qpQR6|Y-LofRgII@l9{YjIXl-JuT z8~&fc0aas{O(n407hg()M1#&7Q&vj49DNxL6F+oi=x35S4b#fk51_nAL*muxL7>t_B;e0pxGq9>s|f znMf12Ha(W>Fe=lfwXNuOq1e=U3ye~j6-J9hsVZJmgC%UsL!LvfBLh&Aa)C^biS3q6 z$Nu2!yAHQkj$ggBsc~cGAE&?yhkj~^pByIJ#{!2J4=4m5DJo3xU@(-;dl7a8zH%qe zEt{A7gW&@8GQI)Uh&W;etHVXh<4U1u&g5jX!$tcA&tMa@aj^>o?>@TL;PG@X^k0R? z`wr!t;PQhm=VOr%bhSMllQ-QMAl_BLJGoSxwSE8P5_BsE&Fv#260BN8ecj+xJ+Mxy@ zA=~MQSHxa=40ml6f<1Kb$DR_A#19gzxcZ=17Qnt3+$>Pe;mPq?1+KxT_}dgsw*s53 z?7=fwZs^!(m5xWrvPl-$ugy&Q2A>p^QAeTB;QFpEz-`JOO3tJ3G_y*`JdIPLM^!A) zAquQS^$*{JkW~B)QO^Q6Krh!h$db#U<@&?za3=2Csy@WN4E61wroKZc%gJu{5pLm! z(m|86cv{q!n8UY~ia@S!9cZHxXDw7nn8I8#3kRT3n}BR~DI~y)3N~Y<@#c1n^7ook zpjmH@Nlpv%0H!E za!dCwTPmSwnqDxPhDZeK4OLbi>rkaZ1UI2~dUWj)sG-a(XHe%TFE$bypk^@NqrSTW z8bEyM_#u`nK~)!?e&{`E!6Jwhv1%2+P2NDwDsUsipXPtjuqD!i8@v{`;k%ZCJeHrQy=@F`A%N-5xjK00$GU^UJTvslgdA5GT$=EF{~q9 zK7@r?27vYkFUCACXMJL%>ZMHQ5ado{8QWnw30ovCiwzJjDAP682Kc^+#(oN*2}%lnW4mQFS`BQZosDy98tYd=UV#i^}5O zub8;f-gWM$)0=N{z4t99{G{RpZ?}X6f%xO^ow>~<0~tC~FLR5tUTxd`3gb*qy-2xN z4|)&P{SJry7G0ncuk+%(Fg+ftv-wVOxm7>k2is#+bC^1v^ZkNQgWwcAJ}(!m-|sp@ z2#&_qK|7xu_-Y|d1<##kMRiXcw5YKI)a5eNG|A$5!-YlFKU+CBCFkk3@J}kCzWKf; zbvAt))De>r=MtH}B=JV~RvuVoM{K$7K}hlLkjj>;wa6PUjODA?Df}@)$fRB?n@d(t zl<~S?oEuIqQ0@p_Xw=vF6IQ3DKEyQE|_uU^RyQ%*F$ot6_NF+mylhXEl3c zZFW##H8=@nG5RvXV#%vl3bA0zL!9T`2XAmfj17oRHFPC5k^pLSEkN@lS!1m<+vprq|%k*rA zHdmwSvFvf~&uVUN%VuW)y-h}{&hGFaF=Bx0Kenx_Y_glyL$0L6T zamoL7bKuSoSe&g@bJ(<%OI799Y@N-+c0~9oC-u)^QyZEY{tDJYQ3#0_|6iS*3KnFn z!GCWovH$Am^Xh2YjQ(TWM++t9Pd05U-l{%+T%C8*4(D=(4}6k{qYK3!C+{JXz)1Gp=*27X+hLf39f9 z#d+nXn3^h?)OPrW>uzqSaLv8rr^$RIfRFc1W#(-}jF<>FU$0MU^<}GzoqX5cs349f6fdsCW5p=2ZUGiq>ee(e-V2Ix z3ZCQ!qa_e(8itl0JJdFg)Lh+UJ_%`3*D{P#ouXYHPA9j^TKrmje`leQS+bB`$^G3C z0Jma$Cf?k}4_+lJ{dcb8^drF1xC5sFUdzPh?p}rsVsy>9lX;| zAWnWh?H&flv2V;`P>_7}_qtz|mo*1MMgie{Jr6QRk5O-*nP?RD+l@T2-2%gUor-sl zQ$f&4^4Ms>zLI9!7hIsZgJOth)d{j+p2-+@s&5)MzEPwQYgj9CBe2A;f2cSlPU=^G zDpu<+^!3j+R&ub$RBQnBek~yFhGMh$_=GT)xy#8>Z0t97-AgfsD z%b&f6^oE{X2K>-+FxQX|MYeD2*)1IK2??kQ{p8l9$hT4V`eF2tBOxLHNG0yZCxEwJ z^g6QKqh6ef1fdXijC2GCADvdI8qfVn*??{$FW2u-w|<;^Rdhph_Uw%Z1awf10_tDlGmi z5`V9i{dvXnaT3BlpxI~U=X0dBRgn!}-tG7Uq6`n$$ir!%L&0-tzO;)V=hT%f;wPrk zZA`8WEBZEo_cU7J(x`!s!7x|o>RL_v{i_Wj*l*aMLT3VOx2&k#u2R)owM(E;VyA!P z8?`(+75E6n;|hRg&%@F63HM5XW=ML8j^%5Qu*40$L$u6Zz9(n zXw_d4nM08OTPWMO?GU`vvIM&z{6@k0f@LgLI4=Did+={O?LqktrWmbZkXChsBUZ}; zx=L;YAJn)AA^ZGc6?&Ei)Hgme0kQ?#-`pcCwE+)$L^xb`=t2va#y7K&;$6He~ihA8_K)?s}%;i&P zX-?5@W}X#EcHaa|>J76#hvN3Ma_G;P%_RJaP^aO>6t?f;p4oG__{qn;@_UGa=C<~e z)D35#q@cPSN*`Q*F3&E?BV}BGg*6@n0`?{pzlRx#GgYao*RHIdX-qo`>A>p6-(Q5> z!2@_DOANY&U4e)&BI+4CRKp+4h+PphSs4N(d5pKCL-M+0@QZHfA(%bf4!5YQ=y6Z4 z^h{s|R8idouyo|yS3Ctdzih=b)Q?UCF^s(dvU7mrBgTLru3!^gtGXG3*$MoQ3Q_p zQU_jDchK7vItpcUDg>!G#m6DN(b9&OY9ZFcV-{-U|9 z-uNm+%*8$zC>{C|R@vDh#Fci>8;2y4o$gWm+t{WG$7`07jcYzIii#{`di>sfWh?ov zoJLxRW{X!iTVwD|f0GVa4yk%WJ>g5^7kuy`DUR4t0UodB zdo+{QfIGKiWC3^eBBBfw5z0nRpFHrG`t>DXIrAg&pF-M{Xu6bx*DKi}+mQV3PLT~s zViat=ANov)Z2r~?w73f1ohhSD-~NU3czWhgbQ7ybfVtNTfr3;ZFaP>gY#!N0=z|W~ zH#bX7WlFzN{J4E|l09F$m;Qq6;LNjU>#LUX#O66~NE>TIc_mEe*A-{dug`<1u64tD zwue4;u)?l8%Cv8x<6^nE>3+j&X~yfv?iLG?Il2K5oa&i4G~vW;=aQwrgps&{w-MhwEeny5BfZ-36K&mDlh9CFc*>foNpxNb z-r=ENgR3@H)3%Lwl9*#uFrFte45+*ZhdT{V+OFW9>nI?p;Z(s9If)&G2T4XAJd`86 zWE?wS8lUM6Uw^2*ldF;SejDv`B6~;}uD)LMY7C9H@L*wkxowcrc9z&`vek;E7^H4G z&xXueH)Q7$wsKI@obIY~%W^h9xS3X0rP_4K+`{wDbAs1v6En6eH~mC1tl0{}6`twm zU(M8f!$O4S5YJ2MSg{LmwDa#oree>~wQyM$gyU8tdn%d4FJ^_#*iPQL+_Pu4+kcz% z^=W!PheH0Vf0_2DMtR-o&#pWa8fC;dcLnLn9XQ-+WZS1$HW{zXRyZKT`~G{^tV;E> zk`W_iTXIg*G9TGLfsI|zqxuAK8y3s?>-6l*@R7x>ruR#|jmHzaC~P2fu=dm>ukrHa z$Ehdp{C{`zUuP5*o$#((`zv0F-@4u~PQKV{;$0a^?0YiQ-#TJtLh4j9219@|) zxNSDnEd{q;GX!Lb_qKwUzuV^3mVRQw7PHMopW4%^P?{?>P#K)ac6_Q9ytq{|hAO!b zCgUF*N^cr-UoOX9Yx%F*r74n)7_Itx$wNl@h`EPdCV}gFI!{|IOxMJW>Io7Ft$yMioVlZX?sm-gQ7pX#d#mMo!@EObIp*G;1+9IZ&!u5oM_ZS(T4$vePLTL_9D2$J zii4X^@E*@#-iGytizar_*E?Cb{O_%mHa2E4$CR-vRBXQ}WxCDkT;f2f1^fOBWb21+ zQg<&yN!t}R#jT-@P!7f0npbmcYb-PKr6na~>;74D+I~|}X0uEX{_?2`Z0?Zb!rt2= z!`Kqp!i-8|ZWe342}=Bi^`5cPU0xHXyECxWT>f;#4(fjCkgW~1gVIoO$ZH#p<_^HF|qPH_nZ6BiJC%EU_GB+Eiv*w z1#6mSS1)R+V1aF5n%b)ON%2FJ`aGb79Ni`q~!r0^J|pd=rwerh8a z^{3)Sgtxm$38sRNEM`gzoD-IR)+^MryX@=aR+Rvqz~r0yd1|CA;}F0xH;(g$b;%si zH8mcdzlpWYl;E=U6it`4H@Wdz%`_R$V?}A#+K2QxWq-)fIZOza5M%f#ie6E>N{hR8 zrkMyv7S2hj*=I_9iIIy@8?&oh=c|4Rif&(De5y9;v(vbzMIVnJ^YFOSFkJxBcy4wL zbJC{C08b8B1ehBljnL~4M1K6>pR4+y`v#|$JpEM+Q~1^J5ojUiI6LcZBz|D8u`dmY z>~WC9b@L{dPL$q%<-kKnwmka<8xpk6mYmfxEBBcBwt0)BQZAN`v6z+Sr_cX>BS1=k)aBFf?v4R!kk%o?pJB69ltfo6mp%-N^rTFC`DXyQ+H~}VQ{!E)!3@ERF-pz z-0&O|@!DRDll!mm>FZj81p|dRK5`=V4$~pgC8B1+|IpziX2Bu>1`ct?P$*NRl(&ym5DU{Rf)-?4caoIHwK>gE$wB| z74tSfv6dR=+|01BQ?2m>DFUmeAgk7JBI2?PenJ(4k)*%Hh_Qo2R4(6yy7t3*lHBf& zWO4lHxkO1nT28T=(Q2(ee)k|)mcf*ba4~Y3;)*hy%(ps2^a0X5SGmWaNR#QKE10?C^ziFjBUN~}Q+6~1z=7q~FaGuB{4ezU{}Xy{Ad@JXWhZPw zR5wqOH{}_*l99hx?{#t6+nfU_BPOe#6+#IcDq%8a;)+Jw?copFZqd@vqZE^EL;eqX C^0jRM diff --git a/doc/technical/RuleBlacklist.md b/doc/technical/RuleBlacklist.md index 9ebe1aa..bace50e 100644 --- a/doc/technical/RuleBlacklist.md +++ b/doc/technical/RuleBlacklist.md @@ -69,4 +69,4 @@ Single-item operations (`addAddress`, `removeAddress`) revert on duplicate/missi ### Usage scenario -The operator deploys `RuleBlacklist`, grants `ADDRESS_LIST_ADD_ROLE` to a compliance manager, and registers the rule in the `RuleEngine`. The compliance manager calls `addAddresses([badActor])`. Any transfer from, to, or by the blacklisted address is rejected with codes 36, 37, or 38. +The operator deploys `RuleBlacklist`, grants `ADDRESS_LIST_ADD_ROLE` to a compliance manager, and registers the rule in the `RuleEngine`. The compliance manager calls `addAddresses([badActor])`. Any transfer from, to, or by the blacklisted address is rejected with codes 36, 37, or 38.rea diff --git a/src/rules/operation/RuleConditionalTransferLight.sol b/src/rules/operation/RuleConditionalTransferLight.sol index d32774d..e58a736 100644 --- a/src/rules/operation/RuleConditionalTransferLight.sol +++ b/src/rules/operation/RuleConditionalTransferLight.sol @@ -22,10 +22,7 @@ contract RuleConditionalTransferLight is /** * @param admin Address of the contract admin. */ - constructor(address admin) AccessControlModuleStandalone(admin) { - require(admin != address(0), RuleConditionalTransferLight_AdminAddressZeroNotAllowed()); - - } + constructor(address admin) AccessControlModuleStandalone(admin) {} function supportsInterface(bytes4 interfaceId) public diff --git a/test/Coverage/DeploymentOperationCoverage.t.sol b/test/Coverage/DeploymentOperationCoverage.t.sol new file mode 100644 index 0000000..f71291a --- /dev/null +++ b/test/Coverage/DeploymentOperationCoverage.t.sol @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {HelperContract} from "../HelperContract.sol"; +import {IERC165} from "OZ/utils/introspection/IERC165.sol"; +import {IRule} from "RuleEngine/interfaces/IRule.sol"; +import {RuleInterfaceId} from "RuleEngine/modules/library/RuleInterfaceId.sol"; +import {ISanctionsList} from "src/rules/interfaces/ISanctionsList.sol"; +import {RuleConditionalTransferLight} from "src/rules/operation/RuleConditionalTransferLight.sol"; +import {RuleConditionalTransferLightOwnable2Step} from "src/rules/operation/RuleConditionalTransferLightOwnable2Step.sol"; +import {RuleBlacklist} from "src/rules/validation/deployment/RuleBlacklist.sol"; +import {RuleWhitelist} from "src/rules/validation/deployment/RuleWhitelist.sol"; +import {RuleWhitelistWrapper} from "src/rules/validation/deployment/RuleWhitelistWrapper.sol"; +import {RuleERC2980} from "src/rules/validation/deployment/RuleERC2980.sol"; +import {RuleSanctionsList} from "src/rules/validation/deployment/RuleSanctionsList.sol"; +import {RuleBlacklistOwnable2Step} from "src/rules/validation/deployment/RuleBlacklistOwnable2Step.sol"; +import {RuleWhitelistOwnable2Step} from "src/rules/validation/deployment/RuleWhitelistOwnable2Step.sol"; +import {RuleWhitelistWrapperOwnable2Step} from "src/rules/validation/deployment/RuleWhitelistWrapperOwnable2Step.sol"; +import {RuleERC2980Ownable2Step} from "src/rules/validation/deployment/RuleERC2980Ownable2Step.sol"; + +contract RuleBlacklistHarness is RuleBlacklist { + constructor(address admin, address forwarderIrrevocable) RuleBlacklist(admin, forwarderIrrevocable) {} + + function exposedMsgDataLength() external view returns (uint256) { + return _msgData().length; + } +} + +contract RuleWhitelistHarness is RuleWhitelist { + constructor(address admin, address forwarderIrrevocable, bool checkSpender_) + RuleWhitelist(admin, forwarderIrrevocable, checkSpender_) + {} + + function exposedMsgDataLength() external view returns (uint256) { + return _msgData().length; + } +} + +contract RuleWhitelistWrapperHarness is RuleWhitelistWrapper { + constructor(address admin, address forwarderIrrevocable, bool checkSpender_) + RuleWhitelistWrapper(admin, forwarderIrrevocable, checkSpender_) + {} + + function exposedMsgDataLength() external view returns (uint256) { + return _msgData().length; + } +} + +contract RuleERC2980Harness is RuleERC2980 { + constructor(address admin, address forwarderIrrevocable) RuleERC2980(admin, forwarderIrrevocable) {} + + function exposedMsgDataLength() external view returns (uint256) { + return _msgData().length; + } +} + +contract RuleSanctionsListHarness is RuleSanctionsList { + constructor(address admin, address forwarderIrrevocable, ISanctionsList sanctionContractOracle_) + RuleSanctionsList(admin, forwarderIrrevocable, sanctionContractOracle_) + {} + + function exposedMsgDataLength() external view returns (uint256) { + return _msgData().length; + } +} + +contract RuleBlacklistOwnable2StepHarness is RuleBlacklistOwnable2Step { + constructor(address owner, address forwarderIrrevocable) RuleBlacklistOwnable2Step(owner, forwarderIrrevocable) {} + + function exposedMsgDataLength() external view returns (uint256) { + return _msgData().length; + } +} + +contract RuleWhitelistOwnable2StepHarness is RuleWhitelistOwnable2Step { + constructor(address owner, address forwarderIrrevocable, bool checkSpender_) + RuleWhitelistOwnable2Step(owner, forwarderIrrevocable, checkSpender_) + {} + + function exposedMsgDataLength() external view returns (uint256) { + return _msgData().length; + } +} + +contract RuleWhitelistWrapperOwnable2StepHarness is RuleWhitelistWrapperOwnable2Step { + constructor(address owner, address forwarderIrrevocable, bool checkSpender_) + RuleWhitelistWrapperOwnable2Step(owner, forwarderIrrevocable, checkSpender_) + {} + + function exposedMsgDataLength() external view returns (uint256) { + return _msgData().length; + } +} + +contract RuleERC2980Ownable2StepHarness is RuleERC2980Ownable2Step { + constructor(address owner, address forwarderIrrevocable) RuleERC2980Ownable2Step(owner, forwarderIrrevocable) {} + + function exposedMsgDataLength() external view returns (uint256) { + return _msgData().length; + } +} + +contract DeploymentCoverageExtraTest is Test, HelperContract { + function testDeploymentWrappersAndHooksCoverage() public { + RuleBlacklistHarness blacklist = new RuleBlacklistHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); + RuleWhitelistHarness whitelist = new RuleWhitelistHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true); + RuleWhitelistWrapperHarness wrapper = new RuleWhitelistWrapperHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true); + RuleERC2980Harness erc2980 = new RuleERC2980Harness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); + RuleSanctionsListHarness sanctions = + new RuleSanctionsListHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, ISanctionsList(ZERO_ADDRESS)); + + RuleBlacklistOwnable2StepHarness blacklistOwnable = + new RuleBlacklistOwnable2StepHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); + RuleWhitelistOwnable2StepHarness whitelistOwnable = + new RuleWhitelistOwnable2StepHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true); + RuleWhitelistWrapperOwnable2StepHarness wrapperOwnable = + new RuleWhitelistWrapperOwnable2StepHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, true); + RuleERC2980Ownable2StepHarness erc2980Ownable = + new RuleERC2980Ownable2StepHarness(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); + + assertGe(blacklist.exposedMsgDataLength(), 4); + assertGe(whitelist.exposedMsgDataLength(), 4); + assertGe(wrapper.exposedMsgDataLength(), 4); + assertGe(erc2980.exposedMsgDataLength(), 4); + assertGe(sanctions.exposedMsgDataLength(), 4); + assertGe(blacklistOwnable.exposedMsgDataLength(), 4); + assertGe(whitelistOwnable.exposedMsgDataLength(), 4); + assertGe(wrapperOwnable.exposedMsgDataLength(), 4); + assertGe(erc2980Ownable.exposedMsgDataLength(), 4); + + vm.prank(DEFAULT_ADMIN_ADDRESS); + blacklist.addAddress(ADDRESS1); + vm.prank(DEFAULT_ADMIN_ADDRESS); + blacklist.removeAddress(ADDRESS1); + + vm.prank(DEFAULT_ADMIN_ADDRESS); + whitelist.setCheckSpender(false); + + vm.prank(DEFAULT_ADMIN_ADDRESS); + wrapper.setCheckSpender(false); + + bytes32 rulesManagerRole = wrapper.RULES_MANAGEMENT_ROLE(); + vm.prank(DEFAULT_ADMIN_ADDRESS); + wrapper.grantRole(rulesManagerRole, ADDRESS1); + vm.prank(DEFAULT_ADMIN_ADDRESS); + wrapper.revokeRole(rulesManagerRole, ADDRESS1); + + assertFalse(blacklist.supportsInterface(bytes4(0xdeadbeef))); + assertFalse(whitelist.supportsInterface(bytes4(0xdeadbeef))); + assertFalse(wrapper.supportsInterface(bytes4(0xdeadbeef))); + assertFalse(erc2980.supportsInterface(bytes4(0xdeadbeef))); + assertFalse(sanctions.supportsInterface(bytes4(0xdeadbeef))); + } +} + +contract OperationCoverageExtraTest is Test, HelperContract { + function testConditionalTransferLightCreatedDestroyedAndInterfaces() public { + RuleConditionalTransferLight rule = new RuleConditionalTransferLight(DEFAULT_ADMIN_ADDRESS); + + vm.prank(DEFAULT_ADMIN_ADDRESS); + rule.bindToken(address(this)); + + rule.created(ADDRESS1, 1); + rule.destroyed(ADDRESS1, 1); + + assertTrue(rule.supportsInterface(type(IRule).interfaceId)); + assertTrue(rule.supportsInterface(RuleInterfaceId.IRULE_INTERFACE_ID)); + assertFalse(rule.supportsInterface(bytes4(0xdeadbeef))); + } + + function testConditionalTransferLightOwnableViewAndOverloads() public { + RuleConditionalTransferLightOwnable2Step rule = + new RuleConditionalTransferLightOwnable2Step(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + + vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + rule.approveTransfer(ADDRESS1, ADDRESS2, 77); + + vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); + rule.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 77); + + assertEq(rule.approvedCount(ADDRESS1, ADDRESS2, 77), 0); + assertEq(rule.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 77), CODE_TRANSFER_REQUEST_NOT_APPROVED); + assertFalse(rule.canTransfer(ADDRESS1, ADDRESS2, 77)); + assertFalse(rule.canTransferFrom(ADDRESS3, ADDRESS1, ADDRESS2, 77)); + assertTrue(rule.canReturnTransferRestrictionCode(CODE_TRANSFER_REQUEST_NOT_APPROVED)); + assertEq(rule.messageForTransferRestriction(CODE_TRANSFER_REQUEST_NOT_APPROVED), TEXT_TRANSFER_REQUEST_NOT_APPROVED); + assertEq(rule.messageForTransferRestriction(CODE_NONEXISTENT), TEXT_CODE_NOT_FOUND); + + assertTrue(rule.supportsInterface(type(IERC165).interfaceId)); + assertTrue(rule.supportsInterface(type(IRule).interfaceId)); + assertTrue(rule.supportsInterface(RuleInterfaceId.IRULE_INTERFACE_ID)); + assertFalse(rule.supportsInterface(bytes4(0xdeadbeef))); + } +} diff --git a/test/RuleConditionalTransferLight/RuleConditionalTransferLightApproveAndTransfer.t.sol b/test/RuleConditionalTransferLight/RuleConditionalTransferLightApproveAndTransfer.t.sol index ddb2087..24a2891 100644 --- a/test/RuleConditionalTransferLight/RuleConditionalTransferLightApproveAndTransfer.t.sol +++ b/test/RuleConditionalTransferLight/RuleConditionalTransferLightApproveAndTransfer.t.sol @@ -6,6 +6,22 @@ import {HelperContract} from "../HelperContract.sol"; import {RuleConditionalTransferLight} from "src/rules/operation/RuleConditionalTransferLight.sol"; import {MockERC20WithTransferContext} from "../utils/MockERC20WithTransferContext.sol"; +contract MockERC20TransferFromFalse { + mapping(address => mapping(address => uint256)) private _allowances; + + function setAllowance(address owner, address spender, uint256 value) external { + _allowances[owner][spender] = value; + } + + function allowance(address owner, address spender) external view returns (uint256) { + return _allowances[owner][spender]; + } + + function transferFrom(address, address, uint256) external pure returns (bool) { + return false; + } +} + contract RuleConditionalTransferLightApproveAndTransfer is Test, HelperContract { RuleConditionalTransferLight private rule; MockERC20WithTransferContext private token; @@ -33,4 +49,29 @@ contract RuleConditionalTransferLightApproveAndTransfer is Test, HelperContract assertEq(token.balanceOf(ADDRESS2), 10); assertEq(rule.approvedCount(ADDRESS1, ADDRESS2, 10), 0); } + + function testApproveAndTransferIfAllowedRevertsOnZeroToken() public { + vm.expectRevert(RuleConditionalTransferLight_TokenAddressZeroNotAllowed.selector); + vm.prank(DEFAULT_ADMIN_ADDRESS); + rule.approveAndTransferIfAllowed(ZERO_ADDRESS, ADDRESS1, ADDRESS2, 10); + } + + function testApproveAndTransferIfAllowedRevertsOnInsufficientAllowance() public { + vm.expectRevert( + abi.encodeWithSelector( + RuleConditionalTransferLight_InsufficientAllowance.selector, address(token), ADDRESS1, 0, 10 + ) + ); + vm.prank(DEFAULT_ADMIN_ADDRESS); + rule.approveAndTransferIfAllowed(address(token), ADDRESS1, ADDRESS2, 10); + } + + function testApproveAndTransferIfAllowedRevertsOnTransferFailure() public { + MockERC20TransferFromFalse failingToken = new MockERC20TransferFromFalse(); + failingToken.setAllowance(ADDRESS1, address(rule), 10); + + vm.expectRevert(RuleConditionalTransferLight_TransferFailed.selector); + vm.prank(DEFAULT_ADMIN_ADDRESS); + rule.approveAndTransferIfAllowed(address(failingToken), ADDRESS1, ADDRESS2, 10); + } } diff --git a/test/RuleConditionalTransferLight/RuleConditionalTransferLightRuleEngineIntegration.t.sol b/test/RuleConditionalTransferLight/RuleConditionalTransferLightRuleEngineIntegration.t.sol index b6f599b..b93b76c 100644 --- a/test/RuleConditionalTransferLight/RuleConditionalTransferLightRuleEngineIntegration.t.sol +++ b/test/RuleConditionalTransferLight/RuleConditionalTransferLightRuleEngineIntegration.t.sol @@ -90,6 +90,7 @@ contract RuleConditionalTransferLightRuleEngineIntegration is Test, HelperContra function testFuzz_ApproveAndConsume(address from, address to, uint96 value, uint8 approvals, uint8 consumes) public { approvals = uint8(bound(approvals, 0, 20)); consumes = uint8(bound(consumes, 0, approvals)); + bool isMintOrBurnPath = from == address(0) || to == address(0); for (uint256 i = 0; i < approvals; ++i) { vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS); @@ -102,6 +103,7 @@ contract RuleConditionalTransferLightRuleEngineIntegration is Test, HelperContra } resUint256 = ruleConditionalTransferLight.approvedCount(from, to, value); - assertEq(resUint256, approvals - consumes); + uint256 expectedCount = isMintOrBurnPath ? approvals : approvals - consumes; + assertEq(resUint256, expectedCount); } } diff --git a/test/RuleConditionalTransferLight/RuleConditionalTransferLightUnit.t.sol b/test/RuleConditionalTransferLight/RuleConditionalTransferLightUnit.t.sol index 4d730ee..d19f79b 100644 --- a/test/RuleConditionalTransferLight/RuleConditionalTransferLightUnit.t.sol +++ b/test/RuleConditionalTransferLight/RuleConditionalTransferLightUnit.t.sol @@ -14,6 +14,11 @@ contract RuleConditionalTransferLightUnit is Test, HelperContract { rule.bindToken(ADDRESS3); } + function testConstructorRevertsOnZeroAdmin() public { + vm.expectRevert(); + new RuleConditionalTransferLight(address(0)); + } + function testApproveTransfer_OnlyOperator() public { vm.expectRevert(); vm.prank(ADDRESS1); @@ -60,4 +65,18 @@ contract RuleConditionalTransferLightUnit is Test, HelperContract { resBool = rule.canTransfer(ADDRESS1, ADDRESS2, 10); assertEq(resBool, true); } + + function testDetectRestrictionMintOrBurnPathReturnsTransferOk() public { + resUint8 = rule.detectTransferRestriction(address(0), ADDRESS2, 10); + assertEq(resUint8, TRANSFER_OK); + + resUint8 = rule.detectTransferRestriction(ADDRESS1, address(0), 10); + assertEq(resUint8, TRANSFER_OK); + + resBool = rule.canTransfer(address(0), ADDRESS2, 10); + assertTrue(resBool); + + resBool = rule.canTransfer(ADDRESS1, address(0), 10); + assertTrue(resBool); + } } diff --git a/test/RuleERC2980/RuleERC2980.t.sol b/test/RuleERC2980/RuleERC2980.t.sol index 71fb707..bfebdfb 100644 --- a/test/RuleERC2980/RuleERC2980.t.sol +++ b/test/RuleERC2980/RuleERC2980.t.sol @@ -401,4 +401,36 @@ contract RuleERC2980Test is Test, HelperContract { assertTrue(results[0]); assertFalse(results[1]); } + + function testBatchOperationsSkipDuplicatesAndMissingEntries() public { + // Whitelist: duplicate entry should be skipped in batch add path. + address[] memory whitelistToAdd = new address[](1); + whitelistToAdd[0] = ADDRESS2; // already whitelisted in setUp + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleERC2980.addWhitelistAddresses(whitelistToAdd); + assertEq(ruleERC2980.whitelistAddressCount(), 1); + + // Whitelist: removing a missing address should be skipped in batch remove path. + address[] memory whitelistToRemove = new address[](1); + whitelistToRemove[0] = ADDRESS3; // not whitelisted + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleERC2980.removeWhitelistAddresses(whitelistToRemove); + assertEq(ruleERC2980.whitelistAddressCount(), 1); + + // Frozenlist: duplicate entry should be skipped in batch add path. + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleERC2980.addFrozenlistAddress(ADDRESS1); + address[] memory frozenToAdd = new address[](1); + frozenToAdd[0] = ADDRESS1; // already frozen + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleERC2980.addFrozenlistAddresses(frozenToAdd); + assertEq(ruleERC2980.frozenlistAddressCount(), 1); + + // Frozenlist: removing a missing address should be skipped in batch remove path. + address[] memory frozenToRemove = new address[](1); + frozenToRemove[0] = ADDRESS3; // not frozen + vm.prank(DEFAULT_ADMIN_ADDRESS); + ruleERC2980.removeFrozenlistAddresses(frozenToRemove); + assertEq(ruleERC2980.frozenlistAddressCount(), 1); + } } diff --git a/test/RuleIdentityRegistry/Ownable/RuleIdentityRegistryOwnable2Step.t.sol b/test/RuleIdentityRegistry/Ownable/RuleIdentityRegistryOwnable2Step.t.sol new file mode 100644 index 0000000..4f8b069 --- /dev/null +++ b/test/RuleIdentityRegistry/Ownable/RuleIdentityRegistryOwnable2Step.t.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {HelperContract} from "../../HelperContract.sol"; +import {Ownable2StepTestBase, IOwnable2StepLike} from "../../utils/Ownable2StepTestBase.sol"; +import {IdentityRegistryMock} from "../../utils/IdentityRegistryMock.sol"; +import {RuleIdentityRegistryOwnable2Step} from + "src/rules/validation/deployment/RuleIdentityRegistryOwnable2Step.sol"; + +contract RuleIdentityRegistryOwnable2StepTest is Ownable2StepTestBase { + function _deployOwnable2Step() internal override returns (IOwnable2StepLike, address) { + address ownerAddr = WHITELIST_OPERATOR_ADDRESS; + IdentityRegistryMock registry = new IdentityRegistryMock(); + RuleIdentityRegistryOwnable2Step rule = new RuleIdentityRegistryOwnable2Step(ownerAddr, address(registry)); + return (IOwnable2StepLike(address(rule)), ownerAddr); + } +} + +contract RuleIdentityRegistryOwnable2StepAccessControl is Test, HelperContract { + error OwnableUnauthorizedAccount(address account); + + RuleIdentityRegistryOwnable2Step private rule; + IdentityRegistryMock private registry; + + function setUp() public { + registry = new IdentityRegistryMock(); + rule = new RuleIdentityRegistryOwnable2Step(WHITELIST_OPERATOR_ADDRESS, address(registry)); + } + + function testOwnerCanSetAndClearIdentityRegistry() public { + IdentityRegistryMock newRegistry = new IdentityRegistryMock(); + + vm.prank(WHITELIST_OPERATOR_ADDRESS); + rule.setIdentityRegistry(address(newRegistry)); + assertEq(address(rule.identityRegistry()), address(newRegistry)); + + vm.prank(WHITELIST_OPERATOR_ADDRESS); + rule.clearIdentityRegistry(); + assertEq(address(rule.identityRegistry()), ZERO_ADDRESS); + } + + function testNonOwnerCannotManageIdentityRegistry() public { + vm.expectRevert(abi.encodeWithSelector(OwnableUnauthorizedAccount.selector, ATTACKER)); + vm.prank(ATTACKER); + rule.setIdentityRegistry(address(registry)); + + vm.expectRevert(abi.encodeWithSelector(OwnableUnauthorizedAccount.selector, ATTACKER)); + vm.prank(ATTACKER); + rule.clearIdentityRegistry(); + } +} diff --git a/test/RuleIdentityRegistry/RuleIdentityRegistryUnit.t.sol b/test/RuleIdentityRegistry/RuleIdentityRegistryUnit.t.sol index 3a886e1..f59db86 100644 --- a/test/RuleIdentityRegistry/RuleIdentityRegistryUnit.t.sol +++ b/test/RuleIdentityRegistry/RuleIdentityRegistryUnit.t.sol @@ -51,6 +51,14 @@ contract RuleIdentityRegistryUnit is Test, HelperContract { assertEq(resUint8, CODE_ADDRESS_SPENDER_NOT_VERIFIED); } + function testDetectRestrictionFrom_NoRegistry_ReturnsOk() public { + vm.prank(DEFAULT_ADMIN_ADDRESS); + rule.clearIdentityRegistry(); + + resUint8 = rule.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 1); + assertEq(resUint8, TRANSFER_OK); + } + function testSetIdentityRegistry_RevertsOnZeroAddress() public { vm.expectRevert(RuleIdentityRegistry_RegistryAddressZeroNotAllowed.selector); vm.prank(DEFAULT_ADMIN_ADDRESS); @@ -102,4 +110,35 @@ contract RuleIdentityRegistryUnit is Test, HelperContract { ); rule.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 10); } + + function testTransferred_DoesNotRevertWhenValid() public { + registry.setVerified(ADDRESS1, true); + registry.setVerified(ADDRESS2, true); + + rule.transferred(ADDRESS1, ADDRESS2, 10); + } + + function testTransferredFrom_DoesNotRevertWhenValid() public { + registry.setVerified(ADDRESS1, true); + registry.setVerified(ADDRESS2, true); + registry.setVerified(ADDRESS3, true); + + rule.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 10); + } + + function testCanReturnTransferRestrictionCode() public view { + assertTrue(rule.canReturnTransferRestrictionCode(CODE_ADDRESS_FROM_NOT_VERIFIED)); + assertTrue(rule.canReturnTransferRestrictionCode(CODE_ADDRESS_TO_NOT_VERIFIED)); + assertTrue(rule.canReturnTransferRestrictionCode(CODE_ADDRESS_SPENDER_NOT_VERIFIED)); + assertFalse(rule.canReturnTransferRestrictionCode(CODE_NONEXISTENT)); + } + + function testMessageForTransferRestriction() public view { + assertEq(rule.messageForTransferRestriction(CODE_ADDRESS_FROM_NOT_VERIFIED), TEXT_ADDRESS_FROM_NOT_VERIFIED); + assertEq(rule.messageForTransferRestriction(CODE_ADDRESS_TO_NOT_VERIFIED), TEXT_ADDRESS_TO_NOT_VERIFIED); + assertEq( + rule.messageForTransferRestriction(CODE_ADDRESS_SPENDER_NOT_VERIFIED), TEXT_ADDRESS_SPENDER_NOT_VERIFIED + ); + assertEq(rule.messageForTransferRestriction(CODE_NONEXISTENT), TEXT_CODE_NOT_FOUND); + } } diff --git a/test/RuleMaxTotalSupply/Ownable/RuleMaxTotalSupplyOwnable2Step.t.sol b/test/RuleMaxTotalSupply/Ownable/RuleMaxTotalSupplyOwnable2Step.t.sol new file mode 100644 index 0000000..b1028df --- /dev/null +++ b/test/RuleMaxTotalSupply/Ownable/RuleMaxTotalSupplyOwnable2Step.t.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {HelperContract} from "../../HelperContract.sol"; +import {Ownable2StepTestBase, IOwnable2StepLike} from "../../utils/Ownable2StepTestBase.sol"; +import {TotalSupplyMock} from "../../utils/TotalSupplyMock.sol"; +import {RuleMaxTotalSupplyOwnable2Step} from "src/rules/validation/deployment/RuleMaxTotalSupplyOwnable2Step.sol"; + +contract RuleMaxTotalSupplyOwnable2StepTest is Ownable2StepTestBase { + function _deployOwnable2Step() internal override returns (IOwnable2StepLike, address) { + address ownerAddr = WHITELIST_OPERATOR_ADDRESS; + TotalSupplyMock token = new TotalSupplyMock(); + RuleMaxTotalSupplyOwnable2Step rule = new RuleMaxTotalSupplyOwnable2Step(ownerAddr, address(token), 100); + return (IOwnable2StepLike(address(rule)), ownerAddr); + } +} + +contract RuleMaxTotalSupplyOwnable2StepAccessControl is Test, HelperContract { + error OwnableUnauthorizedAccount(address account); + + RuleMaxTotalSupplyOwnable2Step private rule; + TotalSupplyMock private token; + + function setUp() public { + token = new TotalSupplyMock(); + rule = new RuleMaxTotalSupplyOwnable2Step(WHITELIST_OPERATOR_ADDRESS, address(token), 100); + } + + function testOwnerCanManageMaxTotalSupply() public { + TotalSupplyMock newToken = new TotalSupplyMock(); + + vm.prank(WHITELIST_OPERATOR_ADDRESS); + rule.setMaxTotalSupply(150); + assertEq(rule.maxTotalSupply(), 150); + + vm.prank(WHITELIST_OPERATOR_ADDRESS); + rule.setTokenContract(address(newToken)); + assertEq(address(rule.tokenContract()), address(newToken)); + } + + function testNonOwnerCannotManageMaxTotalSupply() public { + vm.expectRevert(abi.encodeWithSelector(OwnableUnauthorizedAccount.selector, ATTACKER)); + vm.prank(ATTACKER); + rule.setMaxTotalSupply(200); + + vm.expectRevert(abi.encodeWithSelector(OwnableUnauthorizedAccount.selector, ATTACKER)); + vm.prank(ATTACKER); + rule.setTokenContract(address(token)); + } +} diff --git a/test/RuleMaxTotalSupply/RuleMaxTotalSupplyUnit.t.sol b/test/RuleMaxTotalSupply/RuleMaxTotalSupplyUnit.t.sol index 62277c8..d4de2cc 100644 --- a/test/RuleMaxTotalSupply/RuleMaxTotalSupplyUnit.t.sol +++ b/test/RuleMaxTotalSupply/RuleMaxTotalSupplyUnit.t.sol @@ -87,4 +87,24 @@ contract RuleMaxTotalSupplyUnit is Test, HelperContract { ); rule.transferred(ADDRESS3, ZERO_ADDRESS, ADDRESS1, 1); } + + function testTransferred_DoesNotRevertWhenValid() public { + token.setTotalSupply(90); + rule.transferred(ZERO_ADDRESS, ADDRESS1, 10); + } + + function testTransferredFrom_DoesNotRevertWhenValid() public { + token.setTotalSupply(90); + rule.transferred(ADDRESS3, ZERO_ADDRESS, ADDRESS1, 10); + } + + function testCanReturnTransferRestrictionCode() public view { + assertTrue(rule.canReturnTransferRestrictionCode(CODE_MAX_TOTAL_SUPPLY_EXCEEDED)); + assertFalse(rule.canReturnTransferRestrictionCode(CODE_NONEXISTENT)); + } + + function testMessageForTransferRestriction() public view { + assertEq(rule.messageForTransferRestriction(CODE_MAX_TOTAL_SUPPLY_EXCEEDED), TEXT_MAX_TOTAL_SUPPLY_EXCEEDED); + assertEq(rule.messageForTransferRestriction(CODE_NONEXISTENT), TEXT_CODE_NOT_FOUND); + } } diff --git a/test/RuleSanctionList/Ownable/RuleSanctionsListOwnable2Step.t.sol b/test/RuleSanctionList/Ownable/RuleSanctionsListOwnable2Step.t.sol new file mode 100644 index 0000000..090f0f3 --- /dev/null +++ b/test/RuleSanctionList/Ownable/RuleSanctionsListOwnable2Step.t.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {HelperContract} from "../../HelperContract.sol"; +import {Ownable2StepTestBase, IOwnable2StepLike} from "../../utils/Ownable2StepTestBase.sol"; +import {SanctionListOracle} from "../../utils/SanctionListOracle.sol"; +import {ISanctionsList} from "src/rules/interfaces/ISanctionsList.sol"; +import {RuleSanctionsListOwnable2Step} from "src/rules/validation/deployment/RuleSanctionsListOwnable2Step.sol"; + +contract RuleSanctionsListOwnable2StepHarness is RuleSanctionsListOwnable2Step { + constructor(address owner, address forwarderIrrevocable, ISanctionsList sanctionContractOracle_) + RuleSanctionsListOwnable2Step(owner, forwarderIrrevocable, sanctionContractOracle_) + {} + + function exposedMsgSender() external view returns (address) { + return _msgSender(); + } + + function exposedMsgData() external view returns (bytes memory) { + return _msgData(); + } + + function exposedContextSuffixLength() external view returns (uint256) { + return _contextSuffixLength(); + } +} + +contract RuleSanctionsListOwnable2StepTest is Ownable2StepTestBase { + function _deployOwnable2Step() internal override returns (IOwnable2StepLike, address) { + address ownerAddr = SANCTIONLIST_OPERATOR_ADDRESS; + RuleSanctionsListOwnable2Step rule = + new RuleSanctionsListOwnable2Step(ownerAddr, ZERO_ADDRESS, ISanctionsList(ZERO_ADDRESS)); + return (IOwnable2StepLike(address(rule)), ownerAddr); + } +} + +contract RuleSanctionsListOwnable2StepAccessControl is Test, HelperContract { + error OwnableUnauthorizedAccount(address account); + + RuleSanctionsListOwnable2StepHarness private rule; + SanctionListOracle private oracle; + + function setUp() public { + oracle = new SanctionListOracle(); + rule = new RuleSanctionsListOwnable2StepHarness( + SANCTIONLIST_OPERATOR_ADDRESS, ZERO_ADDRESS, ISanctionsList(ZERO_ADDRESS) + ); + } + + function testOwnerCanSetAndClearOracle() public { + vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); + rule.setSanctionListOracle(oracle); + assertEq(address(rule.sanctionsList()), address(oracle)); + + vm.prank(SANCTIONLIST_OPERATOR_ADDRESS); + rule.clearSanctionListOracle(); + assertEq(address(rule.sanctionsList()), ZERO_ADDRESS); + } + + function testNonOwnerCannotSetOracle() public { + vm.expectRevert(abi.encodeWithSelector(OwnableUnauthorizedAccount.selector, ATTACKER)); + vm.prank(ATTACKER); + rule.setSanctionListOracle(oracle); + } + + function testMetaTxOverridesAreReachable() public view { + assertEq(rule.exposedMsgSender(), address(this)); + assertEq(rule.exposedContextSuffixLength(), 20); + assertGe(rule.exposedMsgData().length, 4); + } +} diff --git a/test/RuleWhitelist/RuleWhitelist.t.sol b/test/RuleWhitelist/RuleWhitelist.t.sol index 35b0fa4..7ac30a0 100644 --- a/test/RuleWhitelist/RuleWhitelist.t.sol +++ b/test/RuleWhitelist/RuleWhitelist.t.sol @@ -64,6 +64,27 @@ contract RuleWhitelistTest is Test, HelperContract { assertEq(resBool, true); } + function testContainsReflectsListingStatus() public { + // Act - Assert + assertFalse(ruleWhitelist.contains(ADDRESS1)); + + // Arrange + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS1); + + // Act - Assert + assertTrue(ruleWhitelist.contains(ADDRESS1)); + } + + function testIsVerifiedReflectsListingStatus() public { + assertFalse(ruleWhitelist.isVerified(ADDRESS1)); + + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS1); + + assertTrue(ruleWhitelist.isVerified(ADDRESS1)); + } + function testAddressesIsIndicatedAsWhitelisted() public { // Arrange _addAddresses(); diff --git a/test/RuleWhitelist/WhitelistWrapper.t.sol b/test/RuleWhitelist/WhitelistWrapper.t.sol index 27d6271..cfc1f4a 100644 --- a/test/RuleWhitelist/WhitelistWrapper.t.sol +++ b/test/RuleWhitelist/WhitelistWrapper.t.sol @@ -10,6 +10,16 @@ import {RuleWhitelistWrapper} from "src/rules/validation/deployment/RuleWhitelis * @title Integration test with the CMTAT */ +contract RuleWhitelistWrapperHarnessInternal is RuleWhitelistWrapper { + constructor(address admin, address forwarderIrrevocable, bool checkSpender_) + RuleWhitelistWrapper(admin, forwarderIrrevocable, checkSpender_) + {} + + function exposedTransferredSpenderInternal(address spender, address from, address to, uint256 value) external view { + _transferred(spender, from, to, value); + } +} + contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { uint256 constant ADDRESS1_BALANCE_INIT = 31; uint256 constant ADDRESS2_BALANCE_INIT = 32; @@ -221,6 +231,38 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { ruleWhitelistWrapper.transferred(ADDRESS3, ADDRESS1, ADDRESS2, 0, 20); } + function testDetectTransferRestrictionWithSpenderFromNotWhitelisted() public { + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS2); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS3); + + resUint8 = ruleWhitelistWrapper.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + assertEq(resUint8, CODE_ADDRESS_FROM_NOT_WHITELISTED); + } + + function testDetectTransferRestrictionWithSpenderToNotWhitelisted() public { + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS1); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS3); + + resUint8 = ruleWhitelistWrapper.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + assertEq(resUint8, CODE_ADDRESS_TO_NOT_WHITELISTED); + } + + function testDetectTransferRestrictionFromIgnoresSpenderWhenCheckDisabled() public { + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelistWrapper.setCheckSpender(false); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS1); + vm.prank(WHITELIST_OPERATOR_ADDRESS); + ruleWhitelist.addAddress(ADDRESS2); + + resUint8 = ruleWhitelistWrapper.detectTransferRestrictionFrom(ADDRESS3, ADDRESS1, ADDRESS2, 20); + assertEq(resUint8, NO_ERROR); + } + function testDetectTransferRestrictionOk() public { // Arrange vm.prank(WHITELIST_OPERATOR_ADDRESS); @@ -310,4 +352,21 @@ contract CMTATIntegrationWhitelistWrapper is Test, HelperContract { new RuleWhitelistWrapper(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true); assertFalse(emptyWrapper.isVerified(ADDRESS1)); } + + function testInternalTransferredSpenderOverload() public { + RuleWhitelistWrapperHarnessInternal wrapperHarness = + new RuleWhitelistWrapperHarnessInternal(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true); + RuleWhitelist child = new RuleWhitelist(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS, true); + + vm.prank(WHITELIST_OPERATOR_ADDRESS); + wrapperHarness.addRule(child); + + vm.startPrank(WHITELIST_OPERATOR_ADDRESS); + child.addAddress(ADDRESS1); + child.addAddress(ADDRESS2); + child.addAddress(ADDRESS3); + vm.stopPrank(); + + wrapperHarness.exposedTransferredSpenderInternal(ADDRESS3, ADDRESS1, ADDRESS2, 20); + } } diff --git a/test/TransferContext/TransferContext.t.sol b/test/TransferContext/TransferContext.t.sol index 3c55783..e05510b 100644 --- a/test/TransferContext/TransferContext.t.sol +++ b/test/TransferContext/TransferContext.t.sol @@ -72,4 +72,28 @@ contract TransferContextTest is Test, HelperContract { vm.prank(ADDRESS3); token.transferFromWithContext(ADDRESS1, ADDRESS2, 10, true, 0); } + + function testTransferFromContextFungibleWhitelist() public { + RuleWhitelist rule = _deployWhitelistRule(); + token.setRule(address(rule)); + token.mint(ADDRESS1, 100); + + vm.prank(ADDRESS1); + token.approve(ADDRESS3, 10); + + vm.prank(ADDRESS3); + token.transferFromWithContext(ADDRESS1, ADDRESS2, 10, true, 0); + } + + function testTransferFromContextWithTokenIdWhitelist() public { + RuleWhitelist rule = _deployWhitelistRule(); + token.setRule(address(rule)); + token.mint(ADDRESS1, 100); + + vm.prank(ADDRESS1); + token.approve(ADDRESS3, 10); + + vm.prank(ADDRESS3); + token.transferFromWithContext(ADDRESS1, ADDRESS2, 10, false, 1); + } } From 19fb08d9d57ec23f63d9c26655045187fa03e6d8 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Tue, 10 Mar 2026 12:49:53 +0100 Subject: [PATCH 2/2] Update documentation --- .gitignore | 4 ++++ README.md | 10 ++++++++++ doc/schema/Rule-Rule.drawio.png | Bin 0 -> 34623 bytes doc/schema/Rule-RuleEngine.drawio.png | Bin 0 -> 49704 bytes doc/schema/Rule.drawio | 1 + doc/schema/RuleEngine.drawio | 1 - 6 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 doc/schema/Rule-Rule.drawio.png create mode 100644 doc/schema/Rule-RuleEngine.drawio.png create mode 100644 doc/schema/Rule.drawio delete mode 100644 doc/schema/RuleEngine.drawio diff --git a/.gitignore b/.gitignore index 7b3c91f..ac3da17 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,7 @@ node_modules/ /ERCSpecification *.dbg.json /skills + +#drawio +*.bkp +*.dtmp diff --git a/README.md b/README.md index ace16e8..5122c55 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,16 @@ Each rule can be used **standalone**, directly plugged into a CMTAT token, **or* Latest update: completed 100% coverage across `src/` contracts, including direct coverage for `RuleAddressSet.contains(address)`, mint/burn-path coverage for `RuleConditionalTransferLightBase.detectTransferRestriction(...)`, and removal of an unreachable duplicate admin-zero check in `RuleConditionalTransferLight` constructor. +## Schema + +- Using rules with CMTAT and ERC-3643 tokens through a [RuleEngine](ttps://github.com/CMTA/RuleEngine) + +![Rule-RuleEngine.drawio](./doc/schema/Rule-RuleEngine.drawio.png) + +- Using a rule directly with CMTAT and ERC-3643 tokens + +![Rule-Rule.drawio](./doc/schema/Rule-Rule.drawio.png) + ## Table of Contents [TOC] diff --git a/doc/schema/Rule-Rule.drawio.png b/doc/schema/Rule-Rule.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..c2f9799e4373c6ca40847ef0920c809a64cdb6cc GIT binary patch literal 34623 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 literal 0 HcmV?d00001 diff --git a/doc/schema/Rule-RuleEngine.drawio.png b/doc/schema/Rule-RuleEngine.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..0498e669ce4b52396a75ff62bf551a46ec473c46 GIT binary patch literal 49704 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 \ No newline at end of file diff --git a/doc/schema/RuleEngine.drawio b/doc/schema/RuleEngine.drawio deleted file mode 100644 index e908186..0000000 --- a/doc/schema/RuleEngine.drawio +++ /dev/null @@ -1 +0,0 @@ -1VpLc+I4EP41VO0e4rIkP/AxkMzMYac2NWEnm70JW4AqxqJkMcD8+pWxbCzJBEIwIblEar3s7q+/7hbuoeF8/ZXjxew7S0jag26y7qG7HoQA+VD+KySbUuL3+6VgymmiJu0Ej/Q3UUJXSZc0Ibk2UTCWCrrQhTHLMhILTYY5Zyt92oSl+qkLPCWW4DHGqS19oomYlVKIULAb+EbodFYdHfheOTLH1Wz1KvkMJ2zVEKH7HhpyxkTZmq+HJC20VymmXPdlz2j9ZJxk4pgF3og/hzzA5Gnz9/PLqj/65+d/N2qXXzhdqjcefh/djtQTi02lh9WMCvK4wHHRX0lb99BgJuap7AHZxPmi1P6Erok8b2A/XHUS4YKsGyL1sF8JmxPBN3KKGoWhUpyCDvD9sr/aGQJUc2ZNG1RCrIw/rffeqUc2lIbeoC1oaQs4guMsnxD+h2A9OKxG/7Q0SLLktgCk7MUpznMa6yrkbJklhe7uXNmTauObf2XnxnVcACvJczHseCisBHfr5oK7TbP3QDiV7024Eu61icB8SsRhlJBEcxbbcg3L+C2GqWScpFjQX7qLtRlLnfDAqHziGhgA6sCAyLB3zpY8JmpV0yOMjWBgICwyNioVY220xU792qfDCVlwGrEXkhVakzwl7WZiSFLIomgu5+ltLJg07KDwJyr56i88JukDy6mgLJNTxkwINm9MuE3ptBgQzPBdthQpzciwZtBXsXK8//qGlSpKb4AEtYAk6Mp5PUvb5/JRV3dP/4Bz7tVtidvDfnjQX/2r8tcA6UhA7on+GkQGpEysdOyvgYUg6MgOTbAgIxUGbExJI2yd04iYyh1jCQLCW/x0TpOk2GPASU5/4/F2vwI+i+L1ti/sD3r+XSugXnUA04Pr7EkdouUnbZ7tOqgfIt0UZ0HKDQy1XW/6+g5sMslJJ6b1LdP+WKbkPptKZrRM+gHJkN+/umQo7IxPgc6n4cmE+skSG9PIsI9OJErP3OiyRNm3oCG4bEFXpiyyCMNpbjvV9fBkBewz8KQXeUBnNPA+pHTPhJFlO4SdRJYRsahi3A+SC07jbab5MSkUWVNRM4VsPzfkuyVF5/1Jl38sl7hXRSaBb0UMx238GRseSy1916AWeFlqqbRsRGopqa5ZdljUsXYgap8hSEeGbiK74qlr14uUPMC+sFDKAlenLOi2ZDSX1ZZdj3sXp77uUh14VfQUmtcD3olFYWgWhf6FCelt9woZy4pkJcH5bAsFoGOkkD9gIVOdbCuBLpJSiTn2Ul9AQxtLKhyqwNlxQARHR8TrglzkehpSUFVDvRVykZleB8ZGXUOuvVqVEpuUPprWkffhtN5WqAapPHYwlo1p0SDO1JFTngr1pDQvbM23Gi3nyXPrqZaGpWKErsbSXYcsLW5oK4+f0DQ1RMfXNm120y17BtMBFxzOX7wW03X3e4sdkf3LFyPwlGoEdES+R3Pvdd0Bh4EVpc9RjUTmT0Heq0VOx7wM7VTAGzt8B9AhS1ouPi5zSVbnCM0MQS3rIkmARwL1unEKgrNUzZHBrMD8yXIPMiUw8KYxTd1p7X18qzoPtW8CZKPc8bywtwOs3xnsm0h/brrBG2DfFTcfnRhfF+YtEg3Ows0W5UfQOS5P3o/6szO2fVONxl0RtuMCXydt4KEuWPttX38chrX7OWENPg2s95A5NGPRu8hcdncfm5XTd9/sofv/AQ== \ No newline at end of file