Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
4da330f
Update CMTAT and RuleEngine library
rya-sge Feb 23, 2026
0a3d229
Add integration test with RuleEngine
rya-sge Feb 23, 2026
4b9c40a
Add ci profil
rya-sge Feb 23, 2026
bb076f2
Add new Operation rule Transfer Light
rya-sge Feb 23, 2026
8aa05b5
Add rule on max total supply
rya-sge Feb 23, 2026
765e0e0
Add identity rule
rya-sge Feb 23, 2026
83b76c6
Implement flexible access control with ownable version for two rules
rya-sge Feb 24, 2026
20c424d
Use Ownable2Steps instead of Ownable
rya-sge Feb 26, 2026
23e62e5
Fix warning and lint issues
rya-sge Feb 27, 2026
4fc6f88
Implement sanctions oracle clear, approval cancel, and whitelist wrap…
rya-sge Mar 3, 2026
ff41664
Improve documentation
rya-sge Mar 3, 2026
38d4b95
Fix RuleNFTAdapter overloads and batch summary events
rya-sge Mar 3, 2026
2e0a0b7
Refactor transfer hooks to avoid external calls; run tests and update…
rya-sge Mar 3, 2026
193f2a0
Align rule restriction codes to README
rya-sge Mar 3, 2026
7b8993f
Update Solidity version to 0.8.34
rya-sge Mar 3, 2026
342466a
Rename files and create sub directory
rya-sge Mar 3, 2026
e97877e
Update changelog
rya-sge Mar 3, 2026
5353b0c
Update surya schema
rya-sge Mar 3, 2026
b8bd65d
Create two separate contet for ERC-20 and NFT
rya-sge Mar 3, 2026
be0d12d
Use require with custom error, remove skip address event for gas opti…
rya-sge Mar 4, 2026
2647371
Rename contract to specify Ownable2Step
rya-sge Mar 4, 2026
c227576
Update and improve readme
rya-sge Mar 4, 2026
91f9d3a
Add test with deployment script
rya-sge Mar 4, 2026
cfde948
Raname contract and add Owanble2Step variant for all contracts
rya-sge Mar 4, 2026
13aa86f
Remove ERC-721/1155 compatibility from max total supply rule and upda…
rya-sge Mar 4, 2026
aa742a8
Rename transfer context structs to MultiTokenTransferContext and Fung…
rya-sge Mar 4, 2026
53376a6
Add data argument to transfer context
rya-sge Mar 4, 2026
10c10fb
Use onlyOwner in Ownable2Step rules, harden ConditionalTransferLight…
rya-sge Mar 5, 2026
baa506f
Make all internal functions virtual across rule contracts
rya-sge Mar 5, 2026
fdc8dea
Use onlyRole in AccessControl rule authorization hooks
rya-sge Mar 5, 2026
16c6261
update document and agent files
rya-sge Mar 5, 2026
230f0f6
Add access control enumerable
rya-sge Mar 5, 2026
c75eb18
Give admin all roles by default for RBAC rules + Add dev note for adm…
rya-sge Mar 5, 2026
3cdac1b
Update conditional transfer docs and role member test
rya-sge Mar 5, 2026
926ce37
Add rule which implement ERC-2980
rya-sge Mar 9, 2026
3066855
feat: add RuleERC2980 (ERC-2980 whitelist + frozenlist compliance rule)
rya-sge Mar 9, 2026
5047dc0
Add Ownable2Step version for ERC-2980 rules
rya-sge Mar 9, 2026
6ec9b4d
update package
rya-sge Mar 9, 2026
722c8f7
Update library
rya-sge Mar 9, 2026
907cefb
Update library
rya-sge Mar 9, 2026
7a192f4
update workflow
rya-sge Mar 9, 2026
005afad
Update doc and add gas snapshot
rya-sge Mar 9, 2026
dd11c39
Fix failing test
rya-sge Mar 9, 2026
aa1d969
Run Slither and Aderyn and fix relevant issues
rya-sge Mar 9, 2026
79eec3f
Update readme
rya-sge Mar 9, 2026
ed20c31
Add contract version
rya-sge Mar 9, 2026
d5301c6
update changelog
rya-sge Mar 9, 2026
20776c5
Merge pull request #5 from CMTA/update-lib
rya-sge Mar 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 178 additions & 0 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
CMTATIntegration:testCanMakeATransfer() (gas: 201782)
CMTATIntegration:testCanMint() (gas: 207062)
CMTATIntegration:testCanMintIfAddressNotInTheBlacklist() (gas: 85398)
CMTATIntegration:testCanReturnMessageNotFoundWithUnknownCodeId() (gas: 24277)
CMTATIntegration:testCanTransferIfAddressNotBlacklisted() (gas: 56371)
CMTATIntegration:testCannotMintIfAddressIsInTheBlacklist() (gas: 135889)
CMTATIntegration:testCannotTransferIfAddressFronIsBlacklisted() (gas: 112200)
CMTATIntegration:testCannotTransferIfAddressToIsBlacklisted() (gas: 114615)
CMTATIntegration:testCannotTransferIfBothAddressesAreBlacklisted() (gas: 159653)
CMTATIntegration:testCannotTransferWithoutAddressWhitelisted() (gas: 42245)
CMTATIntegration:testCannotTransferWithoutFromAddressWhitelisted() (gas: 114265)
CMTATIntegration:testCannotTransferWithoutToAddressWhitelisted() (gas: 114580)
CMTATIntegration:testDetectAndMessageWithAValidTransfer() (gas: 158914)
CMTATIntegration:testDetectAndMessageWithFromAndToBlacklisted() (gas: 163890)
CMTATIntegration:testDetectAndMessageWithFromAndToNotBlacklisted() (gas: 41557)
CMTATIntegration:testDetectAndMessageWithFromAndToNotWhitelisted() (gas: 44433)
CMTATIntegration:testDetectAndMessageWithFromBlacklisted() (gas: 139893)
CMTATIntegration:testDetectAndMessageWithFromNotWhitelisted() (gas: 141956)
CMTATIntegration:testDetectAndMessageWithToBlacklisted() (gas: 142286)
CMTATIntegration:testDetectAndMessageWithToNotWhitelisted() (gas: 142307)
CMTATIntegrationDirectBlacklist:testCanMintIfAddressNotInTheBlacklist() (gas: 50799)
CMTATIntegrationDirectBlacklist:testCanReturnMessageNotFoundWithUnknownCodeId() (gas: 16020)
CMTATIntegrationDirectBlacklist:testCanTransferIfAddressNotBlacklisted() (gas: 45848)
CMTATIntegrationDirectBlacklist:testCannotMintIfAddressIsInTheBlacklist() (gas: 103281)
CMTATIntegrationDirectBlacklist:testCannotTransferIfAddressFromIsBlacklisted() (gas: 101784)
CMTATIntegrationDirectBlacklist:testCannotTransferIfAddressToIsBlacklisted() (gas: 104156)
CMTATIntegrationDirectBlacklist:testCannotTransferIfBothAddressesAreBlacklisted() (gas: 149194)
CMTATIntegrationDirectBlacklist:testDetectAndMessageWithFromAndToBlacklisted() (gas: 151726)
CMTATIntegrationDirectBlacklist:testDetectAndMessageWithFromAndToNotBlacklisted() (gas: 33038)
CMTATIntegrationDirectBlacklist:testDetectAndMessageWithFromBlacklisted() (gas: 105580)
CMTATIntegrationDirectBlacklist:testDetectAndMessageWithToBlacklisted() (gas: 107956)
CMTATIntegrationWhitelistWrapper:testCanMakeATransfer() (gas: 213655)
CMTATIntegrationWhitelistWrapper:testCanMakeATransferIfWhitelistedInDifferentList() (gas: 253743)
CMTATIntegrationWhitelistWrapper:testCanMakeATransferIfWhitelistedInSeveralDifferentList() (gas: 378311)
CMTATIntegrationWhitelistWrapper:testCanMint() (gas: 224306)
CMTATIntegrationWhitelistWrapper:testCanReturnUnknownTextMessage() (gas: 24257)
CMTATIntegrationWhitelistWrapper:testCannotDeployContractIfAdminAddressIsZero() (gas: 65494)
CMTATIntegrationWhitelistWrapper:testCannotDeployContractIfAdminAddressIsZero() (gas: 65582)
CMTATIntegrationWhitelistWrapper:testCannotTransferWithoutAddressWhitelisted() (gas: 82714)
CMTATIntegrationWhitelistWrapper:testCannotTransferWithoutFromAddressWhitelisted() (gas: 154797)
CMTATIntegrationWhitelistWrapper:testCannotTransferWithoutToAddressWhitelisted() (gas: 155233)
CMTATIntegrationWhitelistWrapper:testDetectAndMessageWithAValidTransfer() (gas: 170646)
CMTATIntegrationWhitelistWrapper:testDetectAndMessageWithFromAndToNotWhitelisted() (gas: 84828)
CMTATIntegrationWhitelistWrapper:testDetectAndMessageWithFromNotWhitelisted() (gas: 180410)
CMTATIntegrationWhitelistWrapper:testDetectAndMessageWithToNotWhitelisted() (gas: 180839)
CMTATIntegrationWhitelistWrapper:testDetectTransferRestrictionFrom() (gas: 143561)
CMTATIntegrationWhitelistWrapper:testDetectTransferRestrictionOk() (gas: 175185)
CMTATIntegrationWhitelistWrapper:testDetectTransferRestrictionTo() (gas: 200558)
CMTATIntegrationWhitelistWrapper:testDetectTransferRestrictionWithSpender() (gas: 314254)
CMTATIntegrationWhitelistWrapper:testDetectTransferRestrictionWithSpenderOk() (gas: 262953)
CMTATIntegrationWhitelistWrapper:testReturnTheRightMessageForAGivenCode() (gas: 67900)
CMTATIntegrationWhitelistWrapper:testWrapperWithZeroRulesRejectsTransfers() (gas: 1530959)
CMTATRuleEngineIntegration:testDetectRestrictionAndCanTransferViaCMTAT() (gas: 140362)
CMTATRuleEngineIntegration:testDetectRestrictionFromAndCanTransferFromViaCMTAT() (gas: 193243)
RuleBlacklistOwnable2Step:testOnlyOwnerCanTransferOwnership() (gas: 43609)
RuleBlacklistOwnable2Step:testPendingOwnerMustAccept() (gas: 33681)
RuleBlacklistOwnableAccessControl:testNonOwnerCannotAddOrRemove() (gas: 16467)
RuleBlacklistOwnableAccessControl:testOwnerCanAddAndRemove() (gas: 66286)
RuleBlacklistRuleEngineIntegration:testDetectRestrictionAndCanTransfer() (gas: 184210)
RuleBlacklistTest:testCanRuleBlacklistReturnMessageNotFoundWithUnknownCodeId() (gas: 9569)
RuleBlacklistTest:testDetectTransferRestrictionFRom() (gas: 115135)
RuleBlacklistTest:testDetectTransferRestrictionOk() (gas: 46032)
RuleBlacklistTest:testDetectTransferRestrictionSpender() (gas: 115995)
RuleBlacklistTest:testDetectTransferRestrictionSpenderFrom() (gas: 112916)
RuleBlacklistTest:testDetectTransferRestrictionSpenderOk() (gas: 48844)
RuleBlacklistTest:testDetectTransferRestrictionSpenderTo() (gas: 116218)
RuleBlacklistTest:testDetectTransferRestrictionTO() (gas: 119279)
RuleBlacklistTest:testReturnTheRightMessageForAGivenCode() (gas: 43683)
RuleConditionalTransferLightRuleEngineIntegration:testApproveAndConsumeMultipleTransfers() (gas: 73349)
RuleConditionalTransferLightRuleEngineIntegration:testCancelApproval() (gas: 58376)
RuleConditionalTransferLightRuleEngineIntegration:testDetectRestrictionAndCanTransferWithoutApproval() (gas: 43051)
RuleConditionalTransferLightRuleEngineIntegration:testFuzz_ApproveAndConsume(address,address,uint96,uint8,uint8) (runs: 256, μ: 97587, ~: 93825)
RuleConditionalTransferLightRuleEngineIntegration:testTransferredWithoutApprovalReverts() (gas: 16065)
RuleConditionalTransferLightUnit:testApproveTransfer_OnlyOperator() (gas: 41763)
RuleConditionalTransferLightUnit:testCancelTransferApproval_OnlyOperator() (gas: 40155)
RuleConditionalTransferLightUnit:testDetectRestrictionAndCanTransferWhenApproved() (gas: 61642)
RuleConditionalTransferLightUnit:testTransferred_OnlyRuleEngineRole() (gas: 33214)
RuleConditionalTransferLightUnit:testTransferred_RevertsWhenNotApproved() (gas: 13931)
RuleEngineIntegration:testDetectRestrictionAndCanTransfer() (gas: 259275)
RuleEngineIntegration:testRulesManagerRoleRequiredToAddRule() (gas: 127990)
RuleIdentityRegistryRuleEngineIntegration:testBurnBypassesVerification() (gas: 23038)
RuleIdentityRegistryRuleEngineIntegration:testClearIdentityRegistryDisablesChecks() (gas: 49972)
RuleIdentityRegistryRuleEngineIntegration:testDetectRestrictionFromWithSpender() (gas: 134139)
RuleIdentityRegistryRuleEngineIntegration:testDetectRestrictionWhenNotVerified() (gas: 49438)
RuleIdentityRegistryRuleEngineIntegration:testDetectRestrictionWhenVerified() (gas: 97889)
RuleIdentityRegistryUnit:testClearIdentityRegistry_OnlyAdmin() (gas: 11424)
RuleIdentityRegistryUnit:testDetectRestrictionFrom_SpenderNotVerified() (gas: 84251)
RuleIdentityRegistryUnit:testDetectRestriction_BurnAllowed() (gas: 10589)
RuleIdentityRegistryUnit:testDetectRestriction_FromNotVerified() (gas: 61087)
RuleIdentityRegistryUnit:testDetectRestriction_NoRegistry_ReturnsOk() (gas: 879439)
RuleIdentityRegistryUnit:testDetectRestriction_ToNotVerified() (gas: 62299)
RuleIdentityRegistryUnit:testSetIdentityRegistry_OnlyAdmin() (gas: 13530)
RuleIdentityRegistryUnit:testSetIdentityRegistry_RevertsOnZeroAddress() (gas: 11198)
RuleIdentityRegistryUnit:testTransferredFrom_RevertsOnInvalidTransfer() (gas: 65705)
RuleIdentityRegistryUnit:testTransferred_RevertsOnInvalidTransfer() (gas: 42513)
RuleMaxTotalSupplyRuleEngineIntegration:testDetectRestrictionForMintExceedingMaxSupply() (gas: 73540)
RuleMaxTotalSupplyRuleEngineIntegration:testDetectRestrictionForMintWithinMaxSupply() (gas: 73642)
RuleMaxTotalSupplyRuleEngineIntegration:testFuzz_MaxTotalSupplyBounds(uint256,uint256,uint256) (runs: 256, μ: 79147, ~: 86502)
RuleMaxTotalSupplyRuleEngineIntegration:testSetMaxTotalSupplyToZero() (gas: 60879)
RuleMaxTotalSupplyRuleEngineIntegration:testTransfersNotAffectedByMaxSupplyRule() (gas: 67767)
RuleMaxTotalSupplyUnit:testConstructor_RevertsOnZeroToken() (gas: 61816)
RuleMaxTotalSupplyUnit:testDetectRestriction_MintExceedsMaxSupply() (gas: 60474)
RuleMaxTotalSupplyUnit:testDetectRestriction_MintWithinMaxSupply() (gas: 40505)
RuleMaxTotalSupplyUnit:testDetectRestriction_NonMintTransfer() (gas: 35624)
RuleMaxTotalSupplyUnit:testSetMaxTotalSupply_OnlyAdmin() (gas: 11453)
RuleMaxTotalSupplyUnit:testSetTokenContract_OnlyAdmin() (gas: 13672)
RuleMaxTotalSupplyUnit:testSetTokenContract_RevertsOnZero() (gas: 11307)
RuleMaxTotalSupplyUnit:testTransferredFrom_RevertsOnInvalidTransfer() (gas: 41934)
RuleMaxTotalSupplyUnit:testTransferred_RevertsOnInvalidTransfer() (gas: 41789)
RuleSanctionListDeploymentTest:testCanSetAnOracleAtDeployment() (gas: 1101957)
RuleSanctionListDeploymentTest:testCannotDeployContractIfAdminAddressIsZero() (gas: 1156635)
RuleSanctionListDeploymentTest:testRightDeployment() (gas: 2088865)
RuleSanctionListDeploymentTest:testcanTransferIfNoOracleSet() (gas: 998199)
RuleSanctionlistAddTest:testCanSetandRemoveOracle() (gas: 31172)
RuleSanctionlistAddTest:testCannotAttackerSetOracle() (gas: 16103)
RuleSanctionlistAddTest:testCannotSetOracleToZero() (gas: 11345)
RuleSanctionlistTest:testCanReturnTransferRestrictionCode() (gas: 20122)
RuleSanctionlistTest:testClearOracleDisablesChecks() (gas: 37370)
RuleSanctionlistTest:testDetectTransferRestrictionFrom() (gas: 49291)
RuleSanctionlistTest:testDetectTransferRestrictionOk() (gas: 30013)
RuleSanctionlistTest:testDetectTransferRestrictionTo() (gas: 55511)
RuleSanctionlistTest:testDetectTransferRestrictionWitSpender() (gas: 49770)
RuleSanctionlistTest:testDetectTransferRestrictionWitSpenderOk() (gas: 66579)
RuleSanctionlistTest:testDetectTransferRestrictionWitSpenderTo() (gas: 58011)
RuleSanctionlistTest:testReturnTheRightMessageForAGivenCode() (gas: 43528)
RuleSanctionlistTest:testTransferFromDetectedAsInvalid() (gas: 18818)
RuleSanctionlistTest:testTransferToDetectedAsInvalid() (gas: 22894)
RuleSanctionlistTest:testcanTransfer() (gas: 50478)
RuleSanctionsListRuleEngineIntegration:testDetectRestrictionAndCanTransfer() (gas: 118590)
RuleWhitelistAccessControl:testCannotAttackeraddAddress() (gas: 24850)
RuleWhitelistAccessControl:testCannotAttackeraddAddresses() (gas: 55832)
RuleWhitelistAccessControl:testCannotAttackerremoveAddress() (gas: 134228)
RuleWhitelistAccessControl:testCannotAttackerremoveAddresses() (gas: 187707)
RuleWhitelistAccessControlOZ:testCanGrantRoleAsAdmin() (gas: 44292)
RuleWhitelistAccessControlOZ:testCannotGrantFromNonAdmin() (gas: 21471)
RuleWhitelistAccessControlOZ:testCannotRevokeFromNonAdmin() (gas: 50186)
RuleWhitelistAccessControlOZ:testRevokeRoleAsAdmin() (gas: 36596)
RuleWhitelistAddTest:testAddAddressTwiceToTheWhitelist() (gas: 129971)
RuleWhitelistAddTest:testAddAddressesTwiceToTheWhitelist() (gas: 239162)
RuleWhitelistAddTest:testCanAddAddressZeroToTheWhitelist() (gas: 85510)
RuleWhitelistAddTest:testCanAddAddressesZeroToTheWhitelist() (gas: 206335)
RuleWhitelistAddTest:testFuzz_AddRemoveIdempotent(address,address) (runs: 256, μ: 125412, ~: 125382)
RuleWhitelistAddTest:testaddAddress() (gas: 130153)
RuleWhitelistAddTest:testaddAddresses() (gas: 185477)
RuleWhitelistDeploymentTest:testCannotDeployContractIfAdminAddressIsZero() (gas: 1179064)
RuleWhitelistDeploymentTest:testRightDeployment() (gas: 2454733)
RuleWhitelistOwnable2Step:testOnlyOwnerCanTransferOwnership() (gas: 43684)
RuleWhitelistOwnable2Step:testPendingOwnerMustAccept() (gas: 33745)
RuleWhitelistOwnableAccessControl:testNonOwnerCannotAddOrRemove() (gas: 16473)
RuleWhitelistOwnableAccessControl:testOwnerCanAddAndRemove() (gas: 66148)
RuleWhitelistOwnableCheckSpender:testOnlyOwnerCanSetCheckSpender() (gas: 19486)
RuleWhitelistRemoveTest:testRemoveAddress() (gas: 86109)
RuleWhitelistRemoveTest:testRemoveAddressNotPresentFromTheWhitelist() (gas: 19910)
RuleWhitelistRemoveTest:testRemoveAddressWhenArrayContainSeveralAddresses() (gas: 131305)
RuleWhitelistRemoveTest:testRemoveAddressesNotPresentFromTheWhitelist() (gas: 153096)
RuleWhitelistTest:testAddressIsIndicatedAsWhitelisted() (gas: 104306)
RuleWhitelistTest:testAddressesIsIndicatedAsWhitelisted() (gas: 181904)
RuleWhitelistTest:testCanReturnTransferRestrictionCode() (gas: 20271)
RuleWhitelistTest:testDetectTransferRestrictionFrom() (gas: 43416)
RuleWhitelistTest:testDetectTransferRestrictionOk() (gas: 136353)
RuleWhitelistTest:testDetectTransferRestrictionTo() (gas: 114827)
RuleWhitelistTest:testDetectTransferRestrictionWithSpender() (gas: 169052)
RuleWhitelistTest:testDetectTransferRestrictionWithSpenderOk() (gas: 216352)
RuleWhitelistTest:testReturnFalseIfAddressNotWhitelisted() (gas: 21033)
RuleWhitelistTest:testReturnTheRightMessageForAGivenCode() (gas: 67716)
RuleWhitelistTest:testTransferDetectedAsInvalid() (gas: 12635)
RuleWhitelistTest:testcanTransfer() (gas: 184412)
RuleWhitelistTest:testlistedAddressCount() (gas: 142282)
RuleWhitelistWrapperOwnable2StepTest:testOnlyOwnerCanAddRule() (gas: 89179)
RuleWhitelistWrapperOwnable2StepTest:testOnlyOwnerCanSetCheckSpender() (gas: 22741)
RuleWhitelistWrapperOwnable2StepTest:testOnlyOwnerCanTransferOwnership() (gas: 43867)
RuleWhitelistWrapperOwnable2StepTest:testPendingOwnerMustAccept() (gas: 33992)
RuleWhitelistWrapperRuleEngineIntegration:testDetectRestrictionAndCanTransfer() (gas: 220864)
RuleWhitelistWrapperRuleEngineIntegration:testDetectRestrictionFromAndCanTransferFrom() (gas: 259586)
TransferContextTest:testTransferContextFungibleConditionalTransferLight() (gas: 868595)
TransferContextTest:testTransferContextFungibleConditionalTransferLightTransferFrom() (gas: 875337)
TransferContextTest:testTransferContextFungibleWhitelist() (gas: 1489289)
TransferContextTest:testTransferContextWithTokenIdWhitelist() (gas: 1489349)
10 changes: 0 additions & 10 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,6 @@ jobs:
with:
submodules: recursive


- name: Setup NodeJS 20.5.0
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 #v4.4.0
with:
node-version: 20.5.0

- name: Install nodes modules inside CMTAT lib
run: npm install
working-directory: ./lib/CMTAT

- name: Install Foundry
#v1.5.0
uses: foundry-rs/foundry-toolchain@50d5a8956f2e319df19e6b57539d7e2acb9f8c1e
Expand Down
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Compiler files
cache/
out/
cache_hardhat/
artifacts/

# Ignores development broadcast logs
!/broadcast
Expand All @@ -9,9 +11,13 @@ out/

# Docs
docs/
docOut/

# Dotenv file
.env
# node_modules
node_modules/

/history
/ERCSpecification
*.dbg.json
/skills
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@
[submodule "lib/CMTAT"]
path = lib/CMTAT
url = https://github.com/CMTA/CMTAT
[submodule "lib/openzeppelin-contracts-upgradeable"]
path = lib/openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
73 changes: 73 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Project Guide

## Purpose
Modular compliance-rule library for CMTAT / ERC-3643 security tokens. Each rule enforces a transfer restriction (whitelist, blacklist, sanctions, max supply, identity, conditional approval) and can be used standalone or composed via a `RuleEngine`.

## Key Directories
| Path | Description |
|---|---|
| `src/rules/validation/` | Read-only rules (view functions, no state changes during transfer) |
| `src/rules/operation/` | Read-write rules (modify state on transfer) |
| `src/rules/validation/abstract/` | Shared base contracts and invariant storage |
| `src/rules/interfaces/` | Shared interfaces (`IAddressList`, `IIdentityRegistry`, `ISanctionsList`) |
| `src/modules/` | Reusable modules (`AccessControlModuleStandalone`, `MetaTxModuleStandalone`, `VersionModule`) |
| `test/` | Foundry tests, one folder per rule |
| `lib/` | Git submodule dependencies (do not edit) |

## Main Contracts
| Contract | Role |
|---|---|
| `RuleWhitelist` / `RuleWhitelistOwnable2Step` | Allow transfers only between whitelisted addresses |
| `RuleWhitelistWrapper` / `Ownable2Step` | Aggregate multiple whitelist rules (OR logic) |
| `RuleBlacklist` / `RuleBlacklistOwnable2Step` | Block transfers involving blacklisted addresses |
| `RuleSanctionsList` | Block sanctioned addresses via Chainalysis oracle |
| `RuleMaxTotalSupply` | Cap minting so total supply never exceeds a maximum |
| `RuleIdentityRegistry` | Check ERC-3643 identity registry for participant verification |
| `RuleERC2980` | ERC-2980 Swiss Compliant rule: whitelist (recipient-only) + frozenlist (blocks sender and recipient); frozenlist takes priority |
| `RuleERC2980Ownable2Step` | Ownable2Step variant of RuleERC2980 |
| `RuleConditionalTransferLight` | Require operator approval before each transfer |
| `RuleConditionalTransferLightOwnable2Step` | Owner-only approval and execution for conditional transfers |
| `AccessControlModuleStandalone` | Base RBAC module; admin implicitly holds all roles |
| `MetaTxModuleStandalone` | ERC-2771 meta-transaction support |
| `VersionModule` | Implements `IERC3643Version`; returns the contract version string |

## Dependencies (lib/)
- `openzeppelin-contracts` v5.5.0 — `AccessControl`, `Ownable2Step`, `EnumerableSet`, `ERC2771Context`
- `CMTAT` v3.0.0 — `IERC1404`, `IERC3643`, `IRuleEngine` interfaces
- `RuleEngine` v3.0.0-rc0 — `IRule`, `RulesManagementModule`
- `forge-std` — Foundry test utilities

Remappings are in `remappings.txt`; aliases used in source: `OZ/`, `CMTAT/`, `RuleEngine/`.

## Toolchain
```bash
forge build # compile
forge test # run all tests
forge test -vvv # verbose output
```
Foundry config: `foundry.toml` (solc 0.8.34, EVM prague, optimizer 200 runs).

## Restriction Code Ranges
| Rule | Codes |
|---|---|
| RuleWhitelist | 21–23 |
| RuleSanctionsList | 30–32 |
| RuleBlacklist | 36–38 |
| RuleConditionalTransferLight | 46 |
| RuleMaxTotalSupply | 50 |
| RuleIdentityRegistry | 55–57 |
| RuleERC2980 | 60–63 |

## Conventions
- Each rule has an `InvariantStorage` abstract contract holding its constants, custom errors, and events.
- Access control is implemented via an abstract `_authorize*()` method overridden by concrete subclasses (template method pattern).
- AccessControl variants must use `onlyRole(ROLE)` in `_authorize*()` methods (avoid direct `_checkRole`).
- AccessControl variants treat the default admin as having all roles via `hasRole`, but the admin may not appear in role member enumerations unless explicitly granted.
- All rules implement `IERC3643Version` via `VersionModule`; the current version string is `"0.2.0"`.
- Batch add/remove operations are non-reverting (skip duplicates); single-item operations revert on invalid input.
- All `internal` functions should be marked `virtual`.
- Do not create git commits; provide commit messages only when requested.
- Always run tests after modifying contracts.
- Use `require(condition, CustomError(...))` for custom errors; avoid direct `revert CustomError(...)`.
- `AGENTS.md` and `CLAUDE.md` are identical — always update both together.
- Always update README.md with the latest change
Loading