Skip to content

feat(account): Add DM gating facet with modular criteria system#4832

Draft
giuseppecrj wants to merge 5 commits into
mainfrom
g/towns-32485-dm-gating-erc6900-module-part-of-account-modules
Draft

feat(account): Add DM gating facet with modular criteria system#4832
giuseppecrj wants to merge 5 commits into
mainfrom
g/towns-32485-dm-gating-erc6900-module-part-of-account-modules

Conversation

@giuseppecrj

Copy link
Copy Markdown
Contributor

Summary

  • Implement DMGatingFacet for controlling who can DM users via installable criteria modules
  • Support AND/OR evaluation modes with hard limit of 8 criteria per account
  • Default behavior blocks all DMs until criteria installed
  • Include AllowlistCriteria for explicit address allowlists
  • Comprehensive test coverage for all gating modes and edge cases

Test plan

  • All tests pass locally
  • Covers install/uninstall, AND/OR modes, max criteria limit, and allowlist operations

🤖 Generated with Claude Code

@vercel

vercel Bot commented Jan 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
river-sample-app Ready Ready Preview, Comment Jan 14, 2026 1:05am

@coderabbitai

coderabbitai Bot commented Jan 8, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Introduces a new DMGating facet system enabling per-account direct messaging criteria management. Includes DMGatingFacet, DMGatingMod library, ICriteria/IDMGating interfaces, AllowlistCriteria implementation, deployment helpers, and comprehensive tests with AND/OR combination logic support.

Changes

Cohort / File(s) Summary
Diamond Deployment
packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
Integrates DMGatingFacet into deployment flow via diamondInitHelper and diamondInitParams
Deployment Helper
packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
New library providing selector assembly, init data encoding, and deployment delegation for DMGatingFacet
Core Interfaces
packages/contracts/src/account/facets/dm/ICriteria.sol, packages/contracts/src/account/facets/dm/IDMGating.sol
Define criteria evaluation interface and DMGating API (install/uninstall/check permissions)
Core Implementation
packages/contracts/src/account/facets/dm/DMGatingFacet.sol, packages/contracts/src/account/facets/dm/DMGatingMod.sol
DMGatingFacet facade with reentrancy guards; DMGatingMod library handles per-account criteria storage, validation, AND/OR evaluation, and error handling
Criteria Implementation
packages/contracts/src/account/criteria/AllowlistCriteria.sol
Implements ICriteria for per-account address allowlisting with add/remove/query operations
Tests
packages/contracts/test/account/DMGating.t.sol
Comprehensive coverage: default behavior, install/uninstall validation, combination modes, OR/AND logic, allowlist integration

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Suggested reviewers

  • jterzis
  • pfives
  • miguel-nascimento
  • shuhuiluo
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly summarizes the main change: adding a DM gating facet with modular criteria system, which aligns with all file additions and core feature.
Description check ✅ Passed Description is well-related to the changeset, detailing DMGatingFacet implementation, evaluation modes, AllowlistCriteria, and test coverage.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch g/towns-32485-dm-gating-erc6900-module-part-of-account-modules

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In @packages/contracts/src/account/criteria/AllowlistCriteria.sol:
- Around line 22-23: The declared error AllowlistCriteria__Unauthorized is
unused; implement access control in the onInstall and onUninstall functions to
revert with AllowlistCriteria__Unauthorized when callers are not permitted
(e.g., onlyOwner or a specific manager role), or remove the error if access
control is not required; locate the onInstall and onUninstall functions in
AllowlistCriteria.sol and add a require/check (using owner(), onlyOwner
modifier, or IERC173/IERC165 role check) that reverts with
AllowlistCriteria__Unauthorized on unauthorized calls so the declared error is
actually used.
- Around line 57-67: onInstall currently allows any caller to add addresses for
any account; restrict it by verifying the caller before calling _addAddresses.
Add an authorization check in onInstall (e.g., require(msg.sender == account ||
msg.sender == authorizedGatingFacet) or call into the contract's policy/registry
to confirm the caller is the DMGatingFacet) and revert with a clear error
message if unauthorized; reference the onInstall function and the _addAddresses
call when making the change and ensure the chosen authorized address/lookup is
initialized or fetched from your existing registry/facet lookup logic.
- Around line 69-77: The onUninstall function currently allows anyone to wipe an
account's allowlist; add the same access control check used in onInstall to
prevent unauthorized callers from clearing _allowlists[account]. Specifically,
in onUninstall (which manipulates EnumerableSetLib.AddressSet storage allowlist,
address[] memory addresses, and calls allowlist.remove), guard the function with
the same require/authorization logic present in onInstall so only the account
owner or an authorized installer can call it; implement the identical
access-check code path as in onInstall before iterating and removing addresses.
🧹 Nitpick comments (1)
packages/contracts/src/account/facets/dm/DMGatingMod.sol (1)

173-184: Consider defensive handling for reverting criteria in view function.

If a criteria contract reverts in canDM(), the entire canReceiveDMFrom call fails. A malicious or buggy criteria could DoS the view. Consider wrapping in try-catch and treating reverts as false (for AND) or skipping (for OR).

♻️ Optional defensive approach
         for (uint256 i; i < length; ++i) {
-            bool result = ICriteria(criteriaList[i]).canDM(
-                sender,
-                account,
-                extraData
-            );
+            bool result;
+            try ICriteria(criteriaList[i]).canDM(sender, account, extraData) returns (bool r) {
+                result = r;
+            } catch {
+                // Treat reverting criteria as failing
+                result = false;
+            }

             // Early exit on success for OR mode
             if (mode == CombinationMode.OR && result) return true;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cfa3ff1 and 4ae398f.

📒 Files selected for processing (8)
  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
  • packages/contracts/src/account/criteria/AllowlistCriteria.sol
  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
  • packages/contracts/src/account/facets/dm/DMGatingMod.sol
  • packages/contracts/src/account/facets/dm/ICriteria.sol
  • packages/contracts/src/account/facets/dm/IDMGating.sol
  • packages/contracts/test/account/DMGating.t.sol
🧰 Additional context used
📓 Path-based instructions (12)
packages/contracts/**/*.sol

📄 CodeRabbit inference engine (packages/contracts/.cursor/rules/design-philosophy.mdc)

packages/contracts/**/*.sol: Minimize complexity in software structure, prioritizing obviousness and ease of modification in Solidity contracts and facets
Invest time in design upfront rather than quick tactical fixes; prioritize long-term structure over short-term convenience when adding new facets or features
Design code to be obvious: developers should quickly understand existing code and confidently make changes without requiring multiple file traces and dependency navigation
Minimize coupling between modules; use events and interfaces to decouple components so changes in one facet rarely require changes in others
Name entities precisely and document non-obvious behavior; if a function's purpose isn't clear from its signature and name, the design needs improvement
Avoid change amplification: small logical changes should not require modifying many files; high coupling indicates architecture problems
Reduce cognitive load by making facet interfaces self-documenting and isolating storage layouts so developers don't need extensive context to complete tasks
Make it obvious which code must be modified for a given change through clear module boundaries and interfaces to prevent hidden dependencies
Strive for deep modules in Solidity: provide powerful functionality through simple interfaces while hiding complex implementation details
Design facet interfaces to be minimal and clear, hiding internal complexity such as cross-chain calls, rule evaluation, and caching logic
Design facets to be somewhat general-purpose; separate specialized logic from general mechanisms to maximize code reusability
Implement information hiding to ensure each facet has isolated storage slots and facets communicate through libraries, abstracts, or well-defined interfaces rather than shared knowledge
Do not expose storage layout details of one facet to another; each facet must have isolated storage and communicate through interfaces
Avoid temporal decomposition: do not structure code solely ba...

Files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/src/account/facets/dm/ICriteria.sol
  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
  • packages/contracts/src/account/criteria/AllowlistCriteria.sol
  • packages/contracts/src/account/facets/dm/IDMGating.sol
  • packages/contracts/test/account/DMGating.t.sol
  • packages/contracts/src/account/facets/dm/DMGatingMod.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
packages/contracts/scripts/deployments/**/*.s.sol

📄 CodeRabbit inference engine (packages/contracts/AGENTS.md)

Add deployment scripts in scripts/deployments/[type]/Deploy[Feature].s.sol when adding new facets or core contracts

Files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
packages/contracts/scripts/**/*.sol

📄 CodeRabbit inference engine (packages/contracts/.cursor/rules/contracts.mdc)

packages/contracts/scripts/**/*.sol: Document upgrade procedures
Use modular facet deployment that can be customized by passing different facet lists

Files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
packages/contracts/scripts/**/*Deploy*.sol

📄 CodeRabbit inference engine (packages/contracts/.cursor/rules/contracts.mdc)

Each facet deployment library must provide selectors and cut data

Files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
**/*.{ts,tsx,js,jsx,yaml,yml,sol,json,md}

📄 CodeRabbit inference engine (AGENTS.md)

All non-Go files must pass Prettier formatting, run bun run prettier:fix to automatically format TypeScript, JavaScript, YAML, Solidity, and other supported files

Files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/src/account/facets/dm/ICriteria.sol
  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
  • packages/contracts/src/account/criteria/AllowlistCriteria.sol
  • packages/contracts/src/account/facets/dm/IDMGating.sol
  • packages/contracts/test/account/DMGating.t.sol
  • packages/contracts/src/account/facets/dm/DMGatingMod.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
packages/contracts/src/**/*.sol

📄 CodeRabbit inference engine (packages/contracts/AGENTS.md)

Organize contract code with separate Storage library, Base contract with internal logic, and Facet contract with external interface

Files:

  • packages/contracts/src/account/facets/dm/ICriteria.sol
  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
  • packages/contracts/src/account/criteria/AllowlistCriteria.sol
  • packages/contracts/src/account/facets/dm/IDMGating.sol
  • packages/contracts/src/account/facets/dm/DMGatingMod.sol
packages/contracts/src/**/*/{I[A-Z]*.sol,I*.sol}

📄 CodeRabbit inference engine (packages/contracts/AGENTS.md)

Create interface contracts in I[Feature].sol for all facet contracts

Files:

  • packages/contracts/src/account/facets/dm/ICriteria.sol
  • packages/contracts/src/account/facets/dm/IDMGating.sol
packages/contracts/src/**/facets/**/*.sol

📄 CodeRabbit inference engine (packages/contracts/.cursor/rules/contracts.mdc)

packages/contracts/src/**/facets/**/*.sol: Split facet implementation into Storage Library, Base Contract, Facet Contract, and Interfaces for upgrade safety
Place business logic in a base contract and expose only protected/external calls in the facet contract

Files:

  • packages/contracts/src/account/facets/dm/ICriteria.sol
  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
  • packages/contracts/src/account/facets/dm/IDMGating.sol
  • packages/contracts/src/account/facets/dm/DMGatingMod.sol
packages/contracts/src/**/facets/**/*Facet.sol

📄 CodeRabbit inference engine (packages/contracts/AGENTS.md)

Create facet contracts with external functions in [Feature]Facet.sol that inherit from corresponding [Feature]Base contracts

Files:

  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
packages/contracts/test/**/*.t.sol

📄 CodeRabbit inference engine (packages/contracts/AGENTS.md)

packages/contracts/test/**/*.t.sol: Write comprehensive unit tests for all functionality with fuzz testing for numeric inputs using 4096 test runs minimum
Test permission and access control logic thoroughly including edge cases and unauthorized access attempts
Use fork tests to test cross-chain functionality against actual deployed contracts
Test upgrade paths for diamond facets when modifying existing facet contracts

Files:

  • packages/contracts/test/account/DMGating.t.sol
packages/contracts/**/*.t.sol

📄 CodeRabbit inference engine (packages/contracts/.cursor/rules/contracts.mdc)

packages/contracts/**/*.t.sol: Write comprehensive unit tests
Test all edge cases
Test permission/access control logic
Test cross-chain functionality
Test upgrade paths

Files:

  • packages/contracts/test/account/DMGating.t.sol
packages/contracts/scripts/deployments/facets/*.s.sol

📄 CodeRabbit inference engine (packages/contracts/AGENTS.md)

Deploy facets using dedicated deployment scripts in scripts/deployments/facets/Deploy[Feature].s.sol

Files:

  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
🧠 Learnings (33)
📚 Learning: 2025-12-17T01:18:07.265Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/.cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-17T01:18:07.265Z
Learning: Applies to packages/contracts/scripts/**/*.sol : Use modular facet deployment that can be customized by passing different facet lists

Applied to files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
📚 Learning: 2025-12-06T08:15:28.770Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/AGENTS.md:0-0
Timestamp: 2025-12-06T08:15:28.770Z
Learning: Applies to packages/contracts/scripts/deployments/facets/*.s.sol : Deploy facets using dedicated deployment scripts in `scripts/deployments/facets/Deploy[Feature].s.sol`

Applied to files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
📚 Learning: 2025-12-17T01:18:07.265Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/.cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-17T01:18:07.265Z
Learning: Applies to packages/contracts/scripts/**/*Deploy*.sol : Each facet deployment library must provide selectors and cut data

Applied to files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
📚 Learning: 2025-12-06T08:15:28.770Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/AGENTS.md:0-0
Timestamp: 2025-12-06T08:15:28.770Z
Learning: Applies to packages/contracts/scripts/deployments/**/*.s.sol : Add deployment scripts in `scripts/deployments/[type]/Deploy[Feature].s.sol` when adding new facets or core contracts

Applied to files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
📚 Learning: 2025-12-06T08:15:28.770Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/AGENTS.md:0-0
Timestamp: 2025-12-06T08:15:28.770Z
Learning: Applies to packages/contracts/test/**/*.t.sol : Test upgrade paths for diamond facets when modifying existing facet contracts

Applied to files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
  • packages/contracts/test/account/DMGating.t.sol
📚 Learning: 2025-05-11T12:35:14.828Z
Learnt from: shuhuiluo
Repo: towns-protocol/towns PR: 3041
File: packages/contracts/test/base/registry/RewardsDistributionV2.t.sol:83-94
Timestamp: 2025-05-11T12:35:14.828Z
Learning: In the Towns Protocol codebase, the types `FacetCut` and `FacetCutAction` are available through the `IDiamond` interface, not just through `IDiamondCut`. This means contracts inheriting from `IDiamond` can use these types without qualification.

Applied to files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
📚 Learning: 2025-12-06T08:15:28.770Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/AGENTS.md:0-0
Timestamp: 2025-12-06T08:15:28.770Z
Learning: Applies to packages/contracts/src/**/facets/**/*Facet.sol : Create facet contracts with external functions in `[Feature]Facet.sol` that inherit from corresponding `[Feature]Base` contracts

Applied to files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
📚 Learning: 2025-05-11T12:37:26.014Z
Learnt from: shuhuiluo
Repo: towns-protocol/towns PR: 3041
File: packages/contracts/scripts/deployments/diamonds/DeployBaseRegistry.s.sol:92-106
Timestamp: 2025-05-11T12:37:26.014Z
Learning: The DeployFacet helper in the Towns Protocol contract deployment system uses CREATE2 for deterministic address calculation and maintains a mapping of deployed addresses to prevent redeploying the same facet even if it's queued multiple times. The facet queue isn't reset between deployments, but this doesn't cause issues since the helper checks if each facet is already deployed.

Applied to files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
📚 Learning: 2025-12-17T01:18:07.265Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/.cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-17T01:18:07.265Z
Learning: Applies to packages/contracts/src/**/facets/**/*.sol : Split facet implementation into Storage Library, Base Contract, Facet Contract, and Interfaces for upgrade safety

Applied to files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
  • packages/contracts/src/account/facets/dm/IDMGating.sol
  • packages/contracts/src/account/facets/dm/DMGatingMod.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
📚 Learning: 2025-12-10T22:31:40.807Z
Learnt from: giuseppecrj
Repo: towns-protocol/towns PR: 4640
File: packages/contracts/src/account/facets/hub/AccountHubMod.sol:91-94
Timestamp: 2025-12-10T22:31:40.807Z
Learning: In packages/contracts/src/account/facets/hub/AccountHubMod.sol and similar module files, file-level functions are used as internal helpers and default to internal visibility in Solidity, but explicit visibility modifiers are still preferred per coding guidelines.

Applied to files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
  • packages/contracts/src/account/facets/dm/IDMGating.sol
  • packages/contracts/src/account/facets/dm/DMGatingMod.sol
📚 Learning: 2025-11-25T08:45:45.263Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/.cursor/rules/design-philosophy.mdc:0-0
Timestamp: 2025-11-25T08:45:45.263Z
Learning: Applies to packages/contracts/**/*.sol : Design facets to be somewhat general-purpose; separate specialized logic from general mechanisms to maximize code reusability

Applied to files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
📚 Learning: 2025-12-17T01:18:07.265Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/.cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-17T01:18:07.265Z
Learning: Applies to packages/contracts/src/**/facets/**/*.sol : Place business logic in a base contract and expose only protected/external calls in the facet contract

Applied to files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
📚 Learning: 2025-11-17T17:41:02.370Z
Learnt from: giuseppecrj
Repo: towns-protocol/towns PR: 4507
File: packages/contracts/src/apps/facets/reputation/ReputationRegistryFacet.sol:78-80
Timestamp: 2025-11-17T17:41:02.370Z
Learning: In the towns-protocol/towns repository, the IdentityRegistryFacet and ReputationRegistryFacet are both facets of the same diamond proxy (EIP-2535 pattern). Therefore, ReputationRegistryFacet.getIdentityRegistry() correctly returns address(this), which is the diamond's address where both registry functionalities are accessible.

Applied to files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
📚 Learning: 2025-12-19T20:33:59.100Z
Learnt from: shuhuiluo
Repo: towns-protocol/towns PR: 4717
File: packages/contracts/test/spaces/membership/unit/MembershipCurrencyMigration.t.sol:2-2
Timestamp: 2025-12-19T20:33:59.100Z
Learning: In Foundry projects, the compiler version is governed by foundry.toml; file-level pragmas only need to be compatible. Do not require exact version matches. Ensure pragma solidity in .sol files is compatible with the version configured in foundry.toml and avoid mismatches that would cause compilation issues.

Applied to files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/src/account/facets/dm/ICriteria.sol
  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
  • packages/contracts/src/account/criteria/AllowlistCriteria.sol
  • packages/contracts/src/account/facets/dm/IDMGating.sol
  • packages/contracts/test/account/DMGating.t.sol
  • packages/contracts/src/account/facets/dm/DMGatingMod.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
📚 Learning: 2026-01-06T21:19:34.734Z
Learnt from: giuseppecrj
Repo: towns-protocol/towns PR: 4720
File: packages/contracts/scripts/deployments/diamonds/DeployL1Resolver.s.sol:40-46
Timestamp: 2026-01-06T21:19:34.734Z
Learning: In Solidity deployment script files under packages/contracts/scripts/ (e.g., DeployL1Resolver.s.sol), treat them as local build-time tools that run during deployment and are not deployed on-chain. Do not add runtime access controls (like onlyOwner) or on-chain input validations that are only relevant for production contracts. Reviewers should ensure such script files focus on deployment logic and do not introduce on-chain security concerns meant for deployed contracts.

Applied to files:

  • packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
📚 Learning: 2025-12-06T08:15:28.770Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/AGENTS.md:0-0
Timestamp: 2025-12-06T08:15:28.770Z
Learning: Applies to packages/contracts/src/**/*/{I[A-Z]*.sol,I*.sol} : Create interface contracts in `I[Feature].sol` for all facet contracts

Applied to files:

  • packages/contracts/src/account/facets/dm/ICriteria.sol
  • packages/contracts/src/account/facets/dm/IDMGating.sol
📚 Learning: 2025-12-17T01:18:07.265Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/.cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-17T01:18:07.265Z
Learning: Applies to packages/contracts/src/**/*Interface.sol : Define interfaces for external APIs

Applied to files:

  • packages/contracts/src/account/facets/dm/ICriteria.sol
  • packages/contracts/src/account/facets/dm/IDMGating.sol
📚 Learning: 2025-11-25T08:45:45.263Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/.cursor/rules/design-philosophy.mdc:0-0
Timestamp: 2025-11-25T08:45:45.263Z
Learning: Applies to packages/contracts/**/*.sol : Design facet interfaces to be minimal and clear, hiding internal complexity such as cross-chain calls, rule evaluation, and caching logic

Applied to files:

  • packages/contracts/src/account/facets/dm/ICriteria.sol
  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
  • packages/contracts/src/account/facets/dm/IDMGating.sol
📚 Learning: 2025-05-19T23:57:16.097Z
Learnt from: shuhuiluo
Repo: towns-protocol/towns PR: 3104
File: packages/contracts/src/airdrop/drop/DropFacet.sol:54-75
Timestamp: 2025-05-19T23:57:16.097Z
Learning: The DropFacet contract follows the Checks-Effects-Interactions pattern in its claim functions, with state modifications happening before external calls to prevent re-entrancy attacks. Additionally, the ERC-20 tokens used in the system are set by governance, providing an extra layer of security.

Applied to files:

  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
📚 Learning: 2025-12-06T08:15:28.770Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/AGENTS.md:0-0
Timestamp: 2025-12-06T08:15:28.770Z
Learning: Applies to packages/contracts/src/**/facets/**/*Base.sol : Create base contracts with internal logic in `[Feature]Base.sol` alongside facet contracts

Applied to files:

  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
📚 Learning: 2025-11-25T08:45:45.263Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/.cursor/rules/design-philosophy.mdc:0-0
Timestamp: 2025-11-25T08:45:45.263Z
Learning: Applies to packages/contracts/**/*.sol : Implement information hiding to ensure each facet has isolated storage slots and facets communicate through libraries, abstracts, or well-defined interfaces rather than shared knowledge

Applied to files:

  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
📚 Learning: 2025-05-20T00:00:31.574Z
Learnt from: shuhuiluo
Repo: towns-protocol/towns PR: 3104
File: packages/contracts/src/airdrop/drop/DropFacet.sol:133-139
Timestamp: 2025-05-20T00:00:31.574Z
Learning: The DropFacet contract uses an assembly memory optimization technique in getter functions that return structs, resetting the free memory pointer to deallocate the memory that Solidity automatically allocates for named return variables. This is marked as "memory-safe" and used to improve gas efficiency.

Applied to files:

  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
📚 Learning: 2025-11-25T08:45:45.263Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/.cursor/rules/design-philosophy.mdc:0-0
Timestamp: 2025-11-25T08:45:45.263Z
Learning: Applies to packages/contracts/**/*.sol : Do not expose storage layout details of one facet to another; each facet must have isolated storage and communicate through interfaces

Applied to files:

  • packages/contracts/src/account/facets/dm/DMGatingFacet.sol
📚 Learning: 2025-12-17T01:18:07.265Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/.cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-17T01:18:07.265Z
Learning: Applies to packages/contracts/**/*.t.sol : Test upgrade paths

Applied to files:

  • packages/contracts/test/account/DMGating.t.sol
📚 Learning: 2025-12-17T01:18:07.265Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/.cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-17T01:18:07.265Z
Learning: Applies to packages/contracts/**/*.t.sol : Test cross-chain functionality

Applied to files:

  • packages/contracts/test/account/DMGating.t.sol
📚 Learning: 2025-12-17T01:18:07.265Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/.cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-17T01:18:07.265Z
Learning: Applies to packages/contracts/**/*.t.sol : Write comprehensive unit tests

Applied to files:

  • packages/contracts/test/account/DMGating.t.sol
📚 Learning: 2025-12-17T01:18:07.265Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/.cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-17T01:18:07.265Z
Learning: Applies to packages/contracts/**/*.t.sol : Test all edge cases

Applied to files:

  • packages/contracts/test/account/DMGating.t.sol
📚 Learning: 2025-12-06T08:15:28.770Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/AGENTS.md:0-0
Timestamp: 2025-12-06T08:15:28.770Z
Learning: Applies to packages/contracts/test/**/*.t.sol : Test permission and access control logic thoroughly including edge cases and unauthorized access attempts

Applied to files:

  • packages/contracts/test/account/DMGating.t.sol
📚 Learning: 2025-12-17T01:18:07.265Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/.cursor/rules/contracts.mdc:0-0
Timestamp: 2025-12-17T01:18:07.265Z
Learning: Applies to packages/contracts/**/*.t.sol : Test permission/access control logic

Applied to files:

  • packages/contracts/test/account/DMGating.t.sol
📚 Learning: 2025-12-06T08:15:28.770Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/AGENTS.md:0-0
Timestamp: 2025-12-06T08:15:28.770Z
Learning: Applies to packages/contracts/test/**/*.t.sol : Write comprehensive unit tests for all functionality with fuzz testing for numeric inputs using 4096 test runs minimum

Applied to files:

  • packages/contracts/test/account/DMGating.t.sol
📚 Learning: 2025-11-25T08:45:45.263Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/.cursor/rules/design-philosophy.mdc:0-0
Timestamp: 2025-11-25T08:45:45.263Z
Learning: Applies to packages/contracts/**/*.sol : Reduce cognitive load by making facet interfaces self-documenting and isolating storage layouts so developers don't need extensive context to complete tasks

Applied to files:

  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
📚 Learning: 2025-12-06T08:15:28.770Z
Learnt from: CR
Repo: towns-protocol/towns PR: 0
File: packages/contracts/AGENTS.md:0-0
Timestamp: 2025-12-06T08:15:28.770Z
Learning: Applies to packages/contracts/src/**/*.sol : Organize contract code with separate Storage library, Base contract with internal logic, and Facet contract with external interface

Applied to files:

  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
📚 Learning: 2025-10-23T02:55:15.291Z
Learnt from: giuseppecrj
Repo: towns-protocol/towns PR: 4339
File: packages/contracts/src/apps/facets/factory/AppFactoryBase.sol:73-86
Timestamp: 2025-10-23T02:55:15.291Z
Learning: In packages/contracts/src/apps/facets/factory/AppFactoryBase.sol, the separate deploy + initialize pattern (deployERC1967BeaconProxy followed by ITownsApp.initialize) is the correct approach for beacon proxies. LibClone overloads with additional arguments use immutable args (constructor parameters), not initialization calldata, so they cannot be used for initializable proxy patterns.

Applied to files:

  • packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol
🔇 Additional comments (8)
packages/contracts/src/account/facets/dm/ICriteria.sol (1)

1-31: Clean, minimal interface.

Well-designed interface following best practices. NatSpec is complete, functions are appropriately scoped, and the abstraction is clear.

packages/contracts/scripts/deployments/diamonds/DeployAccountModules.s.sol (1)

74-76: DMGatingFacet integration follows established patterns.

Consistent with existing facet deployment conventions. Properly adds selectors, queues deployment, and provides init data.

Also applies to: 89-89, 122-127

packages/contracts/src/account/facets/dm/IDMGating.sol (1)

1-48: Solid interface design.

Minimal surface area, complete NatSpec, and proper type reuse from DMGatingMod for CombinationMode.

packages/contracts/scripts/deployments/facets/DeployDMGatingFacet.s.sol (1)

1-38: Deployment helper follows established conventions.

Selector count matches reserved capacity (7), init data encoding is correct, and deploy pattern is consistent with other facet deployers.

packages/contracts/src/account/facets/dm/DMGatingFacet.sol (1)

14-75: Clean facet implementation.

Thin external layer properly delegates to DMGatingMod. Reentrancy guards on state-changing functions, interface registration in init. Follows the pattern.

packages/contracts/test/account/DMGating.t.sol (1)

1-368: Comprehensive test coverage.

Good coverage of success paths, error conditions, AND/OR modes, and allowlist integration. Fuzz testing for addresses is appropriate given the feature's input types.

packages/contracts/src/account/facets/dm/DMGatingMod.sol (1)

59-78: Storage layout follows diamond storage best practices.

ERC-7201 namespaced storage slot, proper assembly accessor, and clear Layout struct documentation.

packages/contracts/src/account/criteria/AllowlistCriteria.sol (1)

44-50: LGTM — remaining functions are correctly implemented.

  • canDM correctly checks recipient's allowlist for sender.
  • addToAllowlist/removeFromAllowlist properly use msg.sender for self-modification.
  • View functions are safe and well-documented.
  • _addAddresses validates against address(0) and emits events appropriately.

Also applies to: 83-99, 101-132, 138-151

Comment thread packages/contracts/src/account/criteria/AllowlistCriteria.sol
Comment thread packages/contracts/src/account/criteria/AllowlistCriteria.sol
Comment thread packages/contracts/src/account/criteria/AllowlistCriteria.sol
@giuseppecrj giuseppecrj changed the base branch from main to g/01-08-prettier_fix January 8, 2026 19:08
Base automatically changed from g/01-08-prettier_fix to main January 8, 2026 19:27
@giuseppecrj giuseppecrj marked this pull request as draft January 8, 2026 19:28

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

giuseppecrj and others added 4 commits January 13, 2026 19:52
Implement DMGatingFacet that allows users to control who can DM them through installable criteria modules. Users can configure AND/OR evaluation modes with a hard limit of 8 criteria per account. Default behavior blocks all DMs until at least one criteria is installed. Includes AllowlistCriteria for explicit address allowlists.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Updated AllowlistCriteria to require an authorized DMGating module for onInstall and onUninstall functions, preventing unauthorized modifications.
- Added a constructor to initialize the DMGating module address.
- Introduced a modifier to restrict access to DMGating functions.
- Updated tests to reflect the new constructor requirements for AllowlistCriteria.
… related logic

- Renamed the function canReceiveDMFrom to isEntitled for clarity in the DM gating logic.
- Updated the function signature to include the receiver address.
- Adjusted internal logic to reflect the new naming and ensure correct criteria checks.
- Modified tests to align with the new function name and behavior.

This change enhances the readability and understanding of the DM gating functionality.
@giuseppecrj giuseppecrj force-pushed the g/towns-32485-dm-gating-erc6900-module-part-of-account-modules branch from dede117 to 92219df Compare January 14, 2026 00:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant