Feature: Governance-controlled trading blacklist (compliance / incident response) #308

Closed
opened 2026-06-05 04:08:26 +00:00 by PlasticDigits · 8 comments
PlasticDigits commented 2026-06-05 04:08:26 +00:00 (Migrated from gitlab.com)

Current codebase

Fee-discount blacklist (Tier 255) exists today — governance assigns wallets to tier 255 for 0% fee discount (full fees still apply). See smartcontracts/contracts/fee-discount/, docs/security-model.md, TiersPage.tsx.

This is not a trading ban. Swaps, LP, limits, and cancels still execute.

No governance-controlled blocklist for tokens, pairs, or accounts that halts protocol interaction for compliance / incident response.

Factory has pause per pair (is_paused) but not wallet-level or token-level global bans.

Why this is needed

Compliance and security incidents require fast, governance-controlled ability to:

  • Block all trades involving blacklisted tokens or pairs
  • Block all actions from blacklisted wallets (swap, LP add/remove, limit place/cancel/claim, router ops)
  • Prevent blacklisted wallets from withdrawing or transferring assets through protocol paths (escrow release, LP burn, expired claim)

Tier 255 alone is insufficient — it only removes fee discounts.

Constraints / guardrails

  • Governance-only mutations (multisig / admin); no self-service blacklist.
  • Must not brick unrelated users' funds permanently — document recovery / governance unban.
  • Prefer centralized registry contract or factory extension — avoid N-way drift across pair/router.
  • Native + CW20 paths both covered.
  • Router multihop must reject if any hop touches blacklisted asset or sender.
  • Indexer should expose blacklist status for dApp UX (read-only).
  • Migration / upgrade path for deployed factories.
  • Legal/compliance copy in dApp when user is blocked.

Relevant files

Area Path
Factory smartcontracts/contracts/factory/src/contract.rs
Pair smartcontracts/contracts/pair/src/contract.rs
Router smartcontracts/contracts/router/src/contract.rs
Fee discount (prior art) smartcontracts/contracts/fee-discount/src/contract.rs
Common types smartcontracts/packages/dex-common/
Frontend Swap/Pool/Limit pages, risk surfacing
Docs docs/security-model.md, docs/architecture.md
  1. Design ADR — registry vs factory maps; dimensions: wallet, token, pair; action matrix.
  2. Execute guards — early assert_not_blacklisted in pair/router entrypoints:
    • swap, hybrid, provide_liquidity, withdraw_liquidity
    • place_limit_order*, cancel_limit_order*, claim_expired*, update_limit_order*
  3. Transfer blocking — ensure CW20 Send hooks and escrow releases cannot route value out for banned wallets.
  4. Governance msgs — BlacklistWallet, UnblacklistWallet, BlacklistToken, BlacklistPair (batch optional).
  5. Events for indexer + audit trail.
  6. dApp — query + disable CTAs with incident message.
  7. Tests — matrix per action × blacklist type.

Acceptance criteria

  • Blacklisted wallet cannot swap, LP, place/cancel/claim limits on any pair.
  • Blacklisted token/pair blocks trades involving that asset (both directions).
  • Non-governance cannot mutate lists.
  • Governance can unban and restore functionality.
  • Router multihop rejects tainted paths.
  • dApp surfaces block reason when wallet blacklisted.
  • Security model doc updated.

Test plan (all paths)

Action Wallet BL Token BL Pair BL
Swap Reject Reject Reject
Hybrid Reject Reject Reject
Add LP Reject Reject Reject
Remove LP Reject Reject Reject
Place limit Reject Reject Reject
Cancel own limit Reject — —
Claim expired Reject — —
Router multihop Reject Reject Reject
Unrelated user on clean pair Pass Pass Pass

Attack / abuse / hack vectors

Vector Test
Bypass via router callback Block at pair entry
CW20 direct send to pair Hook rejects blacklisted sender
LP token transfer workaround Withdraw blocked for BL wallet
Governance spoof Only gov address executes blacklist msgs
Denial-of-service banning innocent wallets Governance process + unban test

Verification criteria

  • Full make test-contracts matrix for blacklist.
  • Manual governance flow on LocalTerra.
  • Legal/compliance review of messaging.
## Current codebase **Fee-discount blacklist (Tier 255)** exists today — governance assigns wallets to tier 255 for **0% fee discount** (full fees still apply). See `smartcontracts/contracts/fee-discount/`, `docs/security-model.md`, `TiersPage.tsx`. This is **not** a trading ban. Swaps, LP, limits, and cancels still execute. **No** governance-controlled blocklist for tokens, pairs, or accounts that halts protocol interaction for compliance / incident response. Factory has pause per pair (`is_paused`) but not wallet-level or token-level global bans. ## Why this is needed Compliance and security incidents require fast, governance-controlled ability to: - Block **all trades** involving blacklisted tokens or pairs - Block **all actions** from blacklisted wallets (swap, LP add/remove, limit place/cancel/claim, router ops) - Prevent blacklisted wallets from **withdrawing or transferring** assets through protocol paths (escrow release, LP burn, expired claim) Tier 255 alone is insufficient — it only removes fee discounts. ## Constraints / guardrails - **Governance-only** mutations (multisig / admin); no self-service blacklist. - Must not brick unrelated users' funds permanently — document recovery / governance unban. - Prefer centralized registry contract or factory extension — avoid N-way drift across pair/router. - Native + CW20 paths both covered. - Router multihop must reject if **any** hop touches blacklisted asset or sender. - Indexer should expose blacklist status for dApp UX (read-only). - Migration / upgrade path for deployed factories. - Legal/compliance copy in dApp when user is blocked. ## Relevant files | Area | Path | |------|------| | Factory | `smartcontracts/contracts/factory/src/contract.rs` | | Pair | `smartcontracts/contracts/pair/src/contract.rs` | | Router | `smartcontracts/contracts/router/src/contract.rs` | | Fee discount (prior art) | `smartcontracts/contracts/fee-discount/src/contract.rs` | | Common types | `smartcontracts/packages/dex-common/` | | Frontend | Swap/Pool/Limit pages, risk surfacing | | Docs | `docs/security-model.md`, `docs/architecture.md` | ## Recommended direction 1. **Design ADR** — registry vs factory maps; dimensions: `wallet`, `token`, `pair`; action matrix. 2. **Execute guards** — early `assert_not_blacklisted` in pair/router entrypoints: - `swap`, `hybrid`, `provide_liquidity`, `withdraw_liquidity` - `place_limit_order*`, `cancel_limit_order*`, `claim_expired*`, `update_limit_order*` 3. **Transfer blocking** — ensure CW20 `Send` hooks and escrow releases cannot route value out for banned wallets. 4. **Governance msgs** — `BlacklistWallet`, `UnblacklistWallet`, `BlacklistToken`, `BlacklistPair` (batch optional). 5. **Events** for indexer + audit trail. 6. **dApp** — query + disable CTAs with incident message. 7. **Tests** — matrix per action × blacklist type. ## Acceptance criteria - [ ] Blacklisted wallet cannot swap, LP, place/cancel/claim limits on any pair. - [ ] Blacklisted token/pair blocks trades involving that asset (both directions). - [ ] Non-governance cannot mutate lists. - [ ] Governance can unban and restore functionality. - [ ] Router multihop rejects tainted paths. - [ ] dApp surfaces block reason when wallet blacklisted. - [ ] Security model doc updated. ## Test plan (all paths) | Action | Wallet BL | Token BL | Pair BL | |--------|-----------|----------|---------| | Swap | Reject | Reject | Reject | | Hybrid | Reject | Reject | Reject | | Add LP | Reject | Reject | Reject | | Remove LP | Reject | Reject | Reject | | Place limit | Reject | Reject | Reject | | Cancel own limit | Reject | — | — | | Claim expired | Reject | — | — | | Router multihop | Reject | Reject | Reject | | Unrelated user on clean pair | Pass | Pass | Pass | ## Attack / abuse / hack vectors | Vector | Test | |--------|------| | Bypass via router callback | Block at pair entry | | CW20 direct send to pair | Hook rejects blacklisted sender | | LP token transfer workaround | Withdraw blocked for BL wallet | | Governance spoof | Only gov address executes blacklist msgs | | Denial-of-service banning innocent wallets | Governance process + unban test | ## Verification criteria - Full `make test-contracts` matrix for blacklist. - Manual governance flow on LocalTerra. - Legal/compliance review of messaging.
ghost1 commented 2026-06-05 10:03:09 +00:00 (Migrated from gitlab.com)

mentioned in commit 2714307e16

mentioned in commit 2714307e169b38d025c208a202acda216586e696
ghost1 commented 2026-06-05 10:03:09 +00:00 (Migrated from gitlab.com)

mentioned in commit 7c2efdbecd

mentioned in commit 7c2efdbecd3de51ab6ac8a19827b558ffbbe18da
PlasticDigits commented 2026-06-05 10:03:40 +00:00 (Migrated from gitlab.com)

Implementation complete — see !786.

Summary: Factory-level trading blacklist (wallet / token / pair) with pair + router guards, integration tests, dApp UX, indexer GET /api/v1/compliance/blacklist-check, ADR 0003 + security-model update.

Verification: cargo test -p cl8y-dex-tests blacklist_ and full lib suite (369 tests) PASS; make lint-frontend PASS; cargo check in indexer PASS.

Issue left open pending MR merge and on-chain migration (factory 1.5.0 / pair 1.8.0).

Implementation complete — see [!786](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/68). **Summary:** Factory-level trading blacklist (wallet / token / pair) with pair + router guards, integration tests, dApp UX, indexer `GET /api/v1/compliance/blacklist-check`, ADR 0003 + security-model update. **Verification:** `cargo test -p cl8y-dex-tests blacklist_` and full lib suite (369 tests) PASS; `make lint-frontend` PASS; `cargo check` in indexer PASS. Issue left **open** pending MR merge and on-chain migration (factory 1.5.0 / pair 1.8.0).
PlasticDigits commented 2026-06-05 10:03:42 +00:00 (Migrated from gitlab.com)

mentioned in merge request !786

mentioned in merge request !786
PlasticDigits commented 2026-06-05 10:55:13 +00:00 (Migrated from gitlab.com)

mentioned in commit a46a9ccb77

mentioned in commit a46a9ccb77f4eb8890017606d978bcec4c1f2b87
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-06-05 10:55:15 +00:00
PlasticDigits commented 2026-06-05 12:53:12 +00:00 (Migrated from gitlab.com)

mentioned in merge request !798

mentioned in merge request !798
PlasticDigits commented 2026-06-05 14:10:16 +00:00 (Migrated from gitlab.com)

mentioned in merge request !818

mentioned in merge request !818
PlasticDigits commented 2026-08-28 09:24:17 +00:00 (Migrated from gitlab.com)

mentioned in issue #694

mentioned in issue #694
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-dex-terraclassic#308
No description provided.