diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7d29319..56c1241 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - name: Run Forge tests run: forge test -vvv - - name: Setup NodeJS 20.5.0 + - name: Setup NodeJS 20.5.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 #v4.4.0 with: node-version: 20.5.0 diff --git a/AGENTS.md b/AGENTS.md index 76854b9..89370db 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -55,11 +55,13 @@ All three share their core logic through `RuleEngineBase` directly or via `RuleE ``` RuleEngineBase (abstract) ├── VersionModule → version() returns "3.0.0" -├── RulesManagementModule → add/remove/set/clear rules +├── RulesManagementModule → add/remove/set/clear rules, maxRules cap │ ├── AccessControl (OZ) │ └── RulesManagementModuleInvariantStorage → errors, events, roles -├── ERC3643ComplianceModule → bind/unbind tokens -│ └── IERC3643Compliance +├── ERC3643ComplianceExtendedModule → bind/unbind tokens (extended API) +│ └── ERC3643ComplianceModule → core ERC-3643 compliance +│ ├── IERC3643Compliance +│ └── ERC3643ComplianceModuleInvariantStorage → errors ├── RuleEngineInvariantStorage → errors └── IRuleEngineERC1404 → CMTAT interface @@ -87,16 +89,19 @@ Modules define **virtual internal hooks** for access control. Concrete contracts ```solidity // In RulesManagementModule (abstract): function _onlyRulesManager() internal virtual; +function _onlyRulesLimitManager() internal virtual; // guards setMaxRules // In ERC3643ComplianceModule (abstract): function _onlyComplianceManager() internal virtual; // RuleEngine overrides with RBAC: function _onlyRulesManager() internal virtual override onlyRole(RULES_MANAGEMENT_ROLE) {} +function _onlyRulesLimitManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {} function _onlyComplianceManager() internal virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) {} // RuleEngineOwnable overrides with Ownable: function _onlyRulesManager() internal virtual override onlyOwner {} +function _onlyRulesLimitManager() internal virtual override onlyOwner {} function _onlyComplianceManager() internal virtual override onlyOwner {} ``` @@ -127,12 +132,29 @@ function _checkRule(address rule_) internal view virtual override { ### Rule Execution Flow ``` -Token.transfer() → RuleEngine.transferred(from, to, value) - ├── onlyBoundToken modifier (caller must be bound) - └── for each rule in _rules: - rule.transferred(from, to, value) // reverts if disallowed +Token operation → RuleEngine.transferred(spender, from, to, value) ← CMTAT v3.3.0+ primary path + ├── onlyBoundToken modifier (caller must be bound) + └── for each rule in _rules: + rule.transferred(spender, from, to, value) // reverts if disallowed + + RuleEngine.transferred(from, to, value) ← 3-arg fallback (spender == address(0)) + ├── onlyBoundToken modifier + └── for each rule in _rules: + rule.transferred(from, to, value) + + RuleEngine.created(to, value) ← ERC-3643 mint entry point + ├── onlyBoundToken modifier + └── calls _transferred(address(0), to, value) + + RuleEngine.destroyed(from, value) ← ERC-3643 burn entry point + ├── onlyBoundToken modifier + └── calls _transferred(from, address(0), value) ``` +Since CMTAT v3.3.0, mint (`from == address(0)`) and burn (`to == address(0)`) also go through the 4-argument overload with the operator as `spender`. Rules that check `spender` must skip or adapt that check for mint/burn to avoid blocking those operations unintentionally. + +`created` and `destroyed` use the 3-argument `_transferred` path (no spender), consistent with the ERC-3643 spec which does not carry a spender for mint/burn. + View path: `detectTransferRestriction()` iterates rules, returns first non-zero code. ### Storage: EnumerableSet diff --git a/CHANGELOG.md b/CHANGELOG.md index 955ece6..35ffbb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,8 +45,52 @@ forge lint - Update surya doc by running the 3 scripts in [./doc/script](./doc/script) - Update changelog + + +### v3.0.0-rc4 - 2026-05-22 + +### Added + +- Add `RuleMintAllowance` mock rule: admin-controlled per-minter mint allowance with `setMintAllowance(address, uint256)`, enforcement in `transferred(spender, from, to, value)` when `from == address(0)`, and `CODE_MINTER_INSUFFICIENT_ALLOWANCE` (code 81). +- Add `ERC3643ComplianceModuleInvariantStorage` in `src/modules/library/` to hold all `RuleEngine_ERC3643Compliance_*` custom errors, following the invariant storage pattern already used by `RulesManagementModule`. +- Add `ERC3643ComplianceRolesStorage` in `src/modules/library/` as a dedicated contract for `COMPLIANCE_MANAGER_ROLE`, separating role constants from error/event declarations. + +### Changed + +- `ERC3643ComplianceModule` now inherits `ERC3643ComplianceModuleInvariantStorage` and `ERC3643ComplianceRolesStorage`; errors and role constant are no longer declared inline. +- `RuleWhitelist.detectTransferRestrictionFrom`: spender check is now skipped for mint (`from == address(0)`) and burn (`to == address(0)`) operations, as the operator in those cases is the authorized minter/burner rather than a delegated spender. +- `RuleWhitelist.transferred` (both overloads): removed `view` modifier to match the intended mutable-callback semantics of the `IRule` interface. +- `RuleMintAllowance.transferred(address, address, uint256)`: removed `view` modifier for the same reason. +- `COMPLIANCE_MANAGER_ROLE` moved from inline declaration in `ERC3643ComplianceModule` to `ERC3643ComplianceRolesStorage`. +- `VersionModule.VERSION` constant visibility changed from `private` to `internal` to allow direct access by inheriting contracts and tests. +- `IRulesManagementModule.containsRule` now correctly declares `view`. +- `IRulesManagementModule.setMaxRules` NatSpec documents that high cap values re-expose O(n) gas cost for administrative operations such as `clearRules`. +- `IRulesManagementModule.clearRules` NatSpec updated to reflect O(n) cost relative to rule count and the interaction with `maxRules`. +- `RulesManagementModule.setRules` NatSpec now documents that `ClearRules` is emitted when replacing a non-empty rule set, in addition to `AddRule` per new rule. +- `RuleWhitelist` imports converted from plain imports with forge-lint suppression comments to named imports. +- `RuleEngineOwnable2Step` constructor now has full `@notice`/`@param` NatSpec. +- `RuleEngine.grantRole` NatSpec documents the intentional asymmetry: the check prevents granting roles to current rules but does not prevent adding a privileged address as a rule afterwards. +- `ERC3643ComplianceModule.bindToken` and `ERC3643ComplianceExtendedModule.bindTokens` now carry a `@custom:security-note` warning about cross-token state contamination in multi-tenant setups with stateful/operation rules. + +### Documentation + +- CLAUDE.md / AGENTS.md: + - Inheritance hierarchy corrected to show `ERC3643ComplianceExtendedModule` → `ERC3643ComplianceModule` → `ERC3643ComplianceModuleInvariantStorage`. + - Access control pattern section now documents the `_onlyRulesLimitManager` hook alongside `_onlyRulesManager` and `_onlyComplianceManager`. + - Rule Execution Flow diagram extended with `created` and `destroyed` ERC-3643 entry points. +- README: + - CMTAT target version updated to v3.3.0 in both the compatibility table and the dependencies section. + - "Like CMTAT" section rewritten to document the v3.3.0 spender path for mint and burn, with an operation/address table and a rule-authoring note. + - `bindToken`/`unbindToken` function table updated to reflect `COMPLIANCE_MANAGER_ROLE or approved token self-call` access path. + +### Dependencies + +- Update CMTAT submodule to v3.3.0-rc1. + ### v3.0.0-rc3 - 2026-05-07 +Commit: `5827604be4e38f65c055a929c7b62462a20f4bbd` + ### Security - Enforce an on-chain maximum rule count in `RulesManagementModule` to mitigate transfer liveness risk from unbounded per-transfer rule iteration (Nethermind AuditAgent finding 3 follow-up). diff --git a/CLAUDE.md b/CLAUDE.md index 76854b9..89370db 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -55,11 +55,13 @@ All three share their core logic through `RuleEngineBase` directly or via `RuleE ``` RuleEngineBase (abstract) ├── VersionModule → version() returns "3.0.0" -├── RulesManagementModule → add/remove/set/clear rules +├── RulesManagementModule → add/remove/set/clear rules, maxRules cap │ ├── AccessControl (OZ) │ └── RulesManagementModuleInvariantStorage → errors, events, roles -├── ERC3643ComplianceModule → bind/unbind tokens -│ └── IERC3643Compliance +├── ERC3643ComplianceExtendedModule → bind/unbind tokens (extended API) +│ └── ERC3643ComplianceModule → core ERC-3643 compliance +│ ├── IERC3643Compliance +│ └── ERC3643ComplianceModuleInvariantStorage → errors ├── RuleEngineInvariantStorage → errors └── IRuleEngineERC1404 → CMTAT interface @@ -87,16 +89,19 @@ Modules define **virtual internal hooks** for access control. Concrete contracts ```solidity // In RulesManagementModule (abstract): function _onlyRulesManager() internal virtual; +function _onlyRulesLimitManager() internal virtual; // guards setMaxRules // In ERC3643ComplianceModule (abstract): function _onlyComplianceManager() internal virtual; // RuleEngine overrides with RBAC: function _onlyRulesManager() internal virtual override onlyRole(RULES_MANAGEMENT_ROLE) {} +function _onlyRulesLimitManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {} function _onlyComplianceManager() internal virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) {} // RuleEngineOwnable overrides with Ownable: function _onlyRulesManager() internal virtual override onlyOwner {} +function _onlyRulesLimitManager() internal virtual override onlyOwner {} function _onlyComplianceManager() internal virtual override onlyOwner {} ``` @@ -127,12 +132,29 @@ function _checkRule(address rule_) internal view virtual override { ### Rule Execution Flow ``` -Token.transfer() → RuleEngine.transferred(from, to, value) - ├── onlyBoundToken modifier (caller must be bound) - └── for each rule in _rules: - rule.transferred(from, to, value) // reverts if disallowed +Token operation → RuleEngine.transferred(spender, from, to, value) ← CMTAT v3.3.0+ primary path + ├── onlyBoundToken modifier (caller must be bound) + └── for each rule in _rules: + rule.transferred(spender, from, to, value) // reverts if disallowed + + RuleEngine.transferred(from, to, value) ← 3-arg fallback (spender == address(0)) + ├── onlyBoundToken modifier + └── for each rule in _rules: + rule.transferred(from, to, value) + + RuleEngine.created(to, value) ← ERC-3643 mint entry point + ├── onlyBoundToken modifier + └── calls _transferred(address(0), to, value) + + RuleEngine.destroyed(from, value) ← ERC-3643 burn entry point + ├── onlyBoundToken modifier + └── calls _transferred(from, address(0), value) ``` +Since CMTAT v3.3.0, mint (`from == address(0)`) and burn (`to == address(0)`) also go through the 4-argument overload with the operator as `spender`. Rules that check `spender` must skip or adapt that check for mint/burn to avoid blocking those operations unintentionally. + +`created` and `destroyed` use the 3-argument `_transferred` path (no spender), consistent with the ERC-3643 spec which does not carry a spender for mint/burn. + View path: `detectTransferRestriction()` iterates rules, returns first non-zero code. ### Storage: EnumerableSet diff --git a/README.md b/README.md index 3961d5b..f77180c 100644 --- a/README.md +++ b/README.md @@ -77,10 +77,9 @@ This diagram illustrates how a transfer with a CMTAT or ERC-3643 token with a Ru | RuleEngine version | Compatible Versions | | ------------------------------------------------------------ | ------------------------------------------------------------ | -| **v3.0.0-rc3** | CMTAT ≥ v3.0.0
CMTAT target version: [v3.2.0](https://github.com/CMTA/CMTAT/releases/tag/v3.2.0) | +| **v3.0.0-rc4** | CMTAT ≥ v3.0.0
CMTAT target version: [v3.3.0-rc1](https://github.com/CMTA/CMTAT/releases/tag/v3.3.0-rc1) | +| **v3.0.0-rc3** | CMTAT ≥ v3.0.0
CMTAT target version: [v3.3.0](https://github.com/CMTA/CMTAT/releases/tag/v3.3.0) | | **v3.0.0-rc2** | CMTAT ≥ v3.0.0
CMTAT target version: [v3.2.0](https://github.com/CMTA/CMTAT/releases/tag/v3.2.0) | -| **v3.0.0-rc1** | CMTAT ≥ v3.0.0
CMTAT target version: [v3.2.0](https://github.com/CMTA/CMTAT/releases/tag/v3.2.0) | -| **v3.0.0-rc0** | CMTAT ≥ v3.0.0
| | **[v1.0.2.1](https://github.com/CMTA/RuleEngine/releases/tag/v1.0.2.1)** | CMTAT v2.3.0 (audited) | #### CMTAT v3.0.0 @@ -147,17 +146,29 @@ If you need non-standard helper functions (batch bind/unbind, self-binding appro ### Like CMTAT -Before each ERC-20 transfer, the CMTAT calls the function `transferred` which is the entrypoint for the RuleEngine. +Before each ERC-20 transfer, mint, or burn, CMTAT calls the RuleEngine through the internal function `_checkTransferred`, which dispatches to one of two `transferred` overloads depending on whether a non-zero spender is present. ```solidity -function transferred(address from,address to,uint256 value) +// Called when spender == address(0) +function transferred(address from, address to, uint256 value) + +// Called when spender != address(0) +function transferred(address spender, address from, address to, uint256 value) ``` -If you want to apply restrictions on the spender address, you have to call the `transferred` function which takes the spender argument in your ERC-20 function `transferFrom`. +#### CMTAT v3.3.0 — mint and burn use the spender path -```solidity -function transferred(address spender,address from,address to,uint256 value) -``` +Since CMTAT v3.3.0, **mint and burn operations also go through the 4-argument overload**, with the operator (minter or burner) passed as `spender`: + +| Operation | `spender` | `from` | `to` | +|-----------|-----------|--------|------| +| `transfer` / `transferFrom` | caller / approved spender | token holder | recipient | +| `mint` | minter (`_msgSender()`) | `address(0)` | recipient | +| `burn` | burner (`_msgSender()`) | token holder | `address(0)` | + +The 3-argument overload is only called when `spender == address(0)`, which does not occur in normal CMTAT v3.3.0 flows. + +> **Rule authoring note:** Rules that check the `spender` argument in `transferred(spender, from, to, value)` must explicitly handle the mint (`from == address(0)`) and burn (`to == address(0)`) cases. A spender check that is intended only for `transferFrom` will also fire for mints and burns unless the rule skips it when `from` or `to` is the zero address. See `RuleWhitelist` and `RuleSpenderWhitelist` in the Rules repository for reference implementations. For example, CMTAT defines the interaction with the RuleEngine inside a specific module, [ValidationModuleRuleEngine](https://github.com/CMTA/CMTAT/blob/master/contracts/modules/wrapper/extensions/ValidationModule/ValidationModuleRuleEngine.sol) and [CMTATBaseRuleEngine](https://github.com/CMTA/CMTAT/blob/master/contracts/modules/1_CMTATBaseRuleEngine.sol). @@ -169,7 +180,7 @@ For example, CMTAT defines the interaction with the RuleEngine inside a specific ![checkTransferred](./doc/other/CMTAT/checkTransferred.png) -This function `_transferred` is called before each transfer/burn/mint through the internal function `_checkTransferred` defined in [CMTAT_BASE](https://github.com/CMTA/CMTAT/blob/23a1e59f913d079d0c09d32fafbd95ab2d426093/contracts/modules/CMTAT_BASE.sol#L198). +This function `_transferred` is called before each transfer/burn/mint through the internal function `_checkTransferred`. ### Like ERC-3643 @@ -267,7 +278,7 @@ The toolchain includes the following components, where the versions are the late - Foundry (forge-std) [v1.14.0](https://github.com/foundry-rs/forge-std/releases/tag/v1.14.0) - Solidity [0.8.34](https://docs.soliditylang.org/en/v0.8.34/) - OpenZeppelin Contracts (submodule) [v5.6.1](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.6.1) -- CMTAT [v3.2.0](https://github.com/CMTA/CMTAT/releases/tag/v3.2.0) +- CMTAT [v3.3.0](https://github.com/CMTA/CMTAT/releases/tag/v3.3.0) ### Access Control @@ -365,8 +376,8 @@ For function signatures, struct arguments are represented with their correspondi | | `addRule(address rule_)` | public | `IRule rule_` |-|RULES_MANAGEMENT_ROLE| | | `removeRule(address rule_)` | public | `IRule rule_` |-|RULES_MANAGEMENT_ROLE| | ERC3643ComplianceModule | | | | | | -| | `bindToken(address token)` | public | `address token` | - | COMPLIANCE_MANAGER_ROLE | -| | `unbindToken(address token)` | public | `address token` | - | COMPLIANCE_MANAGER_ROLE | +| | `bindToken(address token)` | public | `address token` | - | COMPLIANCE_MANAGER_ROLE or approved token self-call | +| | `unbindToken(address token)` | public | `address token` | - | COMPLIANCE_MANAGER_ROLE or approved token self-call | | ERC3643ComplianceExtendedModule | | | | | | | | `bindTokens(address[] tokens)` | public | `address[] tokens` | - | COMPLIANCE_MANAGER_ROLE | | | `unbindTokens(address[] tokens)` | public | `address[] tokens` | - | COMPLIANCE_MANAGER_ROLE | @@ -1392,20 +1403,20 @@ Here is the list of report performed with [Slither](https://github.com/crytic/sl | Version | Report | Assessment | | ------- | ------ | ---------- | -| v3.0.0-rc2 | [slither-report.md](./doc/security/audits/tools/slither-report.md) | [slither-report-feedback.md](./doc/security/audits/tools/slither-report-feedback.md) | +| v3.0.0-rc4 | [slither-report.md](./doc/security/audits/tools/v3.0.0-rc4/slither-report.md) | [slither-report-feedback.md](./doc/security/audits/tools/v3.0.0-rc4/slither-report-feedback.md) | +| v3.0.0-rc3 | [slither-report.md](./doc/security/audits/tools/v3.0.0-rc3/slither-report.md) | [slither-report-feedback.md](./doc/security/audits/tools/v3.0.0-rc3/slither-report-feedback.md) | +| v3.0.0-rc2 | [slither-report.md](./doc/security/audits/tools/v3.0.0-rc2/slither-report.md) | [slither-report-feedback.md](./doc/security/audits/tools/v3.0.0-rc2/slither-report-feedback.md) | ```bash slither . --checklist --filter-paths "openzeppelin-contracts|test|CMTAT|forge-std|mocks" > slither-report.md ``` -4 finding categories — 0 High · 0 Medium · 10 Low · 4 Informational +2 finding categories — 0 High · 0 Medium · 10 Low · 2 Informational | ID | Detector | Impact | Instances | Assessment | |----|----------|--------|-----------|------------| | 0–9 | `calls-loop` | Low | 10 | Accepted by design — fan-out to rule contracts is the core architecture | -| 10 | `dead-code` | Informational | 1 | Accepted / no action — `_msgData` override is required by inheritance/context pattern | -| 11 | `naming-convention` | Informational | 1 | Ignored — finding is in external CMTAT dependency code | -| 12–13 | `unindexed-event-address` | Informational | 2 | Deferred — adding `indexed` to `TokenBound`/`TokenUnbound` is interface-breaking | +| 10–11 | `unindexed-event-address` | Informational | 2 | Deferred — adding `indexed` to `TokenBound`/`TokenUnbound` is interface-breaking | #### Aderyn @@ -1417,21 +1428,23 @@ aderyn -x mocks --output aderyn-report.md | Version | Report | Assessment | | ------- | ------ | ---------- | -| v3.0.0-rc2 | [aderyn-report.md](./doc/security/audits/tools/aderyn-report.md) | [aderyn-report-feedback.md](./doc/security/audits/tools/aderyn-report-feedback.md) | +| v3.0.0-rc4 | [aderyn-report.md](./doc/security/audits/tools/v3.0.0-rc4/aderyn-report.md) | [aderyn-report-feedback.md](./doc/security/audits/tools/v3.0.0-rc4/aderyn-report-feedback.md) | +| v3.0.0-rc3 | [aderyn-report.md](./doc/security/audits/tools/v3.0.0-rc3/aderyn-report.md) | [aderyn-report-feedback.md](./doc/security/audits/tools/v3.0.0-rc3/aderyn-report-feedback.md) | +| v3.0.0-rc2 | [aderyn-report.md](./doc/security/audits/tools/v3.0.0-rc2/aderyn-report.md) | [aderyn-report-feedback.md](./doc/security/audits/tools/v3.0.0-rc2/aderyn-report-feedback.md) | -Report scope: 18 Solidity files, 542 nSLOC. +Report scope: 24 Solidity files, 629 nSLOC. 0 High · 8 Low | ID | Finding | Instances | Assessment | |----|---------|-----------|------------| | L-1 | Centralization Risk | 14 | Accepted by design — privileged compliance tool | -| L-2 | Unspecific Solidity Pragma | 14 | Accepted by design — intentional for library reusability | -| L-3 | PUSH0 Opcode | 18 | Not applicable — project targets Prague EVM | +| L-2 | Unspecific Solidity Pragma | 19 | Accepted by design — intentional for library reusability | +| L-3 | PUSH0 Opcode | 24 | Not applicable — project targets Prague EVM | | L-4 | Modifier Invoked Only Once | 1 | Accepted by design — keeps hook-style access-control abstraction | | L-5 | Empty Block | 9 | Accepted by design — access-control hook pattern | -| L-6 | Loop Contains `require`/`revert` | 1 | Accepted by design — `setRules` is an atomic batch operation | -| L-7 | Costly Operations Inside Loop | 1 | Accepted — unavoidable `SSTORE` in `setRules` | +| L-6 | Loop Contains `require`/`revert` | 4 | Accepted by design — `setRules` and `bindTokens`/`unbindTokens` are atomic batch operations | +| L-7 | Costly Operations Inside Loop | 4 | Accepted — unavoidable `SSTORE` in batch operations | | L-8 | Unchecked Return | 1 | Accepted — `_grantRole` return is irrelevant in constructor | ## Documentation diff --git a/doc/coverage/code-coverage.png b/doc/coverage/code-coverage.png index b395bbe..4b9eb22 100644 Binary files a/doc/coverage/code-coverage.png and b/doc/coverage/code-coverage.png differ diff --git a/doc/coverage/coverage/index-sort-b.html b/doc/coverage/coverage/index-sort-b.html index 15ae843..17ae624 100644 --- a/doc/coverage/coverage/index-sort-b.html +++ b/doc/coverage/coverage/index-sort-b.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 79 diff --git a/doc/coverage/coverage/index-sort-f.html b/doc/coverage/coverage/index-sort-f.html index b39c30e..7eb445a 100644 --- a/doc/coverage/coverage/index-sort-f.html +++ b/doc/coverage/coverage/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 79 diff --git a/doc/coverage/coverage/index-sort-l.html b/doc/coverage/coverage/index-sort-l.html index 0394496..48fefd9 100644 --- a/doc/coverage/coverage/index-sort-l.html +++ b/doc/coverage/coverage/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 79 diff --git a/doc/coverage/coverage/index.html b/doc/coverage/coverage/index.html index f897605..40a7f7b 100644 --- a/doc/coverage/coverage/index.html +++ b/doc/coverage/coverage/index.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 79 diff --git a/doc/coverage/coverage/src/RuleEngineBase.sol.func-sort-c.html b/doc/coverage/coverage/src/RuleEngineBase.sol.func-sort-c.html index 3386ca0..b18dccb 100644 --- a/doc/coverage/coverage/src/RuleEngineBase.sol.func-sort-c.html +++ b/doc/coverage/coverage/src/RuleEngineBase.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 14 @@ -78,14 +78,14 @@ RuleEngineBase.transferred.0 - 5 + 6 - RuleEngineBase.detectTransferRestrictionFrom - 18 + RuleEngineBase.transferred.1 + 17 - RuleEngineBase.transferred.1 + RuleEngineBase.detectTransferRestrictionFrom 18 diff --git a/doc/coverage/coverage/src/RuleEngineBase.sol.func.html b/doc/coverage/coverage/src/RuleEngineBase.sol.func.html index 32fb24c..ba1ee8b 100644 --- a/doc/coverage/coverage/src/RuleEngineBase.sol.func.html +++ b/doc/coverage/coverage/src/RuleEngineBase.sol.func.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 14 @@ -118,11 +118,11 @@ RuleEngineBase.transferred.0 - 5 + 6 RuleEngineBase.transferred.1 - 18 + 17
diff --git a/doc/coverage/coverage/src/RuleEngineBase.sol.gcov.html b/doc/coverage/coverage/src/RuleEngineBase.sol.gcov.html index 22088f9..38a1d68 100644 --- a/doc/coverage/coverage/src/RuleEngineBase.sol.gcov.html +++ b/doc/coverage/coverage/src/RuleEngineBase.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 14 @@ -111,26 +111,26 @@ 40 : : /* 41 : : * @inheritdoc IRuleEngine 42 : : */ - 43 : 5 : function transferred(address spender, address from, address to, uint256 value) + 43 : 6 : function transferred(address spender, address from, address to, uint256 value) 44 : : public 45 : : virtual 46 : : override(IRuleEngine) 47 : : onlyBoundToken 48 : : { 49 : : // Apply on RuleEngine - 50 : 4 : RulesManagementModule._transferred(spender, from, to, value); + 50 : 5 : RulesManagementModule._transferred(spender, from, to, value); 51 : : } 52 : : 53 : : /** 54 : : * @inheritdoc IERC3643IComplianceContract 55 : : */ - 56 : 18 : function transferred(address from, address to, uint256 value) + 56 : 17 : function transferred(address from, address to, uint256 value) 57 : : public 58 : : virtual 59 : : override(IERC3643IComplianceContract) 60 : : onlyBoundToken 61 : : { - 62 : 16 : _transferred(from, to, value); + 62 : 15 : _transferred(from, to, value); 63 : : } 64 : : 65 : : /// @inheritdoc IERC3643Compliance diff --git a/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.func-sort-c.html b/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.func-sort-c.html index 84148a7..290bad8 100644 --- a/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.func-sort-c.html +++ b/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 6 diff --git a/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.func.html b/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.func.html index b9f0c93..1184f16 100644 --- a/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.func.html +++ b/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.func.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 6 diff --git a/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.gcov.html b/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.gcov.html index cb1af0e..78dc115 100644 --- a/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.gcov.html +++ b/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 6 diff --git a/doc/coverage/coverage/src/deployment/RuleEngine.sol.func-sort-c.html b/doc/coverage/coverage/src/deployment/RuleEngine.sol.func-sort-c.html index 22e3bc9..ab51881 100644 --- a/doc/coverage/coverage/src/deployment/RuleEngine.sol.func-sort-c.html +++ b/doc/coverage/coverage/src/deployment/RuleEngine.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 10 @@ -69,23 +69,23 @@ Hit count Sort by hit count - RuleEngine._msgData + RuleEngine._msgData 1 - RuleEngine._onlyRulesLimitManager + RuleEngine._onlyRulesLimitManager 5 - RuleEngine.supportsInterface + RuleEngine.supportsInterface 21 - RuleEngine.grantRole + RuleEngine.grantRole 39 - RuleEngine._onlyComplianceManager + RuleEngine._onlyComplianceManager 42 @@ -93,19 +93,19 @@ 165 - RuleEngine.hasRole + RuleEngine.hasRole 173 - RuleEngine._onlyRulesManager + RuleEngine._onlyRulesManager 196 - RuleEngine._msgSender + RuleEngine._msgSender 535 - RuleEngine._contextSuffixLength + RuleEngine._contextSuffixLength 536 diff --git a/doc/coverage/coverage/src/deployment/RuleEngine.sol.func.html b/doc/coverage/coverage/src/deployment/RuleEngine.sol.func.html index 8984abe..aff6062 100644 --- a/doc/coverage/coverage/src/deployment/RuleEngine.sol.func.html +++ b/doc/coverage/coverage/src/deployment/RuleEngine.sol.func.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 10 @@ -69,27 +69,27 @@ Hit count Sort by hit count - RuleEngine._contextSuffixLength + RuleEngine._contextSuffixLength 536 - RuleEngine._msgData + RuleEngine._msgData 1 - RuleEngine._msgSender + RuleEngine._msgSender 535 - RuleEngine._onlyComplianceManager + RuleEngine._onlyComplianceManager 42 - RuleEngine._onlyRulesLimitManager + RuleEngine._onlyRulesLimitManager 5 - RuleEngine._onlyRulesManager + RuleEngine._onlyRulesManager 196 @@ -97,15 +97,15 @@ 165 - RuleEngine.grantRole + RuleEngine.grantRole 39 - RuleEngine.hasRole + RuleEngine.hasRole 173 - RuleEngine.supportsInterface + RuleEngine.supportsInterface 21 diff --git a/doc/coverage/coverage/src/deployment/RuleEngine.sol.gcov.html b/doc/coverage/coverage/src/deployment/RuleEngine.sol.gcov.html index 42edf71..60912ad 100644 --- a/doc/coverage/coverage/src/deployment/RuleEngine.sol.gcov.html +++ b/doc/coverage/coverage/src/deployment/RuleEngine.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 10 @@ -110,72 +110,76 @@ 39 : : /* ============ ACCESS CONTROL ============ */ 40 : : /** 41 : : * @notice Grants `role` to `account`. - 42 : : * @dev Prevents granting any role to accounts already configured as rules. - 43 : : */ - 44 : 39 : function grantRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) { - 45 [ + ]: 39 : if (_rules.contains(account)) { - 46 : 3 : revert RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges(); - 47 : : } - 48 : 36 : AccessControl.grantRole(role, account); - 49 : : } - 50 : : - 51 : : /** - 52 : : * @notice Returns `true` if `account` has been granted `role`. - 53 : : * @dev The Default Admin has all roles - 54 : : */ - 55 : 173 : function hasRole(bytes32 role, address account) - 56 : : public - 57 : : view - 58 : : virtual - 59 : : override(AccessControl, IAccessControl) - 60 : : returns (bool) - 61 : : { - 62 [ + + ]: 490 : if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { - 63 : 236 : return true; - 64 : : } else { - 65 : 254 : return AccessControl.hasRole(role, account); - 66 : : } - 67 : : } - 68 : : - 69 : : /* ============ ERC-165 ============ */ - 70 : 21 : function supportsInterface(bytes4 interfaceId) - 71 : : public - 72 : : view - 73 : : virtual - 74 : : override(AccessControlEnumerable, IERC165) - 75 : : returns (bool) - 76 : : { - 77 : 21 : return _supportsRuleEngineBaseInterface(interfaceId) || AccessControlEnumerable.supportsInterface(interfaceId); - 78 : : } - 79 : : - 80 : : /*////////////////////////////////////////////////////////////// - 81 : : ERC-2771 - 82 : : //////////////////////////////////////////////////////////////*/ - 83 : 42 : function _onlyComplianceManager() internal virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) {} - 84 : 196 : function _onlyRulesManager() internal virtual override onlyRole(RULES_MANAGEMENT_ROLE) {} - 85 : 5 : function _onlyRulesLimitManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {} - 86 : : - 87 : : /** - 88 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 89 : : */ - 90 : 535 : function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) { - 91 : 535 : return ERC2771Context._msgSender(); - 92 : : } - 93 : : - 94 : : /** - 95 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 96 : : */ - 97 : 1 : function _msgData() internal view virtual override(ERC2771Context, Context) returns (bytes calldata) { - 98 : 1 : return ERC2771Context._msgData(); - 99 : : } - 100 : : - 101 : : /** - 102 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 103 : : */ - 104 : 536 : function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) { - 105 : 536 : return ERC2771Context._contextSuffixLength(); - 106 : : } - 107 : : } + 42 : : * @dev Prevents granting any role to accounts currently configured as rules. + 43 : : * Note: this check is intentionally one-directional. {addRule} does not verify + 44 : : * whether the rule address already holds a privileged role, and this function does + 45 : : * not prevent adding a privileged address as a rule afterwards. Operators are + 46 : : * responsible for keeping rule contracts and privileged accounts disjoint. + 47 : : */ + 48 : 39 : function grantRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) { + 49 [ + ]: 39 : if (_rules.contains(account)) { + 50 : 3 : revert RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges(); + 51 : : } + 52 : 36 : AccessControl.grantRole(role, account); + 53 : : } + 54 : : + 55 : : /** + 56 : : * @notice Returns `true` if `account` has been granted `role`. + 57 : : * @dev The Default Admin has all roles + 58 : : */ + 59 : 173 : function hasRole(bytes32 role, address account) + 60 : : public + 61 : : view + 62 : : virtual + 63 : : override(AccessControl, IAccessControl) + 64 : : returns (bool) + 65 : : { + 66 [ + + ]: 490 : if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { + 67 : 236 : return true; + 68 : : } else { + 69 : 254 : return AccessControl.hasRole(role, account); + 70 : : } + 71 : : } + 72 : : + 73 : : /* ============ ERC-165 ============ */ + 74 : 21 : function supportsInterface(bytes4 interfaceId) + 75 : : public + 76 : : view + 77 : : virtual + 78 : : override(AccessControlEnumerable, IERC165) + 79 : : returns (bool) + 80 : : { + 81 : 21 : return _supportsRuleEngineBaseInterface(interfaceId) || AccessControlEnumerable.supportsInterface(interfaceId); + 82 : : } + 83 : : + 84 : : /*////////////////////////////////////////////////////////////// + 85 : : ERC-2771 + 86 : : //////////////////////////////////////////////////////////////*/ + 87 : 42 : function _onlyComplianceManager() internal virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) {} + 88 : 196 : function _onlyRulesManager() internal virtual override onlyRole(RULES_MANAGEMENT_ROLE) {} + 89 : 5 : function _onlyRulesLimitManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {} + 90 : : + 91 : : /** + 92 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 93 : : */ + 94 : 535 : function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) { + 95 : 535 : return ERC2771Context._msgSender(); + 96 : : } + 97 : : + 98 : : /** + 99 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 100 : : */ + 101 : 1 : function _msgData() internal view virtual override(ERC2771Context, Context) returns (bytes calldata) { + 102 : 1 : return ERC2771Context._msgData(); + 103 : : } + 104 : : + 105 : : /** + 106 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 107 : : */ + 108 : 536 : function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) { + 109 : 536 : return ERC2771Context._contextSuffixLength(); + 110 : : } + 111 : : } diff --git a/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.func-sort-c.html b/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.func-sort-c.html index 95ca527..a1087f6 100644 --- a/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.func-sort-c.html +++ b/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 7 diff --git a/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.func.html b/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.func.html index d36afdf..214bcbb 100644 --- a/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.func.html +++ b/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.func.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 7 diff --git a/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.gcov.html b/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.gcov.html index 3f1c9d9..3a77998 100644 --- a/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.gcov.html +++ b/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 7 diff --git a/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.func-sort-c.html b/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.func-sort-c.html index 4c225ed..b67c9fb 100644 --- a/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.func-sort-c.html +++ b/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 8 @@ -69,35 +69,35 @@ Hit count Sort by hit count - RuleEngineOwnable2Step._msgData + RuleEngineOwnable2Step._msgData 1 - RuleEngineOwnable2Step._onlyRulesLimitManager + RuleEngineOwnable2Step._onlyRulesLimitManager 2 - RuleEngineOwnable2Step._onlyRulesManager + RuleEngineOwnable2Step._onlyRulesManager 5 - RuleEngineOwnable2Step.transferOwnership + RuleEngineOwnable2Step.transferOwnership 6 - RuleEngineOwnable2Step.supportsInterface + RuleEngineOwnable2Step.supportsInterface 13 - RuleEngineOwnable2Step._onlyComplianceManager + RuleEngineOwnable2Step._onlyComplianceManager 25 - RuleEngineOwnable2Step._msgSender + RuleEngineOwnable2Step._msgSender 68 - RuleEngineOwnable2Step._contextSuffixLength + RuleEngineOwnable2Step._contextSuffixLength 69 diff --git a/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.func.html b/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.func.html index 9187783..5228298 100644 --- a/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.func.html +++ b/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.func.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 8 @@ -69,35 +69,35 @@ Hit count Sort by hit count - RuleEngineOwnable2Step._contextSuffixLength + RuleEngineOwnable2Step._contextSuffixLength 69 - RuleEngineOwnable2Step._msgData + RuleEngineOwnable2Step._msgData 1 - RuleEngineOwnable2Step._msgSender + RuleEngineOwnable2Step._msgSender 68 - RuleEngineOwnable2Step._onlyComplianceManager + RuleEngineOwnable2Step._onlyComplianceManager 25 - RuleEngineOwnable2Step._onlyRulesLimitManager + RuleEngineOwnable2Step._onlyRulesLimitManager 2 - RuleEngineOwnable2Step._onlyRulesManager + RuleEngineOwnable2Step._onlyRulesManager 5 - RuleEngineOwnable2Step.supportsInterface + RuleEngineOwnable2Step.supportsInterface 13 - RuleEngineOwnable2Step.transferOwnership + RuleEngineOwnable2Step.transferOwnership 6 diff --git a/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.gcov.html b/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.gcov.html index ab3556d..cef61d5 100644 --- a/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.gcov.html +++ b/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 8 @@ -85,63 +85,64 @@ 14 : : */ 15 : : contract RuleEngineOwnable2Step is RuleEngineOwnableShared, Ownable2Step { 16 : : /** - 17 : : * @param owner_ Address of the contract owner (ERC-173) - 18 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - 19 : : * @param tokenContract Address of the token contract to bind (can be zero address) - 20 : : */ - 21 : : constructor(address owner_, address forwarderIrrevocable, address tokenContract) - 22 : : RuleEngineOwnableShared(forwarderIrrevocable, tokenContract) - 23 : : Ownable(owner_) - 24 : : {} - 25 : : - 26 : : /* ============ ACCESS CONTROL ============ */ - 27 : : /** - 28 : : * @dev Access control check using Ownable pattern - 29 : : */ - 30 : 5 : function _onlyRulesManager() internal virtual override onlyOwner {} - 31 : 2 : function _onlyRulesLimitManager() internal virtual override onlyOwner {} - 32 : : - 33 : : /** - 34 : : * @dev Access control check using Ownable pattern - 35 : : */ - 36 : 25 : function _onlyComplianceManager() internal virtual override onlyOwner {} - 37 : : - 38 : : /** - 39 : : * @notice Starts ownership transfer to `newOwner`. - 40 : : * @dev Reverts when `newOwner` is already configured as a rule. - 41 : : */ - 42 : 6 : function transferOwnership(address newOwner) public virtual override onlyOwner { - 43 : 6 : RuleEngineOwnableShared._checkOwnershipTransferTarget(newOwner); - 44 : 5 : Ownable2Step.transferOwnership(newOwner); - 45 : : } - 46 : : - 47 : : /* ============ ERC-165 ============ */ - 48 : 13 : function supportsInterface(bytes4 interfaceId) public view virtual override(RuleEngineOwnableShared) returns (bool) { - 49 : 13 : return interfaceId == Ownable2StepInterfaceId.IOWNABLE2STEP_INTERFACE_ID - 50 : 11 : || RuleEngineOwnableShared.supportsInterface(interfaceId); - 51 : : } - 52 : : - 53 : : /** - 54 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 55 : : */ - 56 : 68 : function _msgSender() internal view virtual override(RuleEngineOwnableShared, Context) returns (address sender) { - 57 : 68 : return RuleEngineOwnableShared._msgSender(); - 58 : : } - 59 : : - 60 : : /** - 61 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 62 : : */ - 63 : 1 : function _msgData() internal view virtual override(RuleEngineOwnableShared, Context) returns (bytes calldata) { - 64 : 1 : return RuleEngineOwnableShared._msgData(); - 65 : : } - 66 : : - 67 : : /** - 68 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 69 : : */ - 70 : 69 : function _contextSuffixLength() internal view virtual override(RuleEngineOwnableShared, Context) returns (uint256) { - 71 : 69 : return RuleEngineOwnableShared._contextSuffixLength(); - 72 : : } - 73 : : } + 17 : : * @notice Deploys a RuleEngine with ERC-173 two-step ownership transfer. + 18 : : * @param owner_ Address of the initial contract owner (ERC-173). + 19 : : * @param forwarderIrrevocable Address of the ERC-2771 trusted forwarder (use zero address to disable gasless). + 20 : : * @param tokenContract Address of the token contract to bind at deployment (use zero address to skip). + 21 : : */ + 22 : : constructor(address owner_, address forwarderIrrevocable, address tokenContract) + 23 : : RuleEngineOwnableShared(forwarderIrrevocable, tokenContract) + 24 : : Ownable(owner_) + 25 : : {} + 26 : : + 27 : : /* ============ ACCESS CONTROL ============ */ + 28 : : /** + 29 : : * @dev Access control check using Ownable pattern + 30 : : */ + 31 : 5 : function _onlyRulesManager() internal virtual override onlyOwner {} + 32 : 2 : function _onlyRulesLimitManager() internal virtual override onlyOwner {} + 33 : : + 34 : : /** + 35 : : * @dev Access control check using Ownable pattern + 36 : : */ + 37 : 25 : function _onlyComplianceManager() internal virtual override onlyOwner {} + 38 : : + 39 : : /** + 40 : : * @notice Starts ownership transfer to `newOwner`. + 41 : : * @dev Reverts when `newOwner` is already configured as a rule. + 42 : : */ + 43 : 6 : function transferOwnership(address newOwner) public virtual override onlyOwner { + 44 : 6 : RuleEngineOwnableShared._checkOwnershipTransferTarget(newOwner); + 45 : 5 : Ownable2Step.transferOwnership(newOwner); + 46 : : } + 47 : : + 48 : : /* ============ ERC-165 ============ */ + 49 : 13 : function supportsInterface(bytes4 interfaceId) public view virtual override(RuleEngineOwnableShared) returns (bool) { + 50 : 13 : return interfaceId == Ownable2StepInterfaceId.IOWNABLE2STEP_INTERFACE_ID + 51 : 11 : || RuleEngineOwnableShared.supportsInterface(interfaceId); + 52 : : } + 53 : : + 54 : : /** + 55 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 56 : : */ + 57 : 68 : function _msgSender() internal view virtual override(RuleEngineOwnableShared, Context) returns (address sender) { + 58 : 68 : return RuleEngineOwnableShared._msgSender(); + 59 : : } + 60 : : + 61 : : /** + 62 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 63 : : */ + 64 : 1 : function _msgData() internal view virtual override(RuleEngineOwnableShared, Context) returns (bytes calldata) { + 65 : 1 : return RuleEngineOwnableShared._msgData(); + 66 : : } + 67 : : + 68 : : /** + 69 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule + 70 : : */ + 71 : 69 : function _contextSuffixLength() internal view virtual override(RuleEngineOwnableShared, Context) returns (uint256) { + 72 : 69 : return RuleEngineOwnableShared._contextSuffixLength(); + 73 : : } + 74 : : } diff --git a/doc/coverage/coverage/src/deployment/index-sort-b.html b/doc/coverage/coverage/src/deployment/index-sort-b.html index 5ef3ff6..9786af8 100644 --- a/doc/coverage/coverage/src/deployment/index-sort-b.html +++ b/doc/coverage/coverage/src/deployment/index-sort-b.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 25 diff --git a/doc/coverage/coverage/src/deployment/index-sort-f.html b/doc/coverage/coverage/src/deployment/index-sort-f.html index 414a352..7a8b7c2 100644 --- a/doc/coverage/coverage/src/deployment/index-sort-f.html +++ b/doc/coverage/coverage/src/deployment/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 25 diff --git a/doc/coverage/coverage/src/deployment/index-sort-l.html b/doc/coverage/coverage/src/deployment/index-sort-l.html index eefd8bd..4136abe 100644 --- a/doc/coverage/coverage/src/deployment/index-sort-l.html +++ b/doc/coverage/coverage/src/deployment/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 25 diff --git a/doc/coverage/coverage/src/deployment/index.html b/doc/coverage/coverage/src/deployment/index.html index a680e27..d85f72a 100644 --- a/doc/coverage/coverage/src/deployment/index.html +++ b/doc/coverage/coverage/src/deployment/index.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 25 diff --git a/doc/coverage/coverage/src/index-sort-b.html b/doc/coverage/coverage/src/index-sort-b.html index 353a9a9..ab024be 100644 --- a/doc/coverage/coverage/src/index-sort-b.html +++ b/doc/coverage/coverage/src/index-sort-b.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 20 diff --git a/doc/coverage/coverage/src/index-sort-f.html b/doc/coverage/coverage/src/index-sort-f.html index 8f77607..4c25063 100644 --- a/doc/coverage/coverage/src/index-sort-f.html +++ b/doc/coverage/coverage/src/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 20 diff --git a/doc/coverage/coverage/src/index-sort-l.html b/doc/coverage/coverage/src/index-sort-l.html index d4235ae..8bf2ace 100644 --- a/doc/coverage/coverage/src/index-sort-l.html +++ b/doc/coverage/coverage/src/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 20 diff --git a/doc/coverage/coverage/src/index.html b/doc/coverage/coverage/src/index.html index d0fc157..3a35084 100644 --- a/doc/coverage/coverage/src/index.html +++ b/doc/coverage/coverage/src/index.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 20 diff --git a/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.func-sort-c.html b/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.func-sort-c.html index 13d1d9a..d6030b2 100644 --- a/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.func-sort-c.html +++ b/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 7 @@ -69,31 +69,31 @@ Hit count Sort by hit count - ERC3643ComplianceExtendedModule.getTokenBounds + ERC3643ComplianceExtendedModule.getTokenBounds 4 - ERC3643ComplianceExtendedModule.isTokenSelfBindingApproved + ERC3643ComplianceExtendedModule.isTokenSelfBindingApproved 6 - ERC3643ComplianceExtendedModule.unbindTokens + ERC3643ComplianceExtendedModule.unbindTokens 9 - ERC3643ComplianceExtendedModule.setTokenSelfBindingApprovalBatch + ERC3643ComplianceExtendedModule.setTokenSelfBindingApprovalBatch 12 - ERC3643ComplianceExtendedModule.setTokenSelfBindingApproval + ERC3643ComplianceExtendedModule.setTokenSelfBindingApproval 14 - ERC3643ComplianceExtendedModule.bindTokens + ERC3643ComplianceExtendedModule.bindTokens 18 - ERC3643ComplianceExtendedModule._authorizeComplianceBindingChange + ERC3643ComplianceExtendedModule._authorizeComplianceBindingChange 72 diff --git a/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.func.html b/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.func.html index 51b35e9..a525710 100644 --- a/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.func.html +++ b/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.func.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 7 @@ -69,31 +69,31 @@ Hit count Sort by hit count - ERC3643ComplianceExtendedModule._authorizeComplianceBindingChange + ERC3643ComplianceExtendedModule._authorizeComplianceBindingChange 72 - ERC3643ComplianceExtendedModule.bindTokens + ERC3643ComplianceExtendedModule.bindTokens 18 - ERC3643ComplianceExtendedModule.getTokenBounds + ERC3643ComplianceExtendedModule.getTokenBounds 4 - ERC3643ComplianceExtendedModule.isTokenSelfBindingApproved + ERC3643ComplianceExtendedModule.isTokenSelfBindingApproved 6 - ERC3643ComplianceExtendedModule.setTokenSelfBindingApproval + ERC3643ComplianceExtendedModule.setTokenSelfBindingApproval 14 - ERC3643ComplianceExtendedModule.setTokenSelfBindingApprovalBatch + ERC3643ComplianceExtendedModule.setTokenSelfBindingApprovalBatch 12 - ERC3643ComplianceExtendedModule.unbindTokens + ERC3643ComplianceExtendedModule.unbindTokens 9 diff --git a/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.gcov.html b/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.gcov.html index b228f55..bfdd448 100644 --- a/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.gcov.html +++ b/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 7 @@ -83,63 +83,68 @@ 12 : : 13 : : mapping(address token => bool approved) private _tokenSelfBindingApproval; 14 : : - 15 : : /// @inheritdoc IERC3643ComplianceExtended - 16 : 18 : function bindTokens(address[] calldata tokens) public virtual override onlyComplianceManager { - 17 : 15 : for (uint256 i = 0; i < tokens.length; ++i) { - 18 : 24 : _bindToken(tokens[i]); - 19 : : } - 20 : : } - 21 : : - 22 : : /// @inheritdoc IERC3643ComplianceExtended - 23 : 9 : function unbindTokens(address[] calldata tokens) public virtual override onlyComplianceManager { - 24 : 6 : for (uint256 i = 0; i < tokens.length; ++i) { - 25 : 12 : _unbindToken(tokens[i]); - 26 : : } - 27 : : } - 28 : : - 29 : : /// @inheritdoc IERC3643ComplianceExtended - 30 : 14 : function setTokenSelfBindingApproval(address token, bool approved) public virtual override onlyComplianceManager { - 31 [ + + ]: 11 : require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); - 32 : 8 : _tokenSelfBindingApproval[token] = approved; - 33 : 8 : emit TokenSelfBindingApprovalSet(token, approved); - 34 : : } - 35 : : - 36 : : /// @inheritdoc IERC3643ComplianceExtended - 37 : 12 : function setTokenSelfBindingApprovalBatch(address[] calldata tokens, bool approved) - 38 : : public - 39 : : virtual - 40 : : override - 41 : : onlyComplianceManager - 42 : : { - 43 : 9 : for (uint256 i = 0; i < tokens.length; ++i) { - 44 : 18 : address token = tokens[i]; - 45 [ + + ]: 18 : require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); - 46 : 15 : _tokenSelfBindingApproval[token] = approved; - 47 : : } - 48 : 6 : emit TokenSelfBindingApprovalBatchSet(tokens, approved); - 49 : : } - 50 : : - 51 : : /// @inheritdoc IERC3643ComplianceExtended - 52 : 6 : function isTokenSelfBindingApproved(address token) public view virtual override returns (bool) { - 53 : 6 : return _tokenSelfBindingApproval[token]; + 15 : : /** + 16 : : * @inheritdoc IERC3643ComplianceExtended + 17 : : * @custom:security-note See {bindToken} for multi-tenant accounting risks. All tokens bound + 18 : : * in this batch share the same rule state. Only bind tokens that are equally trusted and + 19 : : * governed together. + 20 : : */ + 21 : 18 : function bindTokens(address[] calldata tokens) public virtual override onlyComplianceManager { + 22 : 15 : for (uint256 i = 0; i < tokens.length; ++i) { + 23 : 24 : _bindToken(tokens[i]); + 24 : : } + 25 : : } + 26 : : + 27 : : /// @inheritdoc IERC3643ComplianceExtended + 28 : 9 : function unbindTokens(address[] calldata tokens) public virtual override onlyComplianceManager { + 29 : 6 : for (uint256 i = 0; i < tokens.length; ++i) { + 30 : 12 : _unbindToken(tokens[i]); + 31 : : } + 32 : : } + 33 : : + 34 : : /// @inheritdoc IERC3643ComplianceExtended + 35 : 14 : function setTokenSelfBindingApproval(address token, bool approved) public virtual override onlyComplianceManager { + 36 [ + + ]: 11 : require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); + 37 : 8 : _tokenSelfBindingApproval[token] = approved; + 38 : 8 : emit TokenSelfBindingApprovalSet(token, approved); + 39 : : } + 40 : : + 41 : : /// @inheritdoc IERC3643ComplianceExtended + 42 : 12 : function setTokenSelfBindingApprovalBatch(address[] calldata tokens, bool approved) + 43 : : public + 44 : : virtual + 45 : : override + 46 : : onlyComplianceManager + 47 : : { + 48 : 9 : for (uint256 i = 0; i < tokens.length; ++i) { + 49 : 18 : address token = tokens[i]; + 50 [ + + ]: 18 : require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); + 51 : 15 : _tokenSelfBindingApproval[token] = approved; + 52 : : } + 53 : 6 : emit TokenSelfBindingApprovalBatchSet(tokens, approved); 54 : : } 55 : : 56 : : /// @inheritdoc IERC3643ComplianceExtended - 57 : 4 : function getTokenBounds() public view virtual override returns (address[] memory) { - 58 : 4 : return _boundTokens.values(); + 57 : 6 : function isTokenSelfBindingApproved(address token) public view virtual override returns (bool) { + 58 : 6 : return _tokenSelfBindingApproval[token]; 59 : : } 60 : : - 61 : : /** - 62 : : * @dev Authorizes bind/unbind operations. - 63 : : * Allows compliance manager, or approved token self-calls for T-REX compatibility. - 64 : : */ - 65 : 72 : function _authorizeComplianceBindingChange(address token) internal virtual override { - 66 [ + ]: 72 : if (_msgSender() == token && _tokenSelfBindingApproval[token]) { - 67 : 72 : return; - 68 : : } - 69 : 60 : _onlyComplianceManager(); - 70 : : } - 71 : : } + 61 : : /// @inheritdoc IERC3643ComplianceExtended + 62 : 4 : function getTokenBounds() public view virtual override returns (address[] memory) { + 63 : 4 : return _boundTokens.values(); + 64 : : } + 65 : : + 66 : : /** + 67 : : * @dev Authorizes bind/unbind operations. + 68 : : * Allows compliance manager, or approved token self-calls for T-REX compatibility. + 69 : : */ + 70 : 72 : function _authorizeComplianceBindingChange(address token) internal virtual override { + 71 [ + ]: 72 : if (_msgSender() == token && _tokenSelfBindingApproval[token]) { + 72 : 72 : return; + 73 : : } + 74 : 60 : _onlyComplianceManager(); + 75 : : } + 76 : : } diff --git a/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func-sort-c.html b/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func-sort-c.html index aef8ae7..f077265 100644 --- a/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func-sort-c.html +++ b/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 9 @@ -69,47 +69,47 @@ Hit count Sort by hit count - ERC3643ComplianceModule._authorizeComplianceBindingChange + ERC3643ComplianceModule._authorizeComplianceBindingChange 0 - ERC3643ComplianceModule._onlyComplianceManager + ERC3643ComplianceModule._onlyComplianceManager 0 - ERC3643ComplianceModule.getTokenBound + ERC3643ComplianceModule.getTokenBound 5 - ERC3643ComplianceModule.onlyBoundToken - 5 + ERC3643ComplianceModule.onlyBoundToken + 6 - ERC3643ComplianceModule.onlyComplianceManager + ERC3643ComplianceModule.onlyComplianceManager 9 - ERC3643ComplianceModule.unbindToken + ERC3643ComplianceModule.unbindToken 20 - ERC3643ComplianceModule._unbindToken + ERC3643ComplianceModule._unbindToken 25 - ERC3643ComplianceModule._checkBoundToken + ERC3643ComplianceModule._checkBoundToken 31 - ERC3643ComplianceModule.isTokenBound + ERC3643ComplianceModule.isTokenBound 37 - ERC3643ComplianceModule.bindToken + ERC3643ComplianceModule.bindToken 52 - ERC3643ComplianceModule._bindToken + ERC3643ComplianceModule._bindToken 101 diff --git a/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func.html b/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func.html index dff97aa..98101c1 100644 --- a/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func.html +++ b/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 9 @@ -69,47 +69,47 @@ Hit count Sort by hit count - ERC3643ComplianceModule._authorizeComplianceBindingChange + ERC3643ComplianceModule._authorizeComplianceBindingChange 0 - ERC3643ComplianceModule._bindToken + ERC3643ComplianceModule._bindToken 101 - ERC3643ComplianceModule._checkBoundToken + ERC3643ComplianceModule._checkBoundToken 31 - ERC3643ComplianceModule._onlyComplianceManager + ERC3643ComplianceModule._onlyComplianceManager 0 - ERC3643ComplianceModule._unbindToken + ERC3643ComplianceModule._unbindToken 25 - ERC3643ComplianceModule.bindToken + ERC3643ComplianceModule.bindToken 52 - ERC3643ComplianceModule.getTokenBound + ERC3643ComplianceModule.getTokenBound 5 - ERC3643ComplianceModule.isTokenBound + ERC3643ComplianceModule.isTokenBound 37 - ERC3643ComplianceModule.onlyBoundToken - 5 + ERC3643ComplianceModule.onlyBoundToken + 6 - ERC3643ComplianceModule.onlyComplianceManager + ERC3643ComplianceModule.onlyComplianceManager 9 - ERC3643ComplianceModule.unbindToken + ERC3643ComplianceModule.unbindToken 20 diff --git a/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.gcov.html b/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.gcov.html index a1c95ac..d20c5d4 100644 --- a/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.gcov.html +++ b/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 9 @@ -78,107 +78,108 @@ 7 : : import {Context} from "@openzeppelin/contracts/utils/Context.sol"; 8 : : /* ==== Interface and other library === */ 9 : : import {IERC3643Compliance} from "../interfaces/IERC3643Compliance.sol"; - 10 : : - 11 : : abstract contract ERC3643ComplianceModule is Context, IERC3643Compliance { - 12 : : /* ==== Type declaration === */ - 13 : : using EnumerableSet for EnumerableSet.AddressSet; - 14 : : /* ==== State Variables === */ - 15 : : // Token binding tracking - 16 : : EnumerableSet.AddressSet internal _boundTokens; - 17 : : // Access Control - 18 : : // Will not be present in the final bytecode if not used - 19 : : bytes32 public constant COMPLIANCE_MANAGER_ROLE = keccak256("COMPLIANCE_MANAGER_ROLE"); - 20 : : - 21 : : /* ==== Errors === */ - 22 : : error RuleEngine_ERC3643Compliance_InvalidTokenAddress(); - 23 : : error RuleEngine_ERC3643Compliance_TokenAlreadyBound(); - 24 : : error RuleEngine_ERC3643Compliance_TokenNotBound(); - 25 : : error RuleEngine_ERC3643Compliance_UnauthorizedCaller(); - 26 : : error RuleEngine_ERC3643Compliance_OperationNotSuccessful(); - 27 : : - 28 : : /* ==== Modifier === */ - 29 : 5 : modifier onlyBoundToken() { - 30 : 5 : _checkBoundToken(); - 31 : : _; - 32 : : } - 33 : : - 34 : 9 : modifier onlyComplianceManager() { - 35 : 9 : _onlyComplianceManager(); - 36 : : _; - 37 : : } - 38 : : - 39 : : /*////////////////////////////////////////////////////////////// - 40 : : PUBLIC/public FUNCTIONS - 41 : : //////////////////////////////////////////////////////////////*/ - 42 : : - 43 : : /* ============ State functions ============ */ - 44 : : /** - 45 : : * @inheritdoc IERC3643Compliance - 46 : : * @dev Operator warning: "multi-tenant" means one RuleEngine is shared by - 47 : : * multiple token contracts. In that setup, bind only tokens that are equally - 48 : : * trusted and governed together. - 49 : : */ - 50 : 52 : function bindToken(address token) public virtual override { - 51 : 52 : _authorizeComplianceBindingChange(token); - 52 : 45 : _bindToken(token); - 53 : : } - 54 : : - 55 : : /** - 56 : : * @inheritdoc IERC3643Compliance - 57 : : * @dev Operator warning: unbinding is an administrative operation and does not - 58 : : * erase any state already stored by external rule contracts in a previously - 59 : : * shared ("multi-tenant") setup. - 60 : : */ - 61 : 20 : function unbindToken(address token) public virtual override { - 62 : 20 : _authorizeComplianceBindingChange(token); - 63 : 13 : _unbindToken(token); - 64 : : } - 65 : : - 66 : : /// @inheritdoc IERC3643Compliance - 67 : 37 : function isTokenBound(address token) public view virtual override returns (bool) { - 68 : 37 : return _boundTokens.contains(token); - 69 : : } - 70 : : - 71 : : /// @inheritdoc IERC3643Compliance - 72 : 5 : function getTokenBound() public view virtual override returns (address) { - 73 [ + + ]: 5 : if (_boundTokens.length() > 0) { - 74 : : // Note that there are no guarantees on the ordering of values inside the array, - 75 : : // and it may change when more values are added or removed. - 76 : 3 : return _boundTokens.at(0); - 77 : : } else { - 78 : 2 : return address(0); - 79 : : } - 80 : : } - 81 : : - 82 : : /*////////////////////////////////////////////////////////////// - 83 : : INTERNAL/PRIVATE FUNCTIONS - 84 : : //////////////////////////////////////////////////////////////*/ - 85 : : - 86 : 25 : function _unbindToken(address token) internal { - 87 [ + + ]: 25 : require(_boundTokens.contains(token), RuleEngine_ERC3643Compliance_TokenNotBound()); - 88 : : // Should never revert because we check if the token address is already set before - 89 [ # + ]: 20 : require(_boundTokens.remove(token), RuleEngine_ERC3643Compliance_OperationNotSuccessful()); - 90 : : - 91 : 20 : emit TokenUnbound(token); - 92 : : } - 93 : : - 94 : 101 : function _bindToken(address token) internal { - 95 [ + + ]: 101 : require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); - 96 [ + + ]: 96 : require(!_boundTokens.contains(token), RuleEngine_ERC3643Compliance_TokenAlreadyBound()); - 97 : : // Should never revert because we check if the token address is already set before - 98 [ # + ]: 91 : require(_boundTokens.add(token), RuleEngine_ERC3643Compliance_OperationNotSuccessful()); - 99 : 91 : emit TokenBound(token); - 100 : : } - 101 : : - 102 : 31 : function _checkBoundToken() internal view virtual { - 103 [ + ]: 31 : if (!_boundTokens.contains(_msgSender())) { - 104 : 7 : revert RuleEngine_ERC3643Compliance_UnauthorizedCaller(); - 105 : : } - 106 : : } - 107 : : - 108 : 0 : function _authorizeComplianceBindingChange(address token) internal virtual; - 109 : 0 : function _onlyComplianceManager() internal virtual; - 110 : : } + 10 : : import {ERC3643ComplianceModuleInvariantStorage} from "./library/ERC3643ComplianceModuleInvariantStorage.sol"; + 11 : : import {ERC3643ComplianceRolesStorage} from "./library/ERC3643ComplianceRolesStorage.sol"; + 12 : : + 13 : : abstract contract ERC3643ComplianceModule is + 14 : : Context, + 15 : : IERC3643Compliance, + 16 : : ERC3643ComplianceModuleInvariantStorage, + 17 : : ERC3643ComplianceRolesStorage + 18 : : { + 19 : : /* ==== Type declaration === */ + 20 : : using EnumerableSet for EnumerableSet.AddressSet; + 21 : : /* ==== State Variables === */ + 22 : : // Token binding tracking + 23 : : EnumerableSet.AddressSet internal _boundTokens; + 24 : : + 25 : : /* ==== Modifier === */ + 26 : 6 : modifier onlyBoundToken() { + 27 : 6 : _checkBoundToken(); + 28 : : _; + 29 : : } + 30 : : + 31 : 9 : modifier onlyComplianceManager() { + 32 : 9 : _onlyComplianceManager(); + 33 : : _; + 34 : : } + 35 : : + 36 : : /*////////////////////////////////////////////////////////////// + 37 : : PUBLIC/public FUNCTIONS + 38 : : //////////////////////////////////////////////////////////////*/ + 39 : : + 40 : : /* ============ State functions ============ */ + 41 : : /** + 42 : : * @inheritdoc IERC3643Compliance + 43 : : * @dev Operator warning: "multi-tenant" means one RuleEngine is shared by + 44 : : * multiple token contracts. In that setup, bind only tokens that are equally + 45 : : * trusted and governed together. + 46 : : * @custom:security-note Operation rules (stateful rules such as `RuleConditionalTransferLight` + 47 : : * or `RuleMintAllowance`) maintain per-address accounting that is shared across all bound tokens. + 48 : : * Binding tokens from different issuers to the same engine will silently cross-contaminate + 49 : : * their accounting. Only bind tokens that are equally trusted and governed together. + 50 : : */ + 51 : 52 : function bindToken(address token) public virtual override { + 52 : 52 : _authorizeComplianceBindingChange(token); + 53 : 45 : _bindToken(token); + 54 : : } + 55 : : + 56 : : /** + 57 : : * @inheritdoc IERC3643Compliance + 58 : : * @dev Operator warning: unbinding is an administrative operation and does not + 59 : : * erase any state already stored by external rule contracts in a previously + 60 : : * shared ("multi-tenant") setup. + 61 : : */ + 62 : 20 : function unbindToken(address token) public virtual override { + 63 : 20 : _authorizeComplianceBindingChange(token); + 64 : 13 : _unbindToken(token); + 65 : : } + 66 : : + 67 : : /// @inheritdoc IERC3643Compliance + 68 : 37 : function isTokenBound(address token) public view virtual override returns (bool) { + 69 : 37 : return _boundTokens.contains(token); + 70 : : } + 71 : : + 72 : : /// @inheritdoc IERC3643Compliance + 73 : 5 : function getTokenBound() public view virtual override returns (address) { + 74 [ + + ]: 5 : if (_boundTokens.length() > 0) { + 75 : : // Note that there are no guarantees on the ordering of values inside the array, + 76 : : // and it may change when more values are added or removed. + 77 : 3 : return _boundTokens.at(0); + 78 : : } else { + 79 : 2 : return address(0); + 80 : : } + 81 : : } + 82 : : + 83 : : /*////////////////////////////////////////////////////////////// + 84 : : INTERNAL/PRIVATE FUNCTIONS + 85 : : //////////////////////////////////////////////////////////////*/ + 86 : : + 87 : 25 : function _unbindToken(address token) internal { + 88 [ + + ]: 25 : require(_boundTokens.contains(token), RuleEngine_ERC3643Compliance_TokenNotBound()); + 89 : : // Should never revert because we check if the token address is already set before + 90 [ # + ]: 20 : require(_boundTokens.remove(token), RuleEngine_ERC3643Compliance_OperationNotSuccessful()); + 91 : : + 92 : 20 : emit TokenUnbound(token); + 93 : : } + 94 : : + 95 : 101 : function _bindToken(address token) internal { + 96 [ + + ]: 101 : require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); + 97 [ + + ]: 96 : require(!_boundTokens.contains(token), RuleEngine_ERC3643Compliance_TokenAlreadyBound()); + 98 : : // Should never revert because we check if the token address is already set before + 99 [ # + ]: 91 : require(_boundTokens.add(token), RuleEngine_ERC3643Compliance_OperationNotSuccessful()); + 100 : 91 : emit TokenBound(token); + 101 : : } + 102 : : + 103 : 31 : function _checkBoundToken() internal view virtual { + 104 [ + ]: 31 : if (!_boundTokens.contains(_msgSender())) { + 105 : 7 : revert RuleEngine_ERC3643Compliance_UnauthorizedCaller(); + 106 : : } + 107 : : } + 108 : : + 109 : 0 : function _authorizeComplianceBindingChange(address token) internal virtual; + 110 : 0 : function _onlyComplianceManager() internal virtual; + 111 : : } diff --git a/doc/coverage/coverage/src/modules/RulesManagementModule.sol.func-sort-c.html b/doc/coverage/coverage/src/modules/RulesManagementModule.sol.func-sort-c.html index 47a830f..00e1452 100644 --- a/doc/coverage/coverage/src/modules/RulesManagementModule.sol.func-sort-c.html +++ b/doc/coverage/coverage/src/modules/RulesManagementModule.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 17 @@ -69,23 +69,23 @@ Hit count Sort by hit count - RulesManagementModule._onlyRulesLimitManager + RulesManagementModule._onlyRulesLimitManager 0 - RulesManagementModule._onlyRulesManager + RulesManagementModule._onlyRulesManager 0 - RulesManagementModule._transferred.1 - 4 + RulesManagementModule._transferred.1 + 5 - RulesManagementModule.rule + RulesManagementModule.rule 5 - RulesManagementModule.maxRules + RulesManagementModule.maxRules 8 @@ -93,19 +93,19 @@ 9 - RulesManagementModule.setMaxRules + RulesManagementModule.setMaxRules 9 - RulesManagementModule._removeRule + RulesManagementModule._removeRule 13 - RulesManagementModule.rules + RulesManagementModule.rules 15 - RulesManagementModule.clearRules + RulesManagementModule.clearRules 16 @@ -113,35 +113,35 @@ 16 - RulesManagementModule.removeRule + RulesManagementModule.removeRule 18 - RulesManagementModule._transferred.0 - 20 + RulesManagementModule._transferred.0 + 19 - RulesManagementModule._clearRules + RulesManagementModule._clearRules 49 - RulesManagementModule.setRules + RulesManagementModule.setRules 51 - RulesManagementModule.containsRule + RulesManagementModule.containsRule 79 - RulesManagementModule.addRule + RulesManagementModule.addRule 181 - RulesManagementModule.rulesCount + RulesManagementModule.rulesCount 183 - RulesManagementModule._checkRule + RulesManagementModule._checkRule 253 diff --git a/doc/coverage/coverage/src/modules/RulesManagementModule.sol.func.html b/doc/coverage/coverage/src/modules/RulesManagementModule.sol.func.html index 89854ca..bd131a2 100644 --- a/doc/coverage/coverage/src/modules/RulesManagementModule.sol.func.html +++ b/doc/coverage/coverage/src/modules/RulesManagementModule.sol.func.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 17 @@ -69,47 +69,47 @@ Hit count Sort by hit count - RulesManagementModule._checkRule + RulesManagementModule._checkRule 253 - RulesManagementModule._clearRules + RulesManagementModule._clearRules 49 - RulesManagementModule._onlyRulesLimitManager + RulesManagementModule._onlyRulesLimitManager 0 - RulesManagementModule._onlyRulesManager + RulesManagementModule._onlyRulesManager 0 - RulesManagementModule._removeRule + RulesManagementModule._removeRule 13 - RulesManagementModule._transferred.0 - 20 + RulesManagementModule._transferred.0 + 19 - RulesManagementModule._transferred.1 - 4 + RulesManagementModule._transferred.1 + 5 - RulesManagementModule.addRule + RulesManagementModule.addRule 181 - RulesManagementModule.clearRules + RulesManagementModule.clearRules 16 - RulesManagementModule.containsRule + RulesManagementModule.containsRule 79 - RulesManagementModule.maxRules + RulesManagementModule.maxRules 8 @@ -121,27 +121,27 @@ 16 - RulesManagementModule.removeRule + RulesManagementModule.removeRule 18 - RulesManagementModule.rule + RulesManagementModule.rule 5 - RulesManagementModule.rules + RulesManagementModule.rules 15 - RulesManagementModule.rulesCount + RulesManagementModule.rulesCount 183 - RulesManagementModule.setMaxRules + RulesManagementModule.setMaxRules 9 - RulesManagementModule.setRules + RulesManagementModule.setRules 51 diff --git a/doc/coverage/coverage/src/modules/RulesManagementModule.sol.gcov.html b/doc/coverage/coverage/src/modules/RulesManagementModule.sol.gcov.html index ade1adf..d17ed7a 100644 --- a/doc/coverage/coverage/src/modules/RulesManagementModule.sol.gcov.html +++ b/doc/coverage/coverage/src/modules/RulesManagementModule.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 17 @@ -115,189 +115,191 @@ 44 : : * Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. 45 : : * To transition from one non-empty set to another without an enforcement gap, 46 : : * call this function directly with the new set. - 47 : : * Security convention: rule contracts should be treated as trusted business logic, - 48 : : * but should not also be granted {RULES_MANAGEMENT_ROLE}. - 49 : : */ - 50 : 51 : function setRules(IRule[] calldata rules_) public virtual override(IRulesManagementModule) onlyRulesManager { - 51 [ + ]: 49 : if (rules_.length == 0) { - 52 : 6 : revert RuleEngine_RulesManagementModule_ArrayIsEmpty(); - 53 : : } - 54 [ + ]: 43 : if (rules_.length > _maxRules) { - 55 : 1 : revert RuleEngine_RulesManagementModule_MaxRulesExceeded(_maxRules); - 56 : : } - 57 [ + ]: 42 : if (_rules.length() > 0) { - 58 : 36 : _clearRules(); - 59 : : } - 60 : 42 : for (uint256 i = 0; i < rules_.length; ++i) { - 61 : 79 : _checkRule(address(rules_[i])); - 62 : : // Should never revert because we check the presence of the rule before - 63 [ # + ]: 74 : require(_rules.add(address(rules_[i])), RuleEngine_RulesManagementModule_OperationNotSuccessful()); - 64 : 74 : emit AddRule(rules_[i]); - 65 : : } - 66 : : } - 67 : : - 68 : : /** - 69 : : * @inheritdoc IRulesManagementModule - 70 : : */ - 71 : 16 : function clearRules() public virtual override(IRulesManagementModule) onlyRulesManager { - 72 : 13 : _clearRules(); - 73 : : } - 74 : : - 75 : : /** - 76 : : * @inheritdoc IRulesManagementModule - 77 : : * @dev Reverts when the configured maximum number of rules is already reached. - 78 : : * Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts. - 79 : : */ - 80 : 181 : function addRule(IRule rule_) public virtual override(IRulesManagementModule) onlyRulesManager { - 81 [ + ]: 176 : if (_rules.length() >= _maxRules) { - 82 : 2 : revert RuleEngine_RulesManagementModule_MaxRulesExceeded(_maxRules); - 83 : : } - 84 : 174 : _checkRule(address(rule_)); - 85 [ # + ]: 164 : require(_rules.add(address(rule_)), RuleEngine_RulesManagementModule_OperationNotSuccessful()); - 86 : 164 : emit AddRule(rule_); - 87 : : } - 88 : : - 89 : : /** - 90 : : * @inheritdoc IRulesManagementModule - 91 : : */ - 92 : 8 : function maxRules() public view virtual override(IRulesManagementModule) returns (uint256) { - 93 : 8 : return _maxRules; - 94 : : } - 95 : : - 96 : : /** - 97 : : * @inheritdoc IRulesManagementModule - 98 : : */ - 99 : 9 : function setMaxRules(uint256 maxRules_) public virtual override(IRulesManagementModule) onlyRulesLimitManager { - 100 [ + ]: 5 : if (maxRules_ == 0) { - 101 : 1 : revert RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed(); - 102 : : } - 103 : 4 : _maxRules = maxRules_; - 104 : 4 : emit SetMaxRules(maxRules_); - 105 : : } - 106 : : - 107 : : /** - 108 : : * @inheritdoc IRulesManagementModule - 109 : : */ - 110 : 18 : function removeRule(IRule rule_) public virtual override(IRulesManagementModule) onlyRulesManager { - 111 [ + + ]: 16 : require(_rules.contains(address(rule_)), RuleEngine_RulesManagementModule_RuleDoNotMatch()); - 112 : 13 : _removeRule(rule_); - 113 : : } - 114 : : - 115 : : /* ============ View functions ============ */ + 47 : : * Emits {ClearRules} when the existing rule set is non-empty, then emits {AddRule} + 48 : : * for each new rule. Off-chain indexers must handle both events to reconstruct state. + 49 : : * Security convention: rule contracts should be treated as trusted business logic, + 50 : : * but should not also be granted {RULES_MANAGEMENT_ROLE}. + 51 : : */ + 52 : 51 : function setRules(IRule[] calldata rules_) public virtual override(IRulesManagementModule) onlyRulesManager { + 53 [ + ]: 49 : if (rules_.length == 0) { + 54 : 6 : revert RuleEngine_RulesManagementModule_ArrayIsEmpty(); + 55 : : } + 56 [ + ]: 43 : if (rules_.length > _maxRules) { + 57 : 1 : revert RuleEngine_RulesManagementModule_MaxRulesExceeded(_maxRules); + 58 : : } + 59 [ + ]: 42 : if (_rules.length() > 0) { + 60 : 36 : _clearRules(); + 61 : : } + 62 : 42 : for (uint256 i = 0; i < rules_.length; ++i) { + 63 : 79 : _checkRule(address(rules_[i])); + 64 : : // Should never revert because we check the presence of the rule before + 65 [ # + ]: 74 : require(_rules.add(address(rules_[i])), RuleEngine_RulesManagementModule_OperationNotSuccessful()); + 66 : 74 : emit AddRule(rules_[i]); + 67 : : } + 68 : : } + 69 : : + 70 : : /** + 71 : : * @inheritdoc IRulesManagementModule + 72 : : */ + 73 : 16 : function clearRules() public virtual override(IRulesManagementModule) onlyRulesManager { + 74 : 13 : _clearRules(); + 75 : : } + 76 : : + 77 : : /** + 78 : : * @inheritdoc IRulesManagementModule + 79 : : * @dev Reverts when the configured maximum number of rules is already reached. + 80 : : * Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts. + 81 : : */ + 82 : 181 : function addRule(IRule rule_) public virtual override(IRulesManagementModule) onlyRulesManager { + 83 [ + ]: 176 : if (_rules.length() >= _maxRules) { + 84 : 2 : revert RuleEngine_RulesManagementModule_MaxRulesExceeded(_maxRules); + 85 : : } + 86 : 174 : _checkRule(address(rule_)); + 87 [ # + ]: 164 : require(_rules.add(address(rule_)), RuleEngine_RulesManagementModule_OperationNotSuccessful()); + 88 : 164 : emit AddRule(rule_); + 89 : : } + 90 : : + 91 : : /** + 92 : : * @inheritdoc IRulesManagementModule + 93 : : */ + 94 : 8 : function maxRules() public view virtual override(IRulesManagementModule) returns (uint256) { + 95 : 8 : return _maxRules; + 96 : : } + 97 : : + 98 : : /** + 99 : : * @inheritdoc IRulesManagementModule + 100 : : */ + 101 : 9 : function setMaxRules(uint256 maxRules_) public virtual override(IRulesManagementModule) onlyRulesLimitManager { + 102 [ + ]: 5 : if (maxRules_ == 0) { + 103 : 1 : revert RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed(); + 104 : : } + 105 : 4 : _maxRules = maxRules_; + 106 : 4 : emit SetMaxRules(maxRules_); + 107 : : } + 108 : : + 109 : : /** + 110 : : * @inheritdoc IRulesManagementModule + 111 : : */ + 112 : 18 : function removeRule(IRule rule_) public virtual override(IRulesManagementModule) onlyRulesManager { + 113 [ + + ]: 16 : require(_rules.contains(address(rule_)), RuleEngine_RulesManagementModule_RuleDoNotMatch()); + 114 : 13 : _removeRule(rule_); + 115 : : } 116 : : - 117 : : /** - 118 : : * @inheritdoc IRulesManagementModule - 119 : : */ - 120 : 183 : function rulesCount() public view virtual override(IRulesManagementModule) returns (uint256) { - 121 : 300 : return _rules.length(); - 122 : : } - 123 : : - 124 : : /** - 125 : : * @inheritdoc IRulesManagementModule - 126 : : */ - 127 : 79 : function containsRule(IRule rule_) public view virtual override(IRulesManagementModule) returns (bool) { - 128 : 89 : return _rules.contains(address(rule_)); - 129 : : } - 130 : : - 131 : : /** - 132 : : * @inheritdoc IRulesManagementModule - 133 : : */ - 134 : 5 : function rule(uint256 ruleId) public view virtual override(IRulesManagementModule) returns (address) { - 135 [ + + ]: 133 : if (ruleId < _rules.length()) { - 136 : : // Note that there are no guarantees on the ordering of values inside the array, - 137 : : // and it may change when more values are added or removed. - 138 : 131 : return _rules.at(ruleId); - 139 : : } else { - 140 : 2 : return address(0); - 141 : : } - 142 : : } - 143 : : - 144 : : /** - 145 : : * @inheritdoc IRulesManagementModule - 146 : : */ - 147 : 15 : function rules() public view virtual override(IRulesManagementModule) returns (address[] memory) { - 148 : 15 : return _rules.values(); - 149 : : } - 150 : : - 151 : : /*////////////////////////////////////////////////////////////// - 152 : : INTERNAL/PRIVATE FUNCTIONS - 153 : : //////////////////////////////////////////////////////////////*/ - 154 : : /** - 155 : : * @notice Clear all the rules of the array of rules - 156 : : * - 157 : : */ - 158 : 49 : function _clearRules() internal virtual { - 159 : 49 : emit ClearRules(); - 160 : 49 : _rules.clear(); - 161 : : } - 162 : : - 163 : : /** - 164 : : * @notice Remove a rule from the array of rules - 165 : : * Revert if the rule found at the specified index does not match the rule in argument - 166 : : * @param rule_ address of the target rule - 167 : : * - 168 : : * - 169 : : */ - 170 : 13 : function _removeRule(IRule rule_) internal virtual { - 171 : : // Should never revert because we check the presence of the rule before - 172 [ # + ]: 13 : require(_rules.remove(address(rule_)), RuleEngine_RulesManagementModule_OperationNotSuccessful()); - 173 : 13 : emit RemoveRule(rule_); - 174 : : } - 175 : : - 176 : : /** - 177 : : * @dev check if a rule is valid, revert otherwise - 178 : : */ - 179 : 253 : function _checkRule(address rule_) internal view virtual { - 180 [ + ]: 253 : if (rule_ == address(0x0)) { - 181 : 3 : revert RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed(); - 182 : : } - 183 [ + ]: 250 : if (_rules.contains(rule_)) { - 184 : 6 : revert RuleEngine_RulesManagementModule_RuleAlreadyExists(); - 185 : : } - 186 : : } - 187 : : - 188 : : /* ============ Transferred functions ============ */ + 117 : : /* ============ View functions ============ */ + 118 : : + 119 : : /** + 120 : : * @inheritdoc IRulesManagementModule + 121 : : */ + 122 : 183 : function rulesCount() public view virtual override(IRulesManagementModule) returns (uint256) { + 123 : 300 : return _rules.length(); + 124 : : } + 125 : : + 126 : : /** + 127 : : * @inheritdoc IRulesManagementModule + 128 : : */ + 129 : 79 : function containsRule(IRule rule_) public view virtual override(IRulesManagementModule) returns (bool) { + 130 : 89 : return _rules.contains(address(rule_)); + 131 : : } + 132 : : + 133 : : /** + 134 : : * @inheritdoc IRulesManagementModule + 135 : : */ + 136 : 5 : function rule(uint256 ruleId) public view virtual override(IRulesManagementModule) returns (address) { + 137 [ + + ]: 133 : if (ruleId < _rules.length()) { + 138 : : // Note that there are no guarantees on the ordering of values inside the array, + 139 : : // and it may change when more values are added or removed. + 140 : 131 : return _rules.at(ruleId); + 141 : : } else { + 142 : 2 : return address(0); + 143 : : } + 144 : : } + 145 : : + 146 : : /** + 147 : : * @inheritdoc IRulesManagementModule + 148 : : */ + 149 : 15 : function rules() public view virtual override(IRulesManagementModule) returns (address[] memory) { + 150 : 15 : return _rules.values(); + 151 : : } + 152 : : + 153 : : /*////////////////////////////////////////////////////////////// + 154 : : INTERNAL/PRIVATE FUNCTIONS + 155 : : //////////////////////////////////////////////////////////////*/ + 156 : : /** + 157 : : * @notice Clear all the rules of the array of rules + 158 : : * + 159 : : */ + 160 : 49 : function _clearRules() internal virtual { + 161 : 49 : emit ClearRules(); + 162 : 49 : _rules.clear(); + 163 : : } + 164 : : + 165 : : /** + 166 : : * @notice Remove a rule from the array of rules + 167 : : * Revert if the rule found at the specified index does not match the rule in argument + 168 : : * @param rule_ address of the target rule + 169 : : * + 170 : : * + 171 : : */ + 172 : 13 : function _removeRule(IRule rule_) internal virtual { + 173 : : // Should never revert because we check the presence of the rule before + 174 [ # + ]: 13 : require(_rules.remove(address(rule_)), RuleEngine_RulesManagementModule_OperationNotSuccessful()); + 175 : 13 : emit RemoveRule(rule_); + 176 : : } + 177 : : + 178 : : /** + 179 : : * @dev check if a rule is valid, revert otherwise + 180 : : */ + 181 : 253 : function _checkRule(address rule_) internal view virtual { + 182 [ + ]: 253 : if (rule_ == address(0x0)) { + 183 : 3 : revert RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed(); + 184 : : } + 185 [ + ]: 250 : if (_rules.contains(rule_)) { + 186 : 6 : revert RuleEngine_RulesManagementModule_RuleAlreadyExists(); + 187 : : } + 188 : : } 189 : : - 190 : : /** - 191 : : * @notice Go through all the rule to know if a restriction exists on the transfer - 192 : : * @dev Complexity is O(number of configured rules). Large rule sets can make - 193 : : * transfers too expensive on chains with lower block gas limits. - 194 : : * Security convention: rule contracts are expected to be trusted and must not - 195 : : * hold {RULES_MANAGEMENT_ROLE}. - 196 : : * @param from the origin address - 197 : : * @param to the destination address - 198 : : * @param value to transfer - 199 : : * - 200 : : */ - 201 : 20 : function _transferred(address from, address to, uint256 value) internal virtual { - 202 : 20 : uint256 rulesLength = _rules.length(); - 203 : 20 : for (uint256 i = 0; i < rulesLength; ++i) { - 204 : 14 : IRule(_rules.at(i)).transferred(from, to, value); - 205 : : } - 206 : : } - 207 : : - 208 : : /** - 209 : : * @notice Go through all the rule to know if a restriction exists on the transfer - 210 : : * @dev Complexity is O(number of configured rules). Large rule sets can make - 211 : : * transfers too expensive on chains with lower block gas limits. - 212 : : * Security convention: rule contracts are expected to be trusted and must not - 213 : : * hold {RULES_MANAGEMENT_ROLE}. - 214 : : * @param spender the spender address (transferFrom) - 215 : : * @param from the origin address - 216 : : * @param to the destination address - 217 : : * @param value to transfer - 218 : : * - 219 : : */ - 220 : 4 : function _transferred(address spender, address from, address to, uint256 value) internal virtual { - 221 : 4 : uint256 rulesLength = _rules.length(); - 222 : 4 : for (uint256 i = 0; i < rulesLength; ++i) { - 223 : 4 : IRule(_rules.at(i)).transferred(spender, from, to, value); - 224 : : } - 225 : : } - 226 : : - 227 : 0 : function _onlyRulesManager() internal virtual; - 228 : 0 : function _onlyRulesLimitManager() internal virtual; - 229 : : } + 190 : : /* ============ Transferred functions ============ */ + 191 : : + 192 : : /** + 193 : : * @notice Go through all the rule to know if a restriction exists on the transfer + 194 : : * @dev Complexity is O(number of configured rules). Large rule sets can make + 195 : : * transfers too expensive on chains with lower block gas limits. + 196 : : * Security convention: rule contracts are expected to be trusted and must not + 197 : : * hold {RULES_MANAGEMENT_ROLE}. + 198 : : * @param from the origin address + 199 : : * @param to the destination address + 200 : : * @param value to transfer + 201 : : * + 202 : : */ + 203 : 19 : function _transferred(address from, address to, uint256 value) internal virtual { + 204 : 19 : uint256 rulesLength = _rules.length(); + 205 : 19 : for (uint256 i = 0; i < rulesLength; ++i) { + 206 : 13 : IRule(_rules.at(i)).transferred(from, to, value); + 207 : : } + 208 : : } + 209 : : + 210 : : /** + 211 : : * @notice Go through all the rule to know if a restriction exists on the transfer + 212 : : * @dev Complexity is O(number of configured rules). Large rule sets can make + 213 : : * transfers too expensive on chains with lower block gas limits. + 214 : : * Security convention: rule contracts are expected to be trusted and must not + 215 : : * hold {RULES_MANAGEMENT_ROLE}. + 216 : : * @param spender the spender address (transferFrom) + 217 : : * @param from the origin address + 218 : : * @param to the destination address + 219 : : * @param value to transfer + 220 : : * + 221 : : */ + 222 : 5 : function _transferred(address spender, address from, address to, uint256 value) internal virtual { + 223 : 5 : uint256 rulesLength = _rules.length(); + 224 : 5 : for (uint256 i = 0; i < rulesLength; ++i) { + 225 : 5 : IRule(_rules.at(i)).transferred(spender, from, to, value); + 226 : : } + 227 : : } + 228 : : + 229 : 0 : function _onlyRulesManager() internal virtual; + 230 : 0 : function _onlyRulesLimitManager() internal virtual; + 231 : : } diff --git a/doc/coverage/coverage/src/modules/VersionModule.sol.func-sort-c.html b/doc/coverage/coverage/src/modules/VersionModule.sol.func-sort-c.html index 3527b2b..9945833 100644 --- a/doc/coverage/coverage/src/modules/VersionModule.sol.func-sort-c.html +++ b/doc/coverage/coverage/src/modules/VersionModule.sol.func-sort-c.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 1 diff --git a/doc/coverage/coverage/src/modules/VersionModule.sol.func.html b/doc/coverage/coverage/src/modules/VersionModule.sol.func.html index 4c659b9..c917463 100644 --- a/doc/coverage/coverage/src/modules/VersionModule.sol.func.html +++ b/doc/coverage/coverage/src/modules/VersionModule.sol.func.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 1 diff --git a/doc/coverage/coverage/src/modules/VersionModule.sol.gcov.html b/doc/coverage/coverage/src/modules/VersionModule.sol.gcov.html index 4929d2f..5217dc3 100644 --- a/doc/coverage/coverage/src/modules/VersionModule.sol.gcov.html +++ b/doc/coverage/coverage/src/modules/VersionModule.sol.gcov.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 1 @@ -82,7 +82,7 @@ 11 : : * @dev 12 : : * Get the current version of the smart contract 13 : : */ - 14 : : string private constant VERSION = "3.0.0"; + 14 : : string internal constant VERSION = "3.0.0"; 15 : : 16 : : /* ============ Events ============ */ 17 : : /*////////////////////////////////////////////////////////////// diff --git a/doc/coverage/coverage/src/modules/index-sort-b.html b/doc/coverage/coverage/src/modules/index-sort-b.html index d6915d3..a13a1af 100644 --- a/doc/coverage/coverage/src/modules/index-sort-b.html +++ b/doc/coverage/coverage/src/modules/index-sort-b.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 34 diff --git a/doc/coverage/coverage/src/modules/index-sort-f.html b/doc/coverage/coverage/src/modules/index-sort-f.html index 1125c04..556cec3 100644 --- a/doc/coverage/coverage/src/modules/index-sort-f.html +++ b/doc/coverage/coverage/src/modules/index-sort-f.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 34 diff --git a/doc/coverage/coverage/src/modules/index-sort-l.html b/doc/coverage/coverage/src/modules/index-sort-l.html index f4ce7fd..557fca2 100644 --- a/doc/coverage/coverage/src/modules/index-sort-l.html +++ b/doc/coverage/coverage/src/modules/index-sort-l.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 34 diff --git a/doc/coverage/coverage/src/modules/index.html b/doc/coverage/coverage/src/modules/index.html index ac7a2f7..f2f0b38 100644 --- a/doc/coverage/coverage/src/modules/index.html +++ b/doc/coverage/coverage/src/modules/index.html @@ -37,7 +37,7 @@ Date: - 2026-05-06 17:22:22 + 2026-05-22 15:31:49 Functions: 34 diff --git a/doc/coverage/lcov.info b/doc/coverage/lcov.info index ef3e869..77ded88 100644 --- a/doc/coverage/lcov.info +++ b/doc/coverage/lcov.info @@ -1,13 +1,13 @@ TN: SF:src/RuleEngineBase.sol -DA:43,5 +DA:43,6 FN:43,RuleEngineBase.transferred.0 -FNDA:5,RuleEngineBase.transferred.0 -DA:50,4 -DA:56,18 +FNDA:6,RuleEngineBase.transferred.0 +DA:50,5 +DA:56,17 FN:56,RuleEngineBase.transferred.1 -FNDA:18,RuleEngineBase.transferred.1 -DA:62,16 +FNDA:17,RuleEngineBase.transferred.1 +DA:62,15 DA:66,4 FN:66,RuleEngineBase.created FNDA:4,RuleEngineBase.created @@ -138,46 +138,46 @@ DA:33,164 BRDA:33,1,0,31 DA:34,31 DA:36,164 -DA:44,39 -FN:44,RuleEngine.grantRole +DA:48,39 +FN:48,RuleEngine.grantRole FNDA:39,RuleEngine.grantRole -DA:45,39 -BRDA:45,2,0,3 -DA:46,3 -DA:48,36 -DA:55,173 -FN:55,RuleEngine.hasRole +DA:49,39 +BRDA:49,2,0,3 +DA:50,3 +DA:52,36 +DA:59,173 +FN:59,RuleEngine.hasRole FNDA:173,RuleEngine.hasRole -DA:62,490 -BRDA:62,3,0,236 -BRDA:62,3,1,254 -DA:63,236 -DA:65,254 -DA:70,21 -FN:70,RuleEngine.supportsInterface +DA:66,490 +BRDA:66,3,0,236 +BRDA:66,3,1,254 +DA:67,236 +DA:69,254 +DA:74,21 +FN:74,RuleEngine.supportsInterface FNDA:21,RuleEngine.supportsInterface -DA:77,21 -DA:83,42 -FN:83,RuleEngine._onlyComplianceManager +DA:81,21 +DA:87,42 +FN:87,RuleEngine._onlyComplianceManager FNDA:42,RuleEngine._onlyComplianceManager -DA:84,196 -FN:84,RuleEngine._onlyRulesManager +DA:88,196 +FN:88,RuleEngine._onlyRulesManager FNDA:196,RuleEngine._onlyRulesManager -DA:85,5 -FN:85,RuleEngine._onlyRulesLimitManager +DA:89,5 +FN:89,RuleEngine._onlyRulesLimitManager FNDA:5,RuleEngine._onlyRulesLimitManager -DA:90,535 -FN:90,RuleEngine._msgSender +DA:94,535 +FN:94,RuleEngine._msgSender FNDA:535,RuleEngine._msgSender -DA:91,535 -DA:97,1 -FN:97,RuleEngine._msgData +DA:95,535 +DA:101,1 +FN:101,RuleEngine._msgData FNDA:1,RuleEngine._msgData -DA:98,1 -DA:104,536 -FN:104,RuleEngine._contextSuffixLength +DA:102,1 +DA:108,536 +FN:108,RuleEngine._contextSuffixLength FNDA:536,RuleEngine._contextSuffixLength -DA:105,536 +DA:109,536 FNF:10 FNH:10 LF:25 @@ -222,37 +222,37 @@ BRH:0 end_of_record TN: SF:src/deployment/RuleEngineOwnable2Step.sol -DA:30,5 -FN:30,RuleEngineOwnable2Step._onlyRulesManager +DA:31,5 +FN:31,RuleEngineOwnable2Step._onlyRulesManager FNDA:5,RuleEngineOwnable2Step._onlyRulesManager -DA:31,2 -FN:31,RuleEngineOwnable2Step._onlyRulesLimitManager +DA:32,2 +FN:32,RuleEngineOwnable2Step._onlyRulesLimitManager FNDA:2,RuleEngineOwnable2Step._onlyRulesLimitManager -DA:36,25 -FN:36,RuleEngineOwnable2Step._onlyComplianceManager +DA:37,25 +FN:37,RuleEngineOwnable2Step._onlyComplianceManager FNDA:25,RuleEngineOwnable2Step._onlyComplianceManager -DA:42,6 -FN:42,RuleEngineOwnable2Step.transferOwnership -FNDA:6,RuleEngineOwnable2Step.transferOwnership DA:43,6 -DA:44,5 -DA:48,13 -FN:48,RuleEngineOwnable2Step.supportsInterface -FNDA:13,RuleEngineOwnable2Step.supportsInterface +FN:43,RuleEngineOwnable2Step.transferOwnership +FNDA:6,RuleEngineOwnable2Step.transferOwnership +DA:44,6 +DA:45,5 DA:49,13 -DA:50,11 -DA:56,68 -FN:56,RuleEngineOwnable2Step._msgSender -FNDA:68,RuleEngineOwnable2Step._msgSender +FN:49,RuleEngineOwnable2Step.supportsInterface +FNDA:13,RuleEngineOwnable2Step.supportsInterface +DA:50,13 +DA:51,11 DA:57,68 -DA:63,1 -FN:63,RuleEngineOwnable2Step._msgData -FNDA:1,RuleEngineOwnable2Step._msgData +FN:57,RuleEngineOwnable2Step._msgSender +FNDA:68,RuleEngineOwnable2Step._msgSender +DA:58,68 DA:64,1 -DA:70,69 -FN:70,RuleEngineOwnable2Step._contextSuffixLength -FNDA:69,RuleEngineOwnable2Step._contextSuffixLength +FN:64,RuleEngineOwnable2Step._msgData +FNDA:1,RuleEngineOwnable2Step._msgData +DA:65,1 DA:71,69 +FN:71,RuleEngineOwnable2Step._contextSuffixLength +FNDA:69,RuleEngineOwnable2Step._contextSuffixLength +DA:72,69 FNF:8 FNH:8 LF:15 @@ -262,49 +262,49 @@ BRH:0 end_of_record TN: SF:src/modules/ERC3643ComplianceExtendedModule.sol -DA:16,18 -FN:16,ERC3643ComplianceExtendedModule.bindTokens +DA:21,18 +FN:21,ERC3643ComplianceExtendedModule.bindTokens FNDA:18,ERC3643ComplianceExtendedModule.bindTokens -DA:17,15 -DA:18,24 -DA:23,9 -FN:23,ERC3643ComplianceExtendedModule.unbindTokens +DA:22,15 +DA:23,24 +DA:28,9 +FN:28,ERC3643ComplianceExtendedModule.unbindTokens FNDA:9,ERC3643ComplianceExtendedModule.unbindTokens -DA:24,6 -DA:25,12 -DA:30,14 -FN:30,ERC3643ComplianceExtendedModule.setTokenSelfBindingApproval +DA:29,6 +DA:30,12 +DA:35,14 +FN:35,ERC3643ComplianceExtendedModule.setTokenSelfBindingApproval FNDA:14,ERC3643ComplianceExtendedModule.setTokenSelfBindingApproval -DA:31,11 -BRDA:31,0,0,3 -BRDA:31,0,1,8 -DA:32,8 -DA:33,8 -DA:37,12 -FN:37,ERC3643ComplianceExtendedModule.setTokenSelfBindingApprovalBatch +DA:36,11 +BRDA:36,0,0,3 +BRDA:36,0,1,8 +DA:37,8 +DA:38,8 +DA:42,12 +FN:42,ERC3643ComplianceExtendedModule.setTokenSelfBindingApprovalBatch FNDA:12,ERC3643ComplianceExtendedModule.setTokenSelfBindingApprovalBatch -DA:43,9 -DA:44,18 -DA:45,18 -BRDA:45,1,0,3 -BRDA:45,1,1,15 -DA:46,15 -DA:48,6 -DA:52,6 -FN:52,ERC3643ComplianceExtendedModule.isTokenSelfBindingApproved -FNDA:6,ERC3643ComplianceExtendedModule.isTokenSelfBindingApproved +DA:48,9 +DA:49,18 +DA:50,18 +BRDA:50,1,0,3 +BRDA:50,1,1,15 +DA:51,15 DA:53,6 -DA:57,4 -FN:57,ERC3643ComplianceExtendedModule.getTokenBounds +DA:57,6 +FN:57,ERC3643ComplianceExtendedModule.isTokenSelfBindingApproved +FNDA:6,ERC3643ComplianceExtendedModule.isTokenSelfBindingApproved +DA:58,6 +DA:62,4 +FN:62,ERC3643ComplianceExtendedModule.getTokenBounds FNDA:4,ERC3643ComplianceExtendedModule.getTokenBounds -DA:58,4 -DA:65,72 -FN:65,ERC3643ComplianceExtendedModule._authorizeComplianceBindingChange +DA:63,4 +DA:70,72 +FN:70,ERC3643ComplianceExtendedModule._authorizeComplianceBindingChange FNDA:72,ERC3643ComplianceExtendedModule._authorizeComplianceBindingChange -DA:66,72 -BRDA:66,2,0,72 -DA:67,72 -DA:69,60 +DA:71,72 +BRDA:71,2,0,72 +DA:72,72 +DA:74,60 FNF:7 FNH:7 LF:24 @@ -314,70 +314,70 @@ BRH:5 end_of_record TN: SF:src/modules/ERC3643ComplianceModule.sol -DA:29,5 -FN:29,ERC3643ComplianceModule.onlyBoundToken -FNDA:5,ERC3643ComplianceModule.onlyBoundToken -DA:30,5 -DA:34,9 -FN:34,ERC3643ComplianceModule.onlyComplianceManager +DA:26,6 +FN:26,ERC3643ComplianceModule.onlyBoundToken +FNDA:6,ERC3643ComplianceModule.onlyBoundToken +DA:27,6 +DA:31,9 +FN:31,ERC3643ComplianceModule.onlyComplianceManager FNDA:9,ERC3643ComplianceModule.onlyComplianceManager -DA:35,9 -DA:50,52 -FN:50,ERC3643ComplianceModule.bindToken -FNDA:52,ERC3643ComplianceModule.bindToken +DA:32,9 DA:51,52 -DA:52,45 -DA:61,20 -FN:61,ERC3643ComplianceModule.unbindToken -FNDA:20,ERC3643ComplianceModule.unbindToken +FN:51,ERC3643ComplianceModule.bindToken +FNDA:52,ERC3643ComplianceModule.bindToken +DA:52,52 +DA:53,45 DA:62,20 -DA:63,13 -DA:67,37 -FN:67,ERC3643ComplianceModule.isTokenBound -FNDA:37,ERC3643ComplianceModule.isTokenBound +FN:62,ERC3643ComplianceModule.unbindToken +FNDA:20,ERC3643ComplianceModule.unbindToken +DA:63,20 +DA:64,13 DA:68,37 -DA:72,5 -FN:72,ERC3643ComplianceModule.getTokenBound -FNDA:5,ERC3643ComplianceModule.getTokenBound +FN:68,ERC3643ComplianceModule.isTokenBound +FNDA:37,ERC3643ComplianceModule.isTokenBound +DA:69,37 DA:73,5 -BRDA:73,0,0,3 -BRDA:73,0,1,2 -DA:76,3 -DA:78,2 -DA:86,25 -FN:86,ERC3643ComplianceModule._unbindToken -FNDA:25,ERC3643ComplianceModule._unbindToken +FN:73,ERC3643ComplianceModule.getTokenBound +FNDA:5,ERC3643ComplianceModule.getTokenBound +DA:74,5 +BRDA:74,0,0,3 +BRDA:74,0,1,2 +DA:77,3 +DA:79,2 DA:87,25 -BRDA:87,1,0,5 -BRDA:87,1,1,20 -DA:89,20 -BRDA:89,2,0,- -BRDA:89,2,1,20 -DA:91,20 -DA:94,101 -FN:94,ERC3643ComplianceModule._bindToken -FNDA:101,ERC3643ComplianceModule._bindToken +FN:87,ERC3643ComplianceModule._unbindToken +FNDA:25,ERC3643ComplianceModule._unbindToken +DA:88,25 +BRDA:88,1,0,5 +BRDA:88,1,1,20 +DA:90,20 +BRDA:90,2,0,- +BRDA:90,2,1,20 +DA:92,20 DA:95,101 -BRDA:95,3,0,5 -BRDA:95,3,1,96 -DA:96,96 -BRDA:96,4,0,5 -BRDA:96,4,1,91 -DA:98,91 -BRDA:98,5,0,- -BRDA:98,5,1,91 +FN:95,ERC3643ComplianceModule._bindToken +FNDA:101,ERC3643ComplianceModule._bindToken +DA:96,101 +BRDA:96,3,0,5 +BRDA:96,3,1,96 +DA:97,96 +BRDA:97,4,0,5 +BRDA:97,4,1,91 DA:99,91 -DA:102,31 -FN:102,ERC3643ComplianceModule._checkBoundToken -FNDA:31,ERC3643ComplianceModule._checkBoundToken +BRDA:99,5,0,- +BRDA:99,5,1,91 +DA:100,91 DA:103,31 -BRDA:103,6,0,7 -DA:104,7 -DA:108,0 -FN:108,ERC3643ComplianceModule._authorizeComplianceBindingChange -FNDA:0,ERC3643ComplianceModule._authorizeComplianceBindingChange +FN:103,ERC3643ComplianceModule._checkBoundToken +FNDA:31,ERC3643ComplianceModule._checkBoundToken +DA:104,31 +BRDA:104,6,0,7 +DA:105,7 DA:109,0 -FN:109,ERC3643ComplianceModule._onlyComplianceManager +FN:109,ERC3643ComplianceModule._authorizeComplianceBindingChange +FNDA:0,ERC3643ComplianceModule._authorizeComplianceBindingChange +DA:110,0 +FN:110,ERC3643ComplianceModule._onlyComplianceManager FNDA:0,ERC3643ComplianceModule._onlyComplianceManager FNF:11 FNH:9 @@ -396,116 +396,116 @@ DA:21,9 FN:21,RulesManagementModule.onlyRulesLimitManager FNDA:9,RulesManagementModule.onlyRulesLimitManager DA:22,9 -DA:50,51 -FN:50,RulesManagementModule.setRules +DA:52,51 +FN:52,RulesManagementModule.setRules FNDA:51,RulesManagementModule.setRules -DA:51,49 -BRDA:51,0,0,6 -DA:52,6 -DA:54,43 -BRDA:54,1,0,1 -DA:55,1 -DA:57,42 -BRDA:57,2,0,36 -DA:58,36 -DA:60,42 -DA:61,79 -DA:63,74 -BRDA:63,3,0,- -BRDA:63,3,1,74 -DA:64,74 -DA:71,16 -FN:71,RulesManagementModule.clearRules +DA:53,49 +BRDA:53,0,0,6 +DA:54,6 +DA:56,43 +BRDA:56,1,0,1 +DA:57,1 +DA:59,42 +BRDA:59,2,0,36 +DA:60,36 +DA:62,42 +DA:63,79 +DA:65,74 +BRDA:65,3,0,- +BRDA:65,3,1,74 +DA:66,74 +DA:73,16 +FN:73,RulesManagementModule.clearRules FNDA:16,RulesManagementModule.clearRules -DA:72,13 -DA:80,181 -FN:80,RulesManagementModule.addRule +DA:74,13 +DA:82,181 +FN:82,RulesManagementModule.addRule FNDA:181,RulesManagementModule.addRule -DA:81,176 -BRDA:81,4,0,2 -DA:82,2 -DA:84,174 -DA:85,164 -BRDA:85,5,0,- -BRDA:85,5,1,164 -DA:86,164 -DA:92,8 -FN:92,RulesManagementModule.maxRules +DA:83,176 +BRDA:83,4,0,2 +DA:84,2 +DA:86,174 +DA:87,164 +BRDA:87,5,0,- +BRDA:87,5,1,164 +DA:88,164 +DA:94,8 +FN:94,RulesManagementModule.maxRules FNDA:8,RulesManagementModule.maxRules -DA:93,8 -DA:99,9 -FN:99,RulesManagementModule.setMaxRules +DA:95,8 +DA:101,9 +FN:101,RulesManagementModule.setMaxRules FNDA:9,RulesManagementModule.setMaxRules -DA:100,5 -BRDA:100,6,0,1 -DA:101,1 -DA:103,4 -DA:104,4 -DA:110,18 -FN:110,RulesManagementModule.removeRule +DA:102,5 +BRDA:102,6,0,1 +DA:103,1 +DA:105,4 +DA:106,4 +DA:112,18 +FN:112,RulesManagementModule.removeRule FNDA:18,RulesManagementModule.removeRule -DA:111,16 -BRDA:111,7,0,3 -BRDA:111,7,1,13 -DA:112,13 -DA:120,183 -FN:120,RulesManagementModule.rulesCount +DA:113,16 +BRDA:113,7,0,3 +BRDA:113,7,1,13 +DA:114,13 +DA:122,183 +FN:122,RulesManagementModule.rulesCount FNDA:183,RulesManagementModule.rulesCount -DA:121,300 -DA:127,79 -FN:127,RulesManagementModule.containsRule +DA:123,300 +DA:129,79 +FN:129,RulesManagementModule.containsRule FNDA:79,RulesManagementModule.containsRule -DA:128,89 -DA:134,5 -FN:134,RulesManagementModule.rule +DA:130,89 +DA:136,5 +FN:136,RulesManagementModule.rule FNDA:5,RulesManagementModule.rule -DA:135,133 -BRDA:135,8,0,131 -BRDA:135,8,1,2 -DA:138,131 -DA:140,2 -DA:147,15 -FN:147,RulesManagementModule.rules +DA:137,133 +BRDA:137,8,0,131 +BRDA:137,8,1,2 +DA:140,131 +DA:142,2 +DA:149,15 +FN:149,RulesManagementModule.rules FNDA:15,RulesManagementModule.rules -DA:148,15 -DA:158,49 -FN:158,RulesManagementModule._clearRules -FNDA:49,RulesManagementModule._clearRules -DA:159,49 +DA:150,15 DA:160,49 -DA:170,13 -FN:170,RulesManagementModule._removeRule -FNDA:13,RulesManagementModule._removeRule +FN:160,RulesManagementModule._clearRules +FNDA:49,RulesManagementModule._clearRules +DA:161,49 +DA:162,49 DA:172,13 -BRDA:172,9,0,- -BRDA:172,9,1,13 -DA:173,13 -DA:179,253 -FN:179,RulesManagementModule._checkRule +FN:172,RulesManagementModule._removeRule +FNDA:13,RulesManagementModule._removeRule +DA:174,13 +BRDA:174,9,0,- +BRDA:174,9,1,13 +DA:175,13 +DA:181,253 +FN:181,RulesManagementModule._checkRule FNDA:253,RulesManagementModule._checkRule -DA:180,253 -BRDA:180,10,0,3 -DA:181,3 -DA:183,250 -BRDA:183,11,0,6 -DA:184,6 -DA:201,20 -FN:201,RulesManagementModule._transferred.0 -FNDA:20,RulesManagementModule._transferred.0 -DA:202,20 -DA:203,20 -DA:204,14 -DA:220,4 -FN:220,RulesManagementModule._transferred.1 -FNDA:4,RulesManagementModule._transferred.1 -DA:221,4 -DA:222,4 -DA:223,4 -DA:227,0 -FN:227,RulesManagementModule._onlyRulesManager +DA:182,253 +BRDA:182,10,0,3 +DA:183,3 +DA:185,250 +BRDA:185,11,0,6 +DA:186,6 +DA:203,19 +FN:203,RulesManagementModule._transferred.0 +FNDA:19,RulesManagementModule._transferred.0 +DA:204,19 +DA:205,19 +DA:206,13 +DA:222,5 +FN:222,RulesManagementModule._transferred.1 +FNDA:5,RulesManagementModule._transferred.1 +DA:223,5 +DA:224,5 +DA:225,5 +DA:229,0 +FN:229,RulesManagementModule._onlyRulesManager FNDA:0,RulesManagementModule._onlyRulesManager -DA:228,0 -FN:228,RulesManagementModule._onlyRulesLimitManager +DA:230,0 +FN:230,RulesManagementModule._onlyRulesLimitManager FNDA:0,RulesManagementModule._onlyRulesLimitManager FNF:19 FNH:17 diff --git a/doc/schema/surya/surya_graph/surya_graph_ERC1404InterfaceId.sol.png b/doc/schema/surya/surya_graph/surya_graph_ERC1404InterfaceId.sol.png new file mode 100644 index 0000000..5b4fa6b Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_ERC1404InterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceExtendedModule.sol.png b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceExtendedModule.sol.png new file mode 100644 index 0000000..58d7d23 Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceExtendedModule.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceModule.sol.png b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceModule.sol.png index e0b1171..4c914ce 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceModule.sol.png and b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceModule.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceModuleInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceModuleInvariantStorage.sol.png new file mode 100644 index 0000000..5b4fa6b Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceModuleInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceRolesStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceRolesStorage.sol.png new file mode 100644 index 0000000..5b4fa6b Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceRolesStorage.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IERC1404Subset.sol.png b/doc/schema/surya/surya_graph/surya_graph_IERC1404Subset.sol.png new file mode 100644 index 0000000..4178753 Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_IERC1404Subset.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IERC173Subset.sol.png b/doc/schema/surya/surya_graph/surya_graph_IERC173Subset.sol.png new file mode 100644 index 0000000..b40d39a Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_IERC173Subset.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IERC3643Compliance.sol.png b/doc/schema/surya/surya_graph/surya_graph_IERC3643Compliance.sol.png index dec0033..2bc3765 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_IERC3643Compliance.sol.png and b/doc/schema/surya/surya_graph/surya_graph_IERC3643Compliance.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IERC3643ComplianceExtended.sol.png b/doc/schema/surya/surya_graph/surya_graph_IERC3643ComplianceExtended.sol.png new file mode 100644 index 0000000..300576b Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_IERC3643ComplianceExtended.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IERC3643ComplianceExtendedSubset.sol.png b/doc/schema/surya/surya_graph/surya_graph_IERC3643ComplianceExtendedSubset.sol.png new file mode 100644 index 0000000..bfb9162 Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_IERC3643ComplianceExtendedSubset.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IOwnable2StepSubset.sol.png b/doc/schema/surya/surya_graph/surya_graph_IOwnable2StepSubset.sol.png new file mode 100644 index 0000000..562ad93 Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_IOwnable2StepSubset.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IRulesManagementModule.sol.png b/doc/schema/surya/surya_graph/surya_graph_IRulesManagementModule.sol.png index be97684..49f6bca 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_IRulesManagementModule.sol.png and b/doc/schema/surya/surya_graph/surya_graph_IRulesManagementModule.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_Ownable2StepInterfaceId.sol.png b/doc/schema/surya/surya_graph/surya_graph_Ownable2StepInterfaceId.sol.png new file mode 100644 index 0000000..5b4fa6b Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_Ownable2StepInterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_OwnableInterfaceId.sol.png b/doc/schema/surya/surya_graph/surya_graph_OwnableInterfaceId.sol.png new file mode 100644 index 0000000..5b4fa6b Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_OwnableInterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLight.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLight.sol.png index e69de29..6b9a42e 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLight.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLight.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngine.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngine.sol.png index 1a90c23..12bc982 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleEngine.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleEngine.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngineBase.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngineBase.sol.png index e69de29..c64cb77 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleEngineBase.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleEngineBase.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngineExposed.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngineExposed.sol.png index 81389b9..04d69c9 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleEngineExposed.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleEngineExposed.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable.sol.png index 40a1ff1..fa8580a 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable2Step.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable2Step.sol.png index 6a8ae98..3bebd20 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable2Step.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable2Step.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnableShared.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnableShared.sol.png index aa36e9f..a4c3db9 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnableShared.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnableShared.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleMintAllowance.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleMintAllowance.sol.png new file mode 100644 index 0000000..5ffe822 Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_RuleMintAllowance.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleMintAllowanceInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleMintAllowanceInvariantStorage.sol.png new file mode 100644 index 0000000..5b4fa6b Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_RuleMintAllowanceInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleOperationRevert.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleOperationRevert.sol.png index e69de29..b8be722 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleOperationRevert.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleOperationRevert.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleWhitelist.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleWhitelist.sol.png index e69de29..7897638 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleWhitelist.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleWhitelist.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RulesManagementModule.sol.png b/doc/schema/surya/surya_graph/surya_graph_RulesManagementModule.sol.png index 9502b0f..e7e179a 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RulesManagementModule.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RulesManagementModule.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RulesManagementModuleRolesStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RulesManagementModuleRolesStorage.sol.png new file mode 100644 index 0000000..5b4fa6b Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_RulesManagementModuleRolesStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC1404InterfaceId.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC1404InterfaceId.sol.png new file mode 100644 index 0000000..3f59ab0 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC1404InterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceExtendedModule.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceExtendedModule.sol.png new file mode 100644 index 0000000..6207848 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceExtendedModule.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceModule.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceModule.sol.png index 04d7663..ca44e14 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceModule.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceModule.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceModuleInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceModuleInvariantStorage.sol.png new file mode 100644 index 0000000..c1e34ba Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceModuleInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceRolesStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceRolesStorage.sol.png new file mode 100644 index 0000000..dca1414 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceRolesStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC1404Subset.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC1404Subset.sol.png new file mode 100644 index 0000000..e9b2bdf Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC1404Subset.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC173Subset.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC173Subset.sol.png new file mode 100644 index 0000000..8faf6ef Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC173Subset.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643ComplianceExtended.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643ComplianceExtended.sol.png new file mode 100644 index 0000000..8c03295 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643ComplianceExtended.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643ComplianceExtendedSubset.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643ComplianceExtendedSubset.sol.png new file mode 100644 index 0000000..7d216ea Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643ComplianceExtendedSubset.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IOwnable2StepSubset.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IOwnable2StepSubset.sol.png new file mode 100644 index 0000000..3e93dcd Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_IOwnable2StepSubset.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_Ownable2StepInterfaceId.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_Ownable2StepInterfaceId.sol.png new file mode 100644 index 0000000..f84cd40 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_Ownable2StepInterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_OwnableInterfaceId.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_OwnableInterfaceId.sol.png new file mode 100644 index 0000000..6e3cf83 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_OwnableInterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngine.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngine.sol.png index 6875d83..7c1f8ce 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngine.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngine.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineBase.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineBase.sol.png index a1eaedd..ec37639 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineBase.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineBase.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineExposed.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineExposed.sol.png index dd11e36..3ceff42 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineExposed.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineExposed.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnableShared.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnableShared.sol.png index 79c3363..762f4fe 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnableShared.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnableShared.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleMintAllowance.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleMintAllowance.sol.png new file mode 100644 index 0000000..306bddc Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleMintAllowance.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleMintAllowanceInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleMintAllowanceInvariantStorage.sol.png new file mode 100644 index 0000000..b97aff6 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleMintAllowanceInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModuleRolesStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModuleRolesStorage.sol.png new file mode 100644 index 0000000..b00833e Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModuleRolesStorage.sol.png differ diff --git a/doc/schema/surya/surya_report/surya_report_ComplianceInterfaceId.sol.md b/doc/schema/surya/surya_report/surya_report_ComplianceInterfaceId.sol.md index 33e301e..268f60e 100644 --- a/doc/schema/surya/surya_report/surya_report_ComplianceInterfaceId.sol.md +++ b/doc/schema/surya/surya_report/surya_report_ComplianceInterfaceId.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/library/ComplianceInterfaceId.sol | 866fb442493595cbaf8fd20bcd8c1767a5f98123 | +| ./modules/library/ComplianceInterfaceId.sol | 3014106773fa069f8dd8ea535ff5fb9b38e71c5f | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_ERC1404InterfaceId.sol.md b/doc/schema/surya/surya_report/surya_report_ERC1404InterfaceId.sol.md new file mode 100644 index 0000000..f69f5ee --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_ERC1404InterfaceId.sol.md @@ -0,0 +1,26 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./modules/library/ERC1404InterfaceId.sol | caeee7c9c7d32d593e490084bcf4229fd264c100 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **ERC1404InterfaceId** | Library | ||| + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_ERC2771ModuleStandalone.sol.md b/doc/schema/surya/surya_report/surya_report_ERC2771ModuleStandalone.sol.md index d1d522f..a649e44 100644 --- a/doc/schema/surya/surya_report/surya_report_ERC2771ModuleStandalone.sol.md +++ b/doc/schema/surya/surya_report/surya_report_ERC2771ModuleStandalone.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/ERC2771ModuleStandalone.sol | 711c9961fcf6e50381cc0bfd8bcb7d9014fbfac6 | +| ./modules/ERC2771ModuleStandalone.sol | 8b584ce82ed0281f9192ca296956221756271055 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceExtendedModule.sol.md b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceExtendedModule.sol.md new file mode 100644 index 0000000..ec925e2 --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceExtendedModule.sol.md @@ -0,0 +1,33 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./modules/ERC3643ComplianceExtendedModule.sol | 4afe34c0d43a0b0ba2e6f2ac77cdc7af3012b23d | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **ERC3643ComplianceExtendedModule** | Implementation | ERC3643ComplianceModule, IERC3643ComplianceExtended ||| +| └ | bindTokens | Public ❗️ | 🛑 | onlyComplianceManager | +| └ | unbindTokens | Public ❗️ | 🛑 | onlyComplianceManager | +| └ | setTokenSelfBindingApproval | Public ❗️ | 🛑 | onlyComplianceManager | +| └ | setTokenSelfBindingApprovalBatch | Public ❗️ | 🛑 | onlyComplianceManager | +| └ | isTokenSelfBindingApproved | Public ❗️ | |NO❗️ | +| └ | getTokenBounds | Public ❗️ | |NO❗️ | +| └ | _authorizeComplianceBindingChange | Internal 🔒 | 🛑 | | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceModule.sol.md b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceModule.sol.md index 5fbd32b..9bbad12 100644 --- a/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceModule.sol.md +++ b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceModule.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/ERC3643ComplianceModule.sol | 450f861a6a5d7178fb1b038503e093e3a5491ac8 | +| ./modules/ERC3643ComplianceModule.sol | 2a66e7dd13981ffa96eb91f3063fc67a40480646 | ### Contracts Description Table @@ -15,15 +15,15 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **ERC3643ComplianceModule** | Implementation | Context, IERC3643Compliance ||| -| └ | bindToken | Public ❗️ | 🛑 | onlyComplianceManager | -| └ | unbindToken | Public ❗️ | 🛑 | onlyComplianceManager | +| **ERC3643ComplianceModule** | Implementation | Context, IERC3643Compliance, ERC3643ComplianceModuleInvariantStorage ||| +| └ | bindToken | Public ❗️ | 🛑 |NO❗️ | +| └ | unbindToken | Public ❗️ | 🛑 |NO❗️ | | └ | isTokenBound | Public ❗️ | |NO❗️ | | └ | getTokenBound | Public ❗️ | |NO❗️ | -| └ | getTokenBounds | Public ❗️ | |NO❗️ | | └ | _unbindToken | Internal 🔒 | 🛑 | | | └ | _bindToken | Internal 🔒 | 🛑 | | | └ | _checkBoundToken | Internal 🔒 | | | +| └ | _authorizeComplianceBindingChange | Internal 🔒 | 🛑 | | | └ | _onlyComplianceManager | Internal 🔒 | 🛑 | | diff --git a/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceModuleInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceModuleInvariantStorage.sol.md new file mode 100644 index 0000000..1c3987e --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceModuleInvariantStorage.sol.md @@ -0,0 +1,26 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./modules/library/ERC3643ComplianceModuleInvariantStorage.sol | 1e69f760c8d85b44b03da08c72b1c22a65baf104 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **ERC3643ComplianceModuleInvariantStorage** | Implementation | ||| + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceRolesStorage.sol.md b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceRolesStorage.sol.md new file mode 100644 index 0000000..9f422fa --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceRolesStorage.sol.md @@ -0,0 +1,26 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./modules/library/ERC3643ComplianceRolesStorage.sol | ec28eadaae97c5a875fda91cc2af884e4bb2f395 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **ERC3643ComplianceRolesStorage** | Implementation | ||| + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_IERC1404Subset.sol.md b/doc/schema/surya/surya_report/surya_report_IERC1404Subset.sol.md new file mode 100644 index 0000000..93cc3cf --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_IERC1404Subset.sol.md @@ -0,0 +1,28 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./mocks/IERC1404Subset.sol | d371148102624f43a7b0f8a2a474c26b08823964 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **IERC1404Subset** | Interface | ||| +| └ | detectTransferRestriction | External ❗️ | |NO❗️ | +| └ | messageForTransferRestriction | External ❗️ | |NO❗️ | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_IERC173Subset.sol.md b/doc/schema/surya/surya_report/surya_report_IERC173Subset.sol.md new file mode 100644 index 0000000..3ae85ec --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_IERC173Subset.sol.md @@ -0,0 +1,28 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./mocks/IERC173Subset.sol | eb469793804c3dcf7a6f1d29648671dd2bfad5c9 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **IERC173Subset** | Interface | ||| +| └ | owner | External ❗️ | |NO❗️ | +| └ | transferOwnership | External ❗️ | 🛑 |NO❗️ | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_IERC3643Compliance.sol.md b/doc/schema/surya/surya_report/surya_report_IERC3643Compliance.sol.md index b6eba44..9ea177f 100644 --- a/doc/schema/surya/surya_report/surya_report_IERC3643Compliance.sol.md +++ b/doc/schema/surya/surya_report/surya_report_IERC3643Compliance.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./interfaces/IERC3643Compliance.sol | fc7795352d154b3fe13fd9df3c8a85b19d667cc5 | +| ./interfaces/IERC3643Compliance.sol | 6a206df8531bc148ae65b3061fe56bd91d64440e | ### Contracts Description Table @@ -20,7 +20,6 @@ | └ | unbindToken | External ❗️ | 🛑 |NO❗️ | | └ | isTokenBound | External ❗️ | |NO❗️ | | └ | getTokenBound | External ❗️ | |NO❗️ | -| └ | getTokenBounds | External ❗️ | |NO❗️ | | └ | created | External ❗️ | 🛑 |NO❗️ | | └ | destroyed | External ❗️ | 🛑 |NO❗️ | diff --git a/doc/schema/surya/surya_report/surya_report_IERC3643ComplianceExtended.sol.md b/doc/schema/surya/surya_report/surya_report_IERC3643ComplianceExtended.sol.md new file mode 100644 index 0000000..6b66009 --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_IERC3643ComplianceExtended.sol.md @@ -0,0 +1,32 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./interfaces/IERC3643ComplianceExtended.sol | 6781b238b62e20fd4e44a16393df58ac13a53d0d | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **IERC3643ComplianceExtended** | Interface | IERC3643Compliance ||| +| └ | bindTokens | External ❗️ | 🛑 |NO❗️ | +| └ | unbindTokens | External ❗️ | 🛑 |NO❗️ | +| └ | setTokenSelfBindingApproval | External ❗️ | 🛑 |NO❗️ | +| └ | setTokenSelfBindingApprovalBatch | External ❗️ | 🛑 |NO❗️ | +| └ | isTokenSelfBindingApproved | External ❗️ | |NO❗️ | +| └ | getTokenBounds | External ❗️ | |NO❗️ | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_IERC3643ComplianceExtendedSubset.sol.md b/doc/schema/surya/surya_report/surya_report_IERC3643ComplianceExtendedSubset.sol.md new file mode 100644 index 0000000..3c3563f --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_IERC3643ComplianceExtendedSubset.sol.md @@ -0,0 +1,32 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./mocks/IERC3643ComplianceExtendedSubset.sol | 232f0855f24c038884560c17588949cdb2772173 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **IERC3643ComplianceExtendedSubset** | Interface | ||| +| └ | bindTokens | External ❗️ | 🛑 |NO❗️ | +| └ | unbindTokens | External ❗️ | 🛑 |NO❗️ | +| └ | setTokenSelfBindingApproval | External ❗️ | 🛑 |NO❗️ | +| └ | setTokenSelfBindingApprovalBatch | External ❗️ | 🛑 |NO❗️ | +| └ | isTokenSelfBindingApproved | External ❗️ | |NO❗️ | +| └ | getTokenBounds | External ❗️ | |NO❗️ | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_IOwnable2StepSubset.sol.md b/doc/schema/surya/surya_report/surya_report_IOwnable2StepSubset.sol.md new file mode 100644 index 0000000..357a4b4 --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_IOwnable2StepSubset.sol.md @@ -0,0 +1,28 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./mocks/IOwnable2StepSubset.sol | 7b5a95bf02e01599484430bab2d3f038e1a26c12 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **IOwnable2StepSubset** | Interface | ||| +| └ | pendingOwner | External ❗️ | |NO❗️ | +| └ | acceptOwnership | External ❗️ | 🛑 |NO❗️ | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_IRuleInterfaceIdHelper.sol.md b/doc/schema/surya/surya_report/surya_report_IRuleInterfaceIdHelper.sol.md index 91f1453..7827964 100644 --- a/doc/schema/surya/surya_report/surya_report_IRuleInterfaceIdHelper.sol.md +++ b/doc/schema/surya/surya_report/surya_report_IRuleInterfaceIdHelper.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/IRuleInterfaceIdHelper.sol | 2f470f5e97559eaec8088913665c854d1725a406 | +| ./mocks/IRuleInterfaceIdHelper.sol | 8362e09891e2200f2fe8aff53b6cf9005bc32fcb | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_IRulesManagementModule.sol.md b/doc/schema/surya/surya_report/surya_report_IRulesManagementModule.sol.md index 2372265..4110545 100644 --- a/doc/schema/surya/surya_report/surya_report_IRulesManagementModule.sol.md +++ b/doc/schema/surya/surya_report/surya_report_IRulesManagementModule.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./interfaces/IRulesManagementModule.sol | 417e61575c2de9c0ac3946d842e738a2c4fa35ed | +| ./interfaces/IRulesManagementModule.sol | c51bcceecca4f78a7bbe5b394786eec2416afe84 | ### Contracts Description Table @@ -16,6 +16,8 @@ | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| | **IRulesManagementModule** | Interface | ||| +| └ | maxRules | External ❗️ | |NO❗️ | +| └ | setMaxRules | External ❗️ | 🛑 |NO❗️ | | └ | setRules | External ❗️ | 🛑 |NO❗️ | | └ | rulesCount | External ❗️ | |NO❗️ | | └ | rule | External ❗️ | |NO❗️ | @@ -23,7 +25,7 @@ | └ | clearRules | External ❗️ | 🛑 |NO❗️ | | └ | addRule | External ❗️ | 🛑 |NO❗️ | | └ | removeRule | External ❗️ | 🛑 |NO❗️ | -| └ | containsRule | External ❗️ | 🛑 |NO❗️ | +| └ | containsRule | External ❗️ | |NO❗️ | ### Legend diff --git a/doc/schema/surya/surya_report/surya_report_Ownable2StepInterfaceId.sol.md b/doc/schema/surya/surya_report/surya_report_Ownable2StepInterfaceId.sol.md new file mode 100644 index 0000000..df2234a --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_Ownable2StepInterfaceId.sol.md @@ -0,0 +1,26 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./modules/library/Ownable2StepInterfaceId.sol | 9dc1aa65e4981b2e01c444ca69f0a56555b72fe7 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **Ownable2StepInterfaceId** | Library | ||| + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_OwnableInterfaceId.sol.md b/doc/schema/surya/surya_report/surya_report_OwnableInterfaceId.sol.md new file mode 100644 index 0000000..ca02a3e --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_OwnableInterfaceId.sol.md @@ -0,0 +1,26 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./modules/library/OwnableInterfaceId.sol | 9dede33864286584e89920ef99b94a0b887917e7 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **OwnableInterfaceId** | Library | ||| + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_RuleAddressList.sol.md b/doc/schema/surya/surya_report/surya_report_RuleAddressList.sol.md index 6e485b5..5ef8290 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleAddressList.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleAddressList.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol | f43b3ee11584c110d14e6decb08078e620431e76 | +| ./mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol | 8255280ac9b5d4063427fc5498e5e5f0b4e9f5cb | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLight.sol.md b/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLight.sol.md index 683987a..29adfcb 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLight.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLight.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/operation/RuleConditionalTransferLight.sol | 372b3d95b5492f195700fd2325a72ebb256629c9 | +| ./mocks/rules/operation/RuleConditionalTransferLight.sol | cf43c496e088f84b15bc3061721d4bd0c2547b4e | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLightInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLightInvariantStorage.sol.md index a1cc02d..e61a169 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLightInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLightInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol | 55df7296e338736005756205089a2ae2643f0b5c | +| ./mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol | 5aae3234538b6a6cdf9714b12bb43f18e4834bbf | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngine.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngine.sol.md index e680920..3333c22 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleEngine.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleEngine.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./deployment/RuleEngine.sol | cfe52f0d2abd4758606453a366c289dda9d91300 | +| ./deployment/RuleEngine.sol | a6e71718a0950a4317d07e4b3481f26d6bc00fc9 | ### Contracts Description Table @@ -15,12 +15,14 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleEngine** | Implementation | ERC2771ModuleStandalone, RuleEngineBase, AccessControlEnumerable ||| +| **RuleEngine** | Implementation | ERC2771ModuleStandalone, RuleEngineBase, AccessControlEnumerable, ERC3643ComplianceRolesStorage, RulesManagementModuleRolesStorage ||| | └ | | Public ❗️ | 🛑 | ERC2771ModuleStandalone | +| └ | grantRole | Public ❗️ | 🛑 |NO❗️ | | └ | hasRole | Public ❗️ | |NO❗️ | | └ | supportsInterface | Public ❗️ | |NO❗️ | | └ | _onlyComplianceManager | Internal 🔒 | 🛑 | onlyRole | | └ | _onlyRulesManager | Internal 🔒 | 🛑 | onlyRole | +| └ | _onlyRulesLimitManager | Internal 🔒 | 🛑 | onlyRole | | └ | _msgSender | Internal 🔒 | | | | └ | _msgData | Internal 🔒 | | | | └ | _contextSuffixLength | Internal 🔒 | | | diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngineBase.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngineBase.sol.md index 22dace3..558396c 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleEngineBase.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleEngineBase.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./RuleEngineBase.sol | 5130f4dd846a01768400a053b1c3ff7a897a7e76 | +| ./RuleEngineBase.sol | 980b240b1a4a9a7b888410cf13a40f47e6bacdfe | ### Contracts Description Table @@ -15,7 +15,7 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleEngineBase** | Implementation | VersionModule, RulesManagementModule, ERC3643ComplianceModule, RuleEngineInvariantStorage, IRuleEngineERC1404 ||| +| **RuleEngineBase** | Implementation | VersionModule, RulesManagementModule, ERC3643ComplianceExtendedModule, RuleEngineInvariantStorage, IRuleEngineERC1404 ||| | └ | transferred | Public ❗️ | 🛑 | onlyBoundToken | | └ | transferred | Public ❗️ | 🛑 | onlyBoundToken | | └ | created | Public ❗️ | 🛑 | onlyBoundToken | diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngineExposed.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngineExposed.sol.md index feb652d..e51ec83 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleEngineExposed.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleEngineExposed.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/RuleEngineExposed.sol | 32dc5064e590129ba225606fb229838bdce53545 | +| ./mocks/RuleEngineExposed.sol | 84e4f8be4361590f336a2771b0feec449d9ac074 | ### Contracts Description Table @@ -22,6 +22,10 @@ | **RuleEngineOwnableExposed** | Implementation | RuleEngineOwnable ||| | └ | | Public ❗️ | 🛑 | RuleEngineOwnable | | └ | exposedMsgData | External ❗️ | |NO❗️ | +|||||| +| **RuleEngineOwnable2StepExposed** | Implementation | RuleEngineOwnable2Step ||| +| └ | | Public ❗️ | 🛑 | RuleEngineOwnable2Step | +| └ | exposedMsgData | External ❗️ | |NO❗️ | ### Legend diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable.sol.md index b407e38..3277dc4 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./deployment/RuleEngineOwnable.sol | 19b70cde4d1a7d7d4e5453ea53d5e69308043167 | +| ./deployment/RuleEngineOwnable.sol | 0cec773602b5703708472364b6280ead7f29906a | ### Contracts Description Table @@ -18,7 +18,9 @@ | **RuleEngineOwnable** | Implementation | RuleEngineOwnableShared, Ownable ||| | └ | | Public ❗️ | 🛑 | RuleEngineOwnableShared Ownable | | └ | _onlyRulesManager | Internal 🔒 | 🛑 | onlyOwner | +| └ | _onlyRulesLimitManager | Internal 🔒 | 🛑 | onlyOwner | | └ | _onlyComplianceManager | Internal 🔒 | 🛑 | onlyOwner | +| └ | transferOwnership | Public ❗️ | 🛑 | onlyOwner | | └ | _msgSender | Internal 🔒 | | | | └ | _msgData | Internal 🔒 | | | | └ | _contextSuffixLength | Internal 🔒 | | | diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable2Step.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable2Step.sol.md index 98217df..75047c3 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable2Step.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable2Step.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./deployment/RuleEngineOwnable2Step.sol | 1e512067a7cba4738ec7f5243ebd6fd769bac157 | +| ./deployment/RuleEngineOwnable2Step.sol | bc745b539127f72509a7c603272a777879fec764 | ### Contracts Description Table @@ -18,7 +18,10 @@ | **RuleEngineOwnable2Step** | Implementation | RuleEngineOwnableShared, Ownable2Step ||| | └ | | Public ❗️ | 🛑 | RuleEngineOwnableShared Ownable | | └ | _onlyRulesManager | Internal 🔒 | 🛑 | onlyOwner | +| └ | _onlyRulesLimitManager | Internal 🔒 | 🛑 | onlyOwner | | └ | _onlyComplianceManager | Internal 🔒 | 🛑 | onlyOwner | +| └ | transferOwnership | Public ❗️ | 🛑 | onlyOwner | +| └ | supportsInterface | Public ❗️ | |NO❗️ | | └ | _msgSender | Internal 🔒 | | | | └ | _msgData | Internal 🔒 | | | | └ | _contextSuffixLength | Internal 🔒 | | | diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngineOwnableShared.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnableShared.sol.md index b0a3586..4782ec3 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleEngineOwnableShared.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnableShared.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./RuleEngineOwnableShared.sol | 3ebee76c60905011d0eb2d936d5839d4fbb17041 | +| ./RuleEngineOwnableShared.sol | d660dcbfcc5dd26f3a81a9c267997c3dd0a6d5ae | ### Contracts Description Table @@ -15,9 +15,10 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleEngineOwnableShared** | Implementation | ERC2771ModuleStandalone, RuleEngineBase ||| +| **RuleEngineOwnableShared** | Implementation | ERC2771ModuleStandalone, RuleEngineBase, ERC165 ||| | └ | | Public ❗️ | 🛑 | ERC2771ModuleStandalone | | └ | supportsInterface | Public ❗️ | |NO❗️ | +| └ | _checkOwnershipTransferTarget | Internal 🔒 | | | | └ | _msgSender | Internal 🔒 | | | | └ | _msgData | Internal 🔒 | | | | └ | _contextSuffixLength | Internal 🔒 | | | diff --git a/doc/schema/surya/surya_report/surya_report_RuleInvalidMock.sol.md b/doc/schema/surya/surya_report/surya_report_RuleInvalidMock.sol.md index 078736a..6d46baa 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleInvalidMock.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleInvalidMock.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/RuleInvalidMock.sol | 28b4ef1d191d6a61aada67050b23a8589a825309 | +| ./mocks/RuleInvalidMock.sol | 7889ad3225dd52ba620d695d5ef33a1fb3b6fd8a | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleMintAllowance.sol.md b/doc/schema/surya/surya_report/surya_report_RuleMintAllowance.sol.md new file mode 100644 index 0000000..bdb2112 --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_RuleMintAllowance.sol.md @@ -0,0 +1,37 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./mocks/rules/operation/RuleMintAllowance.sol | e97489d69ef915fa16584bc17a7974c146258901 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **RuleMintAllowance** | Implementation | AccessControl, RuleMintAllowanceInvariantStorage, IRule ||| +| └ | | Public ❗️ | 🛑 |NO❗️ | +| └ | supportsInterface | Public ❗️ | |NO❗️ | +| └ | setMintAllowance | External ❗️ | 🛑 | onlyRole | +| └ | transferred | Public ❗️ | 🛑 |NO❗️ | +| └ | transferred | Public ❗️ | 🛑 |NO❗️ | +| └ | detectTransferRestriction | Public ❗️ | |NO❗️ | +| └ | detectTransferRestrictionFrom | Public ❗️ | |NO❗️ | +| └ | canTransfer | Public ❗️ | |NO❗️ | +| └ | canTransferFrom | Public ❗️ | |NO❗️ | +| └ | canReturnTransferRestrictionCode | External ❗️ | |NO❗️ | +| └ | messageForTransferRestriction | External ❗️ | |NO❗️ | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_RuleMintAllowanceInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RuleMintAllowanceInvariantStorage.sol.md new file mode 100644 index 0000000..9f4c140 --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_RuleMintAllowanceInvariantStorage.sol.md @@ -0,0 +1,26 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./mocks/rules/operation/abstract/RuleMintAllowanceInvariantStorage.sol | 0b68f34198783eb76a0fa123e5bb59c5c6b63cc2 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **RuleMintAllowanceInvariantStorage** | Implementation | RuleCommonInvariantStorage ||| + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_RuleOperationRevert.sol.md b/doc/schema/surya/surya_report/surya_report_RuleOperationRevert.sol.md index c482aa3..580288f 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleOperationRevert.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleOperationRevert.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/operation/RuleOperationRevert.sol | d73e135daf5ae5f508edb4cd4b616513f3a99655 | +| ./mocks/rules/operation/RuleOperationRevert.sol | 689fae1c2576424be3fe4e39fada0425dd0c3025 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleWhitelist.sol.md b/doc/schema/surya/surya_report/surya_report_RuleWhitelist.sol.md index 53c9edb..d45fca7 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleWhitelist.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleWhitelist.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/validation/RuleWhitelist.sol | cf4b1568b96b381fa66ea41cf675e47455852055 | +| ./mocks/rules/validation/RuleWhitelist.sol | a5f2223286e30d05a0444ab0cc7cfd0a2aef7080 | ### Contracts Description Table @@ -22,8 +22,8 @@ | └ | canTransferFrom | Public ❗️ | |NO❗️ | | └ | detectTransferRestriction | Public ❗️ | |NO❗️ | | └ | detectTransferRestrictionFrom | Public ❗️ | |NO❗️ | -| └ | transferred | Public ❗️ | |NO❗️ | -| └ | transferred | Public ❗️ | |NO❗️ | +| └ | transferred | Public ❗️ | 🛑 |NO❗️ | +| └ | transferred | Public ❗️ | 🛑 |NO❗️ | ### Legend diff --git a/doc/schema/surya/surya_report/surya_report_RulesManagementModule.sol.md b/doc/schema/surya/surya_report/surya_report_RulesManagementModule.sol.md index 8e098d5..2167950 100644 --- a/doc/schema/surya/surya_report/surya_report_RulesManagementModule.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RulesManagementModule.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/RulesManagementModule.sol | 197635bda28fa8af5cba2be10740ab1a044dc95c | +| ./modules/RulesManagementModule.sol | 27d1c99e25a5558da4ddf1e527e5ac9f1e8f4a32 | ### Contracts Description Table @@ -19,6 +19,8 @@ | └ | setRules | Public ❗️ | 🛑 | onlyRulesManager | | └ | clearRules | Public ❗️ | 🛑 | onlyRulesManager | | └ | addRule | Public ❗️ | 🛑 | onlyRulesManager | +| └ | maxRules | Public ❗️ | |NO❗️ | +| └ | setMaxRules | Public ❗️ | 🛑 | onlyRulesLimitManager | | └ | removeRule | Public ❗️ | 🛑 | onlyRulesManager | | └ | rulesCount | Public ❗️ | |NO❗️ | | └ | containsRule | Public ❗️ | |NO❗️ | @@ -30,6 +32,7 @@ | └ | _transferred | Internal 🔒 | 🛑 | | | └ | _transferred | Internal 🔒 | 🛑 | | | └ | _onlyRulesManager | Internal 🔒 | 🛑 | | +| └ | _onlyRulesLimitManager | Internal 🔒 | 🛑 | | ### Legend diff --git a/doc/schema/surya/surya_report/surya_report_RulesManagementModuleInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RulesManagementModuleInvariantStorage.sol.md index 34102c0..ca1591c 100644 --- a/doc/schema/surya/surya_report/surya_report_RulesManagementModuleInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RulesManagementModuleInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/library/RulesManagementModuleInvariantStorage.sol | 1ffedb2b66df5fd884a1df089ec7a5c82f27341d | +| ./modules/library/RulesManagementModuleInvariantStorage.sol | 102ddd407f94cf19d9a53660ab83d1fe23f2def1 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RulesManagementModuleRolesStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RulesManagementModuleRolesStorage.sol.md new file mode 100644 index 0000000..ef5e8ed --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_RulesManagementModuleRolesStorage.sol.md @@ -0,0 +1,26 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./modules/library/RulesManagementModuleRolesStorage.sol | b446550693395e6605d6fa2585a09b5020a5f3c3 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **RulesManagementModuleRolesStorage** | Implementation | ||| + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_VersionModule.sol.md b/doc/schema/surya/surya_report/surya_report_VersionModule.sol.md index 5b4754f..41983c2 100644 --- a/doc/schema/surya/surya_report/surya_report_VersionModule.sol.md +++ b/doc/schema/surya/surya_report/surya_report_VersionModule.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/VersionModule.sol | e6ca5136a4fb06049ed9e45e65dbefc9a759c935 | +| ./modules/VersionModule.sol | 649030ee14a1c1a8466b8de78976ada94a7d9d39 | ### Contracts Description Table diff --git a/doc/security/audits/tools/aderyn-report-feedback.md b/doc/security/audits/tools/v3.0.0-rc3/aderyn-report-feedback.md similarity index 100% rename from doc/security/audits/tools/aderyn-report-feedback.md rename to doc/security/audits/tools/v3.0.0-rc3/aderyn-report-feedback.md diff --git a/doc/security/audits/tools/aderyn-report.md b/doc/security/audits/tools/v3.0.0-rc3/aderyn-report.md similarity index 100% rename from doc/security/audits/tools/aderyn-report.md rename to doc/security/audits/tools/v3.0.0-rc3/aderyn-report.md diff --git a/doc/security/audits/tools/slither-report-feedback.md b/doc/security/audits/tools/v3.0.0-rc3/slither-report-feedback.md similarity index 100% rename from doc/security/audits/tools/slither-report-feedback.md rename to doc/security/audits/tools/v3.0.0-rc3/slither-report-feedback.md diff --git a/doc/security/audits/tools/slither-report.md b/doc/security/audits/tools/v3.0.0-rc3/slither-report.md similarity index 100% rename from doc/security/audits/tools/slither-report.md rename to doc/security/audits/tools/v3.0.0-rc3/slither-report.md diff --git a/doc/security/audits/tools/v3.0.0-rc4/aderyn-report-feedback.md b/doc/security/audits/tools/v3.0.0-rc4/aderyn-report-feedback.md new file mode 100644 index 0000000..690c5da --- /dev/null +++ b/doc/security/audits/tools/v3.0.0-rc4/aderyn-report-feedback.md @@ -0,0 +1,53 @@ +# Aderyn Report — Assessment Feedback + +**Tool:** [Aderyn](https://github.com/Cyfrin/aderyn) +**Report file:** `doc/security/audits/tools/v3.0.0-rc4/aderyn-report.md` +**Assessment date:** 2026-05-22 + +## Summary + +| ID | Finding | Tool Severity | Assessment | Decision | +|----|---------|---------------|------------|----------| +| L-1 | Centralization Risk | Low | Valid observation of privileged governance model | Accepted by design | +| L-2 | Unspecific Solidity Pragma | Low | Intentional library-style pragma with pinned compiler in tooling | Accepted by design | +| L-3 | PUSH0 Opcode | Low | Not applicable for configured target EVM | Accepted by design | +| L-4 | Modifier Invoked Only Once | Low | Style heuristic; modifier supports hook pattern consistency | Accepted by design | +| L-5 | Empty Block | Low | Expected for hook overrides where modifier carries logic | Accepted by design | +| L-6 | Loop Contains `require`/`revert` | Low | Required for atomicity in `setRules` | Accepted by design | +| L-7 | Costly operations inside loop | Low | Storage writes are intrinsic to rule registration | Accepted by design | +| L-8 | Unchecked Return | Low | `_grantRole` return not security-relevant in constructor flow | Accepted by design | + +No High findings were reported. Finding set is unchanged from v3.0.0-rc3. + +## Changes since v3.0.0-rc3 + +Scope grew from 21 files / 607 nSLOC to 24 files / 629 nSLOC (+3 files, +22 nSLOC). The added files are small invariant-storage and roles-storage abstract contracts (`ERC3643ComplianceModuleInvariantStorage`, `ERC3643ComplianceRolesStorage`, `RulesManagementModuleRolesStorage`). None introduce new finding categories. + +## Detailed triage + +### L-1 Centralization Risk +This contract family is explicitly administrative compliance infrastructure. `RuleEngine` (RBAC), `RuleEngineOwnable`, and `RuleEngineOwnable2Step` intentionally expose privileged operations for rule and token binding governance. This is a product requirement, not a vulnerability. + +### L-2 Unspecific Solidity Pragma +`^0.8.20` is intentional for integrator compatibility. Build tooling remains pinned (Solc 0.8.34). This is a common and acceptable pattern for reusable contract packages. + +### L-3 PUSH0 Opcode +The project target is modern EVM (`prague`). `PUSH0` compatibility concerns only pre-Shanghai targets; those are outside the supported deployment matrix. + +### L-4 Modifier Invoked Only Once +`onlyRulesLimitManager` being used once is not a risk. It preserves the same extensible access-control abstraction used across modules and variants. + +### L-5 Empty Block +Empty bodies in `_onlyComplianceManager`, `_onlyRulesManager`, and `_onlyRulesLimitManager` are intentional. Authorization executes in the modifier, and the empty body enforces a clean virtual-hook architecture. + +### L-6 Loop Contains `require`/`revert` +`setRules` must be all-or-nothing. Reverting on invalid element prevents partial updates and inconsistent policy state. + +### L-7 Costly operations inside loop +`EnumerableSet.add` in a loop is unavoidable for persistent rule set updates. Cost scales with rule count and is an operator-controlled admin path. + +### L-8 Unchecked Return +Ignoring `_grantRole` return in constructor is acceptable; no exploitable path is introduced, and constructor semantics do not depend on that boolean. + +## Conclusion +All Aderyn findings are either design tradeoffs or static-analysis style heuristics. No code changes are required based on this report. diff --git a/doc/security/audits/tools/v3.0.0-rc4/aderyn-report.md b/doc/security/audits/tools/v3.0.0-rc4/aderyn-report.md new file mode 100644 index 0000000..f052acb --- /dev/null +++ b/doc/security/audits/tools/v3.0.0-rc4/aderyn-report.md @@ -0,0 +1,615 @@ +# Aderyn Analysis Report + +This report was generated by [Aderyn](https://github.com/Cyfrin/aderyn), a static analysis tool built by [Cyfrin](https://cyfrin.io), a blockchain security company. This report is not a substitute for manual audit or security review. It should not be relied upon for any purpose other than to assist in the identification of potential security vulnerabilities. +# Table of Contents + +- [Summary](#summary) + - [Files Summary](#files-summary) + - [Files Details](#files-details) + - [Issue Summary](#issue-summary) +- [Low Issues](#low-issues) + - [L-1: Centralization Risk](#l-1-centralization-risk) + - [L-2: Unspecific Solidity Pragma](#l-2-unspecific-solidity-pragma) + - [L-3: PUSH0 Opcode](#l-3-push0-opcode) + - [L-4: Modifier Invoked Only Once](#l-4-modifier-invoked-only-once) + - [L-5: Empty Block](#l-5-empty-block) + - [L-6: Loop Contains `require`/`revert`](#l-6-loop-contains-requirerevert) + - [L-7: Costly operations inside loop](#l-7-costly-operations-inside-loop) + - [L-8: Unchecked Return](#l-8-unchecked-return) + + +# Summary + +## Files Summary + +| Key | Value | +| --- | --- | +| .sol Files | 24 | +| Total nSLOC | 629 | + + +## Files Details + +| Filepath | nSLOC | +| --- | --- | +| src/RuleEngineBase.sol | 140 | +| src/RuleEngineOwnableShared.sol | 33 | +| src/deployment/RuleEngine.sol | 71 | +| src/deployment/RuleEngineOwnable.sol | 26 | +| src/deployment/RuleEngineOwnable2Step.sol | 32 | +| src/interfaces/IERC3643Compliance.sol | 12 | +| src/interfaces/IERC3643ComplianceExtended.sol | 12 | +| src/interfaces/IRule.sol | 5 | +| src/interfaces/IRulesManagementModule.sol | 14 | +| src/modules/ERC2771ModuleStandalone.sol | 6 | +| src/modules/ERC3643ComplianceExtendedModule.sol | 48 | +| src/modules/ERC3643ComplianceModule.sol | 57 | +| src/modules/RulesManagementModule.sol | 105 | +| src/modules/VersionModule.sol | 8 | +| src/modules/library/ComplianceInterfaceId.sol | 6 | +| src/modules/library/ERC1404InterfaceId.sol | 4 | +| src/modules/library/ERC3643ComplianceModuleInvariantStorage.sol | 8 | +| src/modules/library/ERC3643ComplianceRolesStorage.sol | 4 | +| src/modules/library/Ownable2StepInterfaceId.sol | 4 | +| src/modules/library/OwnableInterfaceId.sol | 4 | +| src/modules/library/RuleEngineInvariantStorage.sol | 5 | +| src/modules/library/RuleInterfaceId.sol | 4 | +| src/modules/library/RulesManagementModuleInvariantStorage.sol | 17 | +| src/modules/library/RulesManagementModuleRolesStorage.sol | 4 | +| **Total** | **629** | + + +## Issue Summary + +| Category | No. of Issues | +| --- | --- | +| High | 0 | +| Low | 8 | + + +# Low Issues + +## L-1: Centralization Risk + +Contracts have owners with privileged rights to perform admin tasks and need to be trusted to not perform malicious updates or drain funds. + +
14 Found Instances + + +- Found in src/deployment/RuleEngine.sol [Line: 25](src/deployment/RuleEngine.sol#L25) + + ```solidity + AccessControlEnumerable, + ``` + +- Found in src/deployment/RuleEngine.sol [Line: 95](src/deployment/RuleEngine.sol#L95) + + ```solidity + function _onlyComplianceManager() internal virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) {} + ``` + +- Found in src/deployment/RuleEngine.sol [Line: 96](src/deployment/RuleEngine.sol#L96) + + ```solidity + function _onlyRulesManager() internal virtual override onlyRole(RULES_MANAGEMENT_ROLE) {} + ``` + +- Found in src/deployment/RuleEngine.sol [Line: 97](src/deployment/RuleEngine.sol#L97) + + ```solidity + function _onlyRulesLimitManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {} + ``` + +- Found in src/deployment/RuleEngineOwnable.sol [Line: 12](src/deployment/RuleEngineOwnable.sol#L12) + + ```solidity + contract RuleEngineOwnable is RuleEngineOwnableShared, Ownable { + ``` + +- Found in src/deployment/RuleEngineOwnable.sol [Line: 27](src/deployment/RuleEngineOwnable.sol#L27) + + ```solidity + function _onlyRulesManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/RuleEngineOwnable.sol [Line: 28](src/deployment/RuleEngineOwnable.sol#L28) + + ```solidity + function _onlyRulesLimitManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/RuleEngineOwnable.sol [Line: 33](src/deployment/RuleEngineOwnable.sol#L33) + + ```solidity + function _onlyComplianceManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/RuleEngineOwnable.sol [Line: 39](src/deployment/RuleEngineOwnable.sol#L39) + + ```solidity + function transferOwnership(address newOwner) public virtual override onlyOwner { + ``` + +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 15](src/deployment/RuleEngineOwnable2Step.sol#L15) + + ```solidity + contract RuleEngineOwnable2Step is RuleEngineOwnableShared, Ownable2Step { + ``` + +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 31](src/deployment/RuleEngineOwnable2Step.sol#L31) + + ```solidity + function _onlyRulesManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 32](src/deployment/RuleEngineOwnable2Step.sol#L32) + + ```solidity + function _onlyRulesLimitManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 37](src/deployment/RuleEngineOwnable2Step.sol#L37) + + ```solidity + function _onlyComplianceManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 43](src/deployment/RuleEngineOwnable2Step.sol#L43) + + ```solidity + function transferOwnership(address newOwner) public virtual override onlyOwner { + ``` + +
+ + + +## L-2: Unspecific Solidity Pragma + +Consider using a specific version of Solidity in your contracts instead of a wide version. For example, instead of `pragma solidity ^0.8.0;`, use `pragma solidity 0.8.0;` + +
19 Found Instances + + +- Found in src/RuleEngineBase.sol [Line: 3](src/RuleEngineBase.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/RuleEngineOwnableShared.sol [Line: 3](src/RuleEngineOwnableShared.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/deployment/RuleEngine.sol [Line: 3](src/deployment/RuleEngine.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/deployment/RuleEngineOwnable.sol [Line: 3](src/deployment/RuleEngineOwnable.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 3](src/deployment/RuleEngineOwnable2Step.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/interfaces/IERC3643Compliance.sol [Line: 3](src/interfaces/IERC3643Compliance.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/interfaces/IERC3643ComplianceExtended.sol [Line: 3](src/interfaces/IERC3643ComplianceExtended.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/interfaces/IRule.sol [Line: 3](src/interfaces/IRule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/interfaces/IRulesManagementModule.sol [Line: 3](src/interfaces/IRulesManagementModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/ERC2771ModuleStandalone.sol [Line: 3](src/modules/ERC2771ModuleStandalone.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 3](src/modules/ERC3643ComplianceExtendedModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/ERC3643ComplianceModule.sol [Line: 3](src/modules/ERC3643ComplianceModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/RulesManagementModule.sol [Line: 3](src/modules/RulesManagementModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/VersionModule.sol [Line: 3](src/modules/VersionModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/ERC3643ComplianceModuleInvariantStorage.sol [Line: 3](src/modules/library/ERC3643ComplianceModuleInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/ERC3643ComplianceRolesStorage.sol [Line: 3](src/modules/library/ERC3643ComplianceRolesStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/RuleEngineInvariantStorage.sol [Line: 3](src/modules/library/RuleEngineInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/RulesManagementModuleInvariantStorage.sol [Line: 3](src/modules/library/RulesManagementModuleInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/RulesManagementModuleRolesStorage.sol [Line: 3](src/modules/library/RulesManagementModuleRolesStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +
+ + + +## L-3: PUSH0 Opcode + +Solc compiler version 0.8.20 switches the default target EVM version to Shanghai, which means that the generated bytecode will include PUSH0 opcodes. Be sure to select the appropriate EVM version in case you intend to deploy on a chain other than mainnet like L2 chains that may not support PUSH0, otherwise deployment of your contracts will fail. + +
24 Found Instances + + +- Found in src/RuleEngineBase.sol [Line: 3](src/RuleEngineBase.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/RuleEngineOwnableShared.sol [Line: 3](src/RuleEngineOwnableShared.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/deployment/RuleEngine.sol [Line: 3](src/deployment/RuleEngine.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/deployment/RuleEngineOwnable.sol [Line: 3](src/deployment/RuleEngineOwnable.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 3](src/deployment/RuleEngineOwnable2Step.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/interfaces/IERC3643Compliance.sol [Line: 3](src/interfaces/IERC3643Compliance.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/interfaces/IERC3643ComplianceExtended.sol [Line: 3](src/interfaces/IERC3643ComplianceExtended.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/interfaces/IRule.sol [Line: 3](src/interfaces/IRule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/interfaces/IRulesManagementModule.sol [Line: 3](src/interfaces/IRulesManagementModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/ERC2771ModuleStandalone.sol [Line: 3](src/modules/ERC2771ModuleStandalone.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 3](src/modules/ERC3643ComplianceExtendedModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/ERC3643ComplianceModule.sol [Line: 3](src/modules/ERC3643ComplianceModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/RulesManagementModule.sol [Line: 3](src/modules/RulesManagementModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/VersionModule.sol [Line: 3](src/modules/VersionModule.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/ComplianceInterfaceId.sol [Line: 3](src/modules/library/ComplianceInterfaceId.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/ERC1404InterfaceId.sol [Line: 3](src/modules/library/ERC1404InterfaceId.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/ERC3643ComplianceModuleInvariantStorage.sol [Line: 3](src/modules/library/ERC3643ComplianceModuleInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/ERC3643ComplianceRolesStorage.sol [Line: 3](src/modules/library/ERC3643ComplianceRolesStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/Ownable2StepInterfaceId.sol [Line: 3](src/modules/library/Ownable2StepInterfaceId.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/OwnableInterfaceId.sol [Line: 3](src/modules/library/OwnableInterfaceId.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/RuleEngineInvariantStorage.sol [Line: 3](src/modules/library/RuleEngineInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/RuleInterfaceId.sol [Line: 3](src/modules/library/RuleInterfaceId.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/RulesManagementModuleInvariantStorage.sol [Line: 3](src/modules/library/RulesManagementModuleInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +- Found in src/modules/library/RulesManagementModuleRolesStorage.sol [Line: 3](src/modules/library/RulesManagementModuleRolesStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.20; + ``` + +
+ + + +## L-4: Modifier Invoked Only Once + +Consider removing the modifier or inlining the logic into the calling function. + +
1 Found Instances + + +- Found in src/modules/RulesManagementModule.sol [Line: 21](src/modules/RulesManagementModule.sol#L21) + + ```solidity + modifier onlyRulesLimitManager() { + ``` + +
+ + + +## L-5: Empty Block + +Consider removing empty blocks. + +
9 Found Instances + + +- Found in src/deployment/RuleEngine.sol [Line: 95](src/deployment/RuleEngine.sol#L95) + + ```solidity + function _onlyComplianceManager() internal virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) {} + ``` + +- Found in src/deployment/RuleEngine.sol [Line: 96](src/deployment/RuleEngine.sol#L96) + + ```solidity + function _onlyRulesManager() internal virtual override onlyRole(RULES_MANAGEMENT_ROLE) {} + ``` + +- Found in src/deployment/RuleEngine.sol [Line: 97](src/deployment/RuleEngine.sol#L97) + + ```solidity + function _onlyRulesLimitManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {} + ``` + +- Found in src/deployment/RuleEngineOwnable.sol [Line: 27](src/deployment/RuleEngineOwnable.sol#L27) + + ```solidity + function _onlyRulesManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/RuleEngineOwnable.sol [Line: 28](src/deployment/RuleEngineOwnable.sol#L28) + + ```solidity + function _onlyRulesLimitManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/RuleEngineOwnable.sol [Line: 33](src/deployment/RuleEngineOwnable.sol#L33) + + ```solidity + function _onlyComplianceManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 31](src/deployment/RuleEngineOwnable2Step.sol#L31) + + ```solidity + function _onlyRulesManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 32](src/deployment/RuleEngineOwnable2Step.sol#L32) + + ```solidity + function _onlyRulesLimitManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 37](src/deployment/RuleEngineOwnable2Step.sol#L37) + + ```solidity + function _onlyComplianceManager() internal virtual override onlyOwner {} + ``` + +
+ + + +## L-6: Loop Contains `require`/`revert` + +Avoid `require` / `revert` statements in a loop because a single bad item can cause the whole transaction to fail. It's better to forgive on fail and return failed elements post processing of the loop + +
4 Found Instances + + +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 22](src/modules/ERC3643ComplianceExtendedModule.sol#L22) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` + +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 29](src/modules/ERC3643ComplianceExtendedModule.sol#L29) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` + +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 48](src/modules/ERC3643ComplianceExtendedModule.sol#L48) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` + +- Found in src/modules/RulesManagementModule.sol [Line: 62](src/modules/RulesManagementModule.sol#L62) + + ```solidity + for (uint256 i = 0; i < rules_.length; ++i) { + ``` + +
+ + + +## L-7: Costly operations inside loop + +Invoking `SSTORE` operations in loops may waste gas. Use a local variable to hold the loop computation result. + +
4 Found Instances + + +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 22](src/modules/ERC3643ComplianceExtendedModule.sol#L22) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` + +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 29](src/modules/ERC3643ComplianceExtendedModule.sol#L29) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` + +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 48](src/modules/ERC3643ComplianceExtendedModule.sol#L48) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` + +- Found in src/modules/RulesManagementModule.sol [Line: 62](src/modules/RulesManagementModule.sol#L62) + + ```solidity + for (uint256 i = 0; i < rules_.length; ++i) { + ``` + +
+ + + +## L-8: Unchecked Return + +Function returns a value but it is ignored. Consider checking the return value. + +
1 Found Instances + + +- Found in src/deployment/RuleEngine.sol [Line: 44](src/deployment/RuleEngine.sol#L44) + + ```solidity + _grantRole(DEFAULT_ADMIN_ROLE, admin); + ``` + +
+ + + diff --git a/doc/security/audits/tools/v3.0.0-rc4/slither-report-feedback.md b/doc/security/audits/tools/v3.0.0-rc4/slither-report-feedback.md new file mode 100644 index 0000000..da25704 --- /dev/null +++ b/doc/security/audits/tools/v3.0.0-rc4/slither-report-feedback.md @@ -0,0 +1,28 @@ +# Slither Report — Assessment Feedback + +**Tool:** [Slither](https://github.com/crytic/slither) +**Report file:** `doc/security/audits/tools/v3.0.0-rc4/slither-report.md` +**Assessment date:** 2026-05-22 + +## Summary + +| IDs | Detector | Tool Impact | Assessment | Decision | +|-----|----------|-------------|------------|----------| +| 0-9 | `calls-loop` | Low | Inherent to pluggable rule-engine dispatch architecture | Accepted by design | +| 10-11 | `unindexed-event-address` | Informational | Valid optimization note, but ABI-breaking to change now | Deferred | + +## Changes since v3.0.0-rc3 + +`unindexed-event-address` count reduced from 3 to 2. The `TokenSelfBindingApprovalSet(address,bool)` finding (previously ID-12) was resolved by adding `indexed` to the `token` parameter in `ERC3643ComplianceExtendedModule`. The two remaining findings (`TokenBound` and `TokenUnbound` in `IERC3643Compliance`) are deferred as before. + +## Detailed triage + +### IDs 0-9: `calls-loop` +The RuleEngine intentionally iterates `_rules` and performs external rule calls for transfer checks and transfer hooks. This is core product behavior. +Risk is controlled through trusted-rule governance and documented operational limits on rule count. No direct security defect is introduced by this detector output. + +### IDs 10-11: `unindexed-event-address` +`TokenBound(address)` and `TokenUnbound(address)` could add `indexed` for cheaper filtering, but doing so changes event signatures and breaks existing consumers. Keep deferring `TokenBound`/`TokenUnbound` to a planned major ERC-3643 interface revision. + +## Conclusion +No actionable security fixes are required from this Slither run. Findings are architectural by-design or compatibility tradeoffs. diff --git a/doc/security/audits/tools/v3.0.0-rc4/slither-report.md b/doc/security/audits/tools/v3.0.0-rc4/slither-report.md new file mode 100644 index 0000000..8cab5a6 --- /dev/null +++ b/doc/security/audits/tools/v3.0.0-rc4/slither-report.md @@ -0,0 +1,104 @@ +**THIS CHECKLIST IS NOT COMPLETE**. Use `--show-ignored-findings` to show all the results. +Summary + - [calls-loop](#calls-loop) (10 results) (Low) + - [unindexed-event-address](#unindexed-event-address) (2 results) (Informational) +## calls-loop +Impact: Low +Confidence: Medium + - [ ] ID-0 +[RuleEngineBase._detectTransferRestriction(address,address,uint256)](src/RuleEngineBase.sol#L149-L158) has external calls inside a loop: [restriction = IRule(rule(i)).detectTransferRestriction(from,to,value)](src/RuleEngineBase.sol#L152) + Calls stack containing the loop: + RuleEngineBase.canTransfer(address,address,uint256) + RuleEngineBase.detectTransferRestriction(address,address,uint256) + +src/RuleEngineBase.sol#L149-L158 + + + - [ ] ID-1 +[RulesManagementModule._transferred(address,address,uint256)](src/modules/RulesManagementModule.sol#L203-L208) has external calls inside a loop: [IRule(_rules.at(i)).transferred(from,to,value)](src/modules/RulesManagementModule.sol#L206) + Calls stack containing the loop: + RuleEngineBase.destroyed(address,uint256) + +src/modules/RulesManagementModule.sol#L203-L208 + + + - [ ] ID-2 +[RuleEngineBase._messageForTransferRestriction(uint8)](src/RuleEngineBase.sol#L182-L190) has external calls inside a loop: [IRule(rule(i)).messageForTransferRestriction(restrictionCode)](src/RuleEngineBase.sol#L186) + Calls stack containing the loop: + RuleEngineBase.messageForTransferRestriction(uint8) + +src/RuleEngineBase.sol#L182-L190 + + + - [ ] ID-3 +[RuleEngineBase._messageForTransferRestriction(uint8)](src/RuleEngineBase.sol#L182-L190) has external calls inside a loop: [IRule(rule(i)).canReturnTransferRestrictionCode(restrictionCode)](src/RuleEngineBase.sol#L185) + Calls stack containing the loop: + RuleEngineBase.messageForTransferRestriction(uint8) + +src/RuleEngineBase.sol#L182-L190 + + + - [ ] ID-4 +[RuleEngineBase._detectTransferRestrictionFrom(address,address,address,uint256)](src/RuleEngineBase.sol#L160-L174) has external calls inside a loop: [restriction = IRule(rule(i)).detectTransferRestrictionFrom(spender,from,to,value)](src/RuleEngineBase.sol#L168) + Calls stack containing the loop: + RuleEngineBase.canTransferFrom(address,address,address,uint256) + RuleEngineBase.detectTransferRestrictionFrom(address,address,address,uint256) + +src/RuleEngineBase.sol#L160-L174 + + + - [ ] ID-5 +[RulesManagementModule._transferred(address,address,uint256)](src/modules/RulesManagementModule.sol#L203-L208) has external calls inside a loop: [IRule(_rules.at(i)).transferred(from,to,value)](src/modules/RulesManagementModule.sol#L206) + Calls stack containing the loop: + RuleEngineBase.transferred(address,address,uint256) + +src/modules/RulesManagementModule.sol#L203-L208 + + + - [ ] ID-6 +[RulesManagementModule._transferred(address,address,address,uint256)](src/modules/RulesManagementModule.sol#L222-L227) has external calls inside a loop: [IRule(_rules.at(i)).transferred(spender,from,to,value)](src/modules/RulesManagementModule.sol#L225) + Calls stack containing the loop: + RuleEngineBase.transferred(address,address,address,uint256) + +src/modules/RulesManagementModule.sol#L222-L227 + + + - [ ] ID-7 +[RulesManagementModule._transferred(address,address,uint256)](src/modules/RulesManagementModule.sol#L203-L208) has external calls inside a loop: [IRule(_rules.at(i)).transferred(from,to,value)](src/modules/RulesManagementModule.sol#L206) + Calls stack containing the loop: + RuleEngineBase.created(address,uint256) + +src/modules/RulesManagementModule.sol#L203-L208 + + + - [ ] ID-8 +[RuleEngineBase._detectTransferRestriction(address,address,uint256)](src/RuleEngineBase.sol#L149-L158) has external calls inside a loop: [restriction = IRule(rule(i)).detectTransferRestriction(from,to,value)](src/RuleEngineBase.sol#L152) + Calls stack containing the loop: + RuleEngineBase.detectTransferRestriction(address,address,uint256) + +src/RuleEngineBase.sol#L149-L158 + + + - [ ] ID-9 +[RuleEngineBase._detectTransferRestrictionFrom(address,address,address,uint256)](src/RuleEngineBase.sol#L160-L174) has external calls inside a loop: [restriction = IRule(rule(i)).detectTransferRestrictionFrom(spender,from,to,value)](src/RuleEngineBase.sol#L168) + Calls stack containing the loop: + RuleEngineBase.detectTransferRestrictionFrom(address,address,address,uint256) + +src/RuleEngineBase.sol#L160-L174 + + +## unindexed-event-address +Impact: Informational +Confidence: High + - [ ] ID-10 +Event [IERC3643Compliance.TokenBound(address)](src/interfaces/IERC3643Compliance.sol#L14) has address parameters but no indexed parameters + +src/interfaces/IERC3643Compliance.sol#L14 + + + - [ ] ID-11 +Event [IERC3643Compliance.TokenUnbound(address)](src/interfaces/IERC3643Compliance.sol#L20) has address parameters but no indexed parameters + +src/interfaces/IERC3643Compliance.sol#L20 + + diff --git a/lib/CMTAT b/lib/CMTAT index 49544f4..580d477 160000 --- a/lib/CMTAT +++ b/lib/CMTAT @@ -1 +1 @@ -Subproject commit 49544f4de1993008acfc9e848d0bf03bd31d8579 +Subproject commit 580d4776e4cbb857b2da7d83fd79144ae7e47557 diff --git a/script/CMTATWithRuleEngineScript.s.sol b/script/CMTATWithRuleEngineScript.s.sol index 0ea6ee9..377a982 100644 --- a/script/CMTATWithRuleEngineScript.s.sol +++ b/script/CMTATWithRuleEngineScript.s.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.20; import {Script, console} from "forge-std/Script.sol"; -import {ICMTATConstructor, CMTATStandalone} from "CMTAT/deployment/CMTATStandalone.sol"; +import {ICMTATConstructor, CMTATStandardStandalone} from "CMTAT/deployment/CMTATStandardStandalone.sol"; import {IERC1643CMTAT} from "CMTAT/interfaces/tokenization/draft-IERC1643CMTAT.sol"; import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; import {RuleEngine} from "src/deployment/RuleEngine.sol"; @@ -35,8 +35,8 @@ contract CMTATWithRuleEngineScript is Script { "CMTAT_info" ); ICMTATConstructor.Engine memory engines = ICMTATConstructor.Engine(IRuleEngine(address(0))); - CMTATStandalone cmtatContract = - new CMTATStandalone(trustedForwarder, admin, erc20Attributes, extraInformationAttributes, engines); + CMTATStandardStandalone cmtatContract = + new CMTATStandardStandalone(trustedForwarder, admin, erc20Attributes, extraInformationAttributes, engines); console.log("CMTAT cmtatContract : ", address(cmtatContract)); // whitelist RuleWhitelist ruleWhitelist = new RuleWhitelist(admin, trustedForwarder); diff --git a/src/deployment/RuleEngine.sol b/src/deployment/RuleEngine.sol index 44f8c54..8cd4fff 100644 --- a/src/deployment/RuleEngine.sol +++ b/src/deployment/RuleEngine.sol @@ -11,13 +11,21 @@ import {IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; /* ==== Modules === */ import {ERC2771ModuleStandalone, ERC2771Context} from "../modules/ERC2771ModuleStandalone.sol"; +import {ERC3643ComplianceRolesStorage} from "../modules/library/ERC3643ComplianceRolesStorage.sol"; +import {RulesManagementModuleRolesStorage} from "../modules/library/RulesManagementModuleRolesStorage.sol"; /* ==== Base contract === */ import {RuleEngineBase} from "../RuleEngineBase.sol"; /** * @title Implementation of a ruleEngine as defined by the CMTAT */ -contract RuleEngine is ERC2771ModuleStandalone, RuleEngineBase, AccessControlEnumerable { +contract RuleEngine is + ERC2771ModuleStandalone, + RuleEngineBase, + AccessControlEnumerable, + ERC3643ComplianceRolesStorage, + RulesManagementModuleRolesStorage +{ using EnumerableSet for EnumerableSet.AddressSet; /** @@ -39,7 +47,11 @@ contract RuleEngine is ERC2771ModuleStandalone, RuleEngineBase, AccessControlEnu /* ============ ACCESS CONTROL ============ */ /** * @notice Grants `role` to `account`. - * @dev Prevents granting any role to accounts already configured as rules. + * @dev Prevents granting any role to accounts currently configured as rules. + * Note: this check is intentionally one-directional. {addRule} does not verify + * whether the rule address already holds a privileged role, and this function does + * not prevent adding a privileged address as a rule afterwards. Operators are + * responsible for keeping rule contracts and privileged accounts disjoint. */ function grantRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) { if (_rules.contains(account)) { diff --git a/src/deployment/RuleEngineOwnable2Step.sol b/src/deployment/RuleEngineOwnable2Step.sol index 39c4e15..29f0ff4 100644 --- a/src/deployment/RuleEngineOwnable2Step.sol +++ b/src/deployment/RuleEngineOwnable2Step.sol @@ -14,9 +14,10 @@ import {Ownable2StepInterfaceId} from "../modules/library/Ownable2StepInterfaceI */ contract RuleEngineOwnable2Step is RuleEngineOwnableShared, Ownable2Step { /** - * @param owner_ Address of the contract owner (ERC-173) - * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - * @param tokenContract Address of the token contract to bind (can be zero address) + * @notice Deploys a RuleEngine with ERC-173 two-step ownership transfer. + * @param owner_ Address of the initial contract owner (ERC-173). + * @param forwarderIrrevocable Address of the ERC-2771 trusted forwarder (use zero address to disable gasless). + * @param tokenContract Address of the token contract to bind at deployment (use zero address to skip). */ constructor(address owner_, address forwarderIrrevocable, address tokenContract) RuleEngineOwnableShared(forwarderIrrevocable, tokenContract) diff --git a/src/interfaces/IRulesManagementModule.sol b/src/interfaces/IRulesManagementModule.sol index 17c1242..823dbae 100644 --- a/src/interfaces/IRulesManagementModule.sol +++ b/src/interfaces/IRulesManagementModule.sol @@ -14,6 +14,8 @@ interface IRulesManagementModule { /** * @notice Updates the maximum number of rules allowed in the engine. * @dev Access control is implementation specific (admin/owner). + * Setting a very high cap re-exposes unbounded gas cost for administrative operations + * such as {clearRules} even though normal per-transfer cost remains bounded. * @param maxRules_ New maximum number of rules. */ function setMaxRules(uint256 maxRules_) external; @@ -60,9 +62,9 @@ interface IRulesManagementModule { /** * @notice Removes all configured rules. * @dev After calling this function, no rules will remain set. - * Developers should keep in mind that this function has an unbounded cost - * and using it may render the function uncallable if the set grows to the point - * where clearing it consumes too much gas to fit in a block. + * Cost is O(n) in the number of configured rules. With the default cap of 10 this is + * negligible, but a high {maxRules} setting re-exposes unbounded cost here even though + * per-transfer cost remains bounded. */ function clearRules() external; @@ -88,5 +90,5 @@ interface IRulesManagementModule { * @dev Complexity: O(1). * @return exists True if the rule is present, false otherwise. */ - function containsRule(IRule rule_) external returns (bool exists); + function containsRule(IRule rule_) external view returns (bool exists); } diff --git a/src/mocks/rules/operation/RuleMintAllowance.sol b/src/mocks/rules/operation/RuleMintAllowance.sol new file mode 100644 index 0000000..c29fcd7 --- /dev/null +++ b/src/mocks/rules/operation/RuleMintAllowance.sol @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import {IRule} from "../../../interfaces/IRule.sol"; +import {RuleInterfaceId} from "../../../modules/library/RuleInterfaceId.sol"; +import {RuleMintAllowanceInvariantStorage} from "./abstract/RuleMintAllowanceInvariantStorage.sol"; + +/** + * @title RuleMintAllowance + * @notice Rule that enforces per-minter mint allowances set by the contract admin. + * The admin grants each minter address a maximum amount they may mint in total. + * Each mint deducts from the minter's remaining allowance. + * Burns and regular transfers are unrestricted by this rule. + */ +contract RuleMintAllowance is AccessControl, RuleMintAllowanceInvariantStorage, IRule { + bytes4 private constant RULE_ENGINE_INTERFACE_ID = 0x20c49ce7; + bytes4 private constant ERC1404EXTEND_INTERFACE_ID = 0x78a8de7d; + + mapping(address minter => uint256 allowance) public mintAllowance; + + /** + * @param admin Address granted DEFAULT_ADMIN_ROLE + */ + constructor(address admin) { + require(admin != address(0), "RuleMintAllowance: zero admin"); + _grantRole(DEFAULT_ADMIN_ROLE, admin); + } + + /* ============ ERC-165 ============ */ + + function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, IERC165) returns (bool) { + return interfaceId == RULE_ENGINE_INTERFACE_ID || interfaceId == ERC1404EXTEND_INTERFACE_ID + || interfaceId == RuleInterfaceId.IRULE_INTERFACE_ID || AccessControl.supportsInterface(interfaceId); + } + + /* ============ Admin ============ */ + + /** + * @notice Set the mint allowance for a minter. + * @param minter Address of the minter. + * @param amount Maximum amount the minter is allowed to mint. + */ + function setMintAllowance(address minter, uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE) { + mintAllowance[minter] = amount; + emit MintAllowanceSet(minter, amount); + } + + /* ============ IRule — state-changing ============ */ + + /** + * @notice Called for transfers where no spender context is available. + * Mint allowance cannot be enforced without a spender; passes through. + */ + function transferred(address from, address to, uint256 value) public { + // no-op: spender unknown, enforcement requires transferred(spender,...) + } + + /** + * @notice Called for every token operation (transfer, mint, burn) with spender context. + * Deducts from the minter's allowance for mints; passes through for burns and transfers. + */ + function transferred(address spender, address from, address /* to */, uint256 value) public { + if (from == address(0)) { + uint256 allowance = mintAllowance[spender]; + if (allowance < value) { + revert RuleMintAllowance_InsufficientAllowance(spender, allowance, value); + } + mintAllowance[spender] = allowance - value; + emit MintAllowanceConsumed(spender, value, mintAllowance[spender]); + } + } + + /* ============ IRule — view ============ */ + + /** + * @notice Returns TRANSFER_OK; without spender context mint allowance cannot be evaluated. + */ + function detectTransferRestriction(address, address, uint256) public pure override returns (uint8) { + return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + /** + * @notice Returns CODE_MINTER_INSUFFICIENT_ALLOWANCE when a minter's allowance would be + * exceeded. Burns and regular transfers always return TRANSFER_OK. + */ + function detectTransferRestrictionFrom(address spender, address from, address, uint256 value) + public + view + override + returns (uint8) + { + if (from == address(0) && mintAllowance[spender] < value) { + return CODE_MINTER_INSUFFICIENT_ALLOWANCE; + } + return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + function canTransfer(address from, address to, uint256 value) public pure override returns (bool) { + return detectTransferRestriction(from, to, value) == uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + function canTransferFrom(address spender, address from, address to, uint256 value) + public + view + override + returns (bool) + { + return detectTransferRestrictionFrom(spender, from, to, value) == uint8(REJECTED_CODE_BASE.TRANSFER_OK); + } + + function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override returns (bool) { + return restrictionCode == CODE_MINTER_INSUFFICIENT_ALLOWANCE; + } + + function messageForTransferRestriction(uint8 restrictionCode) external pure override returns (string memory) { + if (restrictionCode == CODE_MINTER_INSUFFICIENT_ALLOWANCE) { + return TEXT_MINTER_INSUFFICIENT_ALLOWANCE; + } + return TEXT_CODE_NOT_FOUND; + } +} diff --git a/src/mocks/rules/operation/abstract/RuleMintAllowanceInvariantStorage.sol b/src/mocks/rules/operation/abstract/RuleMintAllowanceInvariantStorage.sol new file mode 100644 index 0000000..9ebce87 --- /dev/null +++ b/src/mocks/rules/operation/abstract/RuleMintAllowanceInvariantStorage.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +// forge-lint: disable-next-line(unaliased-plain-import) +import "../../validation/abstract/RuleCommonInvariantStorage.sol"; + +abstract contract RuleMintAllowanceInvariantStorage is RuleCommonInvariantStorage { + /* ============ Error ============ */ + error RuleMintAllowance_InsufficientAllowance(address minter, uint256 allowance, uint256 value); + + /* ============ Events ============ */ + event MintAllowanceSet(address indexed minter, uint256 allowance); + event MintAllowanceConsumed(address indexed minter, uint256 consumed, uint256 remaining); + + /* ============ Restriction codes ============ */ + // It is very important that each rule uses a unique code + uint8 public constant CODE_MINTER_INSUFFICIENT_ALLOWANCE = 81; + + /* ============ Restriction messages ============ */ + string constant TEXT_MINTER_INSUFFICIENT_ALLOWANCE = "MintAllowance: Insufficient allowance for minter"; +} diff --git a/src/mocks/rules/validation/RuleWhitelist.sol b/src/mocks/rules/validation/RuleWhitelist.sol index 21aa75d..cf03e00 100644 --- a/src/mocks/rules/validation/RuleWhitelist.sol +++ b/src/mocks/rules/validation/RuleWhitelist.sol @@ -2,10 +2,8 @@ pragma solidity ^0.8.20; -// forge-lint: disable-next-line(unaliased-plain-import) -import "./abstract/RuleAddressList/RuleAddressList.sol"; -// forge-lint: disable-next-line(unaliased-plain-import) -import "./abstract/RuleWhitelistCommon.sol"; +import {RuleAddressList} from "./abstract/RuleAddressList/RuleAddressList.sol"; +import {RuleWhitelistCommon} from "./abstract/RuleWhitelistCommon.sol"; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {RuleInterfaceId} from "../../../modules/library/RuleInterfaceId.sol"; @@ -84,19 +82,20 @@ contract RuleWhitelist is RuleAddressList, RuleWhitelistCommon { override returns (uint8) { - if (!addressIsListed(spender)) { + // Mint (from == address(0)) and burn (to == address(0)) are exempt from spender check + if (from != address(0) && to != address(0) && !addressIsListed(spender)) { return CODE_ADDRESS_SPENDER_NOT_WHITELISTED; } else { return detectTransferRestriction(from, to, value); } } - function transferred(address from, address to, uint256 value) public view { + function transferred(address from, address to, uint256 value) public { uint8 code = detectTransferRestriction(from, to, value); require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleWhitelist_InvalidTransfer(from, to, value, code)); } - function transferred(address spender, address from, address to, uint256 value) public view { + function transferred(address spender, address from, address to, uint256 value) public { uint8 code = detectTransferRestrictionFrom(spender, from, to, value); require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleWhitelist_InvalidTransfer(from, to, value, code)); } diff --git a/src/modules/ERC3643ComplianceExtendedModule.sol b/src/modules/ERC3643ComplianceExtendedModule.sol index 5830a3f..5f7b3c4 100644 --- a/src/modules/ERC3643ComplianceExtendedModule.sol +++ b/src/modules/ERC3643ComplianceExtendedModule.sol @@ -12,7 +12,12 @@ abstract contract ERC3643ComplianceExtendedModule is ERC3643ComplianceModule, IE mapping(address token => bool approved) private _tokenSelfBindingApproval; - /// @inheritdoc IERC3643ComplianceExtended + /** + * @inheritdoc IERC3643ComplianceExtended + * @custom:security-note See {bindToken} for multi-tenant accounting risks. All tokens bound + * in this batch share the same rule state. Only bind tokens that are equally trusted and + * governed together. + */ function bindTokens(address[] calldata tokens) public virtual override onlyComplianceManager { for (uint256 i = 0; i < tokens.length; ++i) { _bindToken(tokens[i]); diff --git a/src/modules/ERC3643ComplianceModule.sol b/src/modules/ERC3643ComplianceModule.sol index 1fcad48..f0bb51d 100644 --- a/src/modules/ERC3643ComplianceModule.sol +++ b/src/modules/ERC3643ComplianceModule.sol @@ -7,23 +7,18 @@ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet import {Context} from "@openzeppelin/contracts/utils/Context.sol"; /* ==== Interface and other library === */ import {IERC3643Compliance} from "../interfaces/IERC3643Compliance.sol"; +import {ERC3643ComplianceModuleInvariantStorage} from "./library/ERC3643ComplianceModuleInvariantStorage.sol"; -abstract contract ERC3643ComplianceModule is Context, IERC3643Compliance { +abstract contract ERC3643ComplianceModule is + Context, + IERC3643Compliance, + ERC3643ComplianceModuleInvariantStorage +{ /* ==== Type declaration === */ using EnumerableSet for EnumerableSet.AddressSet; /* ==== State Variables === */ // Token binding tracking EnumerableSet.AddressSet internal _boundTokens; - // Access Control - // Will not be present in the final bytecode if not used - bytes32 public constant COMPLIANCE_MANAGER_ROLE = keccak256("COMPLIANCE_MANAGER_ROLE"); - - /* ==== Errors === */ - error RuleEngine_ERC3643Compliance_InvalidTokenAddress(); - error RuleEngine_ERC3643Compliance_TokenAlreadyBound(); - error RuleEngine_ERC3643Compliance_TokenNotBound(); - error RuleEngine_ERC3643Compliance_UnauthorizedCaller(); - error RuleEngine_ERC3643Compliance_OperationNotSuccessful(); /* ==== Modifier === */ modifier onlyBoundToken() { @@ -46,6 +41,10 @@ abstract contract ERC3643ComplianceModule is Context, IERC3643Compliance { * @dev Operator warning: "multi-tenant" means one RuleEngine is shared by * multiple token contracts. In that setup, bind only tokens that are equally * trusted and governed together. + * @custom:security-note Operation rules (stateful rules such as `RuleConditionalTransferLight` + * or `RuleMintAllowance`) maintain per-address accounting that is shared across all bound tokens. + * Binding tokens from different issuers to the same engine will silently cross-contaminate + * their accounting. Only bind tokens that are equally trusted and governed together. */ function bindToken(address token) public virtual override { _authorizeComplianceBindingChange(token); diff --git a/src/modules/RulesManagementModule.sol b/src/modules/RulesManagementModule.sol index e3d6cff..8551f95 100644 --- a/src/modules/RulesManagementModule.sol +++ b/src/modules/RulesManagementModule.sol @@ -44,6 +44,8 @@ abstract contract RulesManagementModule is RulesManagementModuleInvariantStorage * Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. * To transition from one non-empty set to another without an enforcement gap, * call this function directly with the new set. + * Emits {ClearRules} when the existing rule set is non-empty, then emits {AddRule} + * for each new rule. Off-chain indexers must handle both events to reconstruct state. * Security convention: rule contracts should be treated as trusted business logic, * but should not also be granted {RULES_MANAGEMENT_ROLE}. */ diff --git a/src/modules/VersionModule.sol b/src/modules/VersionModule.sol index 8e5b5ef..8b57d1b 100644 --- a/src/modules/VersionModule.sol +++ b/src/modules/VersionModule.sol @@ -11,7 +11,7 @@ abstract contract VersionModule is IERC3643Version { * @dev * Get the current version of the smart contract */ - string private constant VERSION = "3.0.0"; + string internal constant VERSION = "3.0.0"; /* ============ Events ============ */ /*////////////////////////////////////////////////////////////// diff --git a/src/modules/library/ERC3643ComplianceModuleInvariantStorage.sol b/src/modules/library/ERC3643ComplianceModuleInvariantStorage.sol new file mode 100644 index 0000000..c32a06b --- /dev/null +++ b/src/modules/library/ERC3643ComplianceModuleInvariantStorage.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +abstract contract ERC3643ComplianceModuleInvariantStorage { + /* ==== Errors === */ + error RuleEngine_ERC3643Compliance_InvalidTokenAddress(); + error RuleEngine_ERC3643Compliance_TokenAlreadyBound(); + error RuleEngine_ERC3643Compliance_TokenNotBound(); + error RuleEngine_ERC3643Compliance_UnauthorizedCaller(); + error RuleEngine_ERC3643Compliance_OperationNotSuccessful(); +} diff --git a/src/modules/library/ERC3643ComplianceRolesStorage.sol b/src/modules/library/ERC3643ComplianceRolesStorage.sol new file mode 100644 index 0000000..b7d007a --- /dev/null +++ b/src/modules/library/ERC3643ComplianceRolesStorage.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +abstract contract ERC3643ComplianceRolesStorage { + /* ==== Role === */ + bytes32 public constant COMPLIANCE_MANAGER_ROLE = keccak256("COMPLIANCE_MANAGER_ROLE"); +} diff --git a/src/modules/library/RulesManagementModuleInvariantStorage.sol b/src/modules/library/RulesManagementModuleInvariantStorage.sol index 50ae472..1bada7a 100644 --- a/src/modules/library/RulesManagementModuleInvariantStorage.sol +++ b/src/modules/library/RulesManagementModuleInvariantStorage.sol @@ -41,8 +41,4 @@ abstract contract RulesManagementModuleInvariantStorage { */ event SetMaxRules(uint256 maxRules); - /* ==== Constant === */ - /// @notice Role to manage the ruleEngine - // Will not be present in the final bytecode if not used - bytes32 public constant RULES_MANAGEMENT_ROLE = keccak256("RULES_MANAGEMENT_ROLE"); } diff --git a/src/modules/library/RulesManagementModuleRolesStorage.sol b/src/modules/library/RulesManagementModuleRolesStorage.sol new file mode 100644 index 0000000..f26ca5f --- /dev/null +++ b/src/modules/library/RulesManagementModuleRolesStorage.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +abstract contract RulesManagementModuleRolesStorage { + /* ==== Role === */ + bytes32 public constant RULES_MANAGEMENT_ROLE = keccak256("RULES_MANAGEMENT_ROLE"); +} diff --git a/test/HelperContract.sol b/test/HelperContract.sol index 11aaa6a..7f68e27 100644 --- a/test/HelperContract.sol +++ b/test/HelperContract.sol @@ -3,16 +3,17 @@ pragma solidity ^0.8.20; // forge-lint: disable-next-line(unused-import) import {Test} from "forge-std/Test.sol"; -import {CMTATStandalone} from "CMTAT/deployment/CMTATStandalone.sol"; +import {CMTATStandardStandalone} from "CMTAT/deployment/CMTATStandardStandalone.sol"; import {RuleEngineInvariantStorage} from "src/modules/library/RuleEngineInvariantStorage.sol"; import {RulesManagementModuleInvariantStorage} from "src/modules/library/RulesManagementModuleInvariantStorage.sol"; +import {RulesManagementModuleRolesStorage} from "src/modules/library/RulesManagementModuleRolesStorage.sol"; // RuleEngine import {RuleEngine} from "src/deployment/RuleEngine.sol"; // forge-lint: disable-next-line(unused-import) import {RulesManagementModule} from "src/RuleEngineBase.sol"; // forge-lint: disable-next-line(unused-import) -import {ERC3643ComplianceModule} from "src/modules/ERC3643ComplianceModule.sol"; +import {ERC3643ComplianceModuleInvariantStorage} from "src/modules/library/ERC3643ComplianceModuleInvariantStorage.sol"; // RuleConditionalTransfer import {RuleConditionalTransferLight} from "src/mocks/rules/operation/RuleConditionalTransferLight.sol"; import { @@ -42,7 +43,8 @@ abstract contract HelperContract is RuleAddressListInvariantStorage, RuleEngineInvariantStorage, RuleConditionalTransferLightInvariantStorage, - RulesManagementModuleInvariantStorage + RulesManagementModuleInvariantStorage, + RulesManagementModuleRolesStorage { // Test result uint256 internal resUint256; @@ -72,7 +74,7 @@ abstract contract HelperContract is // CMTAT CMTATDeployment cmtatDeployment; - CMTATStandalone cmtatContract; + CMTATStandardStandalone cmtatContract; // RuleEngine Mock RuleEngine public ruleEngineMock; diff --git a/test/HelperContractOwnable.sol b/test/HelperContractOwnable.sol index 13f0885..cad8d6a 100644 --- a/test/HelperContractOwnable.sol +++ b/test/HelperContractOwnable.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.20; // forge-lint: disable-next-line(unused-import) import {Test} from "forge-std/Test.sol"; -import {CMTATStandalone} from "CMTAT/deployment/CMTATStandalone.sol"; +import {CMTATStandardStandalone} from "CMTAT/deployment/CMTATStandardStandalone.sol"; import {RuleEngineInvariantStorage} from "src/modules/library/RuleEngineInvariantStorage.sol"; import {RulesManagementModuleInvariantStorage} from "src/modules/library/RulesManagementModuleInvariantStorage.sol"; @@ -12,7 +12,7 @@ import {RuleEngineOwnable} from "src/deployment/RuleEngineOwnable.sol"; // forge-lint: disable-next-line(unused-import) import {RulesManagementModule} from "src/RuleEngineBase.sol"; // forge-lint: disable-next-line(unused-import) -import {ERC3643ComplianceModule} from "src/modules/ERC3643ComplianceModule.sol"; +import {ERC3643ComplianceModuleInvariantStorage} from "src/modules/library/ERC3643ComplianceModuleInvariantStorage.sol"; // RuleConditionalTransfer import {RuleConditionalTransferLight} from "src/mocks/rules/operation/RuleConditionalTransferLight.sol"; import { @@ -69,7 +69,7 @@ abstract contract HelperContractOwnable is // CMTAT CMTATDeployment cmtatDeployment; - CMTATStandalone cmtatContract; + CMTATStandardStandalone cmtatContract; // RuleEngineOwnable Mock RuleEngineOwnable public ruleEngineMock; diff --git a/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol b/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol index 2521e97..9664f9f 100644 --- a/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol +++ b/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol @@ -91,7 +91,7 @@ contract RuleEngineTest is Test, HelperContract { function testCannotAttackerOperateOnTransfer() public { // Act vm.prank(ATTACKER); - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); ruleEngineMock.transferred(address(0), ADDRESS1, ADDRESS2, 10); } diff --git a/test/RuleEngine/ERC3643Compliance.t.sol b/test/RuleEngine/ERC3643Compliance.t.sol index e41712c..5a53655 100644 --- a/test/RuleEngine/ERC3643Compliance.t.sol +++ b/test/RuleEngine/ERC3643Compliance.t.sol @@ -6,7 +6,7 @@ import {Vm} from "forge-std/Vm.sol"; // forge-lint: disable-next-line(unaliased-plain-import) import "../HelperContract.sol"; import {IERC3643Compliance} from "../../src/interfaces/IERC3643Compliance.sol"; -import {ERC3643ComplianceModule} from "../../src/modules/ERC3643ComplianceModule.sol"; +import {ERC3643ComplianceModuleInvariantStorage} from "../../src/modules/library/ERC3643ComplianceModuleInvariantStorage.sol"; // Minimal mock ERC-3643 token to simulate calls to RuleEngine contract ERC3643MockToken { @@ -166,13 +166,13 @@ contract RuleEngineTest is Test, HelperContract { } function testCannotBoundIfInvalidAddress() public { - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); vm.prank(admin); ruleEngine.bindToken(address(ZERO_ADDRESS)); } function testCannotUnBoundIfTokenIsNotBound() public { - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenNotBound.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_TokenNotBound.selector); vm.prank(admin); ruleEngine.unbindToken(address(0x100)); } @@ -183,7 +183,7 @@ contract RuleEngineTest is Test, HelperContract { ruleEngine.bindToken(address(0x1)); // Assert - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenAlreadyBound.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_TokenAlreadyBound.selector); vm.prank(admin); ruleEngine.bindToken(address(0x1)); } @@ -278,7 +278,7 @@ contract RuleEngineTest is Test, HelperContract { } function testCannotSetTokenSelfBindingApprovalForZeroAddress() public { - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); vm.prank(operator); ruleEngine.setTokenSelfBindingApproval(address(0), true); } @@ -329,7 +329,7 @@ contract RuleEngineTest is Test, HelperContract { tokens[0] = address(token1); tokens[1] = address(0); - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); vm.prank(operator); ruleEngine.setTokenSelfBindingApprovalBatch(tokens, true); } @@ -398,7 +398,7 @@ contract RuleEngineTest is Test, HelperContract { tokens[0] = address(token1); tokens[1] = address(0); - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); vm.prank(operator); ruleEngine.bindTokens(tokens); } @@ -411,7 +411,7 @@ contract RuleEngineTest is Test, HelperContract { vm.prank(operator); ruleEngine.bindToken(address(token1)); - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenAlreadyBound.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_TokenAlreadyBound.selector); vm.prank(operator); ruleEngine.bindTokens(tokens); } @@ -424,23 +424,23 @@ contract RuleEngineTest is Test, HelperContract { vm.prank(operator); ruleEngine.bindToken(address(token1)); - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenNotBound.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_TokenNotBound.selector); vm.prank(operator); ruleEngine.unbindTokens(tokens); } function testCannotCreatedIfNotBound() public { - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); ruleEngine.created(user1, 100); } function testCannotDestroyedIfNotBound() public { - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); ruleEngine.destroyed(user2, 50); } function testCannotTransferredIfNotBound() public { - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); ruleEngine.transferred(user1, user2, 200); } diff --git a/test/RuleEngine/RulesManagementModuleTest/CMTATIntegration.t.sol b/test/RuleEngine/RulesManagementModuleTest/CMTATIntegration.t.sol index b6ed69e..19d7829 100644 --- a/test/RuleEngine/RulesManagementModuleTest/CMTATIntegration.t.sol +++ b/test/RuleEngine/RulesManagementModuleTest/CMTATIntegration.t.sol @@ -8,7 +8,7 @@ import "./CMTATIntegrationBase.sol"; * @title General functions of the RuleEngine (v3.2.0-rc2) */ contract RuleEngineCMTATIntegrationTest is RuleEngineCMTATIntegrationBase { - function _deployCmtat() internal override returns (CMTATStandalone) { + function _deployCmtat() internal override returns (CMTATStandardStandalone) { cmtatDeployment = new CMTATDeployment(); return cmtatDeployment.cmtat(); } diff --git a/test/RuleEngine/RulesManagementModuleTest/CMTATIntegrationBase.sol b/test/RuleEngine/RulesManagementModuleTest/CMTATIntegrationBase.sol index 072da8c..26fb0cf 100644 --- a/test/RuleEngine/RulesManagementModuleTest/CMTATIntegrationBase.sol +++ b/test/RuleEngine/RulesManagementModuleTest/CMTATIntegrationBase.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; -import {CMTATStandalone} from "CMTAT/deployment/CMTATStandalone.sol"; +import {CMTATStandardStandalone} from "CMTAT/deployment/CMTATStandardStandalone.sol"; // forge-lint: disable-next-line(unaliased-plain-import) import "../../HelperContract.sol"; @@ -12,7 +12,7 @@ import "../../HelperContract.sol"; abstract contract RuleEngineCMTATIntegrationBase is Test, HelperContract { uint256 defaultValue = 20; - function _deployCmtat() internal virtual returns (CMTATStandalone); + function _deployCmtat() internal virtual returns (CMTATStandardStandalone); // Arrange function setUp() public virtual { diff --git a/test/RuleEngine/RulesManagementModuleTest/CMTATIntegrationV3.t.sol b/test/RuleEngine/RulesManagementModuleTest/CMTATIntegrationV3.t.sol index 3739693..f8933a5 100644 --- a/test/RuleEngine/RulesManagementModuleTest/CMTATIntegrationV3.t.sol +++ b/test/RuleEngine/RulesManagementModuleTest/CMTATIntegrationV3.t.sol @@ -9,8 +9,8 @@ import {CMTATDeploymentV3} from "../../utils/CMTATDeploymentV3.sol"; * @title General functions of the RuleEngine (v3.0.0) */ contract RuleEngineCMTATIntegrationV3Test is RuleEngineCMTATIntegrationBase { - function _deployCmtat() internal override returns (CMTATStandalone) { + function _deployCmtat() internal override returns (CMTATStandardStandalone) { CMTATDeploymentV3 v3deploy = new CMTATDeploymentV3(); - return CMTATStandalone(address(v3deploy.cmtat())); + return CMTATStandardStandalone(address(v3deploy.cmtat())); } } diff --git a/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevert.t.sol b/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevert.t.sol index cbf2bcc..92938a4 100644 --- a/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevert.t.sol +++ b/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevert.t.sol @@ -8,7 +8,7 @@ import "./RuleEngineOperationRevertBase.sol"; * @title General functions of the RuleEngine (v3.2.0-rc2) */ contract RuleEngineOperationTestRevert is RuleEngineOperationRevertBase { - function _deployCmtat() internal override returns (CMTATStandalone) { + function _deployCmtat() internal override returns (CMTATStandardStandalone) { cmtatDeployment = new CMTATDeployment(); return cmtatDeployment.cmtat(); } diff --git a/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevertBase.sol b/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevertBase.sol index d63de8a..87d1019 100644 --- a/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevertBase.sol +++ b/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevertBase.sol @@ -11,7 +11,7 @@ import {RuleOperationRevert} from "src/mocks/rules/operation/RuleOperationRevert * @title Base test for RuleEngine operation revert with CMTAT */ abstract contract RuleEngineOperationRevertBase is Test, HelperContract { - function _deployCmtat() internal virtual returns (CMTATStandalone); + function _deployCmtat() internal virtual returns (CMTATStandardStandalone); // Arrange function setUp() public virtual { diff --git a/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevertV3.t.sol b/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevertV3.t.sol index 47cd941..854d746 100644 --- a/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevertV3.t.sol +++ b/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevertV3.t.sol @@ -9,8 +9,8 @@ import {CMTATDeploymentV3} from "../../utils/CMTATDeploymentV3.sol"; * @title General functions of the RuleEngine (v3.0.0) */ contract RuleEngineOperationTestRevertV3 is RuleEngineOperationRevertBase { - function _deployCmtat() internal override returns (CMTATStandalone) { + function _deployCmtat() internal override returns (CMTATStandardStandalone) { CMTATDeploymentV3 v3deploy = new CMTATDeploymentV3(); - return CMTATStandalone(address(v3deploy.cmtat())); + return CMTATStandardStandalone(address(v3deploy.cmtat())); } } diff --git a/test/RuleEngineOwnable/ERC3643Compliance.t.sol b/test/RuleEngineOwnable/ERC3643Compliance.t.sol index 757b2c0..54acd8c 100644 --- a/test/RuleEngineOwnable/ERC3643Compliance.t.sol +++ b/test/RuleEngineOwnable/ERC3643Compliance.t.sol @@ -7,7 +7,7 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; // forge-lint: disable-next-line(unaliased-plain-import) import "../HelperContractOwnable.sol"; import {IERC3643Compliance} from "../../src/interfaces/IERC3643Compliance.sol"; -import {ERC3643ComplianceModule} from "../../src/modules/ERC3643ComplianceModule.sol"; +import {ERC3643ComplianceModuleInvariantStorage} from "../../src/modules/library/ERC3643ComplianceModuleInvariantStorage.sol"; // Minimal mock ERC-3643 token to simulate calls to RuleEngine contract ERC3643MockTokenOwnable { @@ -135,13 +135,13 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { } function testCannotBoundIfInvalidAddress() public { - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.bindToken(address(ZERO_ADDRESS)); } function testCannotUnBoundIfTokenIsNotBound() public { - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenNotBound.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_TokenNotBound.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.unbindToken(address(0x100)); } @@ -152,7 +152,7 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { ruleEngineMock.bindToken(address(0x1)); // Assert - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenAlreadyBound.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_TokenAlreadyBound.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.bindToken(address(0x1)); } @@ -217,7 +217,7 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { } function testCannotSetTokenSelfBindingApprovalForZeroAddress() public { - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.setTokenSelfBindingApproval(address(0), true); } @@ -262,7 +262,7 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { tokens[0] = address(token1); tokens[1] = address(0); - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.setTokenSelfBindingApprovalBatch(tokens, true); } @@ -319,7 +319,7 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { tokens[0] = address(token1); tokens[1] = address(0); - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.bindTokens(tokens); } @@ -332,7 +332,7 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { vm.prank(OWNER_ADDRESS); ruleEngineMock.bindToken(address(token1)); - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenAlreadyBound.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_TokenAlreadyBound.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.bindTokens(tokens); } @@ -345,23 +345,23 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { vm.prank(OWNER_ADDRESS); ruleEngineMock.bindToken(address(token1)); - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenNotBound.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_TokenNotBound.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.unbindTokens(tokens); } function testCannotCreatedIfNotBound() public { - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); ruleEngineMock.created(user1, 100); } function testCannotDestroyedIfNotBound() public { - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); ruleEngineMock.destroyed(user2, 50); } function testCannotTransferredIfNotBound() public { - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); ruleEngineMock.transferred(user1, user2, 200); } } diff --git a/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol b/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol index d5ba966..e425051 100644 --- a/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol +++ b/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol @@ -18,7 +18,7 @@ import {ComplianceInterfaceId} from "src/modules/library/ComplianceInterfaceId.s import {ERC1404InterfaceId} from "src/modules/library/ERC1404InterfaceId.sol"; import {OwnableInterfaceId} from "src/modules/library/OwnableInterfaceId.sol"; import {Ownable2StepInterfaceId} from "src/modules/library/Ownable2StepInterfaceId.sol"; -import {ERC3643ComplianceModule} from "src/modules/ERC3643ComplianceModule.sol"; +import {ERC3643ComplianceModuleInvariantStorage} from "src/modules/library/ERC3643ComplianceModuleInvariantStorage.sol"; import {RulesManagementModuleInvariantStorage} from "src/modules/library/RulesManagementModuleInvariantStorage.sol"; import {RuleEngineOwnable2StepExposed} from "src/mocks/RuleEngineExposed.sol"; // forge-lint: disable-next-line(unaliased-plain-import) @@ -225,7 +225,7 @@ contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { } function testCannotSetTokenSelfBindingApprovalForZeroAddress() public { - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.setTokenSelfBindingApproval(address(0), true); } @@ -270,7 +270,7 @@ contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { tokens[0] = TOKEN_1; tokens[1] = address(0); - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.setTokenSelfBindingApprovalBatch(tokens, true); } @@ -327,7 +327,7 @@ contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { tokens[0] = TOKEN_1; tokens[1] = address(0); - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.bindTokens(tokens); } @@ -340,7 +340,7 @@ contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { vm.prank(OWNER_ADDRESS); ruleEngineMock.bindToken(TOKEN_1); - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenAlreadyBound.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_TokenAlreadyBound.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.bindTokens(tokens); } @@ -353,7 +353,7 @@ contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { vm.prank(OWNER_ADDRESS); ruleEngineMock.bindToken(TOKEN_1); - vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenNotBound.selector); + vm.expectRevert(ERC3643ComplianceModuleInvariantStorage.RuleEngine_ERC3643Compliance_TokenNotBound.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.unbindTokens(tokens); } diff --git a/test/RuleWhitelist/CMTATIntegration.t.sol b/test/RuleWhitelist/CMTATIntegration.t.sol index 929a797..a44441c 100644 --- a/test/RuleWhitelist/CMTATIntegration.t.sol +++ b/test/RuleWhitelist/CMTATIntegration.t.sol @@ -8,7 +8,7 @@ import "./CMTATIntegrationBase.sol"; * @title Integration test with the CMTAT (v3.2.0-rc2) */ contract CMTATIntegration is CMTATIntegrationBase { - function _deployCmtat() internal override returns (CMTATStandalone) { + function _deployCmtat() internal override returns (CMTATStandardStandalone) { cmtatDeployment = new CMTATDeployment(); return cmtatDeployment.cmtat(); } diff --git a/test/RuleWhitelist/CMTATIntegrationBase.sol b/test/RuleWhitelist/CMTATIntegrationBase.sol index 3ad50cb..e3658b3 100644 --- a/test/RuleWhitelist/CMTATIntegrationBase.sol +++ b/test/RuleWhitelist/CMTATIntegrationBase.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; -import {CMTATStandalone} from "CMTAT/deployment/CMTATStandalone.sol"; +import {CMTATStandardStandalone} from "CMTAT/deployment/CMTATStandardStandalone.sol"; // forge-lint: disable-next-line(unaliased-plain-import) import "../HelperContract.sol"; @@ -16,7 +16,7 @@ abstract contract CMTATIntegrationBase is Test, HelperContract { uint256 flag = 5; - function _deployCmtat() internal virtual returns (CMTATStandalone); + function _deployCmtat() internal virtual returns (CMTATStandardStandalone); // Arrange function setUp() public virtual { diff --git a/test/RuleWhitelist/CMTATIntegrationV3.t.sol b/test/RuleWhitelist/CMTATIntegrationV3.t.sol index 37cfa2a..1f52dd3 100644 --- a/test/RuleWhitelist/CMTATIntegrationV3.t.sol +++ b/test/RuleWhitelist/CMTATIntegrationV3.t.sol @@ -9,8 +9,8 @@ import {CMTATDeploymentV3} from "../utils/CMTATDeploymentV3.sol"; * @title Integration test with the CMTAT (v3.0.0) */ contract CMTATIntegrationV3 is CMTATIntegrationBase { - function _deployCmtat() internal override returns (CMTATStandalone) { + function _deployCmtat() internal override returns (CMTATStandardStandalone) { CMTATDeploymentV3 v3deploy = new CMTATDeploymentV3(); - return CMTATStandalone(address(v3deploy.cmtat())); + return CMTATStandardStandalone(address(v3deploy.cmtat())); } } diff --git a/test/script/RuleEngineScript.t.sol b/test/script/RuleEngineScript.t.sol index 96999fd..1c9d423 100644 --- a/test/script/RuleEngineScript.t.sol +++ b/test/script/RuleEngineScript.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; import {CMTATDeployment} from "../utils/CMTATDeployment.sol"; -import {CMTATStandalone} from "CMTAT/deployment/CMTATStandalone.sol"; +import {CMTATStandardStandalone} from "CMTAT/deployment/CMTATStandardStandalone.sol"; import {RuleEngineScript} from "../../script/RuleEngineScript.s.sol"; /** @@ -17,7 +17,7 @@ contract RuleEngineScriptTest is Test { // Deploy a CMTAT first (admin is address(1) by default in CMTATDeployment) CMTATDeployment cmtatDeployment = new CMTATDeployment(); - CMTATStandalone cmtat = cmtatDeployment.cmtat(); + CMTATStandardStandalone cmtat = cmtatDeployment.cmtat(); // Grant DEFAULT_ADMIN_ROLE to the deployer so setRuleEngine succeeds. // Cache the role bytes32 before pranking to avoid consuming the prank on a view call. diff --git a/test/utils/CMTATDeployment.sol b/test/utils/CMTATDeployment.sol index 4f2c379..0ce653f 100644 --- a/test/utils/CMTATDeployment.sol +++ b/test/utils/CMTATDeployment.sol @@ -1,7 +1,7 @@ //SPDX-License-Identifier: MPL-2.0 pragma solidity ^0.8.20; -import {ICMTATConstructor, CMTATStandalone} from "CMTAT/deployment/CMTATStandalone.sol"; +import {ICMTATConstructor, CMTATStandardStandalone} from "CMTAT/deployment/CMTATStandardStandalone.sol"; import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; import {IERC1643CMTAT} from "CMTAT/interfaces/tokenization/draft-IERC1643CMTAT.sol"; @@ -10,7 +10,7 @@ contract CMTATDeployment { address constant ZERO_ADDRESS = address(0); address constant DEFAULT_ADMIN_ADDRESS = address(1); - CMTATStandalone public cmtat; + CMTATStandardStandalone public cmtat; constructor() { // CMTAT @@ -25,7 +25,7 @@ contract CMTATDeployment { "CMTAT_info" ); ICMTATConstructor.Engine memory engines = ICMTATConstructor.Engine(IRuleEngine(ZERO_ADDRESS)); - cmtat = new CMTATStandalone( + cmtat = new CMTATStandardStandalone( ZERO_ADDRESS, DEFAULT_ADMIN_ADDRESS, erc20Attributes, extraInformationAttributes, engines ); }