Skip to content

RWA: country compliance modules#650

Open
pasevin wants to merge 2 commits intoOpenZeppelin:mainfrom
pasevin:feat/rwa-country-standalone
Open

RWA: country compliance modules#650
pasevin wants to merge 2 commits intoOpenZeppelin:mainfrom
pasevin:feat/rwa-country-standalone

Conversation

@pasevin
Copy link
Copy Markdown
Contributor

@pasevin pasevin commented Mar 23, 2026

Summary

Adds country-based compliance modules for RWA tokens: one module allowlists jurisdictions and one module blocks restricted jurisdictions.

Changes

  • Library: adds country_allow and country_restrict compliance modules with their storage and hook implementations.
  • Examples: adds rwa-country-allow and rwa-country-restrict example crates showing how to deploy and bind the modules.
  • Workspace: includes the new example crates in the workspace and module exports.

Test plan

  • cargo +nightly fmt --all -- --check
  • cargo test -p stellar-tokens --lib country_
  • cargo test -p rwa-country-allow --lib
  • cargo test -p rwa-country-restrict --lib

Transplant the reviewed country compliance modules and example crates onto
upstream/main so they can ship as an independent PR without the old stack.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 23, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2ee7b8ad-b550-464e-8b31-19c0d99c8c82

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR introduces two new RWA compliance modules—CountryAllow and CountryRestrict—with corresponding Soroban contract examples. Both modules validate token transfers and mints against Identity Registry Storage country data: one enforces an allowlist, the other a blocklist. The implementation includes trait definitions, storage modules, example contracts, and documentation.

Changes

Cohort / File(s) Summary
Workspace & Crate Configuration
Cargo.toml, examples/rwa-country-allow/Cargo.toml, examples/rwa-country-restrict/Cargo.toml
Added two new example crates to workspace members and created matching Cargo.toml manifests with cdylib/rlib library targets and workspace dependency resolution.
CountryAllow Module (Core)
packages/tokens/src/rwa/compliance/modules/country_allow/mod.rs, packages/tokens/src/rwa/compliance/modules/country_allow/storage.rs
Implemented CountryAllow trait with country allowlist validation logic. Validates transfers/mints by querying IRS for recipient country data and checking membership in per-token allowlists. Includes storage helpers for (token, country) key-value pairs and publishes CountryAllowed/CountryUnallowed events.
CountryRestrict Module (Core)
packages/tokens/src/rwa/compliance/modules/country_restrict/mod.rs, packages/tokens/src/rwa/compliance/modules/country_restrict/storage.rs
Implemented CountryRestrict trait with country restriction list validation logic. Blocks transfers/mints when recipient's IRS country data matches any restricted country. Mirror implementation to CountryAllow with inverted logic. Publishes CountryRestricted/CountryUnrestricted events and includes matching storage helpers.
CountryAllow Example Contract
examples/rwa-country-allow/src/lib.rs, examples/rwa-country-allow/README.md
Created concrete example contract implementing CountryAllow trait with admin/compliance authorization gating, IRS configuration, allowlist management (single and batch updates), and one-time compliance address handoff. Delegates to trait helpers for persistence.
CountryRestrict Example Contract
examples/rwa-country-restrict/src/lib.rs, examples/rwa-country-restrict/README.md
Created concrete example contract implementing CountryRestrict trait with identical authorization and lifecycle patterns to CountryAllow example but enforcing restriction blocklist logic. Mirrors structure for consistency.
Module Registry
packages/tokens/src/rwa/compliance/modules/mod.rs
Exported two new public submodules (country_allow and country_restrict) in compliance modules index.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • RWA: examples #614: Adjusts root Cargo.toml workspace membership to include RWA example crates, directly overlapping with workspace configuration changes in this PR.
  • Rwa reorg #620: Restructures the packages/tokens/src/rwa/compliance/modules/ module namespace that this PR extends with concrete country_allow and country_restrict implementations.
  • feat(rwa): add compliance module base architecture #607: Establishes foundational RWA compliance module infrastructure (helpers, errors, TTL constants) that both trait implementations in this PR build upon.

Suggested labels

Small

Suggested reviewers

  • brozorec
  • ozgunozerk

Poem

🐰✨ Allowlists and blocklists, oh what a sight!
Countries dancing left and right,
With IRS checks and compliance grace,
Two modules find their rightful place!
The rabbit hops with RWA delight! 🚀

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding country-based compliance modules (country_allow and country_restrict) for RWA tokens, which is the primary focus of the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The pull request provides a clear summary of changes, detailed lists of modified components (Library, Examples, Workspace), and a complete test plan with all items checked.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
packages/tokens/src/rwa/compliance/modules/country_restrict/storage.rs (1)

19-28: Optional: Consider extracting a shared storage helper.

The country_allow and country_restrict storage modules share nearly identical logic (read with TTL extension, set with TTL, remove). If more country-based modules are anticipated, a generic helper could reduce duplication. However, keeping them separate is reasonable for clarity and independent evolution.

Also applies to: 37-41, 50-54

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/tokens/src/rwa/compliance/modules/country_restrict/storage.rs`
around lines 19 - 28, Extract the repeated TTL-aware storage operations into a
shared helper to avoid duplication across the country_allow and country_restrict
modules: create a small utility (e.g., functions like get_with_ttl_extend,
set_with_ttl, remove_with_ttl) that accepts the Env reference, a storage key
type (used by CountryRestrictStorageKey and the country_allow key), TTL
threshold and extend amounts, and a closure/type param for the value; then
replace the body of is_country_restricted (and the analogous functions at the
other locations) to call get_with_ttl_extend instead of duplicating
e.storage().persistent().get(...).inspect(...).unwrap_or_default(), and use
set_with_ttl/remove_with_ttl for writes and deletes so all TTL logic is
centralized and consistent.
examples/rwa-country-restrict/src/lib.rs (1)

3-3: Remove unused String import.

The String type is imported but never used in this file.

Suggested fix
-use soroban_sdk::{contract, contractimpl, contracttype, Address, Env, String, Vec};
+use soroban_sdk::{contract, contractimpl, contracttype, Address, Env, Vec};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/rwa-country-restrict/src/lib.rs` at line 3, The import list from
soroban_sdk includes an unused symbol `String`; remove `String` from the `use
soroban_sdk::{contract, contractimpl, contracttype, Address, Env, String, Vec};`
statement so the import becomes only the actually used symbols (`contract`,
`contractimpl`, `contracttype`, `Address`, `Env`, `Vec`), eliminating the unused
`String` import and any related compiler warnings.
examples/rwa-country-allow/src/lib.rs (1)

3-3: Remove unused String import.

The String type is imported but never used in this file.

Suggested fix
-use soroban_sdk::{contract, contractimpl, contracttype, Address, Env, String, Vec};
+use soroban_sdk::{contract, contractimpl, contracttype, Address, Env, Vec};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/rwa-country-allow/src/lib.rs` at line 3, Remove the unused String
import from the module-level use statement: in the use declaration that
currently lists contract, contractimpl, contracttype, Address, Env, String, Vec
remove the String identifier so only used symbols remain; ensure no other code
references String in this file before committing the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@examples/rwa-country-allow/src/lib.rs`:
- Line 3: Remove the unused String import from the module-level use statement:
in the use declaration that currently lists contract, contractimpl,
contracttype, Address, Env, String, Vec remove the String identifier so only
used symbols remain; ensure no other code references String in this file before
committing the change.

In `@examples/rwa-country-restrict/src/lib.rs`:
- Line 3: The import list from soroban_sdk includes an unused symbol `String`;
remove `String` from the `use soroban_sdk::{contract, contractimpl,
contracttype, Address, Env, String, Vec};` statement so the import becomes only
the actually used symbols (`contract`, `contractimpl`, `contracttype`,
`Address`, `Env`, `Vec`), eliminating the unused `String` import and any related
compiler warnings.

In `@packages/tokens/src/rwa/compliance/modules/country_restrict/storage.rs`:
- Around line 19-28: Extract the repeated TTL-aware storage operations into a
shared helper to avoid duplication across the country_allow and country_restrict
modules: create a small utility (e.g., functions like get_with_ttl_extend,
set_with_ttl, remove_with_ttl) that accepts the Env reference, a storage key
type (used by CountryRestrictStorageKey and the country_allow key), TTL
threshold and extend amounts, and a closure/type param for the value; then
replace the body of is_country_restricted (and the analogous functions at the
other locations) to call get_with_ttl_extend instead of duplicating
e.storage().persistent().get(...).inspect(...).unwrap_or_default(), and use
set_with_ttl/remove_with_ttl for writes and deletes so all TTL logic is
centralized and consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a63ad065-ba2e-4f2b-b4b6-cecc0c0c99a3

📥 Commits

Reviewing files that changed from the base of the PR and between ff17d24 and 30c56ef.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • Cargo.toml
  • examples/rwa-country-allow/Cargo.toml
  • examples/rwa-country-allow/README.md
  • examples/rwa-country-allow/src/lib.rs
  • examples/rwa-country-restrict/Cargo.toml
  • examples/rwa-country-restrict/README.md
  • examples/rwa-country-restrict/src/lib.rs
  • packages/tokens/src/rwa/compliance/modules/country_allow/mod.rs
  • packages/tokens/src/rwa/compliance/modules/country_allow/storage.rs
  • packages/tokens/src/rwa/compliance/modules/country_restrict/mod.rs
  • packages/tokens/src/rwa/compliance/modules/country_restrict/storage.rs
  • packages/tokens/src/rwa/compliance/modules/mod.rs

Align the country compliance modules with the repository's preferred test
layout by extracting inline test modules into dedicated test.rs files.
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