From fa41137c667f700b5bc44721b3f55f288823052e Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Wed, 6 May 2026 13:30:09 +0200 Subject: [PATCH 01/11] feat(compliance): gate ERC-3643 token self-bind/unbind with explicit approval and add batch self-binding approvals with tests/docs --- CHANGELOG.md | 26 +- README.md | 35 ++ doc/ERCSpecification/erc-3643.md | 414 ++++++++++++++++++ src/interfaces/IERC3643Compliance.sol | 30 ++ src/modules/ERC3643ComplianceModule.sol | 47 +- test/RuleEngine/ERC3643Compliance.t.sol | 157 ++++++- .../RuleEngineOwnable/ERC3643Compliance.t.sol | 73 ++- .../RuleEngineOwnable2Step.t.sol | 72 ++- 8 files changed, 832 insertions(+), 22 deletions(-) create mode 100644 doc/ERCSpecification/erc-3643.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 142f30e..45ca87a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,7 +54,9 @@ forge lint - Enforce on-chain privilege-separation for rule accounts: - `RuleEngine.grantRole` now reverts for any role when `account` is currently in the rules set. - `RuleEngineOwnable` and `RuleEngineOwnable2Step` now reject `transferOwnership` targets that are currently in the rules set. -- Add T-REX compatibility path for compliance binding operations: `bindToken(token)` / `unbindToken(token)` now allow token self-calls (`msg.sender == token`) in addition to manager/owner authorization. +- Add T-REX compatibility path for compliance binding operations with admission control: + - token self-calls (`msg.sender == token`) for `bindToken(token)` / `unbindToken(token)` are supported only when explicitly approved. + - unapproved token self-calls are rejected and still require manager/owner authorization. ### Added @@ -69,12 +71,19 @@ forge lint - `RuleEngine`: `DEFAULT_ADMIN_ROLE` can update cap. - `RuleEngineOwnable` and `RuleEngineOwnable2Step`: owner can update cap. - Add `RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges()` error for rule-account privilege/ownership target protection. +- Add token self-binding approval management to `IERC3643Compliance` / `ERC3643ComplianceModule`: + - `setTokenSelfBindingApproval(address token, bool approved)` + - `isTokenSelfBindingApproved(address token)` + - `TokenSelfBindingApprovalSet(address token, bool approved)` event. +- Add batch self-binding approval API: + - `setTokenSelfBindingApprovalBatch(address[] tokens, bool approved)`. ### Changed - Ownable variants now rely on OpenZeppelin `ERC165` inheritance in `RuleEngineOwnableShared` for base ERC-165 advertisement and extend it with RuleEngine + ERC-173 interface IDs. - `supportsInterface` advertisement now explicitly includes `IERC1404` in addition to `IERC1404Extend`. - `RuleEngineOwnable2Step.supportsInterface` now advertises the Ownable2Step-specific interface ID in addition to inherited RuleEngine/Ownable interfaces. +- `ERC3643ComplianceModule` authorization logic now requires explicit per-token approval for token-driven self-bind/self-unbind flows. ### Testing @@ -90,9 +99,16 @@ forge lint - Add RBAC tests ensuring roles cannot be granted to rule accounts. - Add ownable and ownable2step tests ensuring ownership cannot be transferred to rule accounts. - Add compliance-binding authorization tests across RBAC/ownable/ownable2step variants for: - - token self-bind - - token self-unbind + - approved token self-bind + - approved token self-unbind + - unapproved token self-bind/self-unbind denial - cross-token bind/unbind denial +- Add tests for self-binding approval management across RBAC/ownable/ownable2step variants: + - single approval set + - batch approval set + - zero-address rejection + - unauthorized caller rejection. +- Add ERC-3643 `setCompliance`-style migration test with a dedicated mock token to validate unbind(old) + bind(new) flow against RuleEngine self-binding approval controls. ### Documentation @@ -100,6 +116,10 @@ forge lint - data-plane = runtime compliance callbacks (`transferred`, `created`, `destroyed`) - control-plane = governance/configuration actions (`bindToken`, `unbindToken`, role grants, ownership changes, and rule management) - Document that token-privilege separation in multi-token setups is an operational recommendation (not enforced on-chain) to preserve integrator flexibility for token-driven control-plane extensions. +- Document ERC-3643 `setCompliance` compatibility details in README: + - token self-bind/self-unbind feature support + - required explicit self-binding approval + - recommended operational sequence for compliance migration. ### v3.0.0-rc2 - 2026-04-14 diff --git a/README.md b/README.md index 38d8b8a..9a4e0b2 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,41 @@ This function is defined in the extension module `ValidationModuleRuleEngine` setCompliance(address _compliance) ``` +### Making `setCompliance` work with RuleEngine + +RuleEngine supports the ERC-3643/T-REX pattern where the token contract binds and unbinds itself when `setCompliance` is called. + +In other words, a token can call: + +- `bindToken(address(this))` +- `unbindToken(address(this))` + +To keep this feature secure, self-bind/self-unbind is gated: + +- A token can call `bindToken(address(this))` and `unbindToken(address(this))` only if it was explicitly approved first. +- Approval is set by governance/compliance admin using: + - `setTokenSelfBindingApproval(address token, bool approved)` +- Approval status can be checked with: + - `isTokenSelfBindingApproved(address token)` + +This preserves compatibility with ERC-3643 tokens that do: + +```solidity +if (address(_tokenCompliance) != address(0)) { + _tokenCompliance.unbindToken(address(this)); +} +_tokenCompliance = IModularCompliance(_compliance); +_tokenCompliance.bindToken(address(this)); +``` + +while preventing arbitrary third-party contracts from self-binding. + +Recommended operational sequence: + +1. On the target RuleEngine, grant self-binding approval for the token. +2. Call token `setCompliance(newRuleEngine)`. +3. (Optional) Revoke self-binding approval after migration if no longer needed. + ## How to include it diff --git a/doc/ERCSpecification/erc-3643.md b/doc/ERCSpecification/erc-3643.md new file mode 100644 index 0000000..c4a5d3a --- /dev/null +++ b/doc/ERCSpecification/erc-3643.md @@ -0,0 +1,414 @@ +--- +eip: 3643 +title: T-REX - Token for Regulated EXchanges +description: An institutional grade security token contract that provides interfaces for the management and compliant transfer of security tokens. +author: Joachim Lebrun (@Joachim-Lebrun), Tony Malghem (@TonyMalghem), Kevin Thizy (@Nakasar), Luc Falempin (@lfalempin), Adam Boudjemaa (@Aboudjem) +discussions-to: https://ethereum-magicians.org/t/eip-3643-proposition-of-the-t-rex-token-standard-for-securities/6844 +status: Final +type: Standards Track +category: ERC +created: 2021-07-09 +requires: 20, 173 +--- + +## Abstract + +The T-REX token is an institutional grade security token standard. This standard provides a library of interfaces for the management and compliant transfer of security tokens, using an automated onchain validator system leveraging onchain identities for eligibility checks. + +The standard defines several interfaces that are described hereunder: + +- Token +- Identity Registry +- Identity Registry Storage +- Compliance +- Trusted Issuers Registry +- Claim Topics Registry + +## Motivation + +The advent of blockchain technology has brought about a new era of efficiency, accessibility, and liquidity in the world of asset transfer. This is particularly evident in the realm of cryptocurrencies, where users can transfer token ownership peer-to-peer without intermediaries. However, when it comes to tokenized securities or security tokens, the situation is more complex due to the need for compliance with securities laws. These tokens cannot be permissionless like utility tokens; they must be permissioned to track ownership and ensure that only eligible investors can hold tokens. + +The existing Ethereum protocol, while powerful and versatile, does not fully address the unique challenges posed by security tokens. There is a need for a standard that supports compliant issuance and management of permissioned tokens, suitable for representing a wide range of asset classes, including small businesses and real estate. + +The proposed [ERC-3643](./eip-3643.md) standard is motivated by this need. It aims to provide a comprehensive framework for managing the lifecycle of security tokens, from issuance to transfers between eligible investors, while enforcing compliance rules at every stage. The standard also supports additional features such as token pausing and freezing, which can be used to manage the token in response to regulatory requirements or changes in the status of the token or its holders. + +Moreover, the standard is designed to work in conjunction with an on-chain Identity system, allowing for the validation of the identities and credentials of investors through signed attestations issued by trusted claim issuers. This ensures compliance with legal and regulatory requirements for the trading of security tokens. + +In summary, the motivation behind the proposed standard is to bring the benefits of blockchain technology to the world of securities, while ensuring compliance with existing securities laws. It aims to provide a robust, flexible, and efficient framework for the issuance and management of security tokens, thereby accelerating the evolution of capital markets. + +## Specification + +The proposed standard has the following requirements: + +- **MUST** be [ERC-20](./eip-20.md) compatible. +- **MUST** be used in combination with an onchain Identity system +- **MUST** be able to apply any rule of compliance that is required by the regulator or by the token issuer (about the factors of eligibility of an identity or about the rules of the token itself) +- **MUST** have a standard interface to pre-check if a transfer is going to pass or fail before sending it to the blockchain +- **MUST** have a recovery system in case an investor loses access to his private key +- **MUST** be able to freeze tokens on the wallet of investors if needed, partially or totally +- **MUST** have the possibility to pause the token +- **MUST** be able to mint and burn tokens +- **MUST** define an Agent role and an Owner (token issuer) role +- **MUST** be able to force transfers from an Agent wallet +- **MUST** be able to issue transactions in batch (to save gas and to have all the transactions performed in the same block) + +While this standard is backwards compatible with ERC-20 and all ERC-20 functions can be called on an ERC-3643 token, the implementation of these functions differs due to the permissioned nature of ERC-3643. Each token transfer under this standard involves a compliance check to validate the transfer and the eligibility of the stakeholder’s identities. + +### Agent Role Interface + +The standard defines an Agent role, which is crucial for managing access to various functions of the smart contracts. The interface for the Agent role is as follows: + +```solidity +interface IAgentRole { + + // events + event AgentAdded(address indexed _agent); + event AgentRemoved(address indexed _agent); + + // functions + // setters + function addAgent(address _agent) external; + function removeAgent(address _agent) external; + + // getters + function isAgent(address _agent) external view returns (bool); +} + ``` + +The `IAgentRole` interface allows for the addition and removal of agents, as well as checking if an address is an agent. In this standard, it is the owner role, as defined by [ERC-173](./eip-173.md), that has the responsibility of appointing and removing agents. Any contract that fulfills the role of a Token contract or an Identity Registry within the context of this standard must be compatible with the `IAgentRole` interface. + +### Main functions + +#### Transfer + +To be able to perform a transfer on T-REX you need to fulfill several conditions : + +- The sender **MUST** hold enough free balance (total balance - frozen tokens, if any) +- The receiver **MUST** be whitelisted on the Identity Registry and verified (hold the necessary claims on his onchain Identity) +- The sender's wallet **MUST NOT** be frozen +- The receiver's wallet **MUST NOT** be frozen +- The token **MUST NOT** be paused +- The transfer **MUST** respect all the rules of compliance defined in the Compliance smart contract (canTransfer needs to return TRUE) + +Here is an example of `transfer` function implementation : + +```solidity +function transfer(address _to, uint256 _amount) public override whenNotPaused returns (bool) { + require(!_frozen[_to] && !_frozen[msg.sender], "ERC-3643: Frozen wallet"); + require(_amount <= balanceOf(msg.sender) - (_frozenTokens[msg.sender]), "ERC-3643: Insufficient Balance"); + require( _tokenIdentityRegistry.isVerified(to), "ERC-3643: Invalid identity" ); + require( _tokenCompliance.canTransfer(from, to, amount), "ERC-3643: Compliance failure" ); + _transfer(msg.sender, _to, _amount); + _tokenCompliance.transferred(msg.sender, _to, _amount); + return true; + } + ``` + +The `transferFrom` function works the same way while the `mint` function and the `forcedTransfer` function only require the receiver to be whitelisted and verified on the Identity Registry (they bypass the compliance rules). The `burn` function bypasses all checks on eligibility. + +#### isVerified + +The `isVerified` function is called from within the transfer functions `transfer`, `transferFrom`, `mint` and +`forcedTransfer` to instruct the `Identity Registry` to check if the receiver is a valid investor, i.e. if his +wallet address is in the `Identity Registry` of the token, and if the `Identity`contract linked to his wallet +contains the claims (see [Claim Holder](../assets/eip-3643/ONCHAINID/IERC735.sol)) required in the `Claim Topics Registry` and +if these claims are signed by an authorized Claim Issuer as required in the `Trusted Issuers Registry`. +If all the requirements are fulfilled, the `isVerified` function returns `TRUE`, otherwise it returns `FALSE`. An +implementation of this function can be found on the T-REX repository of Tokeny. + +#### canTransfer + +The `canTransfer` function is also called from within transfer functions. This function checks if the transfer is compliant with global compliance rules applied to the token, in opposition with `isVerified` that only checks the eligibility of an investor to hold and receive tokens, the `canTransfer` function is looking at global compliance rules, e.g. check if the transfer is compliant in the case there is a fixed maximum number of token holders to respect (can be a limited number of holders per country as well), check if the transfer respects rules setting a maximum amount of tokens per investor, ... +If all the requirements are fulfilled, the `canTransfer` function will return `TRUE` otherwise it will return +`FALSE` and the transfer will not be allowed to happen. An implementation of this function can be found on the T-REX +repository of Tokeny. + +#### Other functions + +Description of other functions of the ERC-3643 can be found in the `interfaces` folder. An implementation of the +ERC-3643 suite of smart contracts can be found on the T-REX repository of Tokeny. + +### Token interface + +ERC-3643 permissioned tokens build upon the standard ERC-20 structure, but with additional functions to ensure compliance in the transactions of the security tokens. The functions `transfer` and `transferFrom` are implemented in a conditional way, allowing them to proceed with a transfer only if the transaction is valid. The permissioned tokens are allowed to be transferred only to validated counterparties, in order to avoid tokens being held in wallets/Identity contracts of ineligible/unauthorized investors. The ERC-3643 standard also supports the recovery of security tokens in case an investor loses access to their wallet private key. A history of recovered tokens is maintained on the blockchain for transparency reasons. + +ERC-3643 tokens implement a range of additional functions to enable the owner or their appointed agents to manage supply, transfer rules, lockups, and any other requirements in the management of a security. The standard relies on ERC-173 to define contract ownership, with the owner having the responsibility of appointing agents. Any contract that fulfills the role of a Token contract within the context of this standard must be compatible with the `IAgentRole` interface. + +A detailed description of the functions can be found in the [interfaces folder](../assets/eip-3643/interfaces/IERC3643.sol). + +```solidity +interface IERC3643 is IERC20 { + + // events + event UpdatedTokenInformation(string _newName, string _newSymbol, uint8 _newDecimals, string _newVersion, address _newOnchainID); + event IdentityRegistryAdded(address indexed _identityRegistry); + event ComplianceAdded(address indexed _compliance); + event RecoverySuccess(address _lostWallet, address _newWallet, address _investorOnchainID); + event AddressFrozen(address indexed _userAddress, bool indexed _isFrozen, address indexed _owner); + event TokensFrozen(address indexed _userAddress, uint256 _amount); + event TokensUnfrozen(address indexed _userAddress, uint256 _amount); + event Paused(address _userAddress); + event Unpaused(address _userAddress); + + + // functions + // getters + function onchainID() external view returns (address); + function version() external view returns (string memory); + function identityRegistry() external view returns (IIdentityRegistry); + function compliance() external view returns (ICompliance); + function paused() external view returns (bool); + function isFrozen(address _userAddress) external view returns (bool); + function getFrozenTokens(address _userAddress) external view returns (uint256); + + // setters + function setName(string calldata _name) external; + function setSymbol(string calldata _symbol) external; + function setOnchainID(address _onchainID) external; + function pause() external; + function unpause() external; + function setAddressFrozen(address _userAddress, bool _freeze) external; + function freezePartialTokens(address _userAddress, uint256 _amount) external; + function unfreezePartialTokens(address _userAddress, uint256 _amount) external; + function setIdentityRegistry(address _identityRegistry) external; + function setCompliance(address _compliance) external; + + // transfer actions + function forcedTransfer(address _from, address _to, uint256 _amount) external returns (bool); + function mint(address _to, uint256 _amount) external; + function burn(address _userAddress, uint256 _amount) external; + function recoveryAddress(address _lostWallet, address _newWallet, address _investorOnchainID) external returns (bool); + + // batch functions + function batchTransfer(address[] calldata _toList, uint256[] calldata _amounts) external; + function batchForcedTransfer(address[] calldata _fromList, address[] calldata _toList, uint256[] calldata _amounts) external; + function batchMint(address[] calldata _toList, uint256[] calldata _amounts) external; + function batchBurn(address[] calldata _userAddresses, uint256[] calldata _amounts) external; + function batchSetAddressFrozen(address[] calldata _userAddresses, bool[] calldata _freeze) external; + function batchFreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external; + function batchUnfreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external; +} + +``` + +### Identity Registry Interface + +The Identity Registry is linked to storage that contains a dynamic whitelist of identities. It establishes the link between a wallet address, an Identity smart contract, and a country code corresponding to the investor's country of residence. This country code is set in accordance with the ISO-3166 standard. The Identity Registry also includes a function called `isVerified()`, which returns a status based on the validity of claims (as per the security token requirements) in the user’s Identity contract. + +The standard relies on ERC-173 to define contract ownership, with the owner having the responsibility of appointing agents. Any contract that fulfills the role of an Identity Registry within the context of this standard must be compatible with the `IAgentRole` interface. The Identity Registry is managed by the agent wallet(s), meaning only the agent(s) can add or remove identities in the registry. Note that the agent role on the Identity Registry is set by the owner, therefore the owner could set themselves as the agent if they want to maintain full control. There is a specific identity registry for each security token. + +A detailed description of the functions can be found in the [interfaces folder](../assets/eip-3643/interfaces/IIdentityRegistry.sol). + +Note that [`IClaimIssuer`](../assets/eip-3643/ONCHAINID/IClaimIssuer.sol) and [`IIdentity`](../assets/eip-3643/ONCHAINID/IIdentity.sol) are needed in this interface as they are required for the Identity eligibility checks. + +```solidity +interface IIdentityRegistry { + + + // events + event ClaimTopicsRegistrySet(address indexed claimTopicsRegistry); + event IdentityStorageSet(address indexed identityStorage); + event TrustedIssuersRegistrySet(address indexed trustedIssuersRegistry); + event IdentityRegistered(address indexed investorAddress, IIdentity indexed identity); + event IdentityRemoved(address indexed investorAddress, IIdentity indexed identity); + event IdentityUpdated(IIdentity indexed oldIdentity, IIdentity indexed newIdentity); + event CountryUpdated(address indexed investorAddress, uint16 indexed country); + + + // functions + // identity registry getters + function identityStorage() external view returns (IIdentityRegistryStorage); + function issuersRegistry() external view returns (ITrustedIssuersRegistry); + function topicsRegistry() external view returns (IClaimTopicsRegistry); + + //identity registry setters + function setIdentityRegistryStorage(address _identityRegistryStorage) external; + function setClaimTopicsRegistry(address _claimTopicsRegistry) external; + function setTrustedIssuersRegistry(address _trustedIssuersRegistry) external; + + // registry actions + function registerIdentity(address _userAddress, IIdentity _identity, uint16 _country) external; + function deleteIdentity(address _userAddress) external; + function updateCountry(address _userAddress, uint16 _country) external; + function updateIdentity(address _userAddress, IIdentity _identity) external; + function batchRegisterIdentity(address[] calldata _userAddresses, IIdentity[] calldata _identities, uint16[] calldata _countries) external; + + // registry consultation + function contains(address _userAddress) external view returns (bool); + function isVerified(address _userAddress) external view returns (bool); + function identity(address _userAddress) external view returns (IIdentity); + function investorCountry(address _userAddress) external view returns (uint16); +} +``` + +### Identity Registry Storage Interface + +The Identity Registry Storage stores the identity addresses of all the authorized investors in the security token(s) linked to the storage contract. These are all identities of investors who have been authorized to hold the token(s) after having gone through the appropriate KYC and eligibility checks. The Identity Registry Storage can be bound to one or several Identity Registry contract(s). The goal of the Identity Registry storage is to separate the Identity Registry functions and specifications from its storage. This way, it is possible to keep one single Identity Registry contract per token, with its own Trusted Issuers Registry and Claim Topics Registry, but with a shared whitelist of investors used by the `isVerifed()` function implemented in the Identity Registries to check the eligibility of the receiver in a transfer transaction. + +The standard relies on ERC-173 to define contract ownership, with the owner having the responsibility of appointing agents(in this case through the `bindIdentityRegistry` function). Any contract that fulfills the role of an Identity Registry Storage within the context of this standard must be compatible with the `IAgentRole` interface. The Identity Registry Storage is managed by the agent addresses (i.e. the bound Identity Registries), meaning only the agent(s) can add or remove identities in the registry. Note that the agent role on the Identity Registry Storage is set by the owner, therefore the owner could set themselves as the agent if they want to modify the storage manually. Otherwise it is the bound Identity Registries that are using the agent role to write in the Identity Registry Storage. + +A detailed description of the functions can be found in the [interfaces folder](../assets/eip-3643/interfaces/IIdentityRegistryStorage.sol). + +```solidity +interface IIdentityRegistryStorage { + + //events + event IdentityStored(address indexed investorAddress, IIdentity indexed identity); + event IdentityUnstored(address indexed investorAddress, IIdentity indexed identity); + event IdentityModified(IIdentity indexed oldIdentity, IIdentity indexed newIdentity); + event CountryModified(address indexed investorAddress, uint16 indexed country); + event IdentityRegistryBound(address indexed identityRegistry); + event IdentityRegistryUnbound(address indexed identityRegistry); + + //functions + // storage related functions + function storedIdentity(address _userAddress) external view returns (IIdentity); + function storedInvestorCountry(address _userAddress) external view returns (uint16); + function addIdentityToStorage(address _userAddress, IIdentity _identity, uint16 _country) external; + function removeIdentityFromStorage(address _userAddress) external; + function modifyStoredInvestorCountry(address _userAddress, uint16 _country) external; + function modifyStoredIdentity(address _userAddress, IIdentity _identity) external; + + // role setter + function bindIdentityRegistry(address _identityRegistry) external; + function unbindIdentityRegistry(address _identityRegistry) external; + + // getter for bound IdentityRegistry role + function linkedIdentityRegistries() external view returns (address[] memory); +} +``` + +### Compliance Interface + +The Compliance contract is used to set the rules of the offering itself and ensures these rules are respected during the whole lifecycle of the token. For example, the Compliance contract will define the maximum amount of investors per country, the maximum amount of tokens per investor, and the accepted countries for the circulation of the token (using the country code corresponding to each investor in the Identity Registry). The Compliance smart contract can be either “tailor-made”, following the legal requirements of the token issuer, or can be deployed under a generic modular form, which can then add and remove external compliance `Modules` to fit the legal requirements of the token in the same way as a custom "tailor-made" contract would. + +This contract is triggered at every transaction by the Token and returns `TRUE` if the transaction is compliant with the rules of the offering and `FALSE` otherwise. + +The standard relies on ERC-173 to define contract ownership, with the owner having the responsibility of setting the Compliance parameters and binding the Compliance to a Token contract. + +A detailed description of the functions can be found in the [interfaces folder](../assets/eip-3643/interfaces/ICompliance.sol). + +```solidity +interface ICompliance { + + // events + event TokenBound(address _token); + event TokenUnbound(address _token); + + // functions + // initialization of the compliance contract + function bindToken(address _token) external; + function unbindToken(address _token) external; + + // check the parameters of the compliance contract + function isTokenBound(address _token) external view returns (bool); + function getTokenBound() external view returns (address); + + // compliance check and state update + function canTransfer(address _from, address _to, uint256 _amount) external view returns (bool); + function transferred(address _from, address _to, uint256 _amount) external; + function created(address _to, uint256 _amount) external; + function destroyed(address _from, uint256 _amount) external; +} +``` + +### Trusted Issuer's Registry Interface + +The Trusted Issuer's Registry stores the contract addresses ([IClaimIssuer](../assets/eip-3643/ONCHAINID/IClaimIssuer.sol)) of all the trusted claim issuers for a specific security token. The Identity contract ([IIdentity](../assets/eip-3643/ONCHAINID/IIdentity.sol)) of token owners (the investors) must have claims signed by the claim issuers stored in this smart contract in order to be able to hold the token. + +The standard relies on ERC-173 to define contract ownership, with the owner having the responsibility of managing this registry as per their requirements. This includes the ability to add, remove, and update the list of Trusted Issuers. + +A detailed description of the functions can be found in the [interfaces folder](../assets/eip-3643/interfaces/ITrustedIssuersRegistry.sol). + +```solidity +interface ITrustedIssuersRegistry { + + // events + event TrustedIssuerAdded(IClaimIssuer indexed trustedIssuer, uint[] claimTopics); + event TrustedIssuerRemoved(IClaimIssuer indexed trustedIssuer); + event ClaimTopicsUpdated(IClaimIssuer indexed trustedIssuer, uint[] claimTopics); + + // functions + // setters + function addTrustedIssuer(IClaimIssuer _trustedIssuer, uint[] calldata _claimTopics) external; + function removeTrustedIssuer(IClaimIssuer _trustedIssuer) external; + function updateIssuerClaimTopics(IClaimIssuer _trustedIssuer, uint[] calldata _claimTopics) external; + + // getters + function getTrustedIssuers() external view returns (IClaimIssuer[] memory); + function isTrustedIssuer(address _issuer) external view returns(bool); + function getTrustedIssuerClaimTopics(IClaimIssuer _trustedIssuer) external view returns(uint[] memory); + function getTrustedIssuersForClaimTopic(uint256 claimTopic) external view returns (IClaimIssuer[] memory); + function hasClaimTopic(address _issuer, uint _claimTopic) external view returns(bool); +} +``` + +### Claim Topics Registry Interface + +The Claim Topics Registry stores all the trusted claim topics for the security token. The Identity contract ([IIdentity](../assets/eip-3643/ONCHAINID/IIdentity.sol)) of token owners must contain claims of the claim topics stored in this smart contract. + +The standard relies on ERC-173 to define contract ownership, with the owner having the responsibility of managing this registry as per their requirements. This includes the ability to add and remove required Claim Topics. + +A detailed description of the functions can be found in the [interfaces folder](../assets/eip-3643/interfaces/IClaimTopicsRegistry.sol). + +```solidity +interface IClaimTopicsRegistry { + + // events + event ClaimTopicAdded(uint256 indexed claimTopic); + event ClaimTopicRemoved(uint256 indexed claimTopic); + + // functions + // setters + function addClaimTopic(uint256 _claimTopic) external; + function removeClaimTopic(uint256 _claimTopic) external; + + // getter + function getClaimTopics() external view returns (uint256[] memory); +} +``` + +## Rationale + +### Transfer Restrictions + +Transfers of securities can fail for a variety of reasons. This is in direct contrast to utility tokens, which generally only require the sender to have a sufficient balance. These conditions can be related to the status of an investor’s wallet, the identity of the sender and receiver of the securities (i.e., whether they have been through a KYC process, whether they are accredited or an affiliate of the issuer) or for reasons unrelated to the specific transfer but instead set at the token level (i.e., the token contract enforces a maximum number of investors or a cap on the percentage held by any single investor). For ERC-20 tokens, the `balanceOf` and `allowance` functions provide a way to check that a transfer is likely to succeed before executing the transfer, which can be executed both on-chain and off-chain. For tokens representing securities, the T-REX standard introduces a function `canTransfer` which provides a more general-purpose way to achieve this. I.e., when the reasons for failure are related to the compliance rules of the token and a function `isVerified` which allows checking the eligibility status of the identity of the investor. Transfers can also fail if the address of the sender and/or receiver is frozen, or if the free balance of the sender (total balance - frozen tokens) is lower than the amount to transfer. Ultimately, the transfer could be blocked if the token is `paused`. + +### Identity Management + +Security and compliance of transfers are enforced through the management of on-chain identities. These include: + +- Identity contract: A unique identifier for each investor, which is used to manage their identity and claims. +- Claim: Signed attestations issued by a trusted claim issuer that confirm certain attributes or qualifications of the token holders, such as their identity, location, investor status, or KYC/AML clearance. +- Identity Storage/Registry: A storage system for all Identity contracts and their associated wallets, which is used to + verify the eligibility of investors during transfers. + +### Token Lifecycle Management + +The T-REX standard provides a comprehensive framework for managing the lifecycle of security tokens. This includes the issuance of tokens, transfers between eligible investors, and the enforcement of compliance rules at every stage of the token's lifecycle. The standard also supports additional features such as token pausing and freezing, which can be used to manage the token in response to regulatory requirements or changes in the status of the token or its holders. + +### Additional Compliance Rules + +The T-REX standard supports the implementation of additional compliance rules through modular compliance. These modules can be used to enforce a wide range of rules and restrictions, such as caps on the number of investors or the percentage of tokens held by a single investor, restrictions on transfers between certain types of investors, and more. This flexibility allows issuers to tailor the compliance rules of their tokens to their specific needs and regulatory environment. + +### Inclusion of Agent-Related Functions + +The inclusion of Agent-scoped functions within the standard interfaces is deliberate. The intent is to accommodate secure and adaptable token management practices that surpass the capabilities of EOA management. We envision scenarios where the agent role is fulfilled by automated systems or smart contracts, capable of programmatically executing operational functions like minting, burning, and freezing in response to specified criteria or regulatory triggers. For example, a smart contract might automatically burn tokens to align with redemption requests in an open-ended fund, or freeze tokens associated with wallets engaged in fraudulent activities. + +Consequently, these functions are standardized to provide a uniform interface for various automated systems interacting with different ERC-3643 tokens, allowing for standardized tooling and interfaces that work across the entire ecosystem. This approach ensures that ERC-3643 remains flexible, future-proof, and capable of supporting a wide array of operational models. + +## Backwards Compatibility + +T-REX tokens should be backwards compatible with ERC-20 and ERC-173 +and should be able to interact with a [Claim Holder contract](../assets/eip-3643/ONCHAINID/IERC735.sol) to validate +the claims linked to an [Identity contract](../assets/eip-3643/ONCHAINID/IIdentity.sol). + + +## Security Considerations + +This specification has been audited by Kapersky and Hacken, and no notable security considerations were found. +While the audits were primarily focused on the specific implementation by Tokeny, they also challenged and validated the core principles of the T-REX standard. The auditing teams approval of these principles provides assurance that the standard itself is robust and does not present any significant security concerns. + +## Copyright + +Copyright and related rights waived via [CC0](../LICENSE.md). diff --git a/src/interfaces/IERC3643Compliance.sol b/src/interfaces/IERC3643Compliance.sol index eb965de..c8f30a0 100644 --- a/src/interfaces/IERC3643Compliance.sol +++ b/src/interfaces/IERC3643Compliance.sol @@ -18,6 +18,12 @@ interface IERC3643Compliance is IERC3643ComplianceRead, IERC3643IComplianceContr * @param token The address of the token that was unbound. */ event TokenUnbound(address token); + /** + * @notice Emitted when self-binding permission is updated for a token. + * @param token The token address whose self-binding permission changed. + * @param approved True if token self-bind/unbind is allowed, false otherwise. + */ + event TokenSelfBindingApprovalSet(address token, bool approved); /* ============ Functions ============ */ /** @@ -47,6 +53,30 @@ interface IERC3643Compliance is IERC3643ComplianceRead, IERC3643IComplianceContr */ function unbindToken(address token) external; + /** + * @notice Sets whether a token is allowed to self-bind and self-unbind. + * @dev Must be restricted by implementation-specific compliance manager access control. + * @param token The token address to configure. + * @param approved Whether self-binding is approved for `token`. + */ + function setTokenSelfBindingApproval(address token, bool approved) external; + + /** + * @notice Sets self-binding approval for multiple tokens in one transaction. + * @dev Must be restricted by implementation-specific compliance manager access control. + * Reverts if any token in `tokens` is the zero address. + * @param tokens The token addresses to configure. + * @param approved Whether self-binding is approved for all provided tokens. + */ + function setTokenSelfBindingApprovalBatch(address[] calldata tokens, bool approved) external; + + /** + * @notice Returns whether a token is approved to self-bind and self-unbind. + * @param token The token address to query. + * @return approved True if self-binding is approved for `token`, false otherwise. + */ + function isTokenSelfBindingApproved(address token) external view returns (bool approved); + /** * @notice Checks whether a token is currently bound to this compliance contract. * @dev diff --git a/src/modules/ERC3643ComplianceModule.sol b/src/modules/ERC3643ComplianceModule.sol index 8a48bcc..92e1c3d 100644 --- a/src/modules/ERC3643ComplianceModule.sol +++ b/src/modules/ERC3643ComplianceModule.sol @@ -14,6 +14,7 @@ abstract contract ERC3643ComplianceModule is Context, IERC3643Compliance { /* ==== State Variables === */ // Token binding tracking EnumerableSet.AddressSet private _boundTokens; + mapping(address token => bool approved) private _tokenSelfBindingApproval; // Access Control // Will not be present in the final bytecode if not used bytes32 public constant COMPLIANCE_MANAGER_ROLE = keccak256("COMPLIANCE_MANAGER_ROLE"); @@ -46,8 +47,11 @@ 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. - * @dev T-REX compatibility: allows token self-binding when caller equals - * `token`, because TREX `Token.setCompliance` invokes `compliance.bindToken(address(this))`. + * @dev T-REX compatibility: supports token self-binding (caller equals + * `token`) when that token was explicitly approved via + * `setTokenSelfBindingApproval(token, true)`. This preserves the + * `Token.setCompliance` integration path while preventing arbitrary + * contracts from self-binding. */ function bindToken(address token) public virtual override { _authorizeComplianceBindingChange(token); @@ -59,14 +63,42 @@ abstract contract ERC3643ComplianceModule is Context, IERC3643Compliance { * @dev Operator warning: unbinding is an administrative operation and does not * erase any state already stored by external rule contracts in a previously * shared ("multi-tenant") setup. - * @dev T-REX compatibility: allows token self-unbinding when caller equals - * `token`, because TREX token contracts may call `compliance.unbindToken(address(this))`. + * @dev T-REX compatibility: supports token self-unbinding (caller equals + * `token`) when that token was explicitly approved via + * `setTokenSelfBindingApproval(token, true)`. */ function unbindToken(address token) public virtual override { _authorizeComplianceBindingChange(token); _unbindToken(token); } + /// @inheritdoc IERC3643Compliance + function setTokenSelfBindingApproval(address token, bool approved) public virtual override onlyComplianceManager { + require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); + _tokenSelfBindingApproval[token] = approved; + emit TokenSelfBindingApprovalSet(token, approved); + } + + /// @inheritdoc IERC3643Compliance + function setTokenSelfBindingApprovalBatch(address[] calldata tokens, bool approved) + public + virtual + override + onlyComplianceManager + { + for (uint256 i = 0; i < tokens.length; ++i) { + address token = tokens[i]; + require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); + _tokenSelfBindingApproval[token] = approved; + emit TokenSelfBindingApprovalSet(token, approved); + } + } + + /// @inheritdoc IERC3643Compliance + function isTokenSelfBindingApproved(address token) public view virtual override returns (bool) { + return _tokenSelfBindingApproval[token]; + } + /// @inheritdoc IERC3643Compliance function isTokenBound(address token) public view virtual override returns (bool) { return _boundTokens.contains(token); @@ -116,12 +148,13 @@ abstract contract ERC3643ComplianceModule is Context, IERC3643Compliance { /** * @dev Authorizes bind/unbind operations. - * Allows compliance manager, or token self-calls for T-REX compatibility. + * Allows compliance manager, or approved token self-calls for T-REX compatibility. */ function _authorizeComplianceBindingChange(address token) internal virtual { - if (_msgSender() != token) { - _onlyComplianceManager(); + if (_msgSender() == token && _tokenSelfBindingApproval[token]) { + return; } + _onlyComplianceManager(); } function _onlyComplianceManager() internal virtual; diff --git a/test/RuleEngine/ERC3643Compliance.t.sol b/test/RuleEngine/ERC3643Compliance.t.sol index b936a43..c63d8ab 100644 --- a/test/RuleEngine/ERC3643Compliance.t.sol +++ b/test/RuleEngine/ERC3643Compliance.t.sol @@ -28,7 +28,32 @@ contract ERC3643MockToken { } } +contract ERC3643MockTokenWithSetCompliance { + IERC3643Compliance public tokenCompliance; + address public owner; + + constructor(address owner_) { + owner = owner_; + } + + modifier onlyOwner() { + require(msg.sender == owner, "Not owner"); + _; + } + + function setCompliance(address compliance) external onlyOwner { + if (address(tokenCompliance) != address(0)) { + tokenCompliance.unbindToken(address(this)); + } + tokenCompliance = IERC3643Compliance(compliance); + tokenCompliance.bindToken(address(this)); + } +} + contract RuleEngineTest is Test, HelperContract { + bytes4 private constant ACCESS_CONTROL_UNAUTHORIZED_ACCOUNT_SELECTOR = + bytes4(keccak256("AccessControlUnauthorizedAccount(address,bytes32)")); + RuleEngine public ruleEngine; ERC3643MockToken public token1; ERC3643MockToken public token2; @@ -162,14 +187,20 @@ contract RuleEngineTest is Test, HelperContract { ruleEngine.bindToken(address(0x1)); } - function testTokenCanBindItself() public { + function testApprovedTokenCanBindItself() public { + vm.prank(operator); + ruleEngine.setTokenSelfBindingApproval(address(token1), true); + vm.prank(address(token1)); ruleEngine.bindToken(address(token1)); assertTrue(ruleEngine.isTokenBound(address(token1))); } - function testBoundTokenCanUnbindItself() public { + function testApprovedBoundTokenCanUnbindItself() public { + vm.prank(operator); + ruleEngine.setTokenSelfBindingApproval(address(token1), true); + vm.prank(address(token1)); ruleEngine.bindToken(address(token1)); @@ -179,8 +210,41 @@ contract RuleEngineTest is Test, HelperContract { assertFalse(ruleEngine.isTokenBound(address(token1))); } + function testTokenCannotBindItselfWithoutApproval() public { + vm.expectRevert( + abi.encodeWithSelector( + ACCESS_CONTROL_UNAUTHORIZED_ACCOUNT_SELECTOR, + address(token1), + ruleEngine.COMPLIANCE_MANAGER_ROLE() + ) + ); + vm.prank(address(token1)); + ruleEngine.bindToken(address(token1)); + } + + function testTokenCannotUnbindItselfWithoutApproval() public { + vm.prank(operator); + ruleEngine.bindToken(address(token1)); + + vm.expectRevert( + abi.encodeWithSelector( + ACCESS_CONTROL_UNAUTHORIZED_ACCOUNT_SELECTOR, + address(token1), + ruleEngine.COMPLIANCE_MANAGER_ROLE() + ) + ); + vm.prank(address(token1)); + ruleEngine.unbindToken(address(token1)); + } + function testTokenCannotBindAnotherToken() public { - vm.expectRevert(); + vm.expectRevert( + abi.encodeWithSelector( + ACCESS_CONTROL_UNAUTHORIZED_ACCOUNT_SELECTOR, + address(token1), + ruleEngine.COMPLIANCE_MANAGER_ROLE() + ) + ); vm.prank(address(token1)); ruleEngine.bindToken(address(token2)); } @@ -189,11 +253,72 @@ contract RuleEngineTest is Test, HelperContract { vm.prank(operator); ruleEngine.bindToken(address(token2)); - vm.expectRevert(); + vm.expectRevert( + abi.encodeWithSelector( + ACCESS_CONTROL_UNAUTHORIZED_ACCOUNT_SELECTOR, + address(token1), + ruleEngine.COMPLIANCE_MANAGER_ROLE() + ) + ); vm.prank(address(token1)); ruleEngine.unbindToken(address(token2)); } + function testOnlyComplianceManagerCanSetTokenSelfBindingApproval() public { + vm.expectRevert( + abi.encodeWithSelector( + ACCESS_CONTROL_UNAUTHORIZED_ACCOUNT_SELECTOR, + user1, + ruleEngine.COMPLIANCE_MANAGER_ROLE() + ) + ); + vm.prank(user1); + ruleEngine.setTokenSelfBindingApproval(address(token1), true); + } + + function testCannotSetTokenSelfBindingApprovalForZeroAddress() public { + vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.prank(operator); + ruleEngine.setTokenSelfBindingApproval(address(0), true); + } + + function testCanSetTokenSelfBindingApprovalBatch() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(token2); + + vm.prank(operator); + ruleEngine.setTokenSelfBindingApprovalBatch(tokens, true); + + assertTrue(ruleEngine.isTokenSelfBindingApproved(address(token1))); + assertTrue(ruleEngine.isTokenSelfBindingApproved(address(token2))); + } + + function testOnlyComplianceManagerCanSetTokenSelfBindingApprovalBatch() public { + address[] memory tokens = new address[](1); + tokens[0] = address(token1); + + vm.expectRevert( + abi.encodeWithSelector( + ACCESS_CONTROL_UNAUTHORIZED_ACCOUNT_SELECTOR, + user1, + ruleEngine.COMPLIANCE_MANAGER_ROLE() + ) + ); + vm.prank(user1); + ruleEngine.setTokenSelfBindingApprovalBatch(tokens, true); + } + + function testCannotSetTokenSelfBindingApprovalBatchWithZeroAddress() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(0); + + vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.prank(operator); + ruleEngine.setTokenSelfBindingApprovalBatch(tokens, true); + } + function testCannotCreatedIfNotBound() public { vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); ruleEngine.created(user1, 100); @@ -208,4 +333,28 @@ contract RuleEngineTest is Test, HelperContract { vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); ruleEngine.transferred(user1, user2, 200); } + + function testTokenSetComplianceCanMigrateBetweenRuleEngines() public { + RuleEngine ruleEngine2 = new RuleEngine(admin, ZERO_ADDRESS, ZERO_ADDRESS); + ERC3643MockTokenWithSetCompliance trexLikeToken = new ERC3643MockTokenWithSetCompliance(user1); + + vm.startPrank(admin); + ruleEngine2.grantRole(ruleEngine2.COMPLIANCE_MANAGER_ROLE(), operator); + vm.stopPrank(); + + vm.startPrank(operator); + ruleEngine.setTokenSelfBindingApproval(address(trexLikeToken), true); + ruleEngine2.setTokenSelfBindingApproval(address(trexLikeToken), true); + vm.stopPrank(); + + vm.prank(user1); + trexLikeToken.setCompliance(address(ruleEngine)); + assertTrue(ruleEngine.isTokenBound(address(trexLikeToken))); + assertFalse(ruleEngine2.isTokenBound(address(trexLikeToken))); + + vm.prank(user1); + trexLikeToken.setCompliance(address(ruleEngine2)); + assertFalse(ruleEngine.isTokenBound(address(trexLikeToken))); + assertTrue(ruleEngine2.isTokenBound(address(trexLikeToken))); + } } diff --git a/test/RuleEngineOwnable/ERC3643Compliance.t.sol b/test/RuleEngineOwnable/ERC3643Compliance.t.sol index 0545a49..81bb0eb 100644 --- a/test/RuleEngineOwnable/ERC3643Compliance.t.sol +++ b/test/RuleEngineOwnable/ERC3643Compliance.t.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; +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"; @@ -155,14 +156,20 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { ruleEngineMock.bindToken(address(0x1)); } - function testTokenCanBindItself() public { + function testApprovedTokenCanBindItself() public { + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApproval(address(token1), true); + vm.prank(address(token1)); ruleEngineMock.bindToken(address(token1)); assertTrue(ruleEngineMock.isTokenBound(address(token1))); } - function testBoundTokenCanUnbindItself() public { + function testApprovedBoundTokenCanUnbindItself() public { + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApproval(address(token1), true); + vm.prank(address(token1)); ruleEngineMock.bindToken(address(token1)); @@ -172,8 +179,23 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { assertFalse(ruleEngineMock.isTokenBound(address(token1))); } + function testTokenCannotBindItselfWithoutApproval() public { + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, address(token1))); + vm.prank(address(token1)); + ruleEngineMock.bindToken(address(token1)); + } + + function testTokenCannotUnbindItselfWithoutApproval() public { + vm.prank(OWNER_ADDRESS); + ruleEngineMock.bindToken(address(token1)); + + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, address(token1))); + vm.prank(address(token1)); + ruleEngineMock.unbindToken(address(token1)); + } + function testTokenCannotBindAnotherToken() public { - vm.expectRevert(); + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, address(token1))); vm.prank(address(token1)); ruleEngineMock.bindToken(address(token2)); } @@ -182,11 +204,54 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { vm.prank(OWNER_ADDRESS); ruleEngineMock.bindToken(address(token2)); - vm.expectRevert(); + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, address(token1))); vm.prank(address(token1)); ruleEngineMock.unbindToken(address(token2)); } + function testOnlyOwnerCanSetTokenSelfBindingApproval() public { + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, user1)); + vm.prank(user1); + ruleEngineMock.setTokenSelfBindingApproval(address(token1), true); + } + + function testCannotSetTokenSelfBindingApprovalForZeroAddress() public { + vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApproval(address(0), true); + } + + function testCanSetTokenSelfBindingApprovalBatch() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(token2); + + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApprovalBatch(tokens, true); + + assertTrue(ruleEngineMock.isTokenSelfBindingApproved(address(token1))); + assertTrue(ruleEngineMock.isTokenSelfBindingApproved(address(token2))); + } + + function testOnlyOwnerCanSetTokenSelfBindingApprovalBatch() public { + address[] memory tokens = new address[](1); + tokens[0] = address(token1); + + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, user1)); + vm.prank(user1); + ruleEngineMock.setTokenSelfBindingApprovalBatch(tokens, true); + } + + function testCannotSetTokenSelfBindingApprovalBatchWithZeroAddress() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(0); + + vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApprovalBatch(tokens, true); + } + function testCannotCreatedIfNotBound() public { vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); ruleEngineMock.created(user1, 100); diff --git a/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol b/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol index 6a5916f..16b5a8a 100644 --- a/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol +++ b/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol @@ -160,14 +160,20 @@ contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { ruleEngineMock.clearRules(); } - function testTokenCanBindItself() public { + function testApprovedTokenCanBindItself() public { + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApproval(TOKEN_1, true); + vm.prank(TOKEN_1); ruleEngineMock.bindToken(TOKEN_1); assertTrue(ruleEngineMock.isTokenBound(TOKEN_1)); } - function testBoundTokenCanUnbindItself() public { + function testApprovedBoundTokenCanUnbindItself() public { + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApproval(TOKEN_1, true); + vm.prank(TOKEN_1); ruleEngineMock.bindToken(TOKEN_1); @@ -177,8 +183,23 @@ contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { assertFalse(ruleEngineMock.isTokenBound(TOKEN_1)); } + function testTokenCannotBindItselfWithoutApproval() public { + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, TOKEN_1)); + vm.prank(TOKEN_1); + ruleEngineMock.bindToken(TOKEN_1); + } + + function testTokenCannotUnbindItselfWithoutApproval() public { + vm.prank(OWNER_ADDRESS); + ruleEngineMock.bindToken(TOKEN_1); + + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, TOKEN_1)); + vm.prank(TOKEN_1); + ruleEngineMock.unbindToken(TOKEN_1); + } + function testTokenCannotBindAnotherToken() public { - vm.expectRevert(); + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, TOKEN_1)); vm.prank(TOKEN_1); ruleEngineMock.bindToken(TOKEN_2); } @@ -187,11 +208,54 @@ contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { vm.prank(OWNER_ADDRESS); ruleEngineMock.bindToken(TOKEN_2); - vm.expectRevert(); + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, TOKEN_1)); vm.prank(TOKEN_1); ruleEngineMock.unbindToken(TOKEN_2); } + function testOnlyOwnerCanSetTokenSelfBindingApproval() public { + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, TOKEN_1)); + vm.prank(TOKEN_1); + ruleEngineMock.setTokenSelfBindingApproval(TOKEN_1, true); + } + + function testCannotSetTokenSelfBindingApprovalForZeroAddress() public { + vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApproval(address(0), true); + } + + function testCanSetTokenSelfBindingApprovalBatch() public { + address[] memory tokens = new address[](2); + tokens[0] = TOKEN_1; + tokens[1] = TOKEN_2; + + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApprovalBatch(tokens, true); + + assertTrue(ruleEngineMock.isTokenSelfBindingApproved(TOKEN_1)); + assertTrue(ruleEngineMock.isTokenSelfBindingApproved(TOKEN_2)); + } + + function testOnlyOwnerCanSetTokenSelfBindingApprovalBatch() public { + address[] memory tokens = new address[](1); + tokens[0] = TOKEN_1; + + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, TOKEN_1)); + vm.prank(TOKEN_1); + ruleEngineMock.setTokenSelfBindingApprovalBatch(tokens, true); + } + + function testCannotSetTokenSelfBindingApprovalBatchWithZeroAddress() public { + address[] memory tokens = new address[](2); + tokens[0] = TOKEN_1; + tokens[1] = address(0); + + vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApprovalBatch(tokens, true); + } + function testMsgDataReturnsCalldata() public view { bytes memory data = ruleEngineOwnable2StepExposed.exposedMsgData(); assertEq(data.length, 4); From 23d3d5b102c77d4e8b6baa94aa49f166652e9580 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Wed, 6 May 2026 13:31:37 +0200 Subject: [PATCH 02/11] fix(rules): restore DEFAULT_MAX_RULES constant and initialize _maxRules from it --- src/modules/RulesManagementModule.sol | 2 +- src/modules/library/RulesManagementModuleInvariantStorage.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/RulesManagementModule.sol b/src/modules/RulesManagementModule.sol index 4f56938..e3d6cff 100644 --- a/src/modules/RulesManagementModule.sol +++ b/src/modules/RulesManagementModule.sol @@ -30,7 +30,7 @@ abstract contract RulesManagementModule is RulesManagementModuleInvariantStorage /// @dev Array of rules EnumerableSet.AddressSet internal _rules; /// @dev Maximum number of rules allowed in the engine. - uint256 internal _maxRules = 10; + uint256 internal _maxRules = DEFAULT_MAX_RULES; /*////////////////////////////////////////////////////////////// PUBLIC/EXTERNAL FUNCTIONS diff --git a/src/modules/library/RulesManagementModuleInvariantStorage.sol b/src/modules/library/RulesManagementModuleInvariantStorage.sol index 377a031..50ae472 100644 --- a/src/modules/library/RulesManagementModuleInvariantStorage.sol +++ b/src/modules/library/RulesManagementModuleInvariantStorage.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.20; import {IRule} from "../../interfaces/IRule.sol"; abstract contract RulesManagementModuleInvariantStorage { - //uint256 public constant DEFAULT_MAX_RULES = 10; + uint256 public constant DEFAULT_MAX_RULES = 10; /* ==== Errors === */ error RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed(); From b0bb65dff494b780f469445cac75dcffa12e4fb7 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Wed, 6 May 2026 16:42:20 +0200 Subject: [PATCH 03/11] test(compliance): add full batch bind/unbind behavior coverage and document IERC3643ComplianceExtended interface split --- CHANGELOG.md | 3 + src/RuleEngineBase.sol | 4 +- src/interfaces/IERC3643Compliance.sol | 39 -------- src/interfaces/IERC3643ComplianceExtended.sol | 67 +++++++++++++ .../IERC3643ComplianceExtendedSubset.sol | 11 +++ src/modules/ERC3643ComplianceModule.sol | 25 ++++- src/modules/library/ComplianceInterfaceId.sol | 1 + test/RuleEngine/ERC3643Compliance.t.sol | 95 +++++++++++++++++++ test/RuleEngine/RuleEngineCoverage.t.sol | 7 ++ test/RuleEngine/RuleEngineDeployment.t.sol | 4 + .../RuleEngineOwnable/ERC3643Compliance.t.sol | 83 ++++++++++++++++ .../RuleEngineOwnableCoverage.t.sol | 7 ++ .../RuleEngineOwnableDeployment.t.sol | 4 + .../RuleEngineOwnable2Step.t.sol | 87 +++++++++++++++++ 14 files changed, 392 insertions(+), 45 deletions(-) create mode 100644 src/interfaces/IERC3643ComplianceExtended.sol create mode 100644 src/mocks/IERC3643ComplianceExtendedSubset.sol diff --git a/CHANGELOG.md b/CHANGELOG.md index 45ca87a..463c93e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,9 @@ forge lint - `supportsInterface` advertisement now explicitly includes `IERC1404` in addition to `IERC1404Extend`. - `RuleEngineOwnable2Step.supportsInterface` now advertises the Ownable2Step-specific interface ID in addition to inherited RuleEngine/Ownable interfaces. - `ERC3643ComplianceModule` authorization logic now requires explicit per-token approval for token-driven self-bind/self-unbind flows. +- Split compliance interfaces between standard and extensions: + - `IERC3643Compliance` now contains the base ERC-3643 compliance surface. + - supplementary functions are grouped in `IERC3643ComplianceExtended` and advertised through a dedicated ERC-165 extension interface ID. ### Testing diff --git a/src/RuleEngineBase.sol b/src/RuleEngineBase.sol index 4e86787..e096e2e 100644 --- a/src/RuleEngineBase.sol +++ b/src/RuleEngineBase.sol @@ -14,11 +14,12 @@ import {IERC3643ComplianceRead, IERC3643IComplianceContract} from "CMTAT/interfa import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol"; /* ==== Modules === */ -import {ERC3643ComplianceModule, IERC3643Compliance} from "./modules/ERC3643ComplianceModule.sol"; +import {ERC3643ComplianceModule} from "./modules/ERC3643ComplianceModule.sol"; import {VersionModule} from "./modules/VersionModule.sol"; import {RulesManagementModule} from "./modules/RulesManagementModule.sol"; /* ==== Interface and other library === */ +import {IERC3643Compliance} from "./interfaces/IERC3643Compliance.sol"; import {IRule} from "./interfaces/IRule.sol"; import {ComplianceInterfaceId} from "./modules/library/ComplianceInterfaceId.sol"; import {ERC1404InterfaceId} from "./modules/library/ERC1404InterfaceId.sol"; @@ -207,6 +208,7 @@ abstract contract RuleEngineBase is || interfaceId == ERC1404InterfaceId.IERC1404_INTERFACE_ID || interfaceId == ERC1404ExtendInterfaceId.ERC1404EXTEND_INTERFACE_ID || interfaceId == ComplianceInterfaceId.ERC3643_COMPLIANCE_INTERFACE_ID + || interfaceId == ComplianceInterfaceId.ERC3643_COMPLIANCE_EXTENDED_INTERFACE_ID || interfaceId == ComplianceInterfaceId.IERC7551_COMPLIANCE_INTERFACE_ID; } } diff --git a/src/interfaces/IERC3643Compliance.sol b/src/interfaces/IERC3643Compliance.sol index c8f30a0..cc7c350 100644 --- a/src/interfaces/IERC3643Compliance.sol +++ b/src/interfaces/IERC3643Compliance.sol @@ -18,12 +18,6 @@ interface IERC3643Compliance is IERC3643ComplianceRead, IERC3643IComplianceContr * @param token The address of the token that was unbound. */ event TokenUnbound(address token); - /** - * @notice Emitted when self-binding permission is updated for a token. - * @param token The token address whose self-binding permission changed. - * @param approved True if token self-bind/unbind is allowed, false otherwise. - */ - event TokenSelfBindingApprovalSet(address token, bool approved); /* ============ Functions ============ */ /** @@ -53,29 +47,6 @@ interface IERC3643Compliance is IERC3643ComplianceRead, IERC3643IComplianceContr */ function unbindToken(address token) external; - /** - * @notice Sets whether a token is allowed to self-bind and self-unbind. - * @dev Must be restricted by implementation-specific compliance manager access control. - * @param token The token address to configure. - * @param approved Whether self-binding is approved for `token`. - */ - function setTokenSelfBindingApproval(address token, bool approved) external; - - /** - * @notice Sets self-binding approval for multiple tokens in one transaction. - * @dev Must be restricted by implementation-specific compliance manager access control. - * Reverts if any token in `tokens` is the zero address. - * @param tokens The token addresses to configure. - * @param approved Whether self-binding is approved for all provided tokens. - */ - function setTokenSelfBindingApprovalBatch(address[] calldata tokens, bool approved) external; - - /** - * @notice Returns whether a token is approved to self-bind and self-unbind. - * @param token The token address to query. - * @return approved True if self-binding is approved for `token`, false otherwise. - */ - function isTokenSelfBindingApproved(address token) external view returns (bool approved); /** * @notice Checks whether a token is currently bound to this compliance contract. @@ -95,16 +66,6 @@ interface IERC3643Compliance is IERC3643ComplianceRead, IERC3643IComplianceContr */ function getTokenBound() external view returns (address token); - /** - * @notice Returns all tokens currently bound to this compliance contract. - * @dev This is a view-only function and does not modify state. - * This function is not part of the original ERC-3643 specification - * This operation will copy the entire storage to memory, which can be quite expensive. - * This is designed to mostly be used by view accessors that are queried without any gas fees. - * @return tokens An array of addresses of bound token contracts. - */ - function getTokenBounds() external view returns (address[] memory tokens); - /** * @notice Updates the compliance contract state when tokens are created (minted). * @dev Called by the token contract when new tokens are issued to an account. diff --git a/src/interfaces/IERC3643ComplianceExtended.sol b/src/interfaces/IERC3643ComplianceExtended.sol new file mode 100644 index 0000000..4275cbb --- /dev/null +++ b/src/interfaces/IERC3643ComplianceExtended.sol @@ -0,0 +1,67 @@ +//SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +import {IERC3643Compliance} from "./IERC3643Compliance.sol"; + +interface IERC3643ComplianceExtended is IERC3643Compliance { + /** + * @notice Emitted when self-binding permission is updated for a token. + * @param token The token address whose self-binding permission changed. + * @param approved True if token self-bind/unbind is allowed, false otherwise. + */ + event TokenSelfBindingApprovalSet(address token, bool approved); + + /** + * @notice Associates multiple token contracts with this compliance contract. + * @dev This function is not part of the original ERC-3643 compliance interface. + * Must be restricted by implementation-specific compliance manager access control. + * Reverts if any token is invalid or already bound. + * @param tokens The token addresses to bind. + */ + function bindTokens(address[] calldata tokens) external; + + /** + * @notice Removes the association of multiple token contracts from this compliance contract. + * @dev This function is not part of the original ERC-3643 compliance interface. + * Must be restricted by implementation-specific compliance manager access control. + * Reverts if any token is not currently bound. + * @param tokens The token addresses to unbind. + */ + function unbindTokens(address[] calldata tokens) external; + + /** + * @notice Sets whether a token is allowed to self-bind and self-unbind. + * @dev This function is not part of the original ERC-3643 compliance interface. + * Must be restricted by implementation-specific compliance manager access control. + * @param token The token address to configure. + * @param approved Whether self-binding is approved for `token`. + */ + function setTokenSelfBindingApproval(address token, bool approved) external; + + /** + * @notice Sets self-binding approval for multiple tokens in one transaction. + * @dev This function is not part of the original ERC-3643 compliance interface. + * Must be restricted by implementation-specific compliance manager access control. + * Reverts if any token in `tokens` is the zero address. + * @param tokens The token addresses to configure. + * @param approved Whether self-binding is approved for all provided tokens. + */ + function setTokenSelfBindingApprovalBatch(address[] calldata tokens, bool approved) external; + + /** + * @notice Returns whether a token is approved to self-bind and self-unbind. + * @dev This function is not part of the original ERC-3643 compliance interface. + * @param token The token address to query. + * @return approved True if self-binding is approved for `token`, false otherwise. + */ + function isTokenSelfBindingApproved(address token) external view returns (bool approved); + + /** + * @notice Returns all tokens currently bound to this compliance contract. + * @dev This function is not part of the original ERC-3643 compliance interface. + * This operation copies the entire storage set to memory and is mainly intended for off-chain reads. + * @return tokens An array of bound token addresses. + */ + function getTokenBounds() external view returns (address[] memory tokens); +} diff --git a/src/mocks/IERC3643ComplianceExtendedSubset.sol b/src/mocks/IERC3643ComplianceExtendedSubset.sol new file mode 100644 index 0000000..a211c2c --- /dev/null +++ b/src/mocks/IERC3643ComplianceExtendedSubset.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +interface IERC3643ComplianceExtendedSubset { + function bindTokens(address[] calldata tokens) external; + function unbindTokens(address[] calldata tokens) external; + function setTokenSelfBindingApproval(address token, bool approved) external; + function setTokenSelfBindingApprovalBatch(address[] calldata tokens, bool approved) external; + function isTokenSelfBindingApproved(address token) external view returns (bool approved); + function getTokenBounds() external view returns (address[] memory tokens); +} diff --git a/src/modules/ERC3643ComplianceModule.sol b/src/modules/ERC3643ComplianceModule.sol index 92e1c3d..fd0edc7 100644 --- a/src/modules/ERC3643ComplianceModule.sol +++ b/src/modules/ERC3643ComplianceModule.sol @@ -7,8 +7,9 @@ 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 {IERC3643ComplianceExtended} from "../interfaces/IERC3643ComplianceExtended.sol"; -abstract contract ERC3643ComplianceModule is Context, IERC3643Compliance { +abstract contract ERC3643ComplianceModule is Context, IERC3643ComplianceExtended { /* ==== Type declaration === */ using EnumerableSet for EnumerableSet.AddressSet; /* ==== State Variables === */ @@ -58,6 +59,13 @@ abstract contract ERC3643ComplianceModule is Context, IERC3643Compliance { _bindToken(token); } + /// @inheritdoc IERC3643ComplianceExtended + function bindTokens(address[] calldata tokens) public virtual override onlyComplianceManager { + for (uint256 i = 0; i < tokens.length; ++i) { + _bindToken(tokens[i]); + } + } + /** * @inheritdoc IERC3643Compliance * @dev Operator warning: unbinding is an administrative operation and does not @@ -72,14 +80,21 @@ abstract contract ERC3643ComplianceModule is Context, IERC3643Compliance { _unbindToken(token); } - /// @inheritdoc IERC3643Compliance + /// @inheritdoc IERC3643ComplianceExtended + function unbindTokens(address[] calldata tokens) public virtual override onlyComplianceManager { + for (uint256 i = 0; i < tokens.length; ++i) { + _unbindToken(tokens[i]); + } + } + + /// @inheritdoc IERC3643ComplianceExtended function setTokenSelfBindingApproval(address token, bool approved) public virtual override onlyComplianceManager { require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); _tokenSelfBindingApproval[token] = approved; emit TokenSelfBindingApprovalSet(token, approved); } - /// @inheritdoc IERC3643Compliance + /// @inheritdoc IERC3643ComplianceExtended function setTokenSelfBindingApprovalBatch(address[] calldata tokens, bool approved) public virtual @@ -94,7 +109,7 @@ abstract contract ERC3643ComplianceModule is Context, IERC3643Compliance { } } - /// @inheritdoc IERC3643Compliance + /// @inheritdoc IERC3643ComplianceExtended function isTokenSelfBindingApproved(address token) public view virtual override returns (bool) { return _tokenSelfBindingApproval[token]; } @@ -115,7 +130,7 @@ abstract contract ERC3643ComplianceModule is Context, IERC3643Compliance { } } - /// @inheritdoc IERC3643Compliance + /// @inheritdoc IERC3643ComplianceExtended function getTokenBounds() public view override returns (address[] memory) { return _boundTokens.values(); } diff --git a/src/modules/library/ComplianceInterfaceId.sol b/src/modules/library/ComplianceInterfaceId.sol index 1c604a8..477948a 100644 --- a/src/modules/library/ComplianceInterfaceId.sol +++ b/src/modules/library/ComplianceInterfaceId.sol @@ -8,5 +8,6 @@ pragma solidity ^0.8.20; */ library ComplianceInterfaceId { bytes4 public constant ERC3643_COMPLIANCE_INTERFACE_ID = 0x3144991c; + bytes4 public constant ERC3643_COMPLIANCE_EXTENDED_INTERFACE_ID = 0x646ba2be; bytes4 public constant IERC7551_COMPLIANCE_INTERFACE_ID = 0x7157797f; } diff --git a/test/RuleEngine/ERC3643Compliance.t.sol b/test/RuleEngine/ERC3643Compliance.t.sol index c63d8ab..92c2a71 100644 --- a/test/RuleEngine/ERC3643Compliance.t.sol +++ b/test/RuleEngine/ERC3643Compliance.t.sol @@ -319,6 +319,101 @@ contract RuleEngineTest is Test, HelperContract { ruleEngine.setTokenSelfBindingApprovalBatch(tokens, true); } + function testCanBindTokensBatch() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(token2); + + vm.prank(operator); + ruleEngine.bindTokens(tokens); + + assertTrue(ruleEngine.isTokenBound(address(token1))); + assertTrue(ruleEngine.isTokenBound(address(token2))); + } + + function testCanUnbindTokensBatch() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(token2); + + vm.startPrank(operator); + ruleEngine.bindTokens(tokens); + ruleEngine.unbindTokens(tokens); + vm.stopPrank(); + + assertFalse(ruleEngine.isTokenBound(address(token1))); + assertFalse(ruleEngine.isTokenBound(address(token2))); + } + + function testOnlyComplianceManagerCanBindTokensBatch() public { + address[] memory tokens = new address[](1); + tokens[0] = address(token1); + + vm.expectRevert( + abi.encodeWithSelector( + ACCESS_CONTROL_UNAUTHORIZED_ACCOUNT_SELECTOR, + user1, + ruleEngine.COMPLIANCE_MANAGER_ROLE() + ) + ); + vm.prank(user1); + ruleEngine.bindTokens(tokens); + } + + function testOnlyComplianceManagerCanUnbindTokensBatch() public { + address[] memory tokens = new address[](1); + tokens[0] = address(token1); + + vm.prank(operator); + ruleEngine.bindTokens(tokens); + + vm.expectRevert( + abi.encodeWithSelector( + ACCESS_CONTROL_UNAUTHORIZED_ACCOUNT_SELECTOR, + user1, + ruleEngine.COMPLIANCE_MANAGER_ROLE() + ) + ); + vm.prank(user1); + ruleEngine.unbindTokens(tokens); + } + + function testCannotBindTokensBatchWithZeroAddress() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(0); + + vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.prank(operator); + ruleEngine.bindTokens(tokens); + } + + function testCannotBindTokensBatchWithAlreadyBoundToken() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(token2); + + vm.prank(operator); + ruleEngine.bindToken(address(token1)); + + vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenAlreadyBound.selector); + vm.prank(operator); + ruleEngine.bindTokens(tokens); + } + + function testCannotUnbindTokensBatchWithTokenNotBound() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(token2); + + vm.prank(operator); + ruleEngine.bindToken(address(token1)); + + vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenNotBound.selector); + vm.prank(operator); + ruleEngine.unbindTokens(tokens); + } + function testCannotCreatedIfNotBound() public { vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); ruleEngine.created(user1, 100); diff --git a/test/RuleEngine/RuleEngineCoverage.t.sol b/test/RuleEngine/RuleEngineCoverage.t.sol index 3328f5f..373f7c5 100644 --- a/test/RuleEngine/RuleEngineCoverage.t.sol +++ b/test/RuleEngine/RuleEngineCoverage.t.sol @@ -8,8 +8,10 @@ import "../HelperContract.sol"; import {RuleEngineExposed} from "src/mocks/RuleEngineExposed.sol"; import {RuleInvalidMock} from "src/mocks/RuleInvalidMock.sol"; import {ICompliance} from "src/mocks/ICompliance.sol"; +import {IERC3643ComplianceExtendedSubset} from "src/mocks/IERC3643ComplianceExtendedSubset.sol"; import {IERC1404Subset} from "src/mocks/IERC1404Subset.sol"; import {IERC7551ComplianceSubset} from "src/mocks/IERC7551ComplianceSubset.sol"; +import {ComplianceInterfaceId} from "src/modules/library/ComplianceInterfaceId.sol"; import {ERC1404InterfaceId} from "src/modules/library/ERC1404InterfaceId.sol"; /** @@ -50,6 +52,11 @@ contract RuleEngineCoverageTest is Test, HelperContract { assertTrue(ruleEngineMock.supportsInterface(type(ICompliance).interfaceId)); } + function testSupportsERC3643ComplianceExtendedSubsetInterface() public view { + assertTrue(ruleEngineMock.supportsInterface(ComplianceInterfaceId.ERC3643_COMPLIANCE_EXTENDED_INTERFACE_ID)); + assertTrue(ruleEngineMock.supportsInterface(type(IERC3643ComplianceExtendedSubset).interfaceId)); + } + function testSupportsIERC7551ComplianceSubsetInterface() public view { assertTrue(ruleEngineMock.supportsInterface(type(IERC7551ComplianceSubset).interfaceId)); } diff --git a/test/RuleEngine/RuleEngineDeployment.t.sol b/test/RuleEngine/RuleEngineDeployment.t.sol index 14ebbe0..d380c61 100644 --- a/test/RuleEngine/RuleEngineDeployment.t.sol +++ b/test/RuleEngine/RuleEngineDeployment.t.sol @@ -11,8 +11,10 @@ import {IAccessControlEnumerable} from "@openzeppelin/contracts/access/extension import {ERC1404ExtendInterfaceId} from "CMTAT/library/ERC1404ExtendInterfaceId.sol"; import {RuleEngineInterfaceId} from "CMTAT/library/RuleEngineInterfaceId.sol"; import {ICompliance} from "src/mocks/ICompliance.sol"; +import {IERC3643ComplianceExtendedSubset} from "src/mocks/IERC3643ComplianceExtendedSubset.sol"; import {IERC7551ComplianceSubset} from "src/mocks/IERC7551ComplianceSubset.sol"; import {IERC1404Subset} from "src/mocks/IERC1404Subset.sol"; +import {ComplianceInterfaceId} from "src/modules/library/ComplianceInterfaceId.sol"; import {ERC1404InterfaceId} from "src/modules/library/ERC1404InterfaceId.sol"; /** @@ -68,6 +70,8 @@ contract RuleEngineTest is Test, HelperContract { assertTrue(ruleEngineMock.supportsInterface(type(IERC1404Subset).interfaceId)); assertTrue(ruleEngineMock.supportsInterface(ERC1404ExtendInterfaceId.ERC1404EXTEND_INTERFACE_ID)); assertTrue(ruleEngineMock.supportsInterface(type(ICompliance).interfaceId)); + assertTrue(ruleEngineMock.supportsInterface(ComplianceInterfaceId.ERC3643_COMPLIANCE_EXTENDED_INTERFACE_ID)); + assertTrue(ruleEngineMock.supportsInterface(type(IERC3643ComplianceExtendedSubset).interfaceId)); assertTrue(ruleEngineMock.supportsInterface(type(IERC7551ComplianceSubset).interfaceId)); } diff --git a/test/RuleEngineOwnable/ERC3643Compliance.t.sol b/test/RuleEngineOwnable/ERC3643Compliance.t.sol index 81bb0eb..418a0a2 100644 --- a/test/RuleEngineOwnable/ERC3643Compliance.t.sol +++ b/test/RuleEngineOwnable/ERC3643Compliance.t.sol @@ -252,6 +252,89 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { ruleEngineMock.setTokenSelfBindingApprovalBatch(tokens, true); } + function testCanBindTokensBatch() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(token2); + + vm.prank(OWNER_ADDRESS); + ruleEngineMock.bindTokens(tokens); + + assertTrue(ruleEngineMock.isTokenBound(address(token1))); + assertTrue(ruleEngineMock.isTokenBound(address(token2))); + } + + function testCanUnbindTokensBatch() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(token2); + + vm.startPrank(OWNER_ADDRESS); + ruleEngineMock.bindTokens(tokens); + ruleEngineMock.unbindTokens(tokens); + vm.stopPrank(); + + assertFalse(ruleEngineMock.isTokenBound(address(token1))); + assertFalse(ruleEngineMock.isTokenBound(address(token2))); + } + + function testOnlyOwnerCanBindTokensBatch() public { + address[] memory tokens = new address[](1); + tokens[0] = address(token1); + + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, user1)); + vm.prank(user1); + ruleEngineMock.bindTokens(tokens); + } + + function testOnlyOwnerCanUnbindTokensBatch() public { + address[] memory tokens = new address[](1); + tokens[0] = address(token1); + + vm.prank(OWNER_ADDRESS); + ruleEngineMock.bindTokens(tokens); + + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, user1)); + vm.prank(user1); + ruleEngineMock.unbindTokens(tokens); + } + + function testCannotBindTokensBatchWithZeroAddress() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(0); + + vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.bindTokens(tokens); + } + + function testCannotBindTokensBatchWithAlreadyBoundToken() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(token2); + + vm.prank(OWNER_ADDRESS); + ruleEngineMock.bindToken(address(token1)); + + vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenAlreadyBound.selector); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.bindTokens(tokens); + } + + function testCannotUnbindTokensBatchWithTokenNotBound() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(token2); + + vm.prank(OWNER_ADDRESS); + ruleEngineMock.bindToken(address(token1)); + + vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenNotBound.selector); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.unbindTokens(tokens); + } + function testCannotCreatedIfNotBound() public { vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_UnauthorizedCaller.selector); ruleEngineMock.created(user1, 100); diff --git a/test/RuleEngineOwnable/RuleEngineOwnableCoverage.t.sol b/test/RuleEngineOwnable/RuleEngineOwnableCoverage.t.sol index cf5d616..9f45d20 100644 --- a/test/RuleEngineOwnable/RuleEngineOwnableCoverage.t.sol +++ b/test/RuleEngineOwnable/RuleEngineOwnableCoverage.t.sol @@ -9,9 +9,11 @@ import {RuleEngineOwnableExposed} from "src/mocks/RuleEngineExposed.sol"; import {RuleInvalidMock} from "src/mocks/RuleInvalidMock.sol"; import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; import {ICompliance} from "src/mocks/ICompliance.sol"; +import {IERC3643ComplianceExtendedSubset} from "src/mocks/IERC3643ComplianceExtendedSubset.sol"; import {IERC173Subset} from "src/mocks/IERC173Subset.sol"; import {IERC1404Subset} from "src/mocks/IERC1404Subset.sol"; import {IERC7551ComplianceSubset} from "src/mocks/IERC7551ComplianceSubset.sol"; +import {ComplianceInterfaceId} from "src/modules/library/ComplianceInterfaceId.sol"; import {ERC1404InterfaceId} from "src/modules/library/ERC1404InterfaceId.sol"; import {OwnableInterfaceId} from "src/modules/library/OwnableInterfaceId.sol"; @@ -58,6 +60,11 @@ contract RuleEngineOwnableCoverageTest is Test, HelperContractOwnable { assertTrue(ruleEngineMock.supportsInterface(type(ICompliance).interfaceId)); } + function testSupportsERC3643ComplianceExtendedSubsetInterface() public view { + assertTrue(ruleEngineMock.supportsInterface(ComplianceInterfaceId.ERC3643_COMPLIANCE_EXTENDED_INTERFACE_ID)); + assertTrue(ruleEngineMock.supportsInterface(type(IERC3643ComplianceExtendedSubset).interfaceId)); + } + function testSupportsIERC7551ComplianceSubsetInterface() public view { assertTrue(ruleEngineMock.supportsInterface(type(IERC7551ComplianceSubset).interfaceId)); } diff --git a/test/RuleEngineOwnable/RuleEngineOwnableDeployment.t.sol b/test/RuleEngineOwnable/RuleEngineOwnableDeployment.t.sol index 3ab94c6..72d1a41 100644 --- a/test/RuleEngineOwnable/RuleEngineOwnableDeployment.t.sol +++ b/test/RuleEngineOwnable/RuleEngineOwnableDeployment.t.sol @@ -9,9 +9,11 @@ import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {ERC1404ExtendInterfaceId} from "CMTAT/library/ERC1404ExtendInterfaceId.sol"; import {RuleEngineInterfaceId} from "CMTAT/library/RuleEngineInterfaceId.sol"; import {ICompliance} from "src/mocks/ICompliance.sol"; +import {IERC3643ComplianceExtendedSubset} from "src/mocks/IERC3643ComplianceExtendedSubset.sol"; import {IERC173Subset} from "src/mocks/IERC173Subset.sol"; import {IERC1404Subset} from "src/mocks/IERC1404Subset.sol"; import {IERC7551ComplianceSubset} from "src/mocks/IERC7551ComplianceSubset.sol"; +import {ComplianceInterfaceId} from "src/modules/library/ComplianceInterfaceId.sol"; import {ERC1404InterfaceId} from "src/modules/library/ERC1404InterfaceId.sol"; import {OwnableInterfaceId} from "src/modules/library/OwnableInterfaceId.sol"; @@ -77,6 +79,8 @@ contract RuleEngineOwnableDeploymentTest is Test, HelperContractOwnable { assertTrue(ruleEngineMock.supportsInterface(RuleEngineInterfaceId.RULE_ENGINE_INTERFACE_ID)); assertTrue(ruleEngineMock.supportsInterface(ERC1404ExtendInterfaceId.ERC1404EXTEND_INTERFACE_ID)); assertTrue(ruleEngineMock.supportsInterface(type(ICompliance).interfaceId)); + assertTrue(ruleEngineMock.supportsInterface(ComplianceInterfaceId.ERC3643_COMPLIANCE_EXTENDED_INTERFACE_ID)); + assertTrue(ruleEngineMock.supportsInterface(type(IERC3643ComplianceExtendedSubset).interfaceId)); assertTrue(ruleEngineMock.supportsInterface(type(IERC7551ComplianceSubset).interfaceId)); } diff --git a/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol b/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol index 16b5a8a..4dff75c 100644 --- a/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol +++ b/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol @@ -8,10 +8,12 @@ import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {ERC1404ExtendInterfaceId} from "CMTAT/library/ERC1404ExtendInterfaceId.sol"; import {RuleEngineInterfaceId} from "CMTAT/library/RuleEngineInterfaceId.sol"; import {ICompliance} from "src/mocks/ICompliance.sol"; +import {IERC3643ComplianceExtendedSubset} from "src/mocks/IERC3643ComplianceExtendedSubset.sol"; import {IERC173Subset} from "src/mocks/IERC173Subset.sol"; import {IOwnable2StepSubset} from "src/mocks/IOwnable2StepSubset.sol"; import {IERC1404Subset} from "src/mocks/IERC1404Subset.sol"; import {IERC7551ComplianceSubset} from "src/mocks/IERC7551ComplianceSubset.sol"; +import {ComplianceInterfaceId} from "src/modules/library/ComplianceInterfaceId.sol"; import {ERC1404InterfaceId} from "src/modules/library/ERC1404InterfaceId.sol"; import {OwnableInterfaceId} from "src/modules/library/OwnableInterfaceId.sol"; import {Ownable2StepInterfaceId} from "src/modules/library/Ownable2StepInterfaceId.sol"; @@ -65,6 +67,8 @@ contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { assertTrue(ruleEngineMock.supportsInterface(RuleEngineInterfaceId.RULE_ENGINE_INTERFACE_ID)); assertTrue(ruleEngineMock.supportsInterface(ERC1404ExtendInterfaceId.ERC1404EXTEND_INTERFACE_ID)); assertTrue(ruleEngineMock.supportsInterface(type(ICompliance).interfaceId)); + assertTrue(ruleEngineMock.supportsInterface(ComplianceInterfaceId.ERC3643_COMPLIANCE_EXTENDED_INTERFACE_ID)); + assertTrue(ruleEngineMock.supportsInterface(type(IERC3643ComplianceExtendedSubset).interfaceId)); assertTrue(ruleEngineMock.supportsInterface(type(IERC7551ComplianceSubset).interfaceId)); } @@ -256,6 +260,89 @@ contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { ruleEngineMock.setTokenSelfBindingApprovalBatch(tokens, true); } + function testCanBindTokensBatch() public { + address[] memory tokens = new address[](2); + tokens[0] = TOKEN_1; + tokens[1] = TOKEN_2; + + vm.prank(OWNER_ADDRESS); + ruleEngineMock.bindTokens(tokens); + + assertTrue(ruleEngineMock.isTokenBound(TOKEN_1)); + assertTrue(ruleEngineMock.isTokenBound(TOKEN_2)); + } + + function testCanUnbindTokensBatch() public { + address[] memory tokens = new address[](2); + tokens[0] = TOKEN_1; + tokens[1] = TOKEN_2; + + vm.startPrank(OWNER_ADDRESS); + ruleEngineMock.bindTokens(tokens); + ruleEngineMock.unbindTokens(tokens); + vm.stopPrank(); + + assertFalse(ruleEngineMock.isTokenBound(TOKEN_1)); + assertFalse(ruleEngineMock.isTokenBound(TOKEN_2)); + } + + function testOnlyOwnerCanBindTokensBatch() public { + address[] memory tokens = new address[](1); + tokens[0] = TOKEN_1; + + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, TOKEN_1)); + vm.prank(TOKEN_1); + ruleEngineMock.bindTokens(tokens); + } + + function testOnlyOwnerCanUnbindTokensBatch() public { + address[] memory tokens = new address[](1); + tokens[0] = TOKEN_1; + + vm.prank(OWNER_ADDRESS); + ruleEngineMock.bindTokens(tokens); + + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, TOKEN_1)); + vm.prank(TOKEN_1); + ruleEngineMock.unbindTokens(tokens); + } + + function testCannotBindTokensBatchWithZeroAddress() public { + address[] memory tokens = new address[](2); + tokens[0] = TOKEN_1; + tokens[1] = address(0); + + vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_InvalidTokenAddress.selector); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.bindTokens(tokens); + } + + function testCannotBindTokensBatchWithAlreadyBoundToken() public { + address[] memory tokens = new address[](2); + tokens[0] = TOKEN_1; + tokens[1] = TOKEN_2; + + vm.prank(OWNER_ADDRESS); + ruleEngineMock.bindToken(TOKEN_1); + + vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenAlreadyBound.selector); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.bindTokens(tokens); + } + + function testCannotUnbindTokensBatchWithTokenNotBound() public { + address[] memory tokens = new address[](2); + tokens[0] = TOKEN_1; + tokens[1] = TOKEN_2; + + vm.prank(OWNER_ADDRESS); + ruleEngineMock.bindToken(TOKEN_1); + + vm.expectRevert(ERC3643ComplianceModule.RuleEngine_ERC3643Compliance_TokenNotBound.selector); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.unbindTokens(tokens); + } + function testMsgDataReturnsCalldata() public view { bytes memory data = ruleEngineOwnable2StepExposed.exposedMsgData(); assertEq(data.length, 4); From 7f126243a4adbe098fcfe3fa830787e2389f67d9 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Wed, 6 May 2026 16:45:21 +0200 Subject: [PATCH 04/11] chore(changelog): document batch self-binding approval event and single-emit behavior --- CHANGELOG.md | 2 ++ src/interfaces/IERC3643ComplianceExtended.sol | 6 ++++++ src/modules/ERC3643ComplianceModule.sol | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 463c93e..60b6837 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,6 +77,7 @@ forge lint - `TokenSelfBindingApprovalSet(address token, bool approved)` event. - Add batch self-binding approval API: - `setTokenSelfBindingApprovalBatch(address[] tokens, bool approved)`. + - `TokenSelfBindingApprovalBatchSet(address[] tokens, bool approved)` event. ### Changed @@ -87,6 +88,7 @@ forge lint - Split compliance interfaces between standard and extensions: - `IERC3643Compliance` now contains the base ERC-3643 compliance surface. - supplementary functions are grouped in `IERC3643ComplianceExtended` and advertised through a dedicated ERC-165 extension interface ID. +- Batch self-binding approval event emission now uses a single batch event (`TokenSelfBindingApprovalBatchSet`) per call instead of per-token `TokenSelfBindingApprovalSet` emissions. ### Testing diff --git a/src/interfaces/IERC3643ComplianceExtended.sol b/src/interfaces/IERC3643ComplianceExtended.sol index 4275cbb..ed67417 100644 --- a/src/interfaces/IERC3643ComplianceExtended.sol +++ b/src/interfaces/IERC3643ComplianceExtended.sol @@ -11,6 +11,12 @@ interface IERC3643ComplianceExtended is IERC3643Compliance { * @param approved True if token self-bind/unbind is allowed, false otherwise. */ event TokenSelfBindingApprovalSet(address token, bool approved); + /** + * @notice Emitted when self-binding permission is updated in batch. + * @param tokens The token addresses whose self-binding permission changed. + * @param approved True if token self-bind/unbind is allowed, false otherwise. + */ + event TokenSelfBindingApprovalBatchSet(address[] tokens, bool approved); /** * @notice Associates multiple token contracts with this compliance contract. diff --git a/src/modules/ERC3643ComplianceModule.sol b/src/modules/ERC3643ComplianceModule.sol index fd0edc7..6ed14a2 100644 --- a/src/modules/ERC3643ComplianceModule.sol +++ b/src/modules/ERC3643ComplianceModule.sol @@ -105,8 +105,8 @@ abstract contract ERC3643ComplianceModule is Context, IERC3643ComplianceExtended address token = tokens[i]; require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); _tokenSelfBindingApproval[token] = approved; - emit TokenSelfBindingApprovalSet(token, approved); } + emit TokenSelfBindingApprovalBatchSet(tokens, approved); } /// @inheritdoc IERC3643ComplianceExtended From 4a897c77355abff4eac2de9b4018f2d1853bfc66 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Wed, 6 May 2026 16:59:20 +0200 Subject: [PATCH 05/11] test(compliance): assert single batch event emission for setTokenSelfBindingApprovalBatch across all variants --- test/RuleEngine/ERC3643Compliance.t.sol | 15 +++++++++++++++ test/RuleEngineOwnable/ERC3643Compliance.t.sol | 15 +++++++++++++++ .../RuleEngineOwnable2Step.t.sol | 15 +++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/test/RuleEngine/ERC3643Compliance.t.sol b/test/RuleEngine/ERC3643Compliance.t.sol index 92c2a71..e41712c 100644 --- a/test/RuleEngine/ERC3643Compliance.t.sol +++ b/test/RuleEngine/ERC3643Compliance.t.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; +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"; @@ -294,6 +295,20 @@ contract RuleEngineTest is Test, HelperContract { assertTrue(ruleEngine.isTokenSelfBindingApproved(address(token2))); } + function testSetTokenSelfBindingApprovalBatchEmitsSingleBatchEvent() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(token2); + + vm.recordLogs(); + vm.prank(operator); + ruleEngine.setTokenSelfBindingApprovalBatch(tokens, true); + Vm.Log[] memory entries = vm.getRecordedLogs(); + + assertEq(entries.length, 1); + assertEq(entries[0].topics[0], keccak256("TokenSelfBindingApprovalBatchSet(address[],bool)")); + } + function testOnlyComplianceManagerCanSetTokenSelfBindingApprovalBatch() public { address[] memory tokens = new address[](1); tokens[0] = address(token1); diff --git a/test/RuleEngineOwnable/ERC3643Compliance.t.sol b/test/RuleEngineOwnable/ERC3643Compliance.t.sol index 418a0a2..757b2c0 100644 --- a/test/RuleEngineOwnable/ERC3643Compliance.t.sol +++ b/test/RuleEngineOwnable/ERC3643Compliance.t.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; +import {Vm} from "forge-std/Vm.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; // forge-lint: disable-next-line(unaliased-plain-import) import "../HelperContractOwnable.sol"; @@ -233,6 +234,20 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { assertTrue(ruleEngineMock.isTokenSelfBindingApproved(address(token2))); } + function testSetTokenSelfBindingApprovalBatchEmitsSingleBatchEvent() public { + address[] memory tokens = new address[](2); + tokens[0] = address(token1); + tokens[1] = address(token2); + + vm.recordLogs(); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApprovalBatch(tokens, true); + Vm.Log[] memory entries = vm.getRecordedLogs(); + + assertEq(entries.length, 1); + assertEq(entries[0].topics[0], keccak256("TokenSelfBindingApprovalBatchSet(address[],bool)")); + } + function testOnlyOwnerCanSetTokenSelfBindingApprovalBatch() public { address[] memory tokens = new address[](1); tokens[0] = address(token1); diff --git a/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol b/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol index 4dff75c..d5ba966 100644 --- a/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol +++ b/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; +import {Vm} from "forge-std/Vm.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {MinimalForwarderMock} from "CMTAT/mocks/MinimalForwarderMock.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; @@ -241,6 +242,20 @@ contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { assertTrue(ruleEngineMock.isTokenSelfBindingApproved(TOKEN_2)); } + function testSetTokenSelfBindingApprovalBatchEmitsSingleBatchEvent() public { + address[] memory tokens = new address[](2); + tokens[0] = TOKEN_1; + tokens[1] = TOKEN_2; + + vm.recordLogs(); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApprovalBatch(tokens, true); + Vm.Log[] memory entries = vm.getRecordedLogs(); + + assertEq(entries.length, 1); + assertEq(entries[0].topics[0], keccak256("TokenSelfBindingApprovalBatchSet(address[],bool)")); + } + function testOnlyOwnerCanSetTokenSelfBindingApprovalBatch() public { address[] memory tokens = new address[](1); tokens[0] = TOKEN_1; From d2f1d4c4b3ee12083368e94dd8f5535b445f06eb Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Wed, 6 May 2026 17:21:00 +0200 Subject: [PATCH 06/11] refactor(compliance): split ERC-3643 core/extended modules, migrate to extended interface APIs, add batch behavior/event coverage, and sync docs/changelog --- CHANGELOG.md | 7 +- README.md | 6 +- src/RuleEngineBase.sol | 4 +- .../ERC3643ComplianceExtendedModule.sol | 71 ++++++++++++++++++ src/modules/ERC3643ComplianceModule.sol | 72 +------------------ test/HelperContract.sol | 2 +- test/HelperContractOwnable.sol | 2 +- 7 files changed, 88 insertions(+), 76 deletions(-) create mode 100644 src/modules/ERC3643ComplianceExtendedModule.sol diff --git a/CHANGELOG.md b/CHANGELOG.md index 60b6837..e2833ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,11 +71,11 @@ forge lint - `RuleEngine`: `DEFAULT_ADMIN_ROLE` can update cap. - `RuleEngineOwnable` and `RuleEngineOwnable2Step`: owner can update cap. - Add `RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges()` error for rule-account privilege/ownership target protection. -- Add token self-binding approval management to `IERC3643Compliance` / `ERC3643ComplianceModule`: +- Add token self-binding approval management to `IERC3643ComplianceExtended` / `ERC3643ComplianceExtendedModule`: - `setTokenSelfBindingApproval(address token, bool approved)` - `isTokenSelfBindingApproved(address token)` - `TokenSelfBindingApprovalSet(address token, bool approved)` event. -- Add batch self-binding approval API: +- Add batch self-binding approval API in `IERC3643ComplianceExtended` / `ERC3643ComplianceExtendedModule`: - `setTokenSelfBindingApprovalBatch(address[] tokens, bool approved)`. - `TokenSelfBindingApprovalBatchSet(address[] tokens, bool approved)` event. @@ -88,6 +88,9 @@ forge lint - Split compliance interfaces between standard and extensions: - `IERC3643Compliance` now contains the base ERC-3643 compliance surface. - supplementary functions are grouped in `IERC3643ComplianceExtended` and advertised through a dedicated ERC-165 extension interface ID. +- Split compliance modules between standard and extensions: + - `ERC3643ComplianceModule` now contains the base ERC-3643 compliance surface. + - supplementary functions are grouped in `ERC3643ComplianceExtendedModule`. - Batch self-binding approval event emission now uses a single batch event (`TokenSelfBindingApprovalBatchSet`) per call instead of per-token `TokenSelfBindingApprovalSet` emissions. ### Testing diff --git a/README.md b/README.md index 9a4e0b2..f794f47 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,7 @@ Recommended operational sequence: While the RuleEngine has been designed for CMTAT and ERC-3643 tokens, it can be used with other contracts to apply transfer restrictions. For that, the only thing to do is to import in your contract the interface `IRuleEngine`(CMTAT) or `IERC3643Compliance` (ERC-3643), which declares the corresponding functions to call by the token contract. This interface can be found [here](https://github.com/CMTA/CMTAT/blob/23a1e59f913d079d0c09d32fafbd95ab2d426093/contracts/interfaces/engine/IRuleEngine.sol). +If you need non-standard helper functions (batch bind/unbind, self-binding approval APIs, multi-token getter), use `IERC3643ComplianceExtended`. ### Like CMTAT @@ -249,8 +250,11 @@ external; ### ERC-3643 The [ERC-3643](https://eips.ethereum.org/EIPS/eip-3643) compliance interface is defined in [IERC3643Compliance.sol](src/interfaces/IERC3643Compliance.sol). +Non-standard helper functions are defined in [IERC3643ComplianceExtended.sol](src/interfaces/IERC3643ComplianceExtended.sol). -A specific module implements this interface for the RuleEngine: [ERC3643ComplianceModule.sol](src/modules/ERC3643ComplianceModule.sol) +The RuleEngine modules are split as follows: +- Base ERC-3643 surface: [ERC3643ComplianceModule.sol](src/modules/ERC3643ComplianceModule.sol) +- Non-standard extensions: [ERC3643ComplianceExtendedModule.sol](src/modules/ERC3643ComplianceExtendedModule.sol) ![ERC3643ComplianceModuleUML](./doc/schema/vscode-uml/ERC3643ComplianceModuleUML.png) diff --git a/src/RuleEngineBase.sol b/src/RuleEngineBase.sol index e096e2e..08d8219 100644 --- a/src/RuleEngineBase.sol +++ b/src/RuleEngineBase.sol @@ -14,7 +14,7 @@ import {IERC3643ComplianceRead, IERC3643IComplianceContract} from "CMTAT/interfa import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol"; /* ==== Modules === */ -import {ERC3643ComplianceModule} from "./modules/ERC3643ComplianceModule.sol"; +import {ERC3643ComplianceExtendedModule} from "./modules/ERC3643ComplianceExtendedModule.sol"; import {VersionModule} from "./modules/VersionModule.sol"; import {RulesManagementModule} from "./modules/RulesManagementModule.sol"; @@ -32,7 +32,7 @@ import {RuleInterfaceId} from "./modules/library/RuleInterfaceId.sol"; abstract contract RuleEngineBase is VersionModule, RulesManagementModule, - ERC3643ComplianceModule, + ERC3643ComplianceExtendedModule, RuleEngineInvariantStorage, IRuleEngineERC1404 { diff --git a/src/modules/ERC3643ComplianceExtendedModule.sol b/src/modules/ERC3643ComplianceExtendedModule.sol new file mode 100644 index 0000000..5830a3f --- /dev/null +++ b/src/modules/ERC3643ComplianceExtendedModule.sol @@ -0,0 +1,71 @@ +//SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.20; + +import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +/* ==== Interface and other library === */ +import {IERC3643ComplianceExtended} from "../interfaces/IERC3643ComplianceExtended.sol"; +import {ERC3643ComplianceModule} from "./ERC3643ComplianceModule.sol"; + +abstract contract ERC3643ComplianceExtendedModule is ERC3643ComplianceModule, IERC3643ComplianceExtended { + using EnumerableSet for EnumerableSet.AddressSet; + + mapping(address token => bool approved) private _tokenSelfBindingApproval; + + /// @inheritdoc IERC3643ComplianceExtended + function bindTokens(address[] calldata tokens) public virtual override onlyComplianceManager { + for (uint256 i = 0; i < tokens.length; ++i) { + _bindToken(tokens[i]); + } + } + + /// @inheritdoc IERC3643ComplianceExtended + function unbindTokens(address[] calldata tokens) public virtual override onlyComplianceManager { + for (uint256 i = 0; i < tokens.length; ++i) { + _unbindToken(tokens[i]); + } + } + + /// @inheritdoc IERC3643ComplianceExtended + function setTokenSelfBindingApproval(address token, bool approved) public virtual override onlyComplianceManager { + require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); + _tokenSelfBindingApproval[token] = approved; + emit TokenSelfBindingApprovalSet(token, approved); + } + + /// @inheritdoc IERC3643ComplianceExtended + function setTokenSelfBindingApprovalBatch(address[] calldata tokens, bool approved) + public + virtual + override + onlyComplianceManager + { + for (uint256 i = 0; i < tokens.length; ++i) { + address token = tokens[i]; + require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); + _tokenSelfBindingApproval[token] = approved; + } + emit TokenSelfBindingApprovalBatchSet(tokens, approved); + } + + /// @inheritdoc IERC3643ComplianceExtended + function isTokenSelfBindingApproved(address token) public view virtual override returns (bool) { + return _tokenSelfBindingApproval[token]; + } + + /// @inheritdoc IERC3643ComplianceExtended + function getTokenBounds() public view virtual override returns (address[] memory) { + return _boundTokens.values(); + } + + /** + * @dev Authorizes bind/unbind operations. + * Allows compliance manager, or approved token self-calls for T-REX compatibility. + */ + function _authorizeComplianceBindingChange(address token) internal virtual override { + if (_msgSender() == token && _tokenSelfBindingApproval[token]) { + return; + } + _onlyComplianceManager(); + } +} diff --git a/src/modules/ERC3643ComplianceModule.sol b/src/modules/ERC3643ComplianceModule.sol index 6ed14a2..1fcad48 100644 --- a/src/modules/ERC3643ComplianceModule.sol +++ b/src/modules/ERC3643ComplianceModule.sol @@ -7,15 +7,13 @@ 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 {IERC3643ComplianceExtended} from "../interfaces/IERC3643ComplianceExtended.sol"; -abstract contract ERC3643ComplianceModule is Context, IERC3643ComplianceExtended { +abstract contract ERC3643ComplianceModule is Context, IERC3643Compliance { /* ==== Type declaration === */ using EnumerableSet for EnumerableSet.AddressSet; /* ==== State Variables === */ // Token binding tracking - EnumerableSet.AddressSet private _boundTokens; - mapping(address token => bool approved) private _tokenSelfBindingApproval; + 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"); @@ -48,72 +46,23 @@ abstract contract ERC3643ComplianceModule is Context, IERC3643ComplianceExtended * @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. - * @dev T-REX compatibility: supports token self-binding (caller equals - * `token`) when that token was explicitly approved via - * `setTokenSelfBindingApproval(token, true)`. This preserves the - * `Token.setCompliance` integration path while preventing arbitrary - * contracts from self-binding. */ function bindToken(address token) public virtual override { _authorizeComplianceBindingChange(token); _bindToken(token); } - /// @inheritdoc IERC3643ComplianceExtended - function bindTokens(address[] calldata tokens) public virtual override onlyComplianceManager { - for (uint256 i = 0; i < tokens.length; ++i) { - _bindToken(tokens[i]); - } - } - /** * @inheritdoc IERC3643Compliance * @dev Operator warning: unbinding is an administrative operation and does not * erase any state already stored by external rule contracts in a previously * shared ("multi-tenant") setup. - * @dev T-REX compatibility: supports token self-unbinding (caller equals - * `token`) when that token was explicitly approved via - * `setTokenSelfBindingApproval(token, true)`. */ function unbindToken(address token) public virtual override { _authorizeComplianceBindingChange(token); _unbindToken(token); } - /// @inheritdoc IERC3643ComplianceExtended - function unbindTokens(address[] calldata tokens) public virtual override onlyComplianceManager { - for (uint256 i = 0; i < tokens.length; ++i) { - _unbindToken(tokens[i]); - } - } - - /// @inheritdoc IERC3643ComplianceExtended - function setTokenSelfBindingApproval(address token, bool approved) public virtual override onlyComplianceManager { - require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); - _tokenSelfBindingApproval[token] = approved; - emit TokenSelfBindingApprovalSet(token, approved); - } - - /// @inheritdoc IERC3643ComplianceExtended - function setTokenSelfBindingApprovalBatch(address[] calldata tokens, bool approved) - public - virtual - override - onlyComplianceManager - { - for (uint256 i = 0; i < tokens.length; ++i) { - address token = tokens[i]; - require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); - _tokenSelfBindingApproval[token] = approved; - } - emit TokenSelfBindingApprovalBatchSet(tokens, approved); - } - - /// @inheritdoc IERC3643ComplianceExtended - function isTokenSelfBindingApproved(address token) public view virtual override returns (bool) { - return _tokenSelfBindingApproval[token]; - } - /// @inheritdoc IERC3643Compliance function isTokenBound(address token) public view virtual override returns (bool) { return _boundTokens.contains(token); @@ -130,11 +79,6 @@ abstract contract ERC3643ComplianceModule is Context, IERC3643ComplianceExtended } } - /// @inheritdoc IERC3643ComplianceExtended - function getTokenBounds() public view override returns (address[] memory) { - return _boundTokens.values(); - } - /*////////////////////////////////////////////////////////////// INTERNAL/PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////*/ @@ -161,16 +105,6 @@ abstract contract ERC3643ComplianceModule is Context, IERC3643ComplianceExtended } } - /** - * @dev Authorizes bind/unbind operations. - * Allows compliance manager, or approved token self-calls for T-REX compatibility. - */ - function _authorizeComplianceBindingChange(address token) internal virtual { - if (_msgSender() == token && _tokenSelfBindingApproval[token]) { - return; - } - _onlyComplianceManager(); - } - + function _authorizeComplianceBindingChange(address token) internal virtual; function _onlyComplianceManager() internal virtual; } diff --git a/test/HelperContract.sol b/test/HelperContract.sol index ef59d3d..11aaa6a 100644 --- a/test/HelperContract.sol +++ b/test/HelperContract.sol @@ -12,7 +12,7 @@ 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/RuleEngineBase.sol"; +import {ERC3643ComplianceModule} from "src/modules/ERC3643ComplianceModule.sol"; // RuleConditionalTransfer import {RuleConditionalTransferLight} from "src/mocks/rules/operation/RuleConditionalTransferLight.sol"; import { diff --git a/test/HelperContractOwnable.sol b/test/HelperContractOwnable.sol index 08c9357..13f0885 100644 --- a/test/HelperContractOwnable.sol +++ b/test/HelperContractOwnable.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/RuleEngineBase.sol"; +import {ERC3643ComplianceModule} from "src/modules/ERC3643ComplianceModule.sol"; // RuleConditionalTransfer import {RuleConditionalTransferLight} from "src/mocks/rules/operation/RuleConditionalTransferLight.sol"; import { From 5bc20ed040c30f9fdd1e10f24b3aeab1cdc313e6 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Thu, 7 May 2026 08:55:00 +0200 Subject: [PATCH 07/11] Update audit tool report and code coverage --- doc/coverage/code-coverage.png | Bin 172036 -> 169179 bytes doc/coverage/coverage/index-sort-b.html | 40 +- doc/coverage/coverage/index-sort-f.html | 40 +- doc/coverage/coverage/index-sort-l.html | 40 +- doc/coverage/coverage/index.html | 40 +- .../src/RuleEngineBase.sol.func-sort-c.html | 36 +- .../coverage/src/RuleEngineBase.sol.func.html | 36 +- .../coverage/src/RuleEngineBase.sol.gcov.html | 392 +++++++-------- ...leEngineOwnableShared.sol.func-sort-c.html | 10 +- .../src/RuleEngineOwnableShared.sol.func.html | 10 +- .../src/RuleEngineOwnableShared.sol.gcov.html | 18 +- .../RuleEngine.sol.func-sort-c.html | 20 +- .../src/deployment/RuleEngine.sol.func.html | 16 +- .../src/deployment/RuleEngine.sol.gcov.html | 38 +- .../RuleEngineOwnable.sol.func-sort-c.html | 8 +- .../RuleEngineOwnable.sol.func.html | 8 +- .../RuleEngineOwnable.sol.gcov.html | 12 +- ...uleEngineOwnable2Step.sol.func-sort-c.html | 38 +- .../RuleEngineOwnable2Step.sol.func.html | 34 +- .../RuleEngineOwnable2Step.sol.gcov.html | 109 +++-- .../coverage/src/deployment/index-sort-b.html | 14 +- .../coverage/src/deployment/index-sort-f.html | 14 +- .../coverage/src/deployment/index-sort-l.html | 14 +- .../coverage/src/deployment/index.html | 14 +- doc/coverage/coverage/src/index-sort-b.html | 8 +- doc/coverage/coverage/src/index-sort-f.html | 8 +- doc/coverage/coverage/src/index-sort-l.html | 8 +- doc/coverage/coverage/src/index.html | 8 +- ...plianceExtendedModule.sol.func-sort-c.html | 109 +++++ ...3643ComplianceExtendedModule.sol.func.html | 109 +++++ ...3643ComplianceExtendedModule.sol.gcov.html | 156 ++++++ ...C3643ComplianceModule.sol.func-sort-c.html | 56 +-- .../ERC3643ComplianceModule.sol.func.html | 56 +-- .../ERC3643ComplianceModule.sol.gcov.html | 162 +++--- ...RulesManagementModule.sol.func-sort-c.html | 2 +- .../RulesManagementModule.sol.func.html | 2 +- .../RulesManagementModule.sol.gcov.html | 4 +- .../VersionModule.sol.func-sort-c.html | 2 +- .../src/modules/VersionModule.sol.func.html | 2 +- .../src/modules/VersionModule.sol.gcov.html | 2 +- .../coverage/src/modules/index-sort-b.html | 46 +- .../coverage/src/modules/index-sort-f.html | 46 +- .../coverage/src/modules/index-sort-l.html | 46 +- doc/coverage/coverage/src/modules/index.html | 46 +- doc/coverage/lcov.info | 461 ++++++++++-------- doc/security/audits/tools/aderyn-report.md | 111 ++++- .../audits/tools/slither-report-feedback.md | 16 +- doc/security/audits/tools/slither-report.md | 70 ++- 48 files changed, 1524 insertions(+), 1013 deletions(-) create mode 100644 doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.func-sort-c.html create mode 100644 doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.func.html create mode 100644 doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.gcov.html diff --git a/doc/coverage/code-coverage.png b/doc/coverage/code-coverage.png index 84075e289221a72e08cd026a42c430554dac0193..b395bbe375f13ba0692cb62f0ac6557582e9afc8 100644 GIT binary patch literal 169179 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
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ERC3643ComplianceExtendedModule.getTokenBounds4
ERC3643ComplianceExtendedModule.isTokenSelfBindingApproved6
ERC3643ComplianceExtendedModule.unbindTokens9
ERC3643ComplianceExtendedModule.setTokenSelfBindingApprovalBatch12
ERC3643ComplianceExtendedModule.setTokenSelfBindingApproval14
ERC3643ComplianceExtendedModule.bindTokens18
ERC3643ComplianceExtendedModule._authorizeComplianceBindingChange72
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.func.html b/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.func.html new file mode 100644 index 0000000..51b35e9 --- /dev/null +++ b/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.func.html @@ -0,0 +1,109 @@ + + + + + + + LCOV - lcov.info - src/modules/ERC3643ComplianceExtendedModule.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/modules - ERC3643ComplianceExtendedModule.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2424100.0 %
Date:2026-05-06 17:22:22Functions:77100.0 %
Branches:55100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ERC3643ComplianceExtendedModule._authorizeComplianceBindingChange72
ERC3643ComplianceExtendedModule.bindTokens18
ERC3643ComplianceExtendedModule.getTokenBounds4
ERC3643ComplianceExtendedModule.isTokenSelfBindingApproved6
ERC3643ComplianceExtendedModule.setTokenSelfBindingApproval14
ERC3643ComplianceExtendedModule.setTokenSelfBindingApprovalBatch12
ERC3643ComplianceExtendedModule.unbindTokens9
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.gcov.html b/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.gcov.html new file mode 100644 index 0000000..b228f55 --- /dev/null +++ b/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.gcov.html @@ -0,0 +1,156 @@ + + + + + + + LCOV - lcov.info - src/modules/ERC3643ComplianceExtendedModule.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/modules - ERC3643ComplianceExtendedModule.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2424100.0 %
Date:2026-05-06 17:22:22Functions:77100.0 %
Branches:55100.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : //SPDX-License-Identifier: MPL-2.0
+       2                 :            : 
+       3                 :            : pragma solidity ^0.8.20;
+       4                 :            : 
+       5                 :            : import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
+       6                 :            : /* ==== Interface and other library === */
+       7                 :            : import {IERC3643ComplianceExtended} from "../interfaces/IERC3643ComplianceExtended.sol";
+       8                 :            : import {ERC3643ComplianceModule} from "./ERC3643ComplianceModule.sol";
+       9                 :            : 
+      10                 :            : abstract contract ERC3643ComplianceExtendedModule is ERC3643ComplianceModule, IERC3643ComplianceExtended {
+      11                 :            :     using EnumerableSet for EnumerableSet.AddressSet;
+      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];
+      54                 :            :     }
+      55                 :            : 
+      56                 :            :     /// @inheritdoc IERC3643ComplianceExtended
+      57                 :          4 :     function getTokenBounds() public view virtual override returns (address[] memory) {
+      58                 :          4 :         return _boundTokens.values();
+      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                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + 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 61a292e..aef8ae7 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 @@ -31,27 +31,27 @@ lcov.info Lines: - 31 - 34 - 91.2 % + 28 + 30 + 93.3 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 10 - 12 - 83.3 % + 9 + 11 + 81.8 % Branches: - 12 - 14 - 85.7 % + 11 + 13 + 84.6 % @@ -69,19 +69,15 @@ Hit count Sort by hit count - ERC3643ComplianceModule._onlyComplianceManager + ERC3643ComplianceModule._authorizeComplianceBindingChange 0 - ERC3643ComplianceModule.onlyComplianceManager + ERC3643ComplianceModule._onlyComplianceManager 0 - ERC3643ComplianceModule.getTokenBounds - 4 - - - ERC3643ComplianceModule.getTokenBound + ERC3643ComplianceModule.getTokenBound 5 @@ -89,32 +85,32 @@ 5 - ERC3643ComplianceModule._unbindToken - 12 + ERC3643ComplianceModule.onlyComplianceManager + 9 - ERC3643ComplianceModule.unbindToken - 16 + ERC3643ComplianceModule.unbindToken + 20 - ERC3643ComplianceModule.isTokenBound - 21 + ERC3643ComplianceModule._unbindToken + 25 - ERC3643ComplianceModule._checkBoundToken + ERC3643ComplianceModule._checkBoundToken 31 - ERC3643ComplianceModule.bindToken - 38 + ERC3643ComplianceModule.isTokenBound + 37 - ERC3643ComplianceModule._authorizeComplianceBindingChange - 54 + ERC3643ComplianceModule.bindToken + 52 - ERC3643ComplianceModule._bindToken - 66 + 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 f5ade38..dff97aa 100644 --- a/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func.html +++ b/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.func.html @@ -31,27 +31,27 @@ lcov.info Lines: - 31 - 34 - 91.2 % + 28 + 30 + 93.3 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 10 - 12 - 83.3 % + 9 + 11 + 81.8 % Branches: - 12 - 14 - 85.7 % + 11 + 13 + 84.6 % @@ -69,40 +69,36 @@ Hit count Sort by hit count - ERC3643ComplianceModule._authorizeComplianceBindingChange - 54 + ERC3643ComplianceModule._authorizeComplianceBindingChange + 0 - ERC3643ComplianceModule._bindToken - 66 + ERC3643ComplianceModule._bindToken + 101 - ERC3643ComplianceModule._checkBoundToken + ERC3643ComplianceModule._checkBoundToken 31 - ERC3643ComplianceModule._onlyComplianceManager + ERC3643ComplianceModule._onlyComplianceManager 0 - ERC3643ComplianceModule._unbindToken - 12 + ERC3643ComplianceModule._unbindToken + 25 - ERC3643ComplianceModule.bindToken - 38 + ERC3643ComplianceModule.bindToken + 52 - ERC3643ComplianceModule.getTokenBound + ERC3643ComplianceModule.getTokenBound 5 - ERC3643ComplianceModule.getTokenBounds - 4 - - - ERC3643ComplianceModule.isTokenBound - 21 + ERC3643ComplianceModule.isTokenBound + 37 ERC3643ComplianceModule.onlyBoundToken @@ -110,11 +106,11 @@ ERC3643ComplianceModule.onlyComplianceManager - 0 + 9 - ERC3643ComplianceModule.unbindToken - 16 + 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 232a450..a1c95ac 100644 --- a/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.gcov.html +++ b/doc/coverage/coverage/src/modules/ERC3643ComplianceModule.sol.gcov.html @@ -31,27 +31,27 @@ lcov.info Lines: - 31 - 34 - 91.2 % + 28 + 30 + 93.3 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 10 - 12 - 83.3 % + 9 + 11 + 81.8 % Branches: - 12 - 14 - 85.7 % + 11 + 13 + 84.6 % @@ -84,7 +84,7 @@ 13 : : using EnumerableSet for EnumerableSet.AddressSet; 14 : : /* ==== State Variables === */ 15 : : // Token binding tracking - 16 : : EnumerableSet.AddressSet private _boundTokens; + 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"); @@ -102,8 +102,8 @@ 31 : : _; 32 : : } 33 : : - 34 : 0 : modifier onlyComplianceManager() { - 35 : 0 : _onlyComplianceManager(); + 34 : 9 : modifier onlyComplianceManager() { + 35 : 9 : _onlyComplianceManager(); 36 : : _; 37 : : } 38 : : @@ -117,86 +117,68 @@ 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 : : * @dev T-REX compatibility: allows token self-binding when caller equals - 50 : : * `token`, because TREX `Token.setCompliance` invokes `compliance.bindToken(address(this))`. - 51 : : */ - 52 : 38 : function bindToken(address token) public virtual override { - 53 : 38 : _authorizeComplianceBindingChange(token); - 54 : 34 : _bindToken(token); - 55 : : } - 56 : : - 57 : : /** - 58 : : * @inheritdoc IERC3643Compliance - 59 : : * @dev Operator warning: unbinding is an administrative operation and does not - 60 : : * erase any state already stored by external rule contracts in a previously - 61 : : * shared ("multi-tenant") setup. - 62 : : * @dev T-REX compatibility: allows token self-unbinding when caller equals - 63 : : * `token`, because TREX token contracts may call `compliance.unbindToken(address(this))`. - 64 : : */ - 65 : 16 : function unbindToken(address token) public virtual override { - 66 : 16 : _authorizeComplianceBindingChange(token); - 67 : 12 : _unbindToken(token); - 68 : : } - 69 : : - 70 : : /// @inheritdoc IERC3643Compliance - 71 : 21 : function isTokenBound(address token) public view virtual override returns (bool) { - 72 : 21 : return _boundTokens.contains(token); - 73 : : } - 74 : : - 75 : : /// @inheritdoc IERC3643Compliance - 76 : 5 : function getTokenBound() public view virtual override returns (address) { - 77 [ + + ]: 5 : if (_boundTokens.length() > 0) { - 78 : : // Note that there are no guarantees on the ordering of values inside the array, - 79 : : // and it may change when more values are added or removed. - 80 : 3 : return _boundTokens.at(0); - 81 : : } else { - 82 : 2 : return address(0); - 83 : : } - 84 : : } + 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 : : /// @inheritdoc IERC3643Compliance - 87 : 4 : function getTokenBounds() public view override returns (address[] memory) { - 88 : 4 : return _boundTokens.values(); - 89 : : } + 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 : : /*////////////////////////////////////////////////////////////// - 92 : : INTERNAL/PRIVATE FUNCTIONS - 93 : : //////////////////////////////////////////////////////////////*/ - 94 : : - 95 : 12 : function _unbindToken(address token) internal { - 96 [ + + ]: 12 : require(_boundTokens.contains(token), RuleEngine_ERC3643Compliance_TokenNotBound()); + 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 [ # + ]: 10 : require(_boundTokens.remove(token), RuleEngine_ERC3643Compliance_OperationNotSuccessful()); - 99 : : - 100 : 10 : emit TokenUnbound(token); - 101 : : } - 102 : : - 103 : 66 : function _bindToken(address token) internal { - 104 [ + + ]: 66 : require(token != address(0), RuleEngine_ERC3643Compliance_InvalidTokenAddress()); - 105 [ + + ]: 64 : require(!_boundTokens.contains(token), RuleEngine_ERC3643Compliance_TokenAlreadyBound()); - 106 : : // Should never revert because we check if the token address is already set before - 107 [ # + ]: 62 : require(_boundTokens.add(token), RuleEngine_ERC3643Compliance_OperationNotSuccessful()); - 108 : 62 : emit TokenBound(token); - 109 : : } - 110 : : - 111 : 31 : function _checkBoundToken() internal view virtual { - 112 [ + ]: 31 : if (!_boundTokens.contains(_msgSender())) { - 113 : 7 : revert RuleEngine_ERC3643Compliance_UnauthorizedCaller(); - 114 : : } - 115 : : } - 116 : : - 117 : : /** - 118 : : * @dev Authorizes bind/unbind operations. - 119 : : * Allows compliance manager, or token self-calls for T-REX compatibility. - 120 : : */ - 121 : 54 : function _authorizeComplianceBindingChange(address token) internal virtual { - 122 [ + ]: 54 : if (_msgSender() != token) { - 123 : 43 : _onlyComplianceManager(); - 124 : : } - 125 : : } - 126 : : - 127 : 0 : function _onlyComplianceManager() internal virtual; - 128 : : } + 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 : : } 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 e3c9a39..47a830f 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-05 13:03:55 + 2026-05-06 17:22:22 Functions: 17 diff --git a/doc/coverage/coverage/src/modules/RulesManagementModule.sol.func.html b/doc/coverage/coverage/src/modules/RulesManagementModule.sol.func.html index f303599..89854ca 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-05 13:03:55 + 2026-05-06 17:22:22 Functions: 17 diff --git a/doc/coverage/coverage/src/modules/RulesManagementModule.sol.gcov.html b/doc/coverage/coverage/src/modules/RulesManagementModule.sol.gcov.html index afffd64..ade1adf 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-05 13:03:55 + 2026-05-06 17:22:22 Functions: 17 @@ -101,7 +101,7 @@ 30 : : /// @dev Array of rules 31 : : EnumerableSet.AddressSet internal _rules; 32 : : /// @dev Maximum number of rules allowed in the engine. - 33 : : uint256 internal _maxRules = 10; + 33 : : uint256 internal _maxRules = DEFAULT_MAX_RULES; 34 : : 35 : : /*////////////////////////////////////////////////////////////// 36 : : PUBLIC/EXTERNAL FUNCTIONS 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 a850218..3527b2b 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-05 13:03:55 + 2026-05-06 17:22:22 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 47875c2..4c659b9 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-05 13:03:55 + 2026-05-06 17:22:22 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 348fd4f..4929d2f 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-05 13:03:55 + 2026-05-06 17:22:22 Functions: 1 diff --git a/doc/coverage/coverage/src/modules/index-sort-b.html b/doc/coverage/coverage/src/modules/index-sort-b.html index fa15856..d6915d3 100644 --- a/doc/coverage/coverage/src/modules/index-sort-b.html +++ b/doc/coverage/coverage/src/modules/index-sort-b.html @@ -31,27 +31,27 @@ lcov.info Lines: - 95 - 100 - 95.0 % + 116 + 120 + 96.7 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 28 - 32 - 87.5 % + 34 + 38 + 89.5 % Branches: - 26 - 31 - 83.9 % + 30 + 35 + 85.7 % @@ -96,14 +96,14 @@ ERC3643ComplianceModule.sol -
91.2%91.2%
+
93.3%93.3%
- 91.2 % - 31 / 34 - 83.3 % - 10 / 12 - 85.7 % - 12 / 14 + 93.3 % + 28 / 30 + 81.8 % + 9 / 11 + 84.6 % + 11 / 13 VersionModule.sol @@ -117,6 +117,18 @@ - 0 / 0 + + ERC3643ComplianceExtendedModule.sol + +
100.0%
+ + 100.0 % + 24 / 24 + 100.0 % + 7 / 7 + 100.0 % + 5 / 5 +
diff --git a/doc/coverage/coverage/src/modules/index-sort-f.html b/doc/coverage/coverage/src/modules/index-sort-f.html index a2c384a..1125c04 100644 --- a/doc/coverage/coverage/src/modules/index-sort-f.html +++ b/doc/coverage/coverage/src/modules/index-sort-f.html @@ -31,27 +31,27 @@ lcov.info Lines: - 95 - 100 - 95.0 % + 116 + 120 + 96.7 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 28 - 32 - 87.5 % + 34 + 38 + 89.5 % Branches: - 26 - 31 - 83.9 % + 30 + 35 + 85.7 % @@ -84,14 +84,14 @@ ERC3643ComplianceModule.sol -
91.2%91.2%
+
93.3%93.3%
- 91.2 % - 31 / 34 - 83.3 % - 10 / 12 - 85.7 % - 12 / 14 + 93.3 % + 28 / 30 + 81.8 % + 9 / 11 + 84.6 % + 11 / 13 RulesManagementModule.sol @@ -117,6 +117,18 @@ - 0 / 0 + + ERC3643ComplianceExtendedModule.sol + +
100.0%
+ + 100.0 % + 24 / 24 + 100.0 % + 7 / 7 + 100.0 % + 5 / 5 +
diff --git a/doc/coverage/coverage/src/modules/index-sort-l.html b/doc/coverage/coverage/src/modules/index-sort-l.html index d18eaa9..f4ce7fd 100644 --- a/doc/coverage/coverage/src/modules/index-sort-l.html +++ b/doc/coverage/coverage/src/modules/index-sort-l.html @@ -31,27 +31,27 @@ lcov.info Lines: - 95 - 100 - 95.0 % + 116 + 120 + 96.7 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 28 - 32 - 87.5 % + 34 + 38 + 89.5 % Branches: - 26 - 31 - 83.9 % + 30 + 35 + 85.7 % @@ -84,14 +84,14 @@ ERC3643ComplianceModule.sol -
91.2%91.2%
+
93.3%93.3%
- 91.2 % - 31 / 34 - 83.3 % - 10 / 12 - 85.7 % - 12 / 14 + 93.3 % + 28 / 30 + 81.8 % + 9 / 11 + 84.6 % + 11 / 13 RulesManagementModule.sol @@ -117,6 +117,18 @@ - 0 / 0 + + ERC3643ComplianceExtendedModule.sol + +
100.0%
+ + 100.0 % + 24 / 24 + 100.0 % + 7 / 7 + 100.0 % + 5 / 5 +
diff --git a/doc/coverage/coverage/src/modules/index.html b/doc/coverage/coverage/src/modules/index.html index 164da3f..ac7a2f7 100644 --- a/doc/coverage/coverage/src/modules/index.html +++ b/doc/coverage/coverage/src/modules/index.html @@ -31,27 +31,27 @@ lcov.info Lines: - 95 - 100 - 95.0 % + 116 + 120 + 96.7 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 28 - 32 - 87.5 % + 34 + 38 + 89.5 % Branches: - 26 - 31 - 83.9 % + 30 + 35 + 85.7 % @@ -81,17 +81,29 @@ Functions Sort by function coverage Branches Sort by branch coverage + + ERC3643ComplianceExtendedModule.sol + +
100.0%
+ + 100.0 % + 24 / 24 + 100.0 % + 7 / 7 + 100.0 % + 5 / 5 + ERC3643ComplianceModule.sol -
91.2%91.2%
+
93.3%93.3%
- 91.2 % - 31 / 34 - 83.3 % - 10 / 12 - 85.7 % - 12 / 14 + 93.3 % + 28 / 30 + 81.8 % + 9 / 11 + 84.6 % + 11 / 13 RulesManagementModule.sol diff --git a/doc/coverage/lcov.info b/doc/coverage/lcov.info index f9c8faf..ef3e869 100644 --- a/doc/coverage/lcov.info +++ b/doc/coverage/lcov.info @@ -1,104 +1,105 @@ TN: SF:src/RuleEngineBase.sol -DA:42,5 -FN:42,RuleEngineBase.transferred.0 +DA:43,5 +FN:43,RuleEngineBase.transferred.0 FNDA:5,RuleEngineBase.transferred.0 -DA:49,4 -DA:55,18 -FN:55,RuleEngineBase.transferred.1 +DA:50,4 +DA:56,18 +FN:56,RuleEngineBase.transferred.1 FNDA:18,RuleEngineBase.transferred.1 -DA:61,16 -DA:65,4 -FN:65,RuleEngineBase.created +DA:62,16 +DA:66,4 +FN:66,RuleEngineBase.created FNDA:4,RuleEngineBase.created -DA:66,2 -DA:70,4 -FN:70,RuleEngineBase.destroyed +DA:67,2 +DA:71,4 +FN:71,RuleEngineBase.destroyed FNDA:4,RuleEngineBase.destroyed -DA:71,2 -DA:83,34 -FN:83,RuleEngineBase.detectTransferRestriction +DA:72,2 +DA:84,34 +FN:84,RuleEngineBase.detectTransferRestriction FNDA:34,RuleEngineBase.detectTransferRestriction -DA:90,59 -DA:96,18 -FN:96,RuleEngineBase.detectTransferRestrictionFrom +DA:91,59 +DA:97,18 +FN:97,RuleEngineBase.detectTransferRestrictionFrom FNDA:18,RuleEngineBase.detectTransferRestrictionFrom -DA:103,39 -DA:109,19 -FN:109,RuleEngineBase.messageForTransferRestriction +DA:104,39 +DA:110,19 +FN:110,RuleEngineBase.messageForTransferRestriction FNDA:19,RuleEngineBase.messageForTransferRestriction -DA:116,19 -DA:122,25 -FN:122,RuleEngineBase.canTransfer +DA:117,19 +DA:123,25 +FN:123,RuleEngineBase.canTransfer FNDA:25,RuleEngineBase.canTransfer -DA:129,25 -DA:135,21 -FN:135,RuleEngineBase.canTransferFrom +DA:130,25 +DA:136,21 +FN:136,RuleEngineBase.canTransferFrom FNDA:21,RuleEngineBase.canTransferFrom -DA:142,21 -DA:148,59 -FN:148,RuleEngineBase._detectTransferRestriction -FNDA:59,RuleEngineBase._detectTransferRestriction +DA:143,21 DA:149,59 +FN:149,RuleEngineBase._detectTransferRestriction +FNDA:59,RuleEngineBase._detectTransferRestriction DA:150,59 DA:151,59 DA:152,59 -BRDA:152,0,0,43 -DA:153,43 -DA:156,16 -DA:159,39 -FN:159,RuleEngineBase._detectTransferRestrictionFrom +DA:153,59 +BRDA:153,0,0,43 +DA:154,43 +DA:157,16 +DA:160,39 +FN:160,RuleEngineBase._detectTransferRestrictionFrom FNDA:39,RuleEngineBase._detectTransferRestrictionFrom -DA:165,39 DA:166,39 DA:167,39 DA:168,39 -BRDA:168,1,0,29 -DA:169,29 -DA:172,10 -DA:181,19 -FN:181,RuleEngineBase._messageForTransferRestriction -FNDA:19,RuleEngineBase._messageForTransferRestriction +DA:169,39 +BRDA:169,1,0,29 +DA:170,29 +DA:173,10 DA:182,19 +FN:182,RuleEngineBase._messageForTransferRestriction +FNDA:19,RuleEngineBase._messageForTransferRestriction DA:183,19 -DA:184,16 -BRDA:184,2,0,14 -DA:185,14 -DA:188,5 -DA:194,253 -FN:194,RuleEngineBase._checkRule -FNDA:253,RuleEngineBase._checkRule +DA:184,19 +DA:185,16 +BRDA:185,2,0,14 +DA:186,14 +DA:189,5 DA:195,253 -DA:196,244 -BRDA:196,3,0,6 -DA:197,6 -DA:205,46 -FN:205,RuleEngineBase._supportsRuleEngineBaseInterface -FNDA:46,RuleEngineBase._supportsRuleEngineBaseInterface -DA:206,46 -DA:207,41 -DA:208,31 -DA:209,26 -DA:210,21 +FN:195,RuleEngineBase._checkRule +FNDA:253,RuleEngineBase._checkRule +DA:196,253 +DA:197,244 +BRDA:197,3,0,6 +DA:198,6 +DA:206,56 +FN:206,RuleEngineBase._supportsRuleEngineBaseInterface +FNDA:56,RuleEngineBase._supportsRuleEngineBaseInterface +DA:207,56 +DA:208,51 +DA:209,41 +DA:210,36 +DA:211,31 +DA:212,21 FNF:14 FNH:14 -LF:48 -LH:48 +LF:49 +LH:49 BRF:4 BRH:4 end_of_record TN: SF:src/RuleEngineOwnableShared.sol -DA:22,128 +DA:22,175 FN:22,RuleEngineOwnableShared.constructor -FNDA:128,RuleEngineOwnableShared.constructor -DA:23,128 +FNDA:175,RuleEngineOwnableShared.constructor +DA:23,175 BRDA:23,0,0,1 DA:24,1 -DA:29,29 +DA:29,35 FN:29,RuleEngineOwnableShared.supportsInterface -FNDA:29,RuleEngineOwnableShared.supportsInterface -DA:30,29 +FNDA:35,RuleEngineOwnableShared.supportsInterface +DA:30,35 DA:31,5 DA:37,10 FN:37,RuleEngineOwnableShared._checkOwnershipTransferTarget @@ -106,18 +107,18 @@ FNDA:10,RuleEngineOwnableShared._checkOwnershipTransferTarget DA:38,10 BRDA:38,1,0,2 DA:39,2 -DA:50,181 +DA:50,249 FN:50,RuleEngineOwnableShared._msgSender -FNDA:181,RuleEngineOwnableShared._msgSender -DA:51,181 +FNDA:249,RuleEngineOwnableShared._msgSender +DA:51,249 DA:57,2 FN:57,RuleEngineOwnableShared._msgData FNDA:2,RuleEngineOwnableShared._msgData DA:58,2 -DA:64,183 +DA:64,251 FN:64,RuleEngineOwnableShared._contextSuffixLength -FNDA:183,RuleEngineOwnableShared._contextSuffixLength -DA:65,183 +FNDA:251,RuleEngineOwnableShared._contextSuffixLength +DA:65,251 FNF:6 FNH:6 LF:15 @@ -127,56 +128,56 @@ BRH:2 end_of_record TN: SF:src/deployment/RuleEngine.sol -DA:27,146 +DA:27,165 FN:27,RuleEngine.constructor -FNDA:146,RuleEngine.constructor -DA:30,146 +FNDA:165,RuleEngine.constructor +DA:30,165 BRDA:30,0,0,1 DA:31,1 -DA:33,145 +DA:33,164 BRDA:33,1,0,31 DA:34,31 -DA:36,145 -DA:44,22 +DA:36,164 +DA:44,39 FN:44,RuleEngine.grantRole -FNDA:22,RuleEngine.grantRole -DA:45,22 +FNDA:39,RuleEngine.grantRole +DA:45,39 BRDA:45,2,0,3 DA:46,3 -DA:48,19 -DA:55,154 +DA:48,36 +DA:55,173 FN:55,RuleEngine.hasRole -FNDA:154,RuleEngine.hasRole -DA:62,413 -BRDA:62,3,0,219 -BRDA:62,3,1,194 -DA:63,219 -DA:65,194 -DA:70,17 +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 -FNDA:17,RuleEngine.supportsInterface -DA:77,17 -DA:83,18 +FNDA:21,RuleEngine.supportsInterface +DA:77,21 +DA:83,42 FN:83,RuleEngine._onlyComplianceManager -FNDA:18,RuleEngine._onlyComplianceManager +FNDA:42,RuleEngine._onlyComplianceManager DA:84,196 FN:84,RuleEngine._onlyRulesManager FNDA:196,RuleEngine._onlyRulesManager DA:85,5 FN:85,RuleEngine._onlyRulesLimitManager FNDA:5,RuleEngine._onlyRulesLimitManager -DA:90,450 +DA:90,535 FN:90,RuleEngine._msgSender -FNDA:450,RuleEngine._msgSender -DA:91,450 +FNDA:535,RuleEngine._msgSender +DA:91,535 DA:97,1 FN:97,RuleEngine._msgData FNDA:1,RuleEngine._msgData DA:98,1 -DA:104,451 +DA:104,536 FN:104,RuleEngine._contextSuffixLength -FNDA:451,RuleEngine._contextSuffixLength -DA:105,451 +FNDA:536,RuleEngine._contextSuffixLength +DA:105,536 FNF:10 FNH:10 LF:25 @@ -192,26 +193,26 @@ FNDA:65,RuleEngineOwnable._onlyRulesManager DA:28,2 FN:28,RuleEngineOwnable._onlyRulesLimitManager FNDA:2,RuleEngineOwnable._onlyRulesLimitManager -DA:33,22 +DA:33,46 FN:33,RuleEngineOwnable._onlyComplianceManager -FNDA:22,RuleEngineOwnable._onlyComplianceManager +FNDA:46,RuleEngineOwnable._onlyComplianceManager DA:39,5 FN:39,RuleEngineOwnable.transferOwnership FNDA:5,RuleEngineOwnable.transferOwnership DA:40,4 DA:41,3 -DA:47,146 +DA:47,181 FN:47,RuleEngineOwnable._msgSender -FNDA:146,RuleEngineOwnable._msgSender -DA:48,146 +FNDA:181,RuleEngineOwnable._msgSender +DA:48,181 DA:54,1 FN:54,RuleEngineOwnable._msgData FNDA:1,RuleEngineOwnable._msgData DA:55,1 -DA:61,147 +DA:61,182 FN:61,RuleEngineOwnable._contextSuffixLength -FNDA:147,RuleEngineOwnable._contextSuffixLength -DA:62,147 +FNDA:182,RuleEngineOwnable._contextSuffixLength +DA:62,182 FNF:7 FNH:7 LF:12 @@ -221,119 +222,169 @@ BRH:0 end_of_record TN: SF:src/deployment/RuleEngineOwnable2Step.sol -DA:29,5 -FN:29,RuleEngineOwnable2Step._onlyRulesManager +DA:30,5 +FN:30,RuleEngineOwnable2Step._onlyRulesManager FNDA:5,RuleEngineOwnable2Step._onlyRulesManager -DA:30,2 -FN:30,RuleEngineOwnable2Step._onlyRulesLimitManager +DA:31,2 +FN:31,RuleEngineOwnable2Step._onlyRulesLimitManager FNDA:2,RuleEngineOwnable2Step._onlyRulesLimitManager -DA:35,3 -FN:35,RuleEngineOwnable2Step._onlyComplianceManager -FNDA:3,RuleEngineOwnable2Step._onlyComplianceManager -DA:41,6 -FN:41,RuleEngineOwnable2Step.transferOwnership -FNDA:6,RuleEngineOwnable2Step.transferOwnership +DA:36,25 +FN:36,RuleEngineOwnable2Step._onlyComplianceManager +FNDA:25,RuleEngineOwnable2Step._onlyComplianceManager DA:42,6 -DA:43,5 -DA:49,35 -FN:49,RuleEngineOwnable2Step._msgSender -FNDA:35,RuleEngineOwnable2Step._msgSender -DA:50,35 -DA:56,1 -FN:56,RuleEngineOwnable2Step._msgData +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 +DA:49,13 +DA:50,11 +DA:56,68 +FN:56,RuleEngineOwnable2Step._msgSender +FNDA:68,RuleEngineOwnable2Step._msgSender +DA:57,68 +DA:63,1 +FN:63,RuleEngineOwnable2Step._msgData FNDA:1,RuleEngineOwnable2Step._msgData -DA:57,1 -DA:63,36 -FN:63,RuleEngineOwnable2Step._contextSuffixLength -FNDA:36,RuleEngineOwnable2Step._contextSuffixLength -DA:64,36 -FNF:7 -FNH:7 -LF:12 -LH:12 +DA:64,1 +DA:70,69 +FN:70,RuleEngineOwnable2Step._contextSuffixLength +FNDA:69,RuleEngineOwnable2Step._contextSuffixLength +DA:71,69 +FNF:8 +FNH:8 +LF:15 +LH:15 BRF:0 BRH:0 end_of_record TN: +SF:src/modules/ERC3643ComplianceExtendedModule.sol +DA:16,18 +FN:16,ERC3643ComplianceExtendedModule.bindTokens +FNDA:18,ERC3643ComplianceExtendedModule.bindTokens +DA:17,15 +DA:18,24 +DA:23,9 +FN:23,ERC3643ComplianceExtendedModule.unbindTokens +FNDA:9,ERC3643ComplianceExtendedModule.unbindTokens +DA:24,6 +DA:25,12 +DA:30,14 +FN:30,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 +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:53,6 +DA:57,4 +FN:57,ERC3643ComplianceExtendedModule.getTokenBounds +FNDA:4,ERC3643ComplianceExtendedModule.getTokenBounds +DA:58,4 +DA:65,72 +FN:65,ERC3643ComplianceExtendedModule._authorizeComplianceBindingChange +FNDA:72,ERC3643ComplianceExtendedModule._authorizeComplianceBindingChange +DA:66,72 +BRDA:66,2,0,72 +DA:67,72 +DA:69,60 +FNF:7 +FNH:7 +LF:24 +LH:24 +BRF:5 +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,0 +DA:34,9 FN:34,ERC3643ComplianceModule.onlyComplianceManager -FNDA:0,ERC3643ComplianceModule.onlyComplianceManager -DA:35,0 -DA:52,38 -FN:52,ERC3643ComplianceModule.bindToken -FNDA:38,ERC3643ComplianceModule.bindToken -DA:53,38 -DA:54,34 -DA:65,16 -FN:65,ERC3643ComplianceModule.unbindToken -FNDA:16,ERC3643ComplianceModule.unbindToken -DA:66,16 -DA:67,12 -DA:71,21 -FN:71,ERC3643ComplianceModule.isTokenBound -FNDA:21,ERC3643ComplianceModule.isTokenBound -DA:72,21 -DA:76,5 -FN:76,ERC3643ComplianceModule.getTokenBound +FNDA:9,ERC3643ComplianceModule.onlyComplianceManager +DA:35,9 +DA:50,52 +FN:50,ERC3643ComplianceModule.bindToken +FNDA:52,ERC3643ComplianceModule.bindToken +DA:51,52 +DA:52,45 +DA:61,20 +FN:61,ERC3643ComplianceModule.unbindToken +FNDA:20,ERC3643ComplianceModule.unbindToken +DA:62,20 +DA:63,13 +DA:67,37 +FN:67,ERC3643ComplianceModule.isTokenBound +FNDA:37,ERC3643ComplianceModule.isTokenBound +DA:68,37 +DA:72,5 +FN:72,ERC3643ComplianceModule.getTokenBound FNDA:5,ERC3643ComplianceModule.getTokenBound -DA:77,5 -BRDA:77,0,0,3 -BRDA:77,0,1,2 -DA:80,3 -DA:82,2 -DA:87,4 -FN:87,ERC3643ComplianceModule.getTokenBounds -FNDA:4,ERC3643ComplianceModule.getTokenBounds -DA:88,4 -DA:95,12 -FN:95,ERC3643ComplianceModule._unbindToken -FNDA:12,ERC3643ComplianceModule._unbindToken -DA:96,12 -BRDA:96,1,0,2 -BRDA:96,1,1,10 -DA:98,10 -BRDA:98,2,0,- -BRDA:98,2,1,10 -DA:100,10 -DA:103,66 -FN:103,ERC3643ComplianceModule._bindToken -FNDA:66,ERC3643ComplianceModule._bindToken -DA:104,66 -BRDA:104,3,0,2 -BRDA:104,3,1,64 -DA:105,64 -BRDA:105,4,0,2 -BRDA:105,4,1,62 -DA:107,62 -BRDA:107,5,0,- -BRDA:107,5,1,62 -DA:108,62 -DA:111,31 -FN:111,ERC3643ComplianceModule._checkBoundToken +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 +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 +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 +DA:99,91 +DA:102,31 +FN:102,ERC3643ComplianceModule._checkBoundToken FNDA:31,ERC3643ComplianceModule._checkBoundToken -DA:112,31 -BRDA:112,6,0,7 -DA:113,7 -DA:121,54 -FN:121,ERC3643ComplianceModule._authorizeComplianceBindingChange -FNDA:54,ERC3643ComplianceModule._authorizeComplianceBindingChange -DA:122,54 -BRDA:122,7,0,43 -DA:123,43 -DA:127,0 -FN:127,ERC3643ComplianceModule._onlyComplianceManager +DA:103,31 +BRDA:103,6,0,7 +DA:104,7 +DA:108,0 +FN:108,ERC3643ComplianceModule._authorizeComplianceBindingChange +FNDA:0,ERC3643ComplianceModule._authorizeComplianceBindingChange +DA:109,0 +FN:109,ERC3643ComplianceModule._onlyComplianceManager FNDA:0,ERC3643ComplianceModule._onlyComplianceManager -FNF:12 -FNH:10 -LF:34 -LH:31 -BRF:14 -BRH:12 +FNF:11 +FNH:9 +LF:30 +LH:28 +BRF:13 +BRH:11 end_of_record TN: SF:src/modules/RulesManagementModule.sol diff --git a/doc/security/audits/tools/aderyn-report.md b/doc/security/audits/tools/aderyn-report.md index 9619842..f2e6879 100644 --- a/doc/security/audits/tools/aderyn-report.md +++ b/doc/security/audits/tools/aderyn-report.md @@ -24,33 +24,36 @@ This report was generated by [Aderyn](https://github.com/Cyfrin/aderyn), a stati | Key | Value | | --- | --- | -| .sol Files | 18 | -| Total nSLOC | 542 | +| .sol Files | 21 | +| Total nSLOC | 607 | ## Files Details | Filepath | nSLOC | | --- | --- | -| src/RuleEngineBase.sol | 138 | +| src/RuleEngineBase.sol | 140 | | src/RuleEngineOwnableShared.sol | 33 | | src/deployment/RuleEngine.sol | 63 | | src/deployment/RuleEngineOwnable.sol | 26 | -| src/deployment/RuleEngineOwnable2Step.sol | 27 | -| src/interfaces/IERC3643Compliance.sol | 13 | +| 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/ERC3643ComplianceModule.sol | 65 | +| src/modules/ERC3643ComplianceExtendedModule.sol | 48 | +| src/modules/ERC3643ComplianceModule.sol | 58 | | src/modules/RulesManagementModule.sol | 105 | | src/modules/VersionModule.sol | 8 | -| src/modules/library/ComplianceInterfaceId.sol | 5 | +| src/modules/library/ComplianceInterfaceId.sol | 6 | | src/modules/library/ERC1404InterfaceId.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 | -| **Total** | **542** | +| src/modules/library/RulesManagementModuleInvariantStorage.sol | 18 | +| **Total** | **607** | ## Issue Summary @@ -124,31 +127,31 @@ Contracts have owners with privileged rights to perform admin tasks and need to function transferOwnership(address newOwner) public virtual override onlyOwner { ``` -- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 14](src/deployment/RuleEngineOwnable2Step.sol#L14) +- 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: 29](src/deployment/RuleEngineOwnable2Step.sol#L29) +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 30](src/deployment/RuleEngineOwnable2Step.sol#L30) ```solidity function _onlyRulesManager() internal virtual override onlyOwner {} ``` -- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 30](src/deployment/RuleEngineOwnable2Step.sol#L30) +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 31](src/deployment/RuleEngineOwnable2Step.sol#L31) ```solidity function _onlyRulesLimitManager() internal virtual override onlyOwner {} ``` -- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 35](src/deployment/RuleEngineOwnable2Step.sol#L35) +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 36](src/deployment/RuleEngineOwnable2Step.sol#L36) ```solidity function _onlyComplianceManager() internal virtual override onlyOwner {} ``` -- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 41](src/deployment/RuleEngineOwnable2Step.sol#L41) +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 42](src/deployment/RuleEngineOwnable2Step.sol#L42) ```solidity function transferOwnership(address newOwner) public virtual override onlyOwner { @@ -162,7 +165,7 @@ Contracts have owners with privileged rights to perform admin tasks and need to 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;` -
14 Found Instances +
16 Found Instances - Found in src/RuleEngineBase.sol [Line: 3](src/RuleEngineBase.sol#L3) @@ -201,6 +204,12 @@ Consider using a specific version of Solidity in your contracts instead of a wid 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 @@ -219,6 +228,12 @@ Consider using a specific version of Solidity in your contracts instead of a wid 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 @@ -257,7 +272,7 @@ Consider using a specific version of Solidity in your contracts instead of a wid 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. -
18 Found Instances +
21 Found Instances - Found in src/RuleEngineBase.sol [Line: 3](src/RuleEngineBase.sol#L3) @@ -296,6 +311,12 @@ Solc compiler version 0.8.20 switches the default target EVM version to Shanghai 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 @@ -314,6 +335,12 @@ Solc compiler version 0.8.20 switches the default target EVM version to Shanghai 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 @@ -344,6 +371,12 @@ Solc compiler version 0.8.20 switches the default target EVM version to Shanghai 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 @@ -432,19 +465,19 @@ Consider removing empty blocks. function _onlyComplianceManager() internal virtual override onlyOwner {} ``` -- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 29](src/deployment/RuleEngineOwnable2Step.sol#L29) +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 30](src/deployment/RuleEngineOwnable2Step.sol#L30) ```solidity function _onlyRulesManager() internal virtual override onlyOwner {} ``` -- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 30](src/deployment/RuleEngineOwnable2Step.sol#L30) +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 31](src/deployment/RuleEngineOwnable2Step.sol#L31) ```solidity function _onlyRulesLimitManager() internal virtual override onlyOwner {} ``` -- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 35](src/deployment/RuleEngineOwnable2Step.sol#L35) +- Found in src/deployment/RuleEngineOwnable2Step.sol [Line: 36](src/deployment/RuleEngineOwnable2Step.sol#L36) ```solidity function _onlyComplianceManager() internal virtual override onlyOwner {} @@ -458,8 +491,26 @@ Consider removing empty blocks. 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 -
1 Found Instances +
4 Found Instances + + +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 17](src/modules/ERC3643ComplianceExtendedModule.sol#L17) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` + +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 24](src/modules/ERC3643ComplianceExtendedModule.sol#L24) + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` + +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 43](src/modules/ERC3643ComplianceExtendedModule.sol#L43) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` - Found in src/modules/RulesManagementModule.sol [Line: 60](src/modules/RulesManagementModule.sol#L60) @@ -475,8 +526,26 @@ Avoid `require` / `revert` statements in a loop because a single bad item can ca Invoking `SSTORE` operations in loops may waste gas. Use a local variable to hold the loop computation result. -
1 Found Instances +
4 Found Instances + + +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 17](src/modules/ERC3643ComplianceExtendedModule.sol#L17) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 24](src/modules/ERC3643ComplianceExtendedModule.sol#L24) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` + +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 43](src/modules/ERC3643ComplianceExtendedModule.sol#L43) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` - Found in src/modules/RulesManagementModule.sol [Line: 60](src/modules/RulesManagementModule.sol#L60) diff --git a/doc/security/audits/tools/slither-report-feedback.md b/doc/security/audits/tools/slither-report-feedback.md index f10c7f5..402cf43 100644 --- a/doc/security/audits/tools/slither-report-feedback.md +++ b/doc/security/audits/tools/slither-report-feedback.md @@ -2,16 +2,14 @@ **Tool:** [Slither](https://github.com/crytic/slither) **Report file:** `doc/security/audits/tools/slither-report.md` -**Assessment date:** 2026-05-05 +**Assessment date:** 2026-05-06 ## Summary | IDs | Detector | Tool Impact | Assessment | Decision | |-----|----------|-------------|------------|----------| | 0-9 | `calls-loop` | Low | Inherent to pluggable rule-engine dispatch architecture | Accepted by design | -| 10 | `dead-code` (`RuleEngineOwnable2Step._msgData`) | Informational | False positive in context; required override in ERC2771/context inheritance chain | Accepted / no action | -| 11 | `naming-convention` (CMTAT dependency enum) | Informational | External dependency style issue, not project code risk | Ignored | -| 12-13 | `unindexed-event-address` | Informational | Valid optimization note, but ABI-breaking to change now | Deferred | +| 10-12 | `unindexed-event-address` | Informational | Valid optimization note, but ABI-breaking to change now | Deferred | ## Detailed triage @@ -19,14 +17,8 @@ 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. -### ID 10: `dead-code` on `RuleEngineOwnable2Step._msgData` -This override is part of required multiple-inheritance context resolution (`RuleEngineOwnableShared` + `Context`) for ERC2771-compatible message handling. Static analysis can mark it as unused even though it is part of the contract’s context surface and override chain. Keep as-is. - -### ID 11: `naming-convention` in `lib/CMTAT/.../draft-IERC1404.sol` -Finding targets vendored dependency naming style. This is not a vulnerability and should not be patched locally unless forking upstream conventions intentionally. - -### IDs 12-13: `unindexed-event-address` -`TokenBound(address)` / `TokenUnbound(address)` could add `indexed` for cheaper filtering, but doing so changes event signature and breaks existing consumers. Given low event frequency and backward-compatibility requirements, defer to a planned major interface revision. +### IDs 10-12: `unindexed-event-address` +`TokenBound(address)` and `TokenUnbound(address)` could add `indexed` for cheaper filtering, but doing so changes event signatures and breaks existing consumers. `TokenSelfBindingApprovalSet(address,bool)` has been updated to index `token` (extension interface, acceptable change in this release). 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, dependency style-only, or compatibility tradeoffs. diff --git a/doc/security/audits/tools/slither-report.md b/doc/security/audits/tools/slither-report.md index 842bbfa..692b43a 100644 --- a/doc/security/audits/tools/slither-report.md +++ b/doc/security/audits/tools/slither-report.md @@ -1,9 +1,7 @@ **THIS CHECKLIST IS NOT COMPLETE**. Use `--show-ignored-findings` to show all the results. Summary - [calls-loop](#calls-loop) (10 results) (Low) - - [dead-code](#dead-code) (1 results) (Informational) - - [naming-convention](#naming-convention) (1 results) (Informational) - - [unindexed-event-address](#unindexed-event-address) (2 results) (Informational) + - [unindexed-event-address](#unindexed-event-address) (3 results) (Informational) ## calls-loop Impact: Low Confidence: Medium @@ -32,91 +30,79 @@ src/modules/RulesManagementModule.sol#L201-L206 - [ ] ID-3 -[RuleEngineBase._messageForTransferRestriction(uint8)](src/RuleEngineBase.sol#L181-L189) has external calls inside a loop: [IRule(rule(i)).messageForTransferRestriction(restrictionCode)](src/RuleEngineBase.sol#L185) +[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.messageForTransferRestriction(uint8) + RuleEngineBase.canTransfer(address,address,uint256) + RuleEngineBase.detectTransferRestriction(address,address,uint256) -src/RuleEngineBase.sol#L181-L189 +src/RuleEngineBase.sol#L149-L158 - [ ] ID-4 -[RulesManagementModule._transferred(address,address,uint256)](src/modules/RulesManagementModule.sol#L201-L206) has external calls inside a loop: [IRule(_rules.at(i)).transferred(from,to,value)](src/modules/RulesManagementModule.sol#L204) +[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.created(address,uint256) + RuleEngineBase.messageForTransferRestriction(uint8) -src/modules/RulesManagementModule.sol#L201-L206 +src/RuleEngineBase.sol#L182-L190 - [ ] ID-5 -[RuleEngineBase._detectTransferRestrictionFrom(address,address,address,uint256)](src/RuleEngineBase.sol#L159-L173) has external calls inside a loop: [restriction = IRule(rule(i)).detectTransferRestrictionFrom(spender,from,to,value)](src/RuleEngineBase.sol#L167) +[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.detectTransferRestrictionFrom(address,address,address,uint256) + RuleEngineBase.messageForTransferRestriction(uint8) -src/RuleEngineBase.sol#L159-L173 +src/RuleEngineBase.sol#L182-L190 - [ ] ID-6 -[RuleEngineBase._messageForTransferRestriction(uint8)](src/RuleEngineBase.sol#L181-L189) has external calls inside a loop: [IRule(rule(i)).canReturnTransferRestrictionCode(restrictionCode)](src/RuleEngineBase.sol#L184) +[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.messageForTransferRestriction(uint8) + RuleEngineBase.canTransferFrom(address,address,address,uint256) + RuleEngineBase.detectTransferRestrictionFrom(address,address,address,uint256) -src/RuleEngineBase.sol#L181-L189 +src/RuleEngineBase.sol#L160-L174 - [ ] ID-7 -[RuleEngineBase._detectTransferRestriction(address,address,uint256)](src/RuleEngineBase.sol#L148-L157) has external calls inside a loop: [restriction = IRule(rule(i)).detectTransferRestriction(from,to,value)](src/RuleEngineBase.sol#L151) +[RulesManagementModule._transferred(address,address,uint256)](src/modules/RulesManagementModule.sol#L201-L206) has external calls inside a loop: [IRule(_rules.at(i)).transferred(from,to,value)](src/modules/RulesManagementModule.sol#L204) Calls stack containing the loop: - RuleEngineBase.detectTransferRestriction(address,address,uint256) + RuleEngineBase.created(address,uint256) -src/RuleEngineBase.sol#L148-L157 +src/modules/RulesManagementModule.sol#L201-L206 - [ ] ID-8 -[RuleEngineBase._detectTransferRestriction(address,address,uint256)](src/RuleEngineBase.sol#L148-L157) has external calls inside a loop: [restriction = IRule(rule(i)).detectTransferRestriction(from,to,value)](src/RuleEngineBase.sol#L151) +[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#L148-L157 +src/RuleEngineBase.sol#L149-L158 - [ ] ID-9 -[RuleEngineBase._detectTransferRestrictionFrom(address,address,address,uint256)](src/RuleEngineBase.sol#L159-L173) has external calls inside a loop: [restriction = IRule(rule(i)).detectTransferRestrictionFrom(spender,from,to,value)](src/RuleEngineBase.sol#L167) +[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#L159-L173 +src/RuleEngineBase.sol#L160-L174 -## dead-code +## unindexed-event-address Impact: Informational -Confidence: Medium +Confidence: High - [ ] ID-10 -[RuleEngineOwnable2Step._msgData()](src/deployment/RuleEngineOwnable2Step.sol#L56-L58) is never used and should be removed +Event [IERC3643Compliance.TokenBound(address)](src/interfaces/IERC3643Compliance.sol#L14) has address parameters but no indexed parameters -src/deployment/RuleEngineOwnable2Step.sol#L56-L58 +src/interfaces/IERC3643Compliance.sol#L14 -## naming-convention -Impact: Informational -Confidence: High - [ ] ID-11 -Enum [IERC1404Extend.REJECTED_CODE_BASE](lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol#L49-L57) is not in CapWords +Event [IERC3643ComplianceExtended.TokenSelfBindingApprovalSet(address,bool)](src/interfaces/IERC3643ComplianceExtended.sol#L13) has address parameters but no indexed parameters -lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol#L49-L57 +src/interfaces/IERC3643ComplianceExtended.sol#L13 -## unindexed-event-address -Impact: Informational -Confidence: High - [ ] ID-12 -Event [IERC3643Compliance.TokenBound(address)](src/interfaces/IERC3643Compliance.sol#L14) has address parameters but no indexed parameters - -src/interfaces/IERC3643Compliance.sol#L14 - - - - [ ] ID-13 Event [IERC3643Compliance.TokenUnbound(address)](src/interfaces/IERC3643Compliance.sol#L20) has address parameters but no indexed parameters src/interfaces/IERC3643Compliance.sol#L20 From b16578852d8c803dc09b9a2497f930da2df5f8b2 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Thu, 7 May 2026 09:02:48 +0200 Subject: [PATCH 08/11] Indexed event --- src/interfaces/IERC3643ComplianceExtended.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interfaces/IERC3643ComplianceExtended.sol b/src/interfaces/IERC3643ComplianceExtended.sol index ed67417..7f334b0 100644 --- a/src/interfaces/IERC3643ComplianceExtended.sol +++ b/src/interfaces/IERC3643ComplianceExtended.sol @@ -10,7 +10,7 @@ interface IERC3643ComplianceExtended is IERC3643Compliance { * @param token The token address whose self-binding permission changed. * @param approved True if token self-bind/unbind is allowed, false otherwise. */ - event TokenSelfBindingApprovalSet(address token, bool approved); + event TokenSelfBindingApprovalSet(address indexed token, bool approved); /** * @notice Emitted when self-binding permission is updated in batch. * @param tokens The token addresses whose self-binding permission changed. From db17679aa971485e8f98c3aa5d668957a4dce78d Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Thu, 7 May 2026 09:38:37 +0200 Subject: [PATCH 09/11] Update documentation --- CHANGELOG.md | 2 +- README.md | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2833ad..d52cec7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,7 +74,7 @@ forge lint - Add token self-binding approval management to `IERC3643ComplianceExtended` / `ERC3643ComplianceExtendedModule`: - `setTokenSelfBindingApproval(address token, bool approved)` - `isTokenSelfBindingApproved(address token)` - - `TokenSelfBindingApprovalSet(address token, bool approved)` event. + - `TokenSelfBindingApprovalSet(address indexed token, bool approved)` event. - Add batch self-binding approval API in `IERC3643ComplianceExtended` / `ERC3643ComplianceExtendedModule`: - `setTokenSelfBindingApprovalBatch(address[] tokens, bool approved)`. - `TokenSelfBindingApprovalBatchSet(address[] tokens, bool approved)` event. diff --git a/README.md b/README.md index f794f47..173de45 100644 --- a/README.md +++ b/README.md @@ -367,6 +367,11 @@ For function signatures, struct arguments are represented with their correspondi | ERC3643ComplianceModule | | | | | | | | `bindToken(address token)` | public | `address token` | - | COMPLIANCE_MANAGER_ROLE | | | `unbindToken(address token)` | public | `address token` | - | COMPLIANCE_MANAGER_ROLE | +| ERC3643ComplianceExtendedModule | | | | | | +| | `bindTokens(address[] tokens)` | public | `address[] tokens` | - | COMPLIANCE_MANAGER_ROLE | +| | `unbindTokens(address[] tokens)` | public | `address[] tokens` | - | COMPLIANCE_MANAGER_ROLE | +| | `setTokenSelfBindingApproval(address token,bool approved)` | public | `address token,bool approved` | - | COMPLIANCE_MANAGER_ROLE | +| | `setTokenSelfBindingApprovalBatch(address[] tokens,bool approved)` | public | `address[] tokens,bool approved` | - | COMPLIANCE_MANAGER_ROLE | | RuleEngineBase | | | | | | | | `transferred(address from,address to,uint256 value)` | public | `address from,address to, uint256 value` | - | onlyBoundToken (modifier) | | | `transferred(address spender,address from,address to,uint256 value)` | public | `address spender,address from,address to, uint256 value` | - | onlyBoundToken (modifier) | @@ -392,7 +397,8 @@ RuleEngineOwnable ├── RuleEngineBase (core functionality) │ ├── VersionModule │ ├── RulesManagementModule -│ ├── ERC3643ComplianceModule +│ ├── ERC3643ComplianceModule (core ERC-3643) +│ ├── ERC3643ComplianceExtendedModule (project extensions) │ └── IRuleEngineERC1404 └── Ownable (ERC-173 access control) ``` @@ -416,7 +422,8 @@ RuleEngineOwnable2Step │ └── RuleEngineBase │ ├── VersionModule │ ├── RulesManagementModule -│ ├── ERC3643ComplianceModule +│ ├── ERC3643ComplianceModule (core ERC-3643) +│ ├── ERC3643ComplianceExtendedModule (project extensions) │ └── IRuleEngineERC1404 └── Ownable2Step (ERC-173 access control with pending owner) ``` @@ -575,7 +582,7 @@ constructor( | :----------------: | :---------------------------: | :----------------------------------------------------------: | :------------: | :------------: | | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | | | | | | | -| **RuleEngineBase** | Implementation | VersionModule, RulesManagementModule, ERC3643ComplianceModule, RuleEngineInvariantStorage, IRuleEngine | | | +| **RuleEngineBase** | Implementation | VersionModule, RulesManagementModule, ERC3643ComplianceExtendedModule, RuleEngineInvariantStorage, IRuleEngine | | | | └ | transferred | Public ❗️ | 🛑 | onlyBoundToken | | └ | transferred | Public ❗️ | 🛑 | onlyBoundToken | | └ | created | Public ❗️ | 🛑 | onlyBoundToken | @@ -926,8 +933,11 @@ Useful for identifying which version of the smart contract is deployed and in us | └ | bindToken | Public ❗️ | 🛑 | onlyRole | | └ | unbindToken | Public ❗️ | 🛑 | onlyRole | | └ | isTokenBound | Public ❗️ | | NO❗️ | -| └ | getTokenBound | External ❗️ | | NO❗️ | -| └ | getTokenBounds | External ❗️ | | NO❗️ | +| └ | getTokenBound | Public ❗️ | | NO❗️ | + +### ERC3643ComplianceExtendedModule + +`ERC3643ComplianceExtendedModule` inherits `ERC3643ComplianceModule` and contains project-specific helpers not part of the ERC-3643 base interface (`IERC3643Compliance`): batch bind/unbind, self-binding approval APIs, and `getTokenBounds()`. | └ | _unbindToken | Internal 🔒 | 🛑 | | | └ | _bindToken | Internal 🔒 | 🛑 | | From 6209e2857b1c1c5119b8cbce8b39952b25cdc95e Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Thu, 7 May 2026 14:14:17 +0200 Subject: [PATCH 10/11] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d52cec7..955ece6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,7 +45,7 @@ forge lint - Update surya doc by running the 3 scripts in [./doc/script](./doc/script) - Update changelog -### v3.0.0-rc3 - 2026-05-06 +### v3.0.0-rc3 - 2026-05-07 ### Security From d28b470079340333492e0c8088d27bfdcafca614 Mon Sep 17 00:00:00 2001 From: Ryan Sauge <71391932+rya-sge@users.noreply.github.com> Date: Thu, 7 May 2026 14:20:13 +0200 Subject: [PATCH 11/11] Update readme --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 173de45..3961d5b 100644 --- a/README.md +++ b/README.md @@ -307,16 +307,16 @@ The table below summarizes which ERC-165 interfaces are advertised by each deplo | Interface | Interface ID | RuleEngine (RBAC deployment) | RuleEngineOwnable deployment | RuleEngineOwnable2Step deployment | | --- | --- | --- | --- | --- | -| `IERC165` | `0x01ffc9a7` | Yes | Yes | Yes | -| `IRuleEngine` | `0x20c49ce7` | Yes | Yes | Yes | -| `IERC1404` | `0xab84a5c8` | Yes | Yes | Yes | -| `IERC1404Extend` | `0x78a8de7d` | Yes | Yes | Yes | -| `IERC3643Compliance` | `0x3144991c` | Yes | Yes | Yes | -| `IERC7551Compliance` (subset) | `0x7157797f` | Yes | Yes | Yes | -| `IERC173` | `0x7f5828d0` | No | Yes | Yes | -| `Ownable2Step` specific (`pendingOwner()`, `acceptOwnership()`) | `0x9ab669ef` | No | No | Yes | -| `IAccessControl` | `0x7965db0b` | Yes | No | No | -| `IAccessControlEnumerable` | `0x5a05180f` | Yes | No | No | +| `IERC165` | `0x01ffc9a7` | | | | +| `IRuleEngine` | `0x20c49ce7` | | | | +| `IERC1404` | `0xab84a5c8` | | | | +| `IERC1404Extend` | `0x78a8de7d` | | | | +| `IERC3643Compliance` | `0x3144991c` | | | | +| `IERC7551Compliance` (subset) | `0x7157797f` | | | | +| `IERC173` | `0x7f5828d0` | | | | +| `Ownable2Step` specific (`pendingOwner()`, `acceptOwnership()`) | `0x9ab669ef` | | | | +| `IAccessControl` | `0x7965db0b` | | | | +| `IAccessControlEnumerable` | `0x5a05180f` | | | | Notes: - `RuleEngine` advertises OpenZeppelin RBAC interfaces because it inherits `AccessControlEnumerable`.

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.info Lines: - 207 - 212 - 97.6 % + 232 + 236 + 98.3 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 72 - 76 - 94.7 % + 79 + 83 + 95.2 % Branches: - 37 - 42 - 88.1 % + 41 + 46 + 89.1 % @@ -84,14 +84,14 @@ src/modules -
95.0%95.0%
+
96.7%96.7%
- 95.0 % - 95 / 100 - 87.5 % - 28 / 32 - 83.9 % - 26 / 31 + 96.7 % + 116 / 120 + 89.5 % + 34 / 38 + 85.7 % + 30 / 35 src/deployment @@ -99,9 +99,9 @@
100.0%
100.0 % - 49 / 49 + 52 / 52 100.0 % - 24 / 24 + 25 / 25 100.0 % 5 / 5 @@ -111,7 +111,7 @@
100.0%
100.0 % - 63 / 63 + 64 / 64 100.0 % 20 / 20 100.0 % diff --git a/doc/coverage/coverage/index-sort-f.html b/doc/coverage/coverage/index-sort-f.html index 1fedf73..b39c30e 100644 --- a/doc/coverage/coverage/index-sort-f.html +++ b/doc/coverage/coverage/index-sort-f.html @@ -31,27 +31,27 @@ lcov.info Lines: - 207 - 212 - 97.6 % + 232 + 236 + 98.3 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 72 - 76 - 94.7 % + 79 + 83 + 95.2 % Branches: - 37 - 42 - 88.1 % + 41 + 46 + 89.1 % @@ -84,14 +84,14 @@ src/modules -
95.0%95.0%
+
96.7%96.7%
- 95.0 % - 95 / 100 - 87.5 % - 28 / 32 - 83.9 % - 26 / 31 + 96.7 % + 116 / 120 + 89.5 % + 34 / 38 + 85.7 % + 30 / 35 src @@ -99,7 +99,7 @@
100.0%
100.0 % - 63 / 63 + 64 / 64 100.0 % 20 / 20 100.0 % @@ -111,9 +111,9 @@
100.0%
100.0 % - 49 / 49 + 52 / 52 100.0 % - 24 / 24 + 25 / 25 100.0 % 5 / 5 diff --git a/doc/coverage/coverage/index-sort-l.html b/doc/coverage/coverage/index-sort-l.html index de8fcda..0394496 100644 --- a/doc/coverage/coverage/index-sort-l.html +++ b/doc/coverage/coverage/index-sort-l.html @@ -31,27 +31,27 @@ lcov.info Lines: - 207 - 212 - 97.6 % + 232 + 236 + 98.3 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 72 - 76 - 94.7 % + 79 + 83 + 95.2 % Branches: - 37 - 42 - 88.1 % + 41 + 46 + 89.1 % @@ -84,14 +84,14 @@ src/modules -
95.0%95.0%
+
96.7%96.7%
- 95.0 % - 95 / 100 - 87.5 % - 28 / 32 - 83.9 % - 26 / 31 + 96.7 % + 116 / 120 + 89.5 % + 34 / 38 + 85.7 % + 30 / 35 src/deployment @@ -99,9 +99,9 @@
100.0%
100.0 % - 49 / 49 + 52 / 52 100.0 % - 24 / 24 + 25 / 25 100.0 % 5 / 5 @@ -111,7 +111,7 @@
100.0%
100.0 % - 63 / 63 + 64 / 64 100.0 % 20 / 20 100.0 % diff --git a/doc/coverage/coverage/index.html b/doc/coverage/coverage/index.html index af90d9e..f897605 100644 --- a/doc/coverage/coverage/index.html +++ b/doc/coverage/coverage/index.html @@ -31,27 +31,27 @@ lcov.info Lines: - 207 - 212 - 97.6 % + 232 + 236 + 98.3 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 72 - 76 - 94.7 % + 79 + 83 + 95.2 % Branches: - 37 - 42 - 88.1 % + 41 + 46 + 89.1 % @@ -87,7 +87,7 @@
100.0%
100.0 % - 63 / 63 + 64 / 64 100.0 % 20 / 20 100.0 % @@ -99,23 +99,23 @@
100.0%
100.0 % - 49 / 49 + 52 / 52 100.0 % - 24 / 24 + 25 / 25 100.0 % 5 / 5 src/modules -
95.0%95.0%
+
96.7%96.7%
- 95.0 % - 95 / 100 - 87.5 % - 28 / 32 - 83.9 % - 26 / 31 + 96.7 % + 116 / 120 + 89.5 % + 34 / 38 + 85.7 % + 30 / 35 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 cad3862..3386ca0 100644 --- a/doc/coverage/coverage/src/RuleEngineBase.sol.func-sort-c.html +++ b/doc/coverage/coverage/src/RuleEngineBase.sol.func-sort-c.html @@ -31,13 +31,13 @@ lcov.info Lines: - 48 - 48 + 49 + 49 100.0 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: 14 @@ -69,59 +69,59 @@ Hit count Sort by hit count - RuleEngineBase.created + RuleEngineBase.created 4 - RuleEngineBase.destroyed + RuleEngineBase.destroyed 4 - RuleEngineBase.transferred.0 + RuleEngineBase.transferred.0 5 - RuleEngineBase.detectTransferRestrictionFrom + RuleEngineBase.detectTransferRestrictionFrom 18 - RuleEngineBase.transferred.1 + RuleEngineBase.transferred.1 18 - RuleEngineBase._messageForTransferRestriction + RuleEngineBase._messageForTransferRestriction 19 - RuleEngineBase.messageForTransferRestriction + RuleEngineBase.messageForTransferRestriction 19 - RuleEngineBase.canTransferFrom + RuleEngineBase.canTransferFrom 21 - RuleEngineBase.canTransfer + RuleEngineBase.canTransfer 25 - RuleEngineBase.detectTransferRestriction + RuleEngineBase.detectTransferRestriction 34 - RuleEngineBase._detectTransferRestrictionFrom + RuleEngineBase._detectTransferRestrictionFrom 39 - RuleEngineBase._supportsRuleEngineBaseInterface - 46 + RuleEngineBase._supportsRuleEngineBaseInterface + 56 - RuleEngineBase._detectTransferRestriction + RuleEngineBase._detectTransferRestriction 59 - RuleEngineBase._checkRule + RuleEngineBase._checkRule 253 diff --git a/doc/coverage/coverage/src/RuleEngineBase.sol.func.html b/doc/coverage/coverage/src/RuleEngineBase.sol.func.html index 906ea70..32fb24c 100644 --- a/doc/coverage/coverage/src/RuleEngineBase.sol.func.html +++ b/doc/coverage/coverage/src/RuleEngineBase.sol.func.html @@ -31,13 +31,13 @@ lcov.info Lines: - 48 - 48 + 49 + 49 100.0 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: 14 @@ -69,59 +69,59 @@ Hit count Sort by hit count - RuleEngineBase._checkRule + RuleEngineBase._checkRule 253 - RuleEngineBase._detectTransferRestriction + RuleEngineBase._detectTransferRestriction 59 - RuleEngineBase._detectTransferRestrictionFrom + RuleEngineBase._detectTransferRestrictionFrom 39 - RuleEngineBase._messageForTransferRestriction + RuleEngineBase._messageForTransferRestriction 19 - RuleEngineBase._supportsRuleEngineBaseInterface - 46 + RuleEngineBase._supportsRuleEngineBaseInterface + 56 - RuleEngineBase.canTransfer + RuleEngineBase.canTransfer 25 - RuleEngineBase.canTransferFrom + RuleEngineBase.canTransferFrom 21 - RuleEngineBase.created + RuleEngineBase.created 4 - RuleEngineBase.destroyed + RuleEngineBase.destroyed 4 - RuleEngineBase.detectTransferRestriction + RuleEngineBase.detectTransferRestriction 34 - RuleEngineBase.detectTransferRestrictionFrom + RuleEngineBase.detectTransferRestrictionFrom 18 - RuleEngineBase.messageForTransferRestriction + RuleEngineBase.messageForTransferRestriction 19 - RuleEngineBase.transferred.0 + RuleEngineBase.transferred.0 5 - RuleEngineBase.transferred.1 + RuleEngineBase.transferred.1 18 diff --git a/doc/coverage/coverage/src/RuleEngineBase.sol.gcov.html b/doc/coverage/coverage/src/RuleEngineBase.sol.gcov.html index 343a1c7..22088f9 100644 --- a/doc/coverage/coverage/src/RuleEngineBase.sol.gcov.html +++ b/doc/coverage/coverage/src/RuleEngineBase.sol.gcov.html @@ -31,13 +31,13 @@ lcov.info Lines: - 48 - 48 + 49 + 49 100.0 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: 14 @@ -85,202 +85,204 @@ 14 : : import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol"; 15 : : 16 : : /* ==== Modules === */ - 17 : : import {ERC3643ComplianceModule, IERC3643Compliance} from "./modules/ERC3643ComplianceModule.sol"; + 17 : : import {ERC3643ComplianceExtendedModule} from "./modules/ERC3643ComplianceExtendedModule.sol"; 18 : : import {VersionModule} from "./modules/VersionModule.sol"; 19 : : import {RulesManagementModule} from "./modules/RulesManagementModule.sol"; 20 : : 21 : : /* ==== Interface and other library === */ - 22 : : import {IRule} from "./interfaces/IRule.sol"; - 23 : : import {ComplianceInterfaceId} from "./modules/library/ComplianceInterfaceId.sol"; - 24 : : import {ERC1404InterfaceId} from "./modules/library/ERC1404InterfaceId.sol"; - 25 : : import {RuleEngineInvariantStorage} from "./modules/library/RuleEngineInvariantStorage.sol"; - 26 : : import {RuleInterfaceId} from "./modules/library/RuleInterfaceId.sol"; - 27 : : - 28 : : /** - 29 : : * @title Implementation of a ruleEngine as defined by the CMTAT - 30 : : */ - 31 : : abstract contract RuleEngineBase is - 32 : : VersionModule, - 33 : : RulesManagementModule, - 34 : : ERC3643ComplianceModule, - 35 : : RuleEngineInvariantStorage, - 36 : : IRuleEngineERC1404 - 37 : : { - 38 : : /* ============ State functions ============ */ - 39 : : /* - 40 : : * @inheritdoc IRuleEngine - 41 : : */ - 42 : 5 : function transferred(address spender, address from, address to, uint256 value) - 43 : : public - 44 : : virtual - 45 : : override(IRuleEngine) - 46 : : onlyBoundToken - 47 : : { - 48 : : // Apply on RuleEngine - 49 : 4 : RulesManagementModule._transferred(spender, from, to, value); - 50 : : } - 51 : : - 52 : : /** - 53 : : * @inheritdoc IERC3643IComplianceContract - 54 : : */ - 55 : 18 : function transferred(address from, address to, uint256 value) - 56 : : public - 57 : : virtual - 58 : : override(IERC3643IComplianceContract) - 59 : : onlyBoundToken - 60 : : { - 61 : 16 : _transferred(from, to, value); - 62 : : } - 63 : : - 64 : : /// @inheritdoc IERC3643Compliance - 65 : 4 : function created(address to, uint256 value) public virtual override(IERC3643Compliance) onlyBoundToken { - 66 : 2 : _transferred(address(0), to, value); - 67 : : } - 68 : : - 69 : : /// @inheritdoc IERC3643Compliance - 70 : 4 : function destroyed(address from, uint256 value) public virtual override(IERC3643Compliance) onlyBoundToken { - 71 : 2 : _transferred(from, address(0), value); - 72 : : } - 73 : : - 74 : : /* ============ View functions ============ */ - 75 : : /** - 76 : : * @notice Go through all the rule to know if a restriction exists on the transfer - 77 : : * @param from the origin address - 78 : : * @param to the destination address - 79 : : * @param value to transfer - 80 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid - 81 : : * - 82 : : */ - 83 : 34 : function detectTransferRestriction(address from, address to, uint256 value) - 84 : : public - 85 : : view - 86 : : virtual - 87 : : override(IERC1404) - 88 : : returns (uint8) - 89 : : { - 90 : 59 : return _detectTransferRestriction(from, to, value); - 91 : : } - 92 : : - 93 : : /** - 94 : : * @inheritdoc IERC1404Extend - 95 : : */ - 96 : 18 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) - 97 : : public - 98 : : view - 99 : : virtual - 100 : : override(IERC1404Extend) - 101 : : returns (uint8) - 102 : : { - 103 : 39 : return _detectTransferRestrictionFrom(spender, from, to, value); - 104 : : } - 105 : : - 106 : : /** - 107 : : * @inheritdoc IERC1404 - 108 : : */ - 109 : 19 : function messageForTransferRestriction(uint8 restrictionCode) - 110 : : public - 111 : : view - 112 : : virtual - 113 : : override(IERC1404) - 114 : : returns (string memory) - 115 : : { - 116 : 19 : return _messageForTransferRestriction(restrictionCode); - 117 : : } - 118 : : - 119 : : /** - 120 : : * @inheritdoc IERC3643ComplianceRead - 121 : : */ - 122 : 25 : function canTransfer(address from, address to, uint256 value) - 123 : : public - 124 : : view - 125 : : virtual - 126 : : override(IERC3643ComplianceRead) - 127 : : returns (bool) - 128 : : { - 129 : 25 : return detectTransferRestriction(from, to, value) == uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 130 : : } - 131 : : - 132 : : /** - 133 : : * @inheritdoc IERC7551Compliance - 134 : : */ - 135 : 21 : function canTransferFrom(address spender, address from, address to, uint256 value) - 136 : : public - 137 : : view - 138 : : virtual - 139 : : override(IERC7551Compliance) - 140 : : returns (bool) - 141 : : { - 142 : 21 : return detectTransferRestrictionFrom(spender, from, to, value) == uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 143 : : } - 144 : : - 145 : : /*////////////////////////////////////////////////////////////// - 146 : : INTERNAL/PRIVATE FUNCTIONS - 147 : : //////////////////////////////////////////////////////////////*/ - 148 : 59 : function _detectTransferRestriction(address from, address to, uint256 value) internal view virtual returns (uint8) { - 149 : 59 : uint256 rulesLength = rulesCount(); - 150 : 59 : for (uint256 i = 0; i < rulesLength; ++i) { - 151 : 59 : uint8 restriction = IRule(rule(i)).detectTransferRestriction(from, to, value); - 152 [ + ]: 59 : if (restriction > 0) { - 153 : 43 : return restriction; - 154 : : } - 155 : : } - 156 : 16 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 157 : : } - 158 : : - 159 : 39 : function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) - 160 : : internal - 161 : : view - 162 : : virtual - 163 : : returns (uint8) - 164 : : { - 165 : 39 : uint256 rulesLength = rulesCount(); - 166 : 39 : for (uint256 i = 0; i < rulesLength; ++i) { - 167 : 39 : uint8 restriction = IRule(rule(i)).detectTransferRestrictionFrom(spender, from, to, value); - 168 [ + ]: 39 : if (restriction > 0) { - 169 : 29 : return restriction; - 170 : : } - 171 : : } - 172 : 10 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); - 173 : : } - 174 : : - 175 : : /** - 176 : : * @dev This function returns the message from the first rule claiming the code. - 177 : : * Rule designers should keep restriction codes unique across rules. - 178 : : * If a code is shared intentionally, all rules using that code should return - 179 : : * the same message to avoid ambiguous operator feedback. - 180 : : */ - 181 : 19 : function _messageForTransferRestriction(uint8 restrictionCode) internal view virtual returns (string memory) { - 182 : 19 : uint256 rulesLength = rulesCount(); - 183 : 19 : for (uint256 i = 0; i < rulesLength; ++i) { - 184 [ + ]: 16 : if (IRule(rule(i)).canReturnTransferRestrictionCode(restrictionCode)) { - 185 : 14 : return IRule(rule(i)).messageForTransferRestriction(restrictionCode); - 186 : : } - 187 : : } - 188 : 5 : return "Unknown restriction code"; - 189 : : } - 190 : : - 191 : : /** - 192 : : * @dev Override to add ERC-165 interface check for the full IRule hierarchy. - 193 : : */ - 194 : 253 : function _checkRule(address rule_) internal view virtual override { - 195 : 253 : RulesManagementModule._checkRule(rule_); - 196 [ + ]: 244 : if (!ERC165Checker.supportsInterface(rule_, RuleInterfaceId.IRULE_INTERFACE_ID)) { - 197 : 6 : revert RuleEngine_RuleInvalidInterface(); - 198 : : } - 199 : : } - 200 : : - 201 : : /** - 202 : : * @dev Shared ERC-165 checks common to all RuleEngine deployment variants. - 203 : : * Concrete deployments can extend this with access-control-specific interfaces. - 204 : : */ - 205 : 46 : function _supportsRuleEngineBaseInterface(bytes4 interfaceId) internal pure returns (bool) { - 206 : 46 : return interfaceId == RuleEngineInterfaceId.RULE_ENGINE_INTERFACE_ID - 207 : 41 : || interfaceId == ERC1404InterfaceId.IERC1404_INTERFACE_ID - 208 : 31 : || interfaceId == ERC1404ExtendInterfaceId.ERC1404EXTEND_INTERFACE_ID - 209 : 26 : || interfaceId == ComplianceInterfaceId.ERC3643_COMPLIANCE_INTERFACE_ID - 210 : 21 : || interfaceId == ComplianceInterfaceId.IERC7551_COMPLIANCE_INTERFACE_ID; - 211 : : } - 212 : : } + 22 : : import {IERC3643Compliance} from "./interfaces/IERC3643Compliance.sol"; + 23 : : import {IRule} from "./interfaces/IRule.sol"; + 24 : : import {ComplianceInterfaceId} from "./modules/library/ComplianceInterfaceId.sol"; + 25 : : import {ERC1404InterfaceId} from "./modules/library/ERC1404InterfaceId.sol"; + 26 : : import {RuleEngineInvariantStorage} from "./modules/library/RuleEngineInvariantStorage.sol"; + 27 : : import {RuleInterfaceId} from "./modules/library/RuleInterfaceId.sol"; + 28 : : + 29 : : /** + 30 : : * @title Implementation of a ruleEngine as defined by the CMTAT + 31 : : */ + 32 : : abstract contract RuleEngineBase is + 33 : : VersionModule, + 34 : : RulesManagementModule, + 35 : : ERC3643ComplianceExtendedModule, + 36 : : RuleEngineInvariantStorage, + 37 : : IRuleEngineERC1404 + 38 : : { + 39 : : /* ============ State functions ============ */ + 40 : : /* + 41 : : * @inheritdoc IRuleEngine + 42 : : */ + 43 : 5 : 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); + 51 : : } + 52 : : + 53 : : /** + 54 : : * @inheritdoc IERC3643IComplianceContract + 55 : : */ + 56 : 18 : function transferred(address from, address to, uint256 value) + 57 : : public + 58 : : virtual + 59 : : override(IERC3643IComplianceContract) + 60 : : onlyBoundToken + 61 : : { + 62 : 16 : _transferred(from, to, value); + 63 : : } + 64 : : + 65 : : /// @inheritdoc IERC3643Compliance + 66 : 4 : function created(address to, uint256 value) public virtual override(IERC3643Compliance) onlyBoundToken { + 67 : 2 : _transferred(address(0), to, value); + 68 : : } + 69 : : + 70 : : /// @inheritdoc IERC3643Compliance + 71 : 4 : function destroyed(address from, uint256 value) public virtual override(IERC3643Compliance) onlyBoundToken { + 72 : 2 : _transferred(from, address(0), value); + 73 : : } + 74 : : + 75 : : /* ============ View functions ============ */ + 76 : : /** + 77 : : * @notice Go through all the rule to know if a restriction exists on the transfer + 78 : : * @param from the origin address + 79 : : * @param to the destination address + 80 : : * @param value to transfer + 81 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid + 82 : : * + 83 : : */ + 84 : 34 : function detectTransferRestriction(address from, address to, uint256 value) + 85 : : public + 86 : : view + 87 : : virtual + 88 : : override(IERC1404) + 89 : : returns (uint8) + 90 : : { + 91 : 59 : return _detectTransferRestriction(from, to, value); + 92 : : } + 93 : : + 94 : : /** + 95 : : * @inheritdoc IERC1404Extend + 96 : : */ + 97 : 18 : function detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) + 98 : : public + 99 : : view + 100 : : virtual + 101 : : override(IERC1404Extend) + 102 : : returns (uint8) + 103 : : { + 104 : 39 : return _detectTransferRestrictionFrom(spender, from, to, value); + 105 : : } + 106 : : + 107 : : /** + 108 : : * @inheritdoc IERC1404 + 109 : : */ + 110 : 19 : function messageForTransferRestriction(uint8 restrictionCode) + 111 : : public + 112 : : view + 113 : : virtual + 114 : : override(IERC1404) + 115 : : returns (string memory) + 116 : : { + 117 : 19 : return _messageForTransferRestriction(restrictionCode); + 118 : : } + 119 : : + 120 : : /** + 121 : : * @inheritdoc IERC3643ComplianceRead + 122 : : */ + 123 : 25 : function canTransfer(address from, address to, uint256 value) + 124 : : public + 125 : : view + 126 : : virtual + 127 : : override(IERC3643ComplianceRead) + 128 : : returns (bool) + 129 : : { + 130 : 25 : return detectTransferRestriction(from, to, value) == uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 131 : : } + 132 : : + 133 : : /** + 134 : : * @inheritdoc IERC7551Compliance + 135 : : */ + 136 : 21 : function canTransferFrom(address spender, address from, address to, uint256 value) + 137 : : public + 138 : : view + 139 : : virtual + 140 : : override(IERC7551Compliance) + 141 : : returns (bool) + 142 : : { + 143 : 21 : return detectTransferRestrictionFrom(spender, from, to, value) == uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 144 : : } + 145 : : + 146 : : /*////////////////////////////////////////////////////////////// + 147 : : INTERNAL/PRIVATE FUNCTIONS + 148 : : //////////////////////////////////////////////////////////////*/ + 149 : 59 : function _detectTransferRestriction(address from, address to, uint256 value) internal view virtual returns (uint8) { + 150 : 59 : uint256 rulesLength = rulesCount(); + 151 : 59 : for (uint256 i = 0; i < rulesLength; ++i) { + 152 : 59 : uint8 restriction = IRule(rule(i)).detectTransferRestriction(from, to, value); + 153 [ + ]: 59 : if (restriction > 0) { + 154 : 43 : return restriction; + 155 : : } + 156 : : } + 157 : 16 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 158 : : } + 159 : : + 160 : 39 : function _detectTransferRestrictionFrom(address spender, address from, address to, uint256 value) + 161 : : internal + 162 : : view + 163 : : virtual + 164 : : returns (uint8) + 165 : : { + 166 : 39 : uint256 rulesLength = rulesCount(); + 167 : 39 : for (uint256 i = 0; i < rulesLength; ++i) { + 168 : 39 : uint8 restriction = IRule(rule(i)).detectTransferRestrictionFrom(spender, from, to, value); + 169 [ + ]: 39 : if (restriction > 0) { + 170 : 29 : return restriction; + 171 : : } + 172 : : } + 173 : 10 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK); + 174 : : } + 175 : : + 176 : : /** + 177 : : * @dev This function returns the message from the first rule claiming the code. + 178 : : * Rule designers should keep restriction codes unique across rules. + 179 : : * If a code is shared intentionally, all rules using that code should return + 180 : : * the same message to avoid ambiguous operator feedback. + 181 : : */ + 182 : 19 : function _messageForTransferRestriction(uint8 restrictionCode) internal view virtual returns (string memory) { + 183 : 19 : uint256 rulesLength = rulesCount(); + 184 : 19 : for (uint256 i = 0; i < rulesLength; ++i) { + 185 [ + ]: 16 : if (IRule(rule(i)).canReturnTransferRestrictionCode(restrictionCode)) { + 186 : 14 : return IRule(rule(i)).messageForTransferRestriction(restrictionCode); + 187 : : } + 188 : : } + 189 : 5 : return "Unknown restriction code"; + 190 : : } + 191 : : + 192 : : /** + 193 : : * @dev Override to add ERC-165 interface check for the full IRule hierarchy. + 194 : : */ + 195 : 253 : function _checkRule(address rule_) internal view virtual override { + 196 : 253 : RulesManagementModule._checkRule(rule_); + 197 [ + ]: 244 : if (!ERC165Checker.supportsInterface(rule_, RuleInterfaceId.IRULE_INTERFACE_ID)) { + 198 : 6 : revert RuleEngine_RuleInvalidInterface(); + 199 : : } + 200 : : } + 201 : : + 202 : : /** + 203 : : * @dev Shared ERC-165 checks common to all RuleEngine deployment variants. + 204 : : * Concrete deployments can extend this with access-control-specific interfaces. + 205 : : */ + 206 : 56 : function _supportsRuleEngineBaseInterface(bytes4 interfaceId) internal pure returns (bool) { + 207 : 56 : return interfaceId == RuleEngineInterfaceId.RULE_ENGINE_INTERFACE_ID + 208 : 51 : || interfaceId == ERC1404InterfaceId.IERC1404_INTERFACE_ID + 209 : 41 : || interfaceId == ERC1404ExtendInterfaceId.ERC1404EXTEND_INTERFACE_ID + 210 : 36 : || interfaceId == ComplianceInterfaceId.ERC3643_COMPLIANCE_INTERFACE_ID + 211 : 31 : || interfaceId == ComplianceInterfaceId.ERC3643_COMPLIANCE_EXTENDED_INTERFACE_ID + 212 : 21 : || interfaceId == ComplianceInterfaceId.IERC7551_COMPLIANCE_INTERFACE_ID; + 213 : : } + 214 : : } 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 2d808cf..84148a7 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-05 13:03:55 + 2026-05-06 17:22:22 Functions: 6 @@ -78,19 +78,19 @@ RuleEngineOwnableShared.supportsInterface - 29 + 35 RuleEngineOwnableShared.constructor - 128 + 175 RuleEngineOwnableShared._msgSender - 181 + 249 RuleEngineOwnableShared._contextSuffixLength - 183 + 251
diff --git a/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.func.html b/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.func.html index 2f76325..b9f0c93 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-05 13:03:55 + 2026-05-06 17:22:22 Functions: 6 @@ -74,7 +74,7 @@ RuleEngineOwnableShared._contextSuffixLength - 183 + 251 RuleEngineOwnableShared._msgData @@ -82,15 +82,15 @@ RuleEngineOwnableShared._msgSender - 181 + 249 RuleEngineOwnableShared.constructor - 128 + 175 RuleEngineOwnableShared.supportsInterface - 29 + 35
diff --git a/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.gcov.html b/doc/coverage/coverage/src/RuleEngineOwnableShared.sol.gcov.html index 96d5846..cb1af0e 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-05 13:03:55 + 2026-05-06 17:22:22 Functions: 6 @@ -90,15 +90,15 @@ 19 : : * (`Ownable` or `Ownable2Step`) while reusing constructor, ERC-165 and ERC-2771 code. 20 : : */ 21 : : abstract contract RuleEngineOwnableShared is ERC2771ModuleStandalone, RuleEngineBase, ERC165 { - 22 : 128 : constructor(address forwarderIrrevocable, address tokenContract) ERC2771ModuleStandalone(forwarderIrrevocable) { - 23 [ + ]: 128 : if (tokenContract != address(0)) { + 22 : 175 : constructor(address forwarderIrrevocable, address tokenContract) ERC2771ModuleStandalone(forwarderIrrevocable) { + 23 [ + ]: 175 : if (tokenContract != address(0)) { 24 : 1 : _bindToken(tokenContract); 25 : : } 26 : : } 27 : : 28 : : /* ============ ERC-165 ============ */ - 29 : 29 : function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { - 30 : 29 : return _supportsRuleEngineBaseInterface(interfaceId) || interfaceId == OwnableInterfaceId.IERC173_INTERFACE_ID + 29 : 35 : function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { + 30 : 35 : return _supportsRuleEngineBaseInterface(interfaceId) || interfaceId == OwnableInterfaceId.IERC173_INTERFACE_ID 31 : 5 : || ERC165.supportsInterface(interfaceId); 32 : : } 33 : : @@ -118,8 +118,8 @@ 47 : : /** 48 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule 49 : : */ - 50 : 181 : function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) { - 51 : 181 : return ERC2771Context._msgSender(); + 50 : 249 : function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) { + 51 : 249 : return ERC2771Context._msgSender(); 52 : : } 53 : : 54 : : /** @@ -132,8 +132,8 @@ 61 : : /** 62 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule 63 : : */ - 64 : 183 : function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) { - 65 : 183 : return ERC2771Context._contextSuffixLength(); + 64 : 251 : function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) { + 65 : 251 : return ERC2771Context._contextSuffixLength(); 66 : : } 67 : : } 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 be7f6ec..22e3bc9 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-05 13:03:55 + 2026-05-06 17:22:22 Functions: 10 @@ -78,23 +78,23 @@ RuleEngine.supportsInterface - 17 + 21 - RuleEngine._onlyComplianceManager - 18 + RuleEngine.grantRole + 39 - RuleEngine.grantRole - 22 + RuleEngine._onlyComplianceManager + 42 RuleEngine.constructor - 146 + 165 RuleEngine.hasRole - 154 + 173 RuleEngine._onlyRulesManager @@ -102,11 +102,11 @@ RuleEngine._msgSender - 450 + 535 RuleEngine._contextSuffixLength - 451 + 536
diff --git a/doc/coverage/coverage/src/deployment/RuleEngine.sol.func.html b/doc/coverage/coverage/src/deployment/RuleEngine.sol.func.html index 1cb351b..8984abe 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-05 13:03:55 + 2026-05-06 17:22:22 Functions: 10 @@ -70,7 +70,7 @@ RuleEngine._contextSuffixLength - 451 + 536 RuleEngine._msgData @@ -78,11 +78,11 @@ RuleEngine._msgSender - 450 + 535 RuleEngine._onlyComplianceManager - 18 + 42 RuleEngine._onlyRulesLimitManager @@ -94,19 +94,19 @@ RuleEngine.constructor - 146 + 165 RuleEngine.grantRole - 22 + 39 RuleEngine.hasRole - 154 + 173 RuleEngine.supportsInterface - 17 + 21
diff --git a/doc/coverage/coverage/src/deployment/RuleEngine.sol.gcov.html b/doc/coverage/coverage/src/deployment/RuleEngine.sol.gcov.html index 25a82b7..42edf71 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-05 13:03:55 + 2026-05-06 17:22:22 Functions: 10 @@ -95,16 +95,16 @@ 24 : : * @param admin Address of the contract (Access Control) 25 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support 26 : : */ - 27 : 146 : constructor(address admin, address forwarderIrrevocable, address tokenContract) + 27 : 165 : constructor(address admin, address forwarderIrrevocable, address tokenContract) 28 : : ERC2771ModuleStandalone(forwarderIrrevocable) 29 : : { - 30 [ + ]: 146 : if (admin == address(0)) { + 30 [ + ]: 165 : if (admin == address(0)) { 31 : 1 : revert RuleEngine_AdminWithAddressZeroNotAllowed(); 32 : : } - 33 [ + ]: 145 : if (tokenContract != address(0)) { + 33 [ + ]: 164 : if (tokenContract != address(0)) { 34 : 31 : _bindToken(tokenContract); 35 : : } - 36 : 145 : _grantRole(DEFAULT_ADMIN_ROLE, admin); + 36 : 164 : _grantRole(DEFAULT_ADMIN_ROLE, admin); 37 : : } 38 : : 39 : : /* ============ ACCESS CONTROL ============ */ @@ -112,54 +112,54 @@ 41 : : * @notice Grants `role` to `account`. 42 : : * @dev Prevents granting any role to accounts already configured as rules. 43 : : */ - 44 : 22 : function grantRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) { - 45 [ + ]: 22 : if (_rules.contains(account)) { + 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 : 19 : AccessControl.grantRole(role, account); + 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 : 154 : function hasRole(bytes32 role, address account) + 55 : 173 : function hasRole(bytes32 role, address account) 56 : : public 57 : : view 58 : : virtual 59 : : override(AccessControl, IAccessControl) 60 : : returns (bool) 61 : : { - 62 [ + + ]: 413 : if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { - 63 : 219 : return true; + 62 [ + + ]: 490 : if (AccessControl.hasRole(DEFAULT_ADMIN_ROLE, account)) { + 63 : 236 : return true; 64 : : } else { - 65 : 194 : return AccessControl.hasRole(role, account); + 65 : 254 : return AccessControl.hasRole(role, account); 66 : : } 67 : : } 68 : : 69 : : /* ============ ERC-165 ============ */ - 70 : 17 : function supportsInterface(bytes4 interfaceId) + 70 : 21 : function supportsInterface(bytes4 interfaceId) 71 : : public 72 : : view 73 : : virtual 74 : : override(AccessControlEnumerable, IERC165) 75 : : returns (bool) 76 : : { - 77 : 17 : return _supportsRuleEngineBaseInterface(interfaceId) || AccessControlEnumerable.supportsInterface(interfaceId); + 77 : 21 : return _supportsRuleEngineBaseInterface(interfaceId) || AccessControlEnumerable.supportsInterface(interfaceId); 78 : : } 79 : : 80 : : /*////////////////////////////////////////////////////////////// 81 : : ERC-2771 82 : : //////////////////////////////////////////////////////////////*/ - 83 : 18 : function _onlyComplianceManager() internal virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) {} + 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 : 450 : function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) { - 91 : 450 : return ERC2771Context._msgSender(); + 90 : 535 : function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) { + 91 : 535 : return ERC2771Context._msgSender(); 92 : : } 93 : : 94 : : /** @@ -172,8 +172,8 @@ 101 : : /** 102 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule 103 : : */ - 104 : 451 : function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) { - 105 : 451 : return ERC2771Context._contextSuffixLength(); + 104 : 536 : function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) { + 105 : 536 : return ERC2771Context._contextSuffixLength(); 106 : : } 107 : : } 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 43de197..95ca527 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-05 13:03:55 + 2026-05-06 17:22:22 Functions: 7 @@ -82,7 +82,7 @@ RuleEngineOwnable._onlyComplianceManager - 22 + 46 RuleEngineOwnable._onlyRulesManager @@ -90,11 +90,11 @@ RuleEngineOwnable._msgSender - 146 + 181 RuleEngineOwnable._contextSuffixLength - 147 + 182
diff --git a/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.func.html b/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.func.html index 778686c..d36afdf 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-05 13:03:55 + 2026-05-06 17:22:22 Functions: 7 @@ -70,7 +70,7 @@ RuleEngineOwnable._contextSuffixLength - 147 + 182 RuleEngineOwnable._msgData @@ -78,11 +78,11 @@ RuleEngineOwnable._msgSender - 146 + 181 RuleEngineOwnable._onlyComplianceManager - 22 + 46 RuleEngineOwnable._onlyRulesLimitManager diff --git a/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.gcov.html b/doc/coverage/coverage/src/deployment/RuleEngineOwnable.sol.gcov.html index c3c3e37..3f1c9d9 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-05 13:03:55 + 2026-05-06 17:22:22 Functions: 7 @@ -101,7 +101,7 @@ 30 : : /** 31 : : * @dev Access control check using Ownable pattern 32 : : */ - 33 : 22 : function _onlyComplianceManager() internal virtual override onlyOwner {} + 33 : 46 : function _onlyComplianceManager() internal virtual override onlyOwner {} 34 : : 35 : : /** 36 : : * @notice Transfers ownership of the contract to a new account (`newOwner`). @@ -115,8 +115,8 @@ 44 : : /** 45 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule 46 : : */ - 47 : 146 : function _msgSender() internal view virtual override(RuleEngineOwnableShared, Context) returns (address sender) { - 48 : 146 : return RuleEngineOwnableShared._msgSender(); + 47 : 181 : function _msgSender() internal view virtual override(RuleEngineOwnableShared, Context) returns (address sender) { + 48 : 181 : return RuleEngineOwnableShared._msgSender(); 49 : : } 50 : : 51 : : /** @@ -129,8 +129,8 @@ 58 : : /** 59 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule 60 : : */ - 61 : 147 : function _contextSuffixLength() internal view virtual override(RuleEngineOwnableShared, Context) returns (uint256) { - 62 : 147 : return RuleEngineOwnableShared._contextSuffixLength(); + 61 : 182 : function _contextSuffixLength() internal view virtual override(RuleEngineOwnableShared, Context) returns (uint256) { + 62 : 182 : return RuleEngineOwnableShared._contextSuffixLength(); 63 : : } 64 : : } 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 d43fc3b..4c225ed 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 @@ -31,17 +31,17 @@ lcov.info Lines: - 12 - 12 + 15 + 15 100.0 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 7 - 7 + 8 + 8 100.0 % @@ -69,32 +69,36 @@ Hit count Sort by hit count - RuleEngineOwnable2Step._msgData + RuleEngineOwnable2Step._msgData 1 - RuleEngineOwnable2Step._onlyRulesLimitManager + RuleEngineOwnable2Step._onlyRulesLimitManager 2 - RuleEngineOwnable2Step._onlyComplianceManager - 3 - - - RuleEngineOwnable2Step._onlyRulesManager + RuleEngineOwnable2Step._onlyRulesManager 5 - RuleEngineOwnable2Step.transferOwnership + RuleEngineOwnable2Step.transferOwnership 6 - RuleEngineOwnable2Step._msgSender - 35 + RuleEngineOwnable2Step.supportsInterface + 13 + + + RuleEngineOwnable2Step._onlyComplianceManager + 25 + + + RuleEngineOwnable2Step._msgSender + 68 - RuleEngineOwnable2Step._contextSuffixLength - 36 + 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 95204c6..9187783 100644 --- a/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.func.html +++ b/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.func.html @@ -31,17 +31,17 @@ lcov.info Lines: - 12 - 12 + 15 + 15 100.0 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 7 - 7 + 8 + 8 100.0 % @@ -69,31 +69,35 @@ Hit count Sort by hit count - RuleEngineOwnable2Step._contextSuffixLength - 36 + RuleEngineOwnable2Step._contextSuffixLength + 69 - RuleEngineOwnable2Step._msgData + RuleEngineOwnable2Step._msgData 1 - RuleEngineOwnable2Step._msgSender - 35 + RuleEngineOwnable2Step._msgSender + 68 - RuleEngineOwnable2Step._onlyComplianceManager - 3 + RuleEngineOwnable2Step._onlyComplianceManager + 25 - RuleEngineOwnable2Step._onlyRulesLimitManager + RuleEngineOwnable2Step._onlyRulesLimitManager 2 - RuleEngineOwnable2Step._onlyRulesManager + RuleEngineOwnable2Step._onlyRulesManager 5 - RuleEngineOwnable2Step.transferOwnership + RuleEngineOwnable2Step.supportsInterface + 13 + + + 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 7d77041..ab3556d 100644 --- a/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.gcov.html +++ b/doc/coverage/coverage/src/deployment/RuleEngineOwnable2Step.sol.gcov.html @@ -31,17 +31,17 @@ lcov.info Lines: - 12 - 12 + 15 + 15 100.0 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 7 - 7 + 8 + 8 100.0 % @@ -78,63 +78,70 @@ 7 : : import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; 8 : : import {Context} from "@openzeppelin/contracts/utils/Context.sol"; 9 : : import {RuleEngineOwnableShared} from "../RuleEngineOwnableShared.sol"; - 10 : : - 11 : : /** - 12 : : * @title Implementation of a ruleEngine with ERC-173 Ownable2Step access control - 13 : : */ - 14 : : contract RuleEngineOwnable2Step is RuleEngineOwnableShared, Ownable2Step { - 15 : : /** - 16 : : * @param owner_ Address of the contract owner (ERC-173) - 17 : : * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - 18 : : * @param tokenContract Address of the token contract to bind (can be zero address) - 19 : : */ - 20 : : constructor(address owner_, address forwarderIrrevocable, address tokenContract) - 21 : : RuleEngineOwnableShared(forwarderIrrevocable, tokenContract) - 22 : : Ownable(owner_) - 23 : : {} - 24 : : - 25 : : /* ============ ACCESS CONTROL ============ */ - 26 : : /** - 27 : : * @dev Access control check using Ownable pattern - 28 : : */ - 29 : 5 : function _onlyRulesManager() internal virtual override onlyOwner {} - 30 : 2 : function _onlyRulesLimitManager() internal virtual override onlyOwner {} - 31 : : - 32 : : /** - 33 : : * @dev Access control check using Ownable pattern - 34 : : */ - 35 : 3 : function _onlyComplianceManager() internal virtual override onlyOwner {} - 36 : : - 37 : : /** - 38 : : * @notice Starts ownership transfer to `newOwner`. - 39 : : * @dev Reverts when `newOwner` is already configured as a rule. - 40 : : */ - 41 : 6 : function transferOwnership(address newOwner) public virtual override onlyOwner { - 42 : 6 : RuleEngineOwnableShared._checkOwnershipTransferTarget(newOwner); - 43 : 5 : Ownable2Step.transferOwnership(newOwner); - 44 : : } - 45 : : - 46 : : /** - 47 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule - 48 : : */ - 49 : 35 : function _msgSender() internal view virtual override(RuleEngineOwnableShared, Context) returns (address sender) { - 50 : 35 : return RuleEngineOwnableShared._msgSender(); + 10 : : import {Ownable2StepInterfaceId} from "../modules/library/Ownable2StepInterfaceId.sol"; + 11 : : + 12 : : /** + 13 : : * @title Implementation of a ruleEngine with ERC-173 Ownable2Step access control + 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 : 1 : function _msgData() internal view virtual override(RuleEngineOwnableShared, Context) returns (bytes calldata) { - 57 : 1 : return RuleEngineOwnableShared._msgData(); + 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 : 36 : function _contextSuffixLength() internal view virtual override(RuleEngineOwnableShared, Context) returns (uint256) { - 64 : 36 : return RuleEngineOwnableShared._contextSuffixLength(); + 63 : 1 : function _msgData() internal view virtual override(RuleEngineOwnableShared, Context) returns (bytes calldata) { + 64 : 1 : return RuleEngineOwnableShared._msgData(); 65 : : } - 66 : : } + 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 : : } diff --git a/doc/coverage/coverage/src/deployment/index-sort-b.html b/doc/coverage/coverage/src/deployment/index-sort-b.html index ed7dd14..5ef3ff6 100644 --- a/doc/coverage/coverage/src/deployment/index-sort-b.html +++ b/doc/coverage/coverage/src/deployment/index-sort-b.html @@ -31,17 +31,17 @@ lcov.info Lines: - 49 - 49 + 52 + 52 100.0 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 24 - 24 + 25 + 25 100.0 % @@ -99,9 +99,9 @@
100.0%
100.0 % - 12 / 12 + 15 / 15 100.0 % - 7 / 7 + 8 / 8 - 0 / 0 diff --git a/doc/coverage/coverage/src/deployment/index-sort-f.html b/doc/coverage/coverage/src/deployment/index-sort-f.html index 465762f..414a352 100644 --- a/doc/coverage/coverage/src/deployment/index-sort-f.html +++ b/doc/coverage/coverage/src/deployment/index-sort-f.html @@ -31,17 +31,17 @@ lcov.info Lines: - 49 - 49 + 52 + 52 100.0 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 24 - 24 + 25 + 25 100.0 % @@ -99,9 +99,9 @@
100.0%
100.0 % - 12 / 12 + 15 / 15 100.0 % - 7 / 7 + 8 / 8 - 0 / 0 diff --git a/doc/coverage/coverage/src/deployment/index-sort-l.html b/doc/coverage/coverage/src/deployment/index-sort-l.html index 761e2e1..eefd8bd 100644 --- a/doc/coverage/coverage/src/deployment/index-sort-l.html +++ b/doc/coverage/coverage/src/deployment/index-sort-l.html @@ -31,17 +31,17 @@ lcov.info Lines: - 49 - 49 + 52 + 52 100.0 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 24 - 24 + 25 + 25 100.0 % @@ -99,9 +99,9 @@
100.0%
100.0 % - 12 / 12 + 15 / 15 100.0 % - 7 / 7 + 8 / 8 - 0 / 0 diff --git a/doc/coverage/coverage/src/deployment/index.html b/doc/coverage/coverage/src/deployment/index.html index 02b7147..a680e27 100644 --- a/doc/coverage/coverage/src/deployment/index.html +++ b/doc/coverage/coverage/src/deployment/index.html @@ -31,17 +31,17 @@ lcov.info Lines: - 49 - 49 + 52 + 52 100.0 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: - 24 - 24 + 25 + 25 100.0 % @@ -111,9 +111,9 @@
100.0%
100.0 % - 12 / 12 + 15 / 15 100.0 % - 7 / 7 + 8 / 8 - 0 / 0 diff --git a/doc/coverage/coverage/src/index-sort-b.html b/doc/coverage/coverage/src/index-sort-b.html index bd41fc0..353a9a9 100644 --- a/doc/coverage/coverage/src/index-sort-b.html +++ b/doc/coverage/coverage/src/index-sort-b.html @@ -31,13 +31,13 @@ lcov.info Lines: - 63 - 63 + 64 + 64 100.0 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: 20 @@ -99,7 +99,7 @@
100.0%
100.0 % - 48 / 48 + 49 / 49 100.0 % 14 / 14 100.0 % diff --git a/doc/coverage/coverage/src/index-sort-f.html b/doc/coverage/coverage/src/index-sort-f.html index 6a0b8cd..8f77607 100644 --- a/doc/coverage/coverage/src/index-sort-f.html +++ b/doc/coverage/coverage/src/index-sort-f.html @@ -31,13 +31,13 @@ lcov.info Lines: - 63 - 63 + 64 + 64 100.0 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: 20 @@ -99,7 +99,7 @@
100.0%
100.0 % - 48 / 48 + 49 / 49 100.0 % 14 / 14 100.0 % diff --git a/doc/coverage/coverage/src/index-sort-l.html b/doc/coverage/coverage/src/index-sort-l.html index 36d479c..d4235ae 100644 --- a/doc/coverage/coverage/src/index-sort-l.html +++ b/doc/coverage/coverage/src/index-sort-l.html @@ -31,13 +31,13 @@ lcov.info Lines: - 63 - 63 + 64 + 64 100.0 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: 20 @@ -99,7 +99,7 @@
100.0%
100.0 % - 48 / 48 + 49 / 49 100.0 % 14 / 14 100.0 % diff --git a/doc/coverage/coverage/src/index.html b/doc/coverage/coverage/src/index.html index eaa4aa1..d0fc157 100644 --- a/doc/coverage/coverage/src/index.html +++ b/doc/coverage/coverage/src/index.html @@ -31,13 +31,13 @@ lcov.info Lines: - 63 - 63 + 64 + 64 100.0 % Date: - 2026-05-05 13:03:55 + 2026-05-06 17:22:22 Functions: 20 @@ -87,7 +87,7 @@
100.0%
100.0 % - 48 / 48 + 49 / 49 100.0 % 14 / 14 100.0 % 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 new file mode 100644 index 0000000..13d1d9a --- /dev/null +++ b/doc/coverage/coverage/src/modules/ERC3643ComplianceExtendedModule.sol.func-sort-c.html @@ -0,0 +1,109 @@ + + + + + + + LCOV - lcov.info - src/modules/ERC3643ComplianceExtendedModule.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - src/modules - ERC3643ComplianceExtendedModule.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:2424100.0 %
Date:2026-05-06 17:22:22Functions:77100.0 %
Branches:55100.0 %
+
+ +