Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2387b04
docs: add implementation proposals to seven Nethermind
rya-sge Aug 17, 2026
766cb29
fix: delegate to the direct restriction check on the
rya-sge Aug 17, 2026
8d87903
fix: reject future-dated Chainlink PoR rounds as malformed answers re…
rya-sge Aug 17, 2026
cf8bff0
fix: route owner-initiated transfers (spender == from) to the direct
rya-sge Aug 17, 2026
aa335e7
feat: add CapAccounting and the notification-phase seam so an ERC-364…
rya-sge Aug 18, 2026
9fdfeca
feat: add RuleChainlinkPoRERC3643 for tokens that call compliance aft…
rya-sge Aug 18, 2026
40c23fd
feat: add RuleMaxTotalSupplyERC3643 with real-T-REX coverage and the …
rya-sge Aug 18, 2026
72c934d
test: pin the PoR supply read on real ERC-3643 and document the deci…
rya-sge Aug 19, 2026
2d16c0a
docs: close NM-11 in the AuditAgent feedback — ERC-3643 cap-rule vari…
rya-sge Aug 19, 2026
9f89fc3
Commit message: docs: state that RuleWhitelistWrapper children must …
rya-sge Aug 19, 2026
994ff60
feat: ERC-165-check RuleWhitelistWrapper children against a minimal I…
rya-sge Aug 19, 2026
8bd269d
fix: assert the approval created by approveAndTransferIfAllowed was c…
rya-sge Aug 19, 2026
da2ea16
feat: make list polarity declarable via IAddressListPolarity and reje…
rya-sge Aug 19, 2026
0e80e53
docs: add a per-rule ERC-3643 compatibility matrix and correct the r…
rya-sge Aug 19, 2026
f67b55f
docs: close NM-19 as won't-do — nesting an OR in an OR is algebraica…
rya-sge Aug 19, 2026
4ba7c71
chore: release v0.6.0 — Nethermind AuditAgent response (7 fixed, 16 …
rya-sge Aug 19, 2026
4f9883f
Update changelog
rya-sge Aug 19, 2026
0117c66
docs: add v0.6.0 Slither and Aderyn reports with triage — nothing to …
rya-sge Aug 19, 2026
c1ebe57
docs: v0.6.0 code-quality review — mark two pointer-passed guards vir…
rya-sge Aug 19, 2026
c0e235e
test: close the last 4 uncovered branches in RuleConditionalTransferL…
rya-sge Aug 19, 2026
f55d4e6
docs: unwrap hard-wrapped prose in the v0.5.0 and v0.6.0 changelog e…
rya-sge Aug 19, 2026
8e73315
docs: split the long v0.6.0 changelog entries into lead-plus-sub-bu…
rya-sge Aug 19, 2026
660ad9d
Update changelog
rya-sge Aug 19, 2026
acb645e
Update surya report
rya-sge Aug 20, 2026
f920b07
deps: update RuleEngine to v3.0.0-rc6 and adopt the TokenBindingModul…
rya-sge Aug 21, 2026
5820a77
docs: re-run Slither and Aderyn for v0.6.0 after the rc6 bump — no …
rya-sge Aug 21, 2026
8dad241
docs: regenerate the Surya call graphs after the RuleEngine v3.0.0-rc…
rya-sge Aug 21, 2026
f69620f
update changelog
rya-sge Aug 24, 2026
275bcf2
docs: restructure the AuditAgent summary in README as bullets and co…
rya-sge Aug 24, 2026
a3fbc27
docs: rewrite parent-relative links for the PDF now that the source R…
rya-sge Aug 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
23 changes: 15 additions & 8 deletions AGENTS.md

Large diffs are not rendered by default.

202 changes: 158 additions & 44 deletions CHANGELOG.md

Large diffs are not rendered by default.

23 changes: 15 additions & 8 deletions CLAUDE.md

Large diffs are not rendered by default.

35 changes: 30 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Each rule enforces one transfer restriction. A rule can be plugged **directly**

| Rules | Contracts report `version()` | CMTAT | RuleEngine | OpenZeppelin |
| --- | --- | --- | --- | --- |
| **v0.5.0** (current) | `"0.5.0"` | **≥ v3.0.0**, validated against `v3.3.0-rc3` | `v3.0.0-rc5` | `v5.7.0` |
| **v0.6.0** (current) | `"0.6.0"` | **≥ v3.0.0**, validated against `v3.3.0-rc3` | `v3.0.0-rc6` | `v5.7.0` |

One rule needs more than the baseline, because it reads the **spender** the token forwards on mint:

Expand All @@ -20,7 +20,7 @@ One rule needs more than the baseline, because it reads the **spender** the toke
| `RuleMintAllowance` | **v3.3** | Debits the minter's quota from the 4-argument `transferred(spender, from, to, value)` / `canTransferFrom`. A token that does not forward the spender cannot drive it. |
| Every other rule | v3.0.0 | Uses the 3-argument path only. |

The submodules in `lib/` are pinned to the validated versions (CMTAT `v3.3.0-rc3`, RuleEngine `v3.0.0-rc5`), so
The submodules in `lib/` are pinned to the validated versions (CMTAT `v3.3.0-rc3`, RuleEngine `v3.0.0-rc6`), so
a `git submodule update --init --recursive` checkout builds and tests against exactly what this release was verified with.

📖 **[Full documentation →](./doc/README.md)** — the complete reference: every rule in detail, the API, access-control model, restriction codes, deployment guide, and security findings. This page is a summary.
Expand Down Expand Up @@ -74,8 +74,10 @@ access-control policy, in either an `AccessControl` or an `Ownable2Step` flavour
| `RuleERC2980` | ERC-2980 whitelist plus frozenlist | 60–65 |
| `RuleIdentityRegistry` | Consults an ERC-3643 identity registry | 55–57 |
| `RuleMaxTotalSupply` | Caps total supply on mint | 50, 51 |
| `RuleMaxTotalSupplyERC3643` | Same, for **ERC-3643 tokens** — compliance called *after* the mint | 50, 51 |
| `RuleMaxBalance` | Caps how many tokens one address may hold | 82, 83 |
| `RuleChainlinkPoR` | Caps minting at Chainlink Proof of Reserve reserves | 75–79 |
| `RuleChainlinkPoRERC3643` | Same, for **ERC-3643 tokens** — compliance called *after* the mint | 75–79 |
| `RuleConditionalTransferLight` | Requires operator approval per transfer | 46 |
| `RuleMintAllowance` | Per-minter mint quota | 70 |

Expand Down Expand Up @@ -104,6 +106,11 @@ Use `RuleEngine`, not a bare rule. ERC-3643 drives mint and burn through `create
The operation rules do implement `created` / `destroyed`, but they are bound to a single token and are not a compliance contract on
their own.

**Not every rule behaves the same on this path.** ERC-3643 never forwards a spender (both `transfer` and `transferFrom` call the
3-argument `transferred`) and calls compliance *after* it moves the value. Some rules are therefore inert, and the two supply-cap
rules need their `…ERC3643` variant. The per-rule matrix is
[`RULE_SEMANTICS.md` §6](./doc/technical/guides/RULE_SEMANTICS.md).

### Identity verification

ERC-3643 decides who may hold a token by asking an **identity registry** one question:
Expand Down Expand Up @@ -190,15 +197,33 @@ AI-assisted review, each triaged by the project team:

| Type | Tool | Latest run |
| --- | --- | --- |
| Static analysis | [Slither](https://github.com/crytic/slither) 0.11.5 | v0.5.0 |
| Static analysis | [Aderyn](https://github.com/Cyfrin/aderyn) 0.6.5 | v0.5.0 |
| Static analysis | [Slither](https://github.com/crytic/slither) 0.11.5 | v0.6.0 |
| Static analysis | [Aderyn](https://github.com/Cyfrin/aderyn) 0.6.5 | v0.6.0 |
| AI automated scan | [Nethermind AuditAgent](https://auditagent.nethermind.io/) | v0.5.0 |
| AI-assisted review | Claude Code (Anthropic) | v0.5.0 |
| AI-assisted review | Claude + custom security-audit skills | v0.4.0 |
| AI-assisted review | [Wake Arena](https://getwake.io) (Ackee Blockchain Security) | v0.2.0 |

Scope is the production contracts under `src/`; mocks, tests and vendored dependencies are excluded.

Every finding carries a written triage, including the ones dismissed as false positives or by-design. Nothing was outstanding as of `v0.5.0`.
Every finding carries a written triage, including the ones dismissed as false positives or by-design. Nothing is outstanding as of `v0.6.0`: the static analysers report nothing to fix (Slither 46 results, Aderyn 346 Low instances — all false-positive, by-design, environmental or cosmetic), and the AuditAgent scan is fully dispositioned.

### Nethermind AuditAgent (v0.5.0)

| Scan | High | Medium | Low | Info | Anything to fix? |
| --- | --- | --- | --- | --- | --- |
| 2026-08-17, commit `01632da` | 0 | 13 | 11 | 0 | **Nothing exploitable** — 7 fixed in `v0.6.0`, 16 accepted as design, 1 declined; nothing left open |

> Note: This scan was performed by an AI-powered automated tool, not a formal human-led audit.

No false positives, but 17 of the 24 findings restate design positions already documented in the source and in the previous audit, so the set collapses to about 11 distinct claims. Seven were fixed in `v0.6.0`; the substantive ones:

- **NM-3** — the identity-registry rule's `transferFrom` path now always delegates to the direct restriction check. A subclass extending only that hook could previously have its check applied to `transfer` but silently skipped on `transferFrom` and `burnFrom`.
- **NM-6** — the ERC-7943 overloads now read an owner-initiated transfer (`spender == from`) as direct, matching the `ITransferContext` entrypoints, so `RuleSpenderWhitelist` no longer blocks an owner moving their own tokens.
- **NM-10** — a Proof-of-Reserve round stamped in the future is rejected as a malformed answer instead of being accepted as fresh.
- **NM-11** — the cap rules assume the token calls the compliance hook *before* moving value. CMTAT does; ERC-3643 / T-REX does not, so the stock rule counted the amount twice and reverted mints that were within the cap. `RuleChainlinkPoRERC3643` and `RuleMaxTotalSupplyERC3643` now ship for that path, verified against the vendored T-REX token; `RuleMaxBalance` stays CMTAT-only by design.

[Report (PDF)](./doc/security/audits/tools/v0.5.0/nethermind_audit_agent_report_v0.5.0.pdf) · [feedback](./doc/security/audits/tools/v0.5.0/nethermind_audit_agent_report_v0.5.0-feedback.md).

Reports, triage and the threat model live in [`doc/security/audits/`](./doc/security/audits/), indexed by [`AUDIT_OVERVIEW.md`](./doc/security/audits/AUDIT_OVERVIEW.md).

Expand Down
2 changes: 1 addition & 1 deletion doc/FOUNDRY.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Here are the settings for [Hardhat](https://hardhat.org) and [Foundry](https://g

- CMTAT [v3.3.0-rc3](https://github.com/CMTA/CMTAT/releases/tag/v3.3.0-rc3)

- RuleEngine [v3.0.0-rc5](https://github.com/CMTA/RuleEngine/releases/tag/v3.0.0-rc5)
- RuleEngine [v3.0.0-rc6](https://github.com/CMTA/RuleEngine/releases/tag/v3.0.0-rc6)

## Toolchain installation

Expand Down
Loading
Loading