feat: CW20 InstantWithdraw + spender registry for ust1-window (vFDUSD) #6
Labels
No labels
bug
docs
documentation
duplicate
enhancement
frontend
good first issue
help wanted
invalid
missing-implementation
priority
medium
product
QA
question
testing
UX
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/ustr-cmm#6
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?
Summary
Add a governance-registered CW20 InstantWithdraw path on the CMM Treasury so
ust1-windowcan redeem UST1→vFDUSD by asking the treasury toTransfervFDUSD to the user — without CW20IncreaseAllowance(treasury is a contract, not an EOA).This is the treasury half of Option 3 (window calls treasury API). Companion issue: PlasticDigits/ust1-window (to be linked after creation). Related: Phase 3 wrap migrate #5; UST1 mainnet deploy ust1-window#19.
Current codebase
contracts/contracts/treasury/src/msg.rsProposeWithdraw/ExecuteWithdraw(Cw20ExecuteMsg::Transfer). Hot pathInstantWithdraw { recipient, denom, amount }is native-only.state.rs→DENOM_WRAPPERSSetDenomWrapper/RemoveDenomWrapper; caller must match registered wrapper for that denom.contract.rs→execute_instant_withdrawBankMsg::Send. No CW20 branch.SetWrappingPaused/config.wrapping_pausedWrapDepositand nativeInstantWithdraw.plans/NATIVE_TOKEN_WRAPPING.md§1.4InstantWithdraw { recipient, asset: AssetInfo, amount }with CW20Transfer— not what shipped (denom: Stringonly).contracts/packages/common/src/asset.rsAssetInfo::{Native, Cw20}available for new msgs if desired.terra16j5u6ey7a84g40sr3gd94nzg5w5fm45046k9s2347qhfpwm5fr6sem3lr2terra1xsecn4snv94ezcez0z3vq8an9j4h4kxxcydp8l;swap_contract: null.Why Option 2 (CW20 allowance) was rejected: Treasury cannot be
--fromforincrease_allowanceon vFDUSD; there is no gov message that emits CW20 allowance. Window withdraw currently expectsTransferFrom(owner=treasury).Why this is needed
ust1-windowdeposits already Transfer bridged vFDUSD into this treasury address.ProposeWithdrawis unusable for a swap window.InstantWithdrawcannot move CW20 balances.Without this, mainnet UST1→vFDUSD redeem stays blocked even after oracle/window instantiate (#19 Phase 5).
Constraints / guardrails
SetDenomWrapper,WrapDeposit, nativeInstantWithdraw) — coordinate with / layer on #5 migrate.SwapDepositproduct; leaveswap_contractnull.wrapping_pausedmust not gate CW20 InstantWithdraw used by UST1 window (pausing wraps must not halt vFDUSD redeem). Use a separate pause flag for the CW20 pull path (or document that only a dedicated pause applies).ProposeWithdrawremains the only path for arbitrary destinations / non-registered spenders.Transfer(fail cleanly).InstantWithdraw { denom }for wrap-mapper; add parallel CW20 msgs (avoid forcing wrap-mapper ABI churn).terra16j5u6…stays stable (window + docs already point here).Relevant files
contracts/contracts/treasury/src/msg.rs— new execute/query variantscontracts/contracts/treasury/src/state.rs— CW20 spender map (+ optional pause/cap)contracts/contracts/treasury/src/contract.rs— handlers, migrate if storage keys addedcontracts/contracts/treasury/src/error.rs— auth / pause / balance errorscontracts/packages/common/src/asset.rs— reuse if msgs takeAssetInfoplans/NATIVE_TOKEN_WRAPPING.md— update to document CW20 InstantWithdraw as separate from native wrapdocs/CONTRACTS.md,docs/ARCHITECTURE.md,docs/DEPLOYMENT.md— operator docs for register/pause/migrateust1-windowwithdraw path (companion issue)Recommended direction
Add a parallel CW20 pull API (do not change wrap-mapper’s
InstantWithdraw { denom }signature):Implementation sketch:
InstantWithdrawCw20: reject if paused; load spender fortoken; requireinfo.sender == spender; validate recipient; query CW20 balance of treasury ≥ amount; emitCw20ExecuteMsg::Transfer { recipient, amount }.SetCw20Spender { token: TERRA_VFDUSD, spender: WINDOW_ADDR }.Out of scope for this issue: changing
ust1-window(companion repo); native wrap feature work (#5) except migrate coordination / non-regression.Acceptance criteria
InstantWithdrawCw20→ recipient receives CW20; treasury balance decreases byamount.wrapping_paused=false.wrapping_paused=truedoes not block InstantWithdrawCw20.ProposeWithdraw/ExecuteWithdrawfor CW20 still work (timelock path unchanged).ust1-windowissue; note mainnetSetCw20Spenderas post-deploy step for #19.Test plan — functional paths
SetCw20SpenderRemoveCw20SpenderTest plan — attack / abuse / hack vectors
denom_wrappersVerification criteria
cargo testin treasury package (and workspace CI) green including new cases above.Cw20Spendersquery works; native wrap (if #5 done) still healthy; no regression onconfig/ pending withdrawals.Dependencies
SetCw20Spenderexecuted.Companion window issue (Option 3 consumer): https://gitlab.com/PlasticDigits/ust1-window/-/work_items/20
Sequencing: land treasury API + migrate here first, then window migrate +
SetCw20Spender { token: vFDUSD, spender: window }.mentioned in issue #5
mentioned in commit
24062f9b13mentioned in merge request !27
mentioned in commit
b0b07e4ca2mentioned in commit
2738a8696fmentioned in issue #7
mentioned in merge request !28
mentioned in issue #8
mentioned in merge request PlasticDigits/ust1-window!23
mentioned in issue #10