design(community-tax): router protocol-exempt vs buy/sell tax — three options (C-2) #607
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic#607
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Parent / related
Audit
INTERNAL_KIMIK3_1787468843C-2. Template #592 (T592-1, T592-2, T592-3, H-01). Router multi-hop was explicitly not a #601 close gate (O601-7). Hybrid always-on #596. PoC:poc_router_exemption_full_tax_bypass(classification only — address named"router", not router wasm).This ticket is design only. Do not implement a tax/router change until one option is written into T592 and accepted here.
Current codebase
Instantiate stamps
PROTOCOL_EXEMPTonconfig.routerwhen set. Columbus-5 launcher does set the official router (terra1e7s0h9…rsrw).Classification in
community-tax-token/src/tax.rs:Send+Cw20HookMsg::Swapto a listed pair and!is_protocol_exempt(from).fromis a listed pair and!is_protocol_exempt(to).A router hop is: user → router (honest inbound) → router
Send+Swapto pair (sell skipped becausefrom=router) → pairTransferto router (buy skipped becauseto=router) → routerTransferto user (wallet↔wallet; transfer tax SKU only, default off).Actually untaxed today: official multi-hop (
swapOpsRequireRouter⇔ops.length >= 2), hybrid ops that execute on the router, permissionless 1-opexecute_swap_operations, invoice wrap-routes via the router.Still taxed: official single-hop pair
Send+Swap(and some Trade pair-direct paths). Do not claim “every official Swap.”If the router were not exempt, it would pay sell extra-debit and typically fail
InsufficientForSellTax(it only holdsamount). That is why the exemption exists — and why it also deletes the tax.Pair and router wasm are unchanged on purpose (H-01).
Why this is needed
Advertised buy/sell bps are not collected on the path the dApp uses for best-execution multi-hop. Direct pair swaps still tax — two economic regimes. Sophisticated flow (router, bots, invoice wraps) is cheaper than the retail pair button. Sinks / AutoLP stay empty on the router path.
This is the product’s central contradiction: inbound 1:1 + unchanged router wasm vs router hops pay tax. There is no one-liner. O601-7 deferred it; it must be decided before the first community token has liquidity.
Constraints / guardrails
code_id11611 does not stop off-dApp router use — not a complete option 1 substitute.Relevant files
smartcontracts/contracts/community-tax-token/src/tax.rs(classify,is_protocol_exempt)smartcontracts/contracts/community-tax-token/src/contract.rs(router stampedPROTOCOL_EXEMPT)smartcontracts/contracts/router/src/contract.rs(execute_swap_operations)frontend-dappSwap / Trade (swapOpsRequireRouter,quoteCw20ViaRouteSolve)skills/AGENTS_COMMUNITY_TAX_CW20.md(T592, O601-7)skills/AGENTS_HYBRID_QUOTING.md/AGENTS_FRONTEND_HYBRID_ALWAYS_ON.mdsmartcontracts/contracts/community-token-launcher/tests/audit_poc.rs(poc_router_exemption_full_tax_bypass)Options and tradeoffs (pick one)
Option 1 — Accept router hops as untaxed (disclose)
What: Write into T592: buy/sell apply to pair-direct
Send+Swap/ pair→EOA only. Router hops are Honest. Swap / Trade copy says so.Keeps: H-01, inbound 1:1, hybrid / #596, no token migrate strictly required (docs + UI).
Costs: Advertised bps do not apply to official multi-hop or any 1-op router Send. Sinks fill only from pair-direct flow. Bots remain cheaper.
Option 2 — Tax the original trader even if
fromis protocol-exemptWhat: Classify
Send+Swapto a listed pair as Sell even whenfromis the router. Extra-debit the original trader (trustedtraderfield — pair already has this for fee discount). Buy: when pair pays the router, tax the final non-exempt recipient (or skip buy on the hop and tax router→user if that is classified).Keeps: Router wasm unchanged; extra-debit stays on the user, not the router’s
amount.Costs: Token classify change → 11611 migrate. Need a trusted trader on every router hop (pair
trader/ router must pass it). Wrong trader field is an abuse vector (see below). Hybrid quotes must include extra-debit. Hardest to specify for buy (pair→router→user).Option 3 — Do not exempt the router; pair-only sells for this template
What: Stop stamping the router
PROTOCOL_EXEMPT(or ignore it for Sell). UsersSendthe tax token to the pair only. dApp forces pair-only execute forcode_id11611.Keeps: Simple classify. Extra-debit works on the path that already works.
Costs: Official hybrid / multi-hop / #596 breaks for this template unless those routes are forbidden. Invoice wrap-routes that hop this token via the router revert or underpay. Integrators who
execute_swap_operations1-op failInsufficientForSellTaxunless they pre-fund the router (they will not). Product cut: “this token is pair-only.”Recommended direction
Record the choice in this issue, then a follow-up implement ticket. Default lean if product wants “bps mean bps on official Swap”: option 2 with an explicit buy-leg spec. Default lean if product wants to keep H-01 + hybrid: option 1 plus honest Swap copy. Do not ship option 3 without accepting a pair-only tax token.
Acceptance criteria (design close)
Test plan — all paths (after a choice; not this ticket)
execute_swap_operations.amount(option 2 must not brick the hop).Test plan — attack / abuse (after a choice)
traderto a victim / exempt address to shift or skip extra-debit. Must be authenticated (pair already-trusted trader rules).route/solvevs on-chain tax after the choice.Verification
poc_router_exemption_full_tax_bypassto match the chosen option (option 1 may keep the PoC as a documented property with a rename).marked as related to #592
marked as related to #596
marked as related to #601
mentioned in merge request !1126
Choice: option 1 — accept router hops as untaxed and disclose.
Not “maybe later.” Written as T592-13 / C593-14 / R607-1–R607-8.
Send+Swap/ pair→non-exempt EOA still pay buy/sell (T592-2 / T592-3).execute_swap_operations, and invoice wrap-routes via the router are Honest.poc_router_exemption_full_tax_bypassstays as a documented property.MR: !1126 · playbook:
skills/AGENTS_COMMUNITY_TAX_ROUTER.md·make verify-issue-607mentioned in issue #603
mentioned in commit
5557f839e9Sanity check of !1126 (merged) vs design-close acceptance.
Acceptance: met. Option 1 is recorded on this issue. T592-13 / C593-14 / R607 written. Implement follow-up waived. No pair/router wasm change (
tax.rscomments only).make verify-issue-6076/6.Problem found and fixed after merge:
SwapPage.tsxdeclaredcommunityTaxHinttwice (identical blocks).verify-issue-607does not runtsc -b, so it stayed green. Pre-committsc --noEmituses the empty roottsconfig.jsonand also missed it. Fixed on !1125 (fix(frontend): drop duplicate communityTaxHint on Swap).Still unchecked (manual):
Sell tax extra+ Max leaves room for extra-debitRoute skips buy/sell tax+ Max is full CW20#603 importer is not blocked by an unwritten C-2 choice; importers must keep T592-13.
mentioned in commit
666e985db3mentioned in issue #612
marked as related to #612
Option 1 is not acceptable. All swaps that go through a buy/sell pair including hybrid and multihop must charge the tax. Investigate an improved version of Option 2.
mentioned in commit
816ae9afdfmentioned in merge request !1127
Choice (supersedes option 1): improved option 2 — tax the original trader on official-router hops.
Not “maybe later.” Written as T592-13 / C593-14 / R607-1–R607-8.
What “improved” means vs the issue’s raw option 2:
Cw20HookMsg::Swap.traderonly whenfromis the stampedconfig.router. Pair-direct extra-debitsfromand ignores a spoofed victimtrader. Missing / protocol-exempt / self trader →RouterTraderRequired(fail closed). Official router wasm already setstraderfor fee discount — no router FoT math, no hopInsufficientForSellTax.Implement: !1127 · playbook:
skills/AGENTS_COMMUNITY_TAX_ROUTER.md·make verify-issue-6078/8.Live columbus-5 11611 still runs pre-option-2 wasm until CMM store + migrate. #603 importers may promise “bps on every official Swap” only after that wasm.
mentioned in issue #615
marked as related to #615
mentioned in merge request !1131
mentioned in commit
cb174fbba1mentioned in commit
aa8991cf02mentioned in commit
574793b4efmarked as related to #616
mentioned in issue #616
Merge sanity (!1127 landed on
main; CI not waited).Automated:
make verify-issue-6078/8 on the integrated tip (docs T592-13 / R607 option 2, extra-debit Max + Create/Manage copy, token hop classify + extra-debit, inverted PoC).make verify-issue-615also re-ran #607 and passed.Acceptance vs live
Swap.traderonly whenfrom == config.router; pair-direct ignores spoofedtrader; missing / protocol-exempt trader fail-closes (RouterTraderRequired). Buy: pair→router 1:1; official router→user outbound split. Hybrid stays on. H-01 held.Post-merge ops (migrate + manual option-2 copy, not disclose): #616. #612 still describes option-1
Route skips buy/sell tax— that copy is stale after !1127.mentioned in issue #621
marked as related to #621
mentioned in issue #622
marked as related to #622
marked as related to #623
mentioned in issue #626
marked as related to #626
mentioned in issue #633
mentioned in issue #690
mentioned in issue #710