Releases: CMTA/Rules
Releases · CMTA/Rules
v0.3.0
Security
- H1 fix —
RuleConditionalTransferLight: enforced single-token binding by overridingbindTokento revert withRuleConditionalTransferLight_TokenAlreadyBoundif a token is already bound. Eliminates cross-token approval replay and approval-draining attacks. UseunbindTokenfirst to migrate to a new token. - M1 fix — Added
IERC7551Compliance(0x7157797f),IERC3643IComplianceContract(validation rules), and the full ERC-3643IComplianceID via flat mockIERC3643ComplianceFull(0x3144991c) to allsupportsInterfaceimplementations. Silentfalseon ERC-165 introspection no longer occurs for compliant callers.
Added
RuleConditionalTransferLightApprovalBase— new abstract contract holding the pure approval state machine (approval counts,approveTransfer,cancelTransferApproval,approvedCount, and thetransferredcallback). No ERC-3643 / IRule knowledge.IERC3643ComplianceFull(src/mocks/IERC3643ComplianceFull.sol) — flat mock interface redeclaring all eight ERC-3643ICompliancefunctions; used to compute the correct ERC-165 ID (0x3144991c) sincetype(IERC3643Compliance).interfaceIdonly XORs directly-defined selectors.
Changed
RuleConditionalTransferLightBaserefactored into two layers:RuleConditionalTransferLightApprovalBase(state machine) +RuleConditionalTransferLightBase(ERC-3643 / IRule compliance integration). Eliminates code duplication between the AccessControl and Ownable2Step variants.RuleConditionalTransferLightOwnable2Stepnow inheritsERC3643ComplianceModulevia the base (consistent with the AccessControl variant);_authorizeTransferExecutionconsolidated into the base and checksisTokenBound(_msgSender()).approveAndTransferIfAllowedno longer takes atokenparameter — bound token is retrieved directly viagetTokenBound().RuleConditionalTransferLightBase.approveAndTransferIfAllowednow uses OpenZeppelinSafeERC20.safeTransferFromto handle non-standard ERC-20 return behavior safely.- Removed unused custom error
RuleConditionalTransferLight_TransferFailedfromRuleConditionalTransferLightInvariantStorage. - Custom error
RuleConditionalTransferLight_TokenAddressZeroNotAllowedrenamed toRuleConditionalTransferLight_TokenNotBoundfor clarity. RuleERC2980andRuleERC2980Ownable2Stepconstructors now includeallowBurnand whitelistaddress(0)at deployment when enabled.RuleWhitelistandRuleWhitelistOwnable2Stepconstructors now includeallowMintBurn; when enabled,address(0)is pre-listed at deployment.- Solidity style guide ordering (type declarations → state variables → events → errors → modifiers → functions; constructor → external → public → internal → private) enforced across all
src/contracts. supportsInterfaceinRuleConditionalTransferLightandRuleConditionalTransferLightOwnable2Stepnow advertisesIERC7551Complianceand the full ERC-3643IComplianceinterface ID instead of the narrowIERC3643IComplianceContract.supportsInterfaceinRuleTransferValidation(cascades to all validation rules) now also advertisesIERC7551ComplianceandIERC3643IComplianceContract.- Update contract version to
0.3.0
Dependencies
- Update RuleEngine to
v3.0.0-rc2. - Update OpenZeppelin Contracts to
v5.6.1. - Update OpenZeppelin Contracts Upgradeable to
v5.6.1.
Documentation
- Wake Arena (Ackee Blockchain Security) AI-assisted static analysis report and project feedback added to
doc/security/audits/tools/v0.2.0/. - README Security section updated with Wake Arena findings summary table.
- README Access Control section updated to document intentional
DEFAULT_ADMIN_ROLEimplicit-role behaviour,grantRoleno-op semantics, and off-chain monitoring guidance (I2). RuleERC2980documentation updated to clarify that a frozen address acting astransferFromspender is also blocked (code 62) (I1).RuleERC2980documentation and README updated to document burn/redemption behavior and the new constructorallowBurnoption.RuleWhitelistdocumentation and README updated to document constructorallowMintBurnand zero-address mint/burn handling.- README updated to document Hardhat support for optional compilation and smoke testing alongside Foundry-first workflows.
CLAUDE.md/AGENTS.mdconvention added: always use pre-computed library constants for ERC-165 IDs; use a flat mock interface when no constant exists.
Testing
- Added
RuleERC2980constructor tests covering default burn-blocked behavior andallowBurn=truezero-address whitelisting. - Added
RuleWhitelistconstructor tests coveringallowMintBurn=truezero-address pre-listing. - Added a Hardhat smoke test (
test/hardhat/smoke.test.js) and npm scripts for Hardhat compile/smoke execution. - Updated
RuleConditionalTransferLightApproveAndTransfertransfer-failure test to assert OpenZeppelinSafeERC20revert semantics. - Removed now-unused
RuleConditionalTransferLight_TransferFaileddeclaration; no behavior change.
We would like to thank @amilazz as well as CMTA Tech Comite for their valuable feedback and contributions to this release. Their input played an important role in improving the project, and we sincerely appreciate their support.
v0.2.0
Added
RuleSpenderWhitelist— validation rule that blockstransferFromwhen spender is not listed; direct transfers are always allowed. Restriction code 66.RuleSpenderWhitelistOwnable2Step— Ownable2Step variant ofRuleSpenderWhitelist.- Technical documentation file
doc/technical/RuleSpenderWhitelist.md. - Transfer-context mocks in
src/mocks:MockERC20WithTransferContextandMockERC721WithTransferContext. - Transfer-context mocks in
src/mocksnow inherit OpenZeppelinERC20/ERC721and emit rule callbacks throughITransferContext. - Transfer-context tests for ERC-20/ERC-721 mock integration in
test/TransferContext/TransferContextMocks.t.sol. RuleERC2980— ERC-2980 Swiss Compliant rule combining a whitelist (recipient-only) and a frozenlist (blocks sender, recipient, and spender); frozenlist takes priority. Restriction codes 60–63.RuleERC2980Ownable2Step— Ownable2Step variant ofRuleERC2980.IERC2980interface with NatSpec documenting the deviation from the ERC example interfaces (single-item functions revert on invalid input rather than returningbool).isVerified(address)toRuleERC2980BaseandRuleWhitelistWrapperBase, implementingIIdentityRegistryVerified; for ERC-2980 it reflects whitelist membership only (frozen status is excluded).VersionModule— abstract module implementingIERC3643Version; all rules now exposeversion()returning"0.2.0".- New deployable rules:
RuleIdentityRegistry,RuleMaxTotalSupply,RuleConditionalTransferLight. - Ownable2Step variants for all rules:
RuleWhitelistOwnable2Step,RuleBlacklistOwnable2Step,RuleSanctionsListOwnable2Step,RuleMaxTotalSupplyOwnable2Step,RuleIdentityRegistryOwnable2Step,RuleWhitelistWrapperOwnable2Step,RuleConditionalTransferLightOwnable2Step. - Transfer-context struct API:
MultiTokenTransferContext/FungibleTransferContextwith an extradatafield. - Explicit sanctions oracle clearing via
clearSanctionListOracle(). - CMTAT deployment scripts for whitelist and blacklist configurations.
DeployCMTATWithBlacklistAndSanctionsListdeployment script — deploys a CMTAT token wired to aRuleEngineconfigured with bothRuleBlacklistandRuleSanctionsList.- Technical documentation for all rules in
doc/technical/: addedRuleMaxTotalSupply.md,RuleIdentityRegistry.md,RuleERC2980.md,RuleConditionalTransferLight.md; updatedRuleWhitelist.md,RuleBlacklist.md,RuleSanctionList.md,RuleWhitelistWrapper.md.
Changed
- RBAC variants now use
AccessControlEnumerable(replacing plainAccessControl); role members can be enumerated withgetRoleMember/getRoleMemberCount. - Default admin implicitly holds all roles via a
hasRoleoverride; may not appear in role member enumerations unless explicitly granted. - Authorization hooks (
_authorize*()) now useonlyRole(ROLE)modifier instead of direct_checkRolecalls. - All
internalfunctions markedvirtualto allow downstream overriding. - Validation flow refactored to internal hooks (no
this.calls) viaRuleTransferValidationandRuleNFTAdapter. RuleConditionalTransferLightandRuleMaxTotalSupplyare ERC-20 only; ERC-721/1155 compliance interfaces are limited to validation rules.- Address list batch updates emit only add/remove events (no summary events).
- Reorganized validation contracts into
abstract/base,abstract/core,abstract/invariant, anddeploymentfolders. - Rule transfer-context dispatch now treats
sender == fromas direct transfer (non-spender path) inRuleNFTAdapter. - Concrete utilities and harness contracts used by tests were moved from
test/intosrc/mocksandsrc/mocks/harness.
Dependencies
- Updated Solidity toolchain to 0.8.34.
- Update OpenZeppelin to 5.6.0
- Update CMTAT to v3.2.0
- Update RuleEngine to v3.0.0-rc1
Documentation
- Access-control role table with keccak256 hashes.
- Rule-engine flow diagrams, API accuracy, directory layout notes.
- Static analysis reports (Aderyn, Slither) with project feedback in
doc/security/audits/tools/v0.2.0/. - Gas benchmarks in
doc/GAS.mdand.gas-snapshot.
v0.1.0
First release !
-
Update Rules to CMTAT v3.0.0 and latest RuleEngine version
-
Use EnumerableSet from OpenZeppelin to store address status for blacklist and whitelist rules.
-
Add function
canTransferFrom,detectTransferRestrictionFromwhich takes the spender argument -
Add functions
canTransfer,canTransferFrom,detectTransferRestriction,detectTransferRestrictionFromwhich takes thetokenIdargument. -
Add support of ERC-165 in each rule.