No description
  • Rust 96.1%
  • Shell 2.7%
  • Python 0.5%
  • Makefile 0.4%
  • Dockerfile 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-21 13:10:25 +00:00
.github/workflows test: close post-merge coverage gaps from #22/#23/#25 (#28) 2026-08-08 18:58:23 +09:00
audits docs(audit): add internal MR !12 / #28 security review 2026-08-08 19:11:27 +09:00
contracts feat(window): emit fee_amount and fee_asset on deposit/withdraw 2026-08-24 11:44:15 +09:00
docs feat(window): emit fee_amount and fee_asset on deposit/withdraw 2026-08-24 11:44:15 +09:00
oracle-service feat(oracle-service): heartbeat same-rate refresh and confirm UpdateRate from DeliverTx wasm events 2026-08-16 22:26:40 +09:00
scripts feat(oracle-service): heartbeat same-rate refresh and confirm UpdateRate from DeliverTx wasm events 2026-08-16 22:26:40 +09:00
skills feat(window): emit fee_amount and fee_asset on deposit/withdraw 2026-08-24 11:44:15 +09:00
smartcontracts-terraclassic feat(window): emit fee_amount and fee_asset on deposit/withdraw 2026-08-24 11:44:15 +09:00
.dockerignore Add oracle-service Dockerfile and record mainnet window migrate. 2026-08-08 19:23:01 +09:00
.gitignore fix: audit hardening bundle for issue #25 2026-08-08 14:20:06 +09:00
.gitlab-ci.yml test: close post-merge coverage gaps from #22/#23/#25 (#28) 2026-08-08 18:58:23 +09:00
.gitleaks.toml chore(gitleaks): allowlist public docs addresses and target/ 2026-08-08 14:20:06 +09:00
.pre-commit-config.yaml Add ust1-window monorepo: contracts, oracle service, hooks, CI 2026-04-20 21:11:51 +09:00
Cargo.lock feat(security): pin InstantWithdrawCw20 wire format to ustr-cmm (#21) 2026-08-08 14:22:38 +09:00
Cargo.toml feat(security): pin InstantWithdrawCw20 wire format to ustr-cmm (#21) 2026-08-08 14:22:38 +09:00
docker-compose.yml Add ust1-window monorepo: contracts, oracle service, hooks, CI 2026-04-20 21:11:51 +09:00
Dockerfile fix(oracle): accept JSON-object CosmWasm smart query data from LCDs 2026-08-08 19:35:41 +09:00
Makefile test: close post-merge coverage gaps from #22/#23/#25 (#28) 2026-08-08 18:58:23 +09:00
README.md feat(window): emit fee_amount and fee_asset on deposit/withdraw 2026-08-24 11:44:15 +09:00
requirements-dev.txt Add ust1-window monorepo: contracts, oracle service, hooks, CI 2026-04-20 21:11:51 +09:00

ust1-window

Monorepo for Terra Classic UST1 swap tooling against bridged Venus vFDUSD (cw20-mintable), with a rate oracle (BSC Venus exchange rate) and a swap window contract, plus a separate native wrap contract for treasury-backed wLUNC / wUSTC (uluna / uusd) with no oracle (1:1 atoms after fee_bps).

Mainnet status (columbus-5)

Tokens + oracle/window live on mainnet (GitLab #19). Window 11566 InstantWithdraw; oracle 11568 with Venus-normalized rate seeded 2026-08-08 11:04:37 UTC (R=1225104516022056627). UST1 add_minter(window) and treasury SetCw20Spender done. Still pending: oracle-service Coolify (normalized ticks), live withdraw probe, window migrate for fee_amount / fee_asset wasm attrs (#33) — full registry in docs/DEPLOYMENT.md. Redeem: #20. Schema pin: #21.

Contracts & tokens

Asset Address Code ID Notes
cw20-mintable — 10184 Shared CW20 code
vFDUSD (bridged CW20) terra1mnl9azefrqpmu888ar2u6zrcwr80hxlt3avf4300r576cw5ar7esvxsvj3 10184 Decimals 6; minter = CL8Y Terra bridge
UST1 terra1f0eqgy9w7e5e7up97vjudqwx38tesf8ylx75x2lv3nwm0clry0pqmgfy72 10184 Decimals 6; minters include window terra1zxwp…
ust1-oracle terra1fmht0t6svq3n24zx03nkfja0m40zhfyyxkdcvlrkl6u7gfe6aagq4gch8n 11568 Operator terra1hm3ph…; Venus seed 2026-08-08 11:04:37 UTC R=1225104516022056627 (~1.225 FDUSD/vFDUSD)
ust1-window terra1zxwpzpzpleatqn39r00grau4yt29sld8pw78s7ktvjafnj5nsaxq0h3rh2 11566 InstantWithdrawCw20; fee_bps=100; per-tx 1000 / rolling 24h 10000 UST1; migrated from 11550
CMM treasury (ustr-cmm) terra16j5u6ey7a84g40sr3gd94nzg5w5fm45046k9s2347qhfpwm5fr6sem3lr2 11564 Contract; window registered spender + limit_24h=10000000000 (#20)
CL8Y Terra bridge terra18m02l2f43c2dagqnz3kfccpgz9pzzz5hk9l5mh5wvr6dcvv47zfqdfs7la — vFDUSD minter; BSC↔Terra registered

Roles & BSC

Role / asset Address
Terra deployer (cl8ydeploy) terra1hu4zggf3f8yw6jw3rxrjxn2drwad675gq5k2lv
Terra admin / governance / bridge admin (cl8y2_admin) terra1xsecn4snv94ezcez0z3vq8an9j4h4kxxcydp8l
Oracle operator terra1hm3ph0jevtkuc9efj9q3ld3ktk3g6la3ruhqna
Venus vFDUSD (BSC, 8 decimals, LockUnlock) 0xC4eF4229FEc74Ccfe17B2bdeF7715fAC740BA0ba
CL8Y BSC TokenRegistry 0x3d8820ec93748fd4df8eee6b763834a23938b207
BSC admin (TokenRegistry owner) 0xcd4eb82cfc16d5785b4f7e3bfc255e735e79f39c

Packages

Path Role
smartcontracts-terraclassic/packages/ust1-common Fixed-point math, oracle policy (INV-* in source), shared with contracts + service
smartcontracts-terraclassic/packages/ust1-cmm CMM constants (e.g. mainnet treasury address); ust1-window depends on crate ust1-cmm via Git (see root Cargo.toml, Cargo.lock). Change this tree, then cargo update -p ust1-cmm and commit the lockfile. Optional later: dedicated ust1-cmm repo.
contracts/ust1-oracle On-chain rate R, 4h min interval, UTC daily +2% cap, monotonic; governance pause surfaces on State.paused (circuit breaker, #22)
contracts/ust1-window cw20 receive: vFDUSD→mint UST1 + forward vFDUSD to CMM treasury; UST1→burn + treasury InstantWithdrawCw20 (registered spender; no CW20 allowance); governance-set fee on UST1 leg (fee_bps, default 1.0% with 50/50 chain-tax vs CMM accounting). Deposit/withdraw wasm names fee_amount + fee_asset (UST1 withheld; INV-FEE-EVENT-001). Skills: window-instant-withdraw-cw20, window-fee-amount-events (#33)
contracts/cmm-native-wrap Native Wrap + cw20 Receive unwrap: uluna↔wLUNC, uusd↔wUSTC only; governance fee_bps (default 1% recommended per GitLab #17) with 50/50 chain-tax vs CMM attribution on events / EffectiveWrap; per-denom limits; no ust1-oracle (GitLab #16)
oracle-service Polls BSC exchangeRateStored, applies same policy as chain, broadcasts UpdateRate (including same-rate heartbeat after 4h), confirms DeliverTx wasm events or State fallback before liveness (poll/silence/heartbeat: skills/oracle-ops-poll-silence; confirm: skills/oracle-liveness-confirm (#23, #32))
scripts/ Python 3 deploy helpers (no business logic)

Invariants (index)

  • INV-MATH-001 / INV-SWAP-001 / INV-SWAP-002 — ust1-common/src/math.rs (reverse path: inv_swap_002_* vector tests lock the fee-then-rate floor semantics)
  • INV-FEE-EVENT-001 — ust1-common fee_amount_ust1 + ust1-window deposit/withdraw wasm fee_amount / fee_asset (raw UST1 withheld; never reconstruct from bps). Skill: skills/window-fee-amount-events (#33; DEX #614)
  • INV-SWAP-003 / INV-SWAP-004 — ust1-window/src/contract.rs (deposit/withdraw revert on zero output; math dust floors in ust1-common before contract guard) (#25)
  • INV-DECIMALS-001 — ust1-window/src/contract.rs (validate_token_decimals: vFDUSD decimals ≥ UST1 decimals at instantiate/migrate) (#25)
  • INV-MINTER-001 — cw20-mintable fork: UpdateMinter clears old primary from MINTERS (#25/#28; cw20-mintable#1; in-repo: ust1-integration-tests cw20_minter_integration)
  • INV-MATH-002 — ust1-common/src/fee_split.rs + ust1-window / cmm-native-wrap event attributes and Effective* queries (GitLab #17)
  • INV-ORACLE-THROTTLE-001 / INV-ORACLE-DAILY-001 / INV-ORACLE-MONO-001 — ust1-common/src/oracle_policy.rs + ust1-oracle
  • INV-ORACLE-OPS-POLL-001 / INV-ORACLE-OPS-SILENCE-001 — oracle-service poll ≪ / silence ≤ window DEFAULT_MAX_ORACLE_AGE_SECS (#24; skill skills/oracle-ops-poll-silence)
  • INV-ORACLE-PAUSE-001 — oracle State.paused + window ensure_oracle_usable fail-closed on deposit/withdraw (#22; skill skills/oracle-circuit-breaker)
  • INV-ORACLE-LIVENESS-001 — oracle-service confirms DeliverTx wasm events (or State fallback) before silence/liveness success (not CheckTx alone); same-rate heartbeat after 4h throttle; oracle-service/src/{confirm,terra_tx,liveness,main}.rs, skills skills/oracle-liveness-confirm, skills/oracle-ops-poll-silence (#23, #32, audit C-3)
  • INV-ORACLE-TICK-001 / INV-ORACLE-ACCOUNT-001 / INV-ORACLE-GAS-001 / INV-ORACLE-HEALTHZ-001 — oracle-service tick timeout, fail-hard account parse, adaptive gas, process-up /healthz (#25; skills/audit-hardening-bundle)
  • INV-LIMIT-001 — ust1-window/src/state.rs, enforced in contract.rs
  • INV-WITHDRAW-001 / INV-WITHDRAW-002 — ust1-window/src/state.rs + treasury.rs / contract.rs (InstantWithdrawCw20; burn-then-pull atomicity) (#20)
  • INV-SCHEMA-001 — ust1-window/src/treasury.rs + golden testdata/instant_withdraw_cw20_golden.json + integration treasury_schema / real_treasury_integration (pinned ustr-cmm wire format) (#21)
  • INV-LIMIT-NATIVE-001 — cmm-native-wrap/src/state.rs / limits.rs, enforced in wrap.rs and unwrap.rs

Operator checklist, BSC + Terra address registry, and mainnet/testnet deployment notes: docs/DEPLOYMENT.md (GitLab #15).

Local development

make start          # LocalTerra (Docker)
make wait-healthy
make test-contracts
make test-localterra-smoke   # TEST-16 / #28: skip-clean if LCD down; see docs/DEPLOYMENT.md
# After deploy (see scripts/):
# export BSC_RPC_URLS=..., VENUS_VTOKEN_ADDRESS=..., TERRA_LCD_URL=..., ORACLE_CONTRACT=...
# cargo run -p ust1-oracle-service

Oracle service: observability and deployment

The ust1-oracle-service binary is intentionally lightweight: it uses structured tracing logs only (no Prometheus or in-process metrics server). Every check_rate_update / oracle_heartbeat and broadcast/confirm outcome is logged at info (policy / confirmed update) or warn (CheckTx / DeliverTx / event or state confirmation failure). BROADCAST_MODE_SYNC CheckTx success alone does not count as success (INV-ORACLE-LIVENESS-001): the service polls for DeliverTx inclusion and confirms wasm update_rate events (or retried oracle State when events are stripped) before recording liveness. Lagged LCD State after event proof does not fail-close. Same-rate Venus readings still submit UpdateRate once the 4h throttle allows so last_update_sec stays inside window max_oracle_age_sec (6h). If there has been no confirmed on-chain oracle update for longer than ORACLE_MAX_SILENCE_SECS (default 21600, i.e. 6 hours — aligned with window DEFAULT_MAX_ORACLE_AGE_SECS), the process emits a high-visibility error! liveness alert on each poll tick. Default POLL_INTERVAL_SECS is 3600 (1h) so a missed tick does not consume the entire 6h staleness budget; on-chain throttle still skips broadcasts inside 4h (INV-ORACLE-OPS-POLL-001 / INV-ORACLE-OPS-SILENCE-001, glab #24, glab #32).

Production-style deployment (Terra Classic wasm + BSC oracle path + operator checklist + address registry) is documented in docs/DEPLOYMENT.md. After exporting env vars, run make verify-oracle-env to confirm required keys are present before starting the service. Agent skills: skills/oracle-ops-poll-silence, skills/oracle-liveness-confirm (#23, #32).

Deployment (e.g. Render): the oracle service exposes a liveness-only HTTP probe — GET /healthz returns 200 when the process is up (bind via HEALTHZ_BIND, default 0.0.0.0:8080; set off to disable). This does not imply on-chain rate freshness or a recent successful UpdateRate; pair it with log alerts (ORACLE_MAX_SILENCE_SECS) and off-platform paging. Tick-level timeouts and gas pricing knobs (TICK_TIMEOUT_SECS, TERRA_GAS_PRICE, BSC_RPC_TIMEOUT_SECS) are documented in docs/DEPLOYMENT.md. Agent notes: skills/audit-hardening-bundle (#25), skills/oracle-ops-poll-silence (#24).

Relevant environment variables: ORACLE_MAX_SILENCE_SECS, ORACLE_TX_CONFIRM_TIMEOUT_SECS, ORACLE_TX_CONFIRM_POLL_INTERVAL_MS, POLL_INTERVAL_SECS, HEALTHZ_BIND, plus the oracle env vars listed under Local development above and in docs/DEPLOYMENT.md.

Build optimized Wasm

make build-optimized   # Docker cosmwasm/optimizer → artifacts/

Contract crates live under top-level contracts/ so CosmWasm bob picks them up (it only builds workspace members with that path prefix).

Git hooks and secret scanning

  • Gitleaks config: .gitleaks.toml. CI runs gitleaks/gitleaks-action on every push/PR.
  • Pre-commit (.pre-commit-config.yaml): merge-conflict / YAML / EOF / whitespace checks, Gitleaks, ShellCheck on scripts/**/*.sh, cargo fmt, cargo check, cargo clippy (warnings denied), and python3 -m compileall on scripts/.
python3 -m venv .venv && . .venv/bin/activate   # recommended on PEP 668–managed systems
pip install -r requirements-dev.txt
make install-hooks                    # pre-commit install
make precommit                        # pre-commit run --all-files

License

MIT OR Apache-2.0 (see individual crates).