feat(soft-launch): CW20 faucet contract + dapp mint page (100 tokens / 5m cooldown) #473
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#473
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
Ship a bundled soft-launch faucet so users on the mainnet frontend (
https://dex.cl8y.com) can select any mintable non-economic gemstone token and mint a fixed 100 units, with a 5-minute per-wallet cooldown. Scope includes:cl8ydeploy(current primary minter) runsAddMinterfor the faucet on each mintable CW20 — no governance/multisig minter handoff (noneconomic tokens; deployer may remain primary minter)Related soft-launch record:
deployments/mainnet-soft-launch/deploy-trace.md, runbookdocs/runbooks/mainnet-soft-launch.md.Current codebase
Soft-launch tokens (columbus-5)
terra1dmuruhht32x8f47nvm73pwp6q7uf2jtfhdt3nxcql4mmqkyfsraqn2dt94terra1k6cqupylk0wp4pj273pntwhv9py0q5guyqye8ssvukn9xq7mes7sdlmenaterra1ejq3mjjgnklpa3pg4jterlfwsny055gpmcjf3fz0ev3ueajnzeysz6xxgrterra178fgrfzv7njtmdp9vghyf2dx77sah8u8jluzs7ym562chaxnmj2s6mn6m9terra1fga508hzx8dd7x8q4uhm6mdhkqv6fxrtsea3r27smdqmv5k2jgxq5zk9fcterra12k67cvfs7y7g8lca3qr4g4py6s6j69fu24gze5pjfamfpckv8mps7cymmeterra17dpnjlpgsnm8muu4msfjra4f2hrptnjp2jdpkka4p0e3px42ayxq0pmc2zterra18fzufz8cs7ez49xjwgs248x85za5v50yug55fj7lyxp9hapxyr7qnh3czsAll soft-launch trading tokens use 6 decimals (invariant SL3). Mint amount 100 human units ⇒
100_000_000base units.Minter reality
Soft-launch instantiate set primary minter to the deploy key (
cl8ydeploy/terra1hu4zggf3f8yw6jw3rxrjxn2drwad675gq5k2lv):Product decision: leave
cl8ydeployas primary minter for these noneconomic tokens. Do not requireUpdateMinter→ governance multisig. Faucet authorization isAddMinter { minter: <faucet> }signed bycl8ydeployon each of the six mintables.PlasticDigits cw20-mintable supports
Mint,AddMinter,RemoveMinter(primary minter + additional minters map). Only the current primary minter (cl8ydeploy) canAddMinter/RemoveMinter.DEX wasm admin /
config.governanceremaining on the multisig is unchanged and out of scope for this faucet work.Frontend today
frontend-dapp/src/App.tsx: Swap, Pool, Create, Tiers, Charts, Portfolio, Limits, Trade, Protocol — no faucet/mint page.frontend-dapp/src/components/common/navItems.ts(primary + More menu).deployments/mainnet-soft-launch/frontend.env.examplepattern from deploy script).frontend-dapp/src/services/terraclassic/(execute + fee estimation); reuse existing Keplr / WalletConnect paths used by Swap/Pool.Contracts today
smartcontracts/contracts/{factory,pair,router,fee-discount,hooks}— no faucet/drip contract.scripts/deploy-dex-local.sh) — useful for LocalTerra faucet QA after adding a local deploy path.Ops / docs today
docs/runbooks/mainnet-soft-launch.md,skills/AGENTS_MAINNET_SOFT_LAUNCH.md,make deploy-mainnet-soft-launch.deployments/mainnet-soft-launch/addresses.env(+ deploy-trace).AddMintergrants.Why this is needed
Soft-launch pools are live with non-economic gemstones, but new users cannot obtain tokens unless someone manually transfers from the deployer inventory. A public faucet:
dex.cl8y.comwithout custodian airdropsMinttxsQUARTZ/PEARL remain non-mintable by design; faucet must not claim to mint them (users obtain them via swaps from mintable legs).
Constraints / guardrails
tokenargs.100000000). No user-chosen amount.cl8ydeployAddMinter. Without this,Mintfails on-chain.cl8ydeployremains primary CW20 minter for noneconomic soft-launch tokens. No multisig minter handoff required for this issue.cl8ydeploy/ designated faucet admin) can pause;cl8ydeploycanRemoveMinteron CW20s in emergency.VITE_FAUCET_ADDRESS(or equivalent) is set; hide/disable on networks without deploy.Relevant files
scripts/deploy-dex-mainnet-soft-launch.sh,scripts/lib/mainnet-soft-launch-defaults.sh,Makefile(deploy-mainnet-soft-launch)docs/runbooks/mainnet-soft-launch.md,skills/AGENTS_MAINNET_SOFT_LAUNCH.md,deployments/mainnet-soft-launch/deploy-trace.md,deployments/mainnet-soft-launch/addresses.envscripts/lib/terrad-host.sh, soft-launch deploy keycl8ydeploysmartcontracts/contracts/faucet/(orsoft-launch-faucet/), workspaceCargo.toml,smartcontracts/artifacts/, optimizer buildcw20-mintable—Mint,AddMinter,RemoveMinter,Minter/Mintersqueriesfrontend-dapp/src/App.tsx,frontend-dapp/src/components/common/navItems.ts,frontend-dapp/src/components/common/Layout.tsxfrontend-dapp/src/services/terraclassic/(execute, queries, fees),frontend-dapp/src/utils/constants.ts,frontend-dapp/.env.exampledocker/frontend/Dockerfile, soft-launchfrontend.env.examplegenerationscripts/deploy-dex-local.sh, LocalTerra env writersRecommended direction
1) Smart contract — soft-launch faucet
New CosmWasm contract, instantiated with:
admin=cl8ydeploy(operator pause/config for noneconomic faucet)allowed_tokens: Vec<Addr>(the six mintables)drip_amount: Uint128=100000000cooldown_seconds: u64=300last_claim: Map<&Addr, Timestamp>(or block time)Execute
Drip { token: String }— sender receivesdrip_amountoftokenvia WasmMsg::ExecuteMint { recipient: info.sender, amount }on the CW20; enforce allowlist + cooldown; emit attributes.Pause/Unpause,UpdateAllowedTokens,UpdateConfig(cooldown/amount within sane bounds).Query
Config {},Cooldown { address }→seconds_remaining,last_claim_at,can_claim.Keep contract minimal (no deposits, no native funds, no arbitrary CW20 sends). Build via existing optimizer (
make build-optimizedtarget include).2) Minter grant sequence (runbook-critical)
All signed by
cl8ydeploy(no multisig):AddMinter { minter: <faucet_addr> }.Mintersshows faucet; sampleDripsmoke.deployments/mainnet-soft-launch/(extend deploy-trace or newfaucet-trace.md).RemoveMinter { minter: faucet }+ faucetPause.Script may broadcast
AddMinterwith the deploy key when explicitly opted in (same keyring pattern as soft-launch deploy).3) Deploy script
Add e.g.
scripts/deploy-soft-launch-faucet.sh+make deploy-soft-launch-faucet:addresses.env/ defaults; admin =cl8ydeployAddMinterfor all six mintables withcl8ydeployFAUCET_ADDRESSintodeployments/mainnet-soft-launch/addresses.env+VITE_FAUCET_ADDRESS/ token list intofrontend.env.exampledeploy-dex-local.shfor E2E4) Frontend
/mintor/faucet(label Mint under More nav — soft-launch only when env set).5) Docs
docs/runbooks/soft-launch-faucet.mdlinked from mainnet soft-launch runbook.skills/AGENTS_MAINNET_SOFT_LAUNCH.mdwith faucet deploy +cl8ydeployAddMinterchecklist.Acceptance criteria
100000000, 300s cooldown, pause, and admin-only config updates.cl8ydeployAddMinterpayloads, verification queries, pause/RemoveMinteremergency — no governance minter handoff.cl8ydeployhas signedAddMinterfor faucet on all six mintables; verified on-chain.frontend.env.exampleincludes faucet + token addresses needed by the UI.Test plan (functional paths)
Contract (unit / cw-multi-test)
100000000.Deploy / ops
DRY_RUN=1deploy script prints instantiate + expectedAddMintermsgs without broadcast.cl8ydeployAddMinterwrites addresses consistently with soft-launch env conventions.Mintersshows faucet; sampleDripfrom funded wallet succeeds.Frontend
LocalTerra / E2E
AddMinter, Playwright: open/mint, drip once, assert balance, retry within cooldown asserts failure messaging.Test plan (attack / abuse / hack vectors)
info.senderonly; CW20 recipient must be sender (no drip-to-other).Addr; no symbol-based trust from client.WasmMsg::ExecuteMint without relying on receiver hooks; CW20 mint should not invoke sender. Add test if mintable ever adds hooks.RemoveMinterrunbook; rotate deploy key per key-custody practices. Acceptable residual for noneconomic demo tokens.cap: nulltoday — faucet rate limit is the sole public throttle; deployer primary minter retained by design for noneconomic tokens.Verification criteria
Configmatches allowlist (6 addresses),drip_amount=100000000,cooldown_seconds=300, not paused.Mintersquery); primary minter remainscl8ydeploy.DripEMBER succeeds once; immediate secondDripfails; after ≥300s succeeds (or time-warp on LocalTerra).https://dex.cl8y.com/mint(or chosen path) with production env — select token, mint 100, cooldown UI correct; QUARTZ/PEARL absent.cl8ydeploy; deploy-trace/faucet-trace filled.make test-mainnet-soft-launch-defaults).Dependencies
cl8ydeploykeyring for instantiate +AddMinter(same soft-launch operator path).deployments/mainnet-soft-launch/).Priority
P1 (soft-launch UX unblocker; noneconomic but user-facing)
Owner type
contracts + frontend + infra/docs (single bundled issue)
changed the description
mentioned in commit
8ace6562f5mentioned in merge request !1012
mentioned in commit
37de409b1cmentioned in commit
c350a9ce68mentioned in issue #474
marked as related to #474
mentioned in issue #475
mentioned in issue #499
mentioned in issue #562
marked as related to #562