fix(scripts): attach pair creation fee uluna on deploy-dex-local create_pair (#276) #320

Closed
opened 2026-06-05 05:42:23 +00:00 by PlasticDigits · 3 comments
PlasticDigits commented 2026-06-05 05:42:23 +00:00 (Migrated from gitlab.com)

Current codebase

Factory CreatePair charges a governance-set pair creation fee in native uluna (default 100_000_000 = 100 LUNC). The fee is forwarded to treasury; underpayment is rejected (GitLab #276).

Layer Detail
Constant DEFAULT_PAIR_CREATION_FEE_ULUNA in smartcontracts/packages/dex-common/src/factory.rs
On-chain check execute_create_pair in smartcontracts/contracts/factory/src/contract.rs — requires info.funds ≥ fee; error: Pair creation requires {required} uluna attached
Contract test create_pair_charges_fee_to_treasury_and_gov_can_set_it in smartcontracts/tests/src/lib.rs

Local deploy script (scripts/deploy-dex-local.sh) calls terrad_tx wasm execute "$FACTORY_ADDRESS" "$CREATE_MSG" for every create_pair without attaching native coins:

  • Phase 4 main pairs (~line 525)
  • Phase 4b unpaired-token pairs (~line 635)
  • Phase 4c wrapped-native pairs (~line 682)

terrad_tx() only sets --fees 500000000uluna (gas); it does not pass --amount for the creation fee.

Related script: scripts/e2e-seed-wrap-pairs.sh (~line 144) has the same gap for wrap E2E pair seeding.

Observed failure (Cloud Agent / fresh LocalTerra, 2026-06-05): Phase 4 fails on the first pair with:

Pair creation requires 100000000 uluna attached

Deploy aborts before writing frontend-dapp/.env.local / indexer/.env, blocking make deploy-local, strict E2E, and manual QA.

Why this is needed

  • Local dev / CI parity: Operators expect make deploy-local to succeed on a funded test1 wallet after make start.
  • Regression since #276: Contract behavior is correct; shell scripts were not updated when the fee was introduced.
  • Agent / QA cost: Verification of unrelated issues (e.g. #302) required ad-hoc sed patches to finish deploy.

Constraints and guardrails

  • Fee amount must stay in sync with on-chain config: prefer DEFAULT_PAIR_CREATION_FEE_ULUNA / factory query, or a single named shell constant (e.g. PAIR_CREATION_FEE_ULUNA=100000000) documented next to deploy — do not hardcode unrelated values in three places.
  • One pair per block (PAIR_CREATION_BLOCK): deploy already sleeps between creates; keep sequential pair creation.
  • Overpay is refunded on-chain; attaching exactly 100000000uluna is sufficient.
  • Unexpected denoms in info.funds are rejected — only attach uluna, not mixed with gas (gas remains --fees).
  • Do not disable or zero the fee in local deploy unless governance explicitly sets fee to zero in instantiate (default is non-zero).
  • test1 on LocalTerra must retain enough uluna for: (N pairs × creation fee) + gas for full deploy (~23+ pairs today).

Relevant files

File Role
scripts/deploy-dex-local.sh Primary fix — all create_pair factory executes
scripts/e2e-seed-wrap-pairs.sh Same pattern for wrap pair seed
scripts/lib/terrad-tx-events.sh Tx parsing helpers (unchanged unless adding helper)
smartcontracts/packages/dex-common/src/factory.rs Fee constant / instantiate default
smartcontracts/contracts/factory/src/contract.rs Fee enforcement
smartcontracts/contracts/factory/src/error.rs Error strings
smartcontracts/tests/src/lib.rs Reference test for fee behavior
Makefile deploy-local target
AGENTS.md Cloud Agent deploy steps
docs/testing.md Local stack / E2E prerequisites
  1. Add a shell constant at top of deploy-dex-local.sh, e.g. PAIR_CREATION_FEE_ULUNA="${PAIR_CREATION_FEE_ULUNA:-100000000}", matching DEFAULT_PAIR_CREATION_FEE_ULUNA.
  2. Introduce a small helper, e.g. terrad_tx_create_pair(), that runs:
    terrad_tx wasm execute "$FACTORY_ADDRESS" "$CREATE_MSG" --amount "${PAIR_CREATION_FEE_ULUNA}uluna"
    and replace the three create_pair call sites.
  3. Mirror the same --amount in e2e-seed-wrap-pairs.sh (or source shared snippet).
  4. Optional hardening: after factory instantiate, terrad query wasm contract-state smart $FACTORY config and use returned pair_creation_fee_uluna instead of a fixed default (helps if local governance changes fee).
  5. Document in AGENTS.md / deploy script header that deploy needs ~(num_pairs × fee) + gas uluna on test1.

Acceptance criteria

  • make start && make wait-healthy && make deploy-local completes on a fresh make reset volume without manual patches.
  • frontend-dapp/.env.local and indexer/.env are written; .qa-deploy-stamp lists expected pair count.
  • All factory create_pair txs in deploy-dex-local.sh include 100000000uluna (or queried fee) attachment.
  • scripts/e2e-seed-wrap-pairs.sh create_pair succeeds when wrap pairs are missing (or fails with clear message if wallet underfunded).
  • No regression to contract tests: cargo test create_pair_charges_fee_to_treasury_and_gov_can_set_it still passes.

Test plan (functional paths)

Path Steps Expected
Happy path make reset && make start && make wait-healthy && make deploy-local Exit 0; env files exist
Re-run deploy Second deploy-local on same chain Idempotent or clear failure (duplicate pairs), not fee error
Underfunded wallet Simulate test1 with < 100M uluna before first pair Tx fails with InsufficientPairCreationFee / attach message; script exits non-zero with readable log
E2E seed Run e2e-seed-wrap-pairs.sh after deploy Wrap pairs created or skipped if present
Governance fee change (Optional) set_pair_creation_fee to different value; deploy uses updated amount Pairs still create

Test plan (attack / abuse / misuse)

Vector Risk Mitigation / check
Fee bypass in scripts Local deploy appears to work while production users still pay fee Fix must only add --amount to honest deploy paths; do not change factory code
Wrong denom attached Factory rejects with UnexpectedPairCreationFunds Only attach uluna; no CW20 in create_pair funds
Underpayment Spam cheap pair creation on public nets On-chain check remains; scripts must not teach --amount 0
Overpayment drain Script sends excessive uluna per pair Attach exact fee (overpay is refunded on-chain, but wastes balance on many pairs)
One-pair-per-block evasion Parallel create_pair in script Keep sequential creates + sleeps; document block gate
Treasury mis-route Fee sent to wrong address Contract sends to configured treasury; script only funds tx

Verification criteria

  • CI / agent checklist: make deploy-local from clean state documented in MR description.
  • Grep: all create_pair executes in scripts/deploy-dex-local.sh and scripts/e2e-seed-wrap-pairs.sh include --amount with uluna.
  • Post-deploy: curl http://127.0.0.1:1317/... factory pair count matches script summary line.
  • Link MR to this issue; close when acceptance criteria pass on main.
  • GitLab #276 — pair creation fee (on-chain)
  • GitLab #302 — verification blocked by deploy failure (2026-06-05)
## Current codebase Factory `CreatePair` charges a governance-set **pair creation fee** in native `uluna` (default **100_000_000** = 100 LUNC). The fee is forwarded to treasury; underpayment is rejected ([GitLab **#276**](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/276)). | Layer | Detail | |-------|--------| | Constant | `DEFAULT_PAIR_CREATION_FEE_ULUNA` in `smartcontracts/packages/dex-common/src/factory.rs` | | On-chain check | `execute_create_pair` in `smartcontracts/contracts/factory/src/contract.rs` — requires `info.funds` ≥ fee; error: `Pair creation requires {required} uluna attached` | | Contract test | `create_pair_charges_fee_to_treasury_and_gov_can_set_it` in `smartcontracts/tests/src/lib.rs` | **Local deploy script** (`scripts/deploy-dex-local.sh`) calls `terrad_tx wasm execute "$FACTORY_ADDRESS" "$CREATE_MSG"` for every `create_pair` **without** attaching native coins: - Phase 4 main pairs (~line 525) - Phase 4b unpaired-token pairs (~line 635) - Phase 4c wrapped-native pairs (~line 682) `terrad_tx()` only sets `--fees 500000000uluna` (gas); it does **not** pass `--amount` for the creation fee. **Related script:** `scripts/e2e-seed-wrap-pairs.sh` (~line 144) has the same gap for wrap E2E pair seeding. **Observed failure (Cloud Agent / fresh LocalTerra, 2026-06-05):** Phase 4 fails on the first pair with: ```text Pair creation requires 100000000 uluna attached ``` Deploy aborts before writing `frontend-dapp/.env.local` / `indexer/.env`, blocking `make deploy-local`, strict E2E, and manual QA. ## Why this is needed - **Local dev / CI parity:** Operators expect `make deploy-local` to succeed on a funded `test1` wallet after `make start`. - **Regression since #276:** Contract behavior is correct; shell scripts were not updated when the fee was introduced. - **Agent / QA cost:** Verification of unrelated issues (e.g. [#302](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/302)) required ad-hoc `sed` patches to finish deploy. ## Constraints and guardrails - Fee amount must stay **in sync** with on-chain config: prefer `DEFAULT_PAIR_CREATION_FEE_ULUNA` / factory query, or a single named shell constant (e.g. `PAIR_CREATION_FEE_ULUNA=100000000`) documented next to deploy — do not hardcode unrelated values in three places. - **One pair per block** (`PAIR_CREATION_BLOCK`): deploy already `sleep`s between creates; keep sequential pair creation. - **Overpay is refunded** on-chain; attaching exactly `100000000uluna` is sufficient. - **Unexpected denoms** in `info.funds` are rejected — only attach `uluna`, not mixed with gas (gas remains `--fees`). - Do not disable or zero the fee in local deploy unless governance explicitly sets fee to zero in instantiate (default is non-zero). - `test1` on LocalTerra must retain enough `uluna` for: (N pairs × creation fee) + gas for full deploy (~23+ pairs today). ## Relevant files | File | Role | |------|------| | `scripts/deploy-dex-local.sh` | Primary fix — all `create_pair` factory executes | | `scripts/e2e-seed-wrap-pairs.sh` | Same pattern for wrap pair seed | | `scripts/lib/terrad-tx-events.sh` | Tx parsing helpers (unchanged unless adding helper) | | `smartcontracts/packages/dex-common/src/factory.rs` | Fee constant / instantiate default | | `smartcontracts/contracts/factory/src/contract.rs` | Fee enforcement | | `smartcontracts/contracts/factory/src/error.rs` | Error strings | | `smartcontracts/tests/src/lib.rs` | Reference test for fee behavior | | `Makefile` | `deploy-local` target | | `AGENTS.md` | Cloud Agent deploy steps | | `docs/testing.md` | Local stack / E2E prerequisites | ## Recommended solution direction 1. Add a shell constant at top of `deploy-dex-local.sh`, e.g. `PAIR_CREATION_FEE_ULUNA="${PAIR_CREATION_FEE_ULUNA:-100000000}"`, matching `DEFAULT_PAIR_CREATION_FEE_ULUNA`. 2. Introduce a small helper, e.g. `terrad_tx_create_pair()`, that runs: `terrad_tx wasm execute "$FACTORY_ADDRESS" "$CREATE_MSG" --amount "${PAIR_CREATION_FEE_ULUNA}uluna"` and replace the three `create_pair` call sites. 3. Mirror the same `--amount` in `e2e-seed-wrap-pairs.sh` (or source shared snippet). 4. Optional hardening: after factory instantiate, `terrad query wasm contract-state smart $FACTORY config` and use returned `pair_creation_fee_uluna` instead of a fixed default (helps if local governance changes fee). 5. Document in `AGENTS.md` / deploy script header that deploy needs ~`(num_pairs × fee) + gas` uluna on `test1`. ## Acceptance criteria - [ ] `make start && make wait-healthy && make deploy-local` completes on a **fresh** `make reset` volume without manual patches. - [ ] `frontend-dapp/.env.local` and `indexer/.env` are written; `.qa-deploy-stamp` lists expected pair count. - [ ] All factory `create_pair` txs in `deploy-dex-local.sh` include `100000000uluna` (or queried fee) attachment. - [ ] `scripts/e2e-seed-wrap-pairs.sh` `create_pair` succeeds when wrap pairs are missing (or fails with clear message if wallet underfunded). - [ ] No regression to contract tests: `cargo test create_pair_charges_fee_to_treasury_and_gov_can_set_it` still passes. ## Test plan (functional paths) | Path | Steps | Expected | |------|--------|----------| | Happy path | `make reset && make start && make wait-healthy && make deploy-local` | Exit 0; env files exist | | Re-run deploy | Second `deploy-local` on same chain | Idempotent or clear failure (duplicate pairs), not fee error | | Underfunded wallet | Simulate `test1` with &lt; 100M uluna before first pair | Tx fails with `InsufficientPairCreationFee` / attach message; script exits non-zero with readable log | | E2E seed | Run `e2e-seed-wrap-pairs.sh` after deploy | Wrap pairs created or skipped if present | | Governance fee change | (Optional) `set_pair_creation_fee` to different value; deploy uses updated amount | Pairs still create | ## Test plan (attack / abuse / misuse) | Vector | Risk | Mitigation / check | |--------|------|-------------------| | **Fee bypass in scripts** | Local deploy appears to work while production users still pay fee | Fix must only add `--amount` to honest deploy paths; do not change factory code | | **Wrong denom attached** | Factory rejects with `UnexpectedPairCreationFunds` | Only attach `uluna`; no CW20 in `create_pair` funds | | **Underpayment** | Spam cheap pair creation on public nets | On-chain check remains; scripts must not teach `--amount 0` | | **Overpayment drain** | Script sends excessive uluna per pair | Attach **exact** fee (overpay is refunded on-chain, but wastes balance on many pairs) | | **One-pair-per-block evasion** | Parallel `create_pair` in script | Keep sequential creates + sleeps; document block gate | | **Treasury mis-route** | Fee sent to wrong address | Contract sends to configured treasury; script only funds tx | ## Verification criteria - [ ] CI / agent checklist: `make deploy-local` from clean state documented in MR description. - [ ] Grep: all `create_pair` executes in `scripts/deploy-dex-local.sh` and `scripts/e2e-seed-wrap-pairs.sh` include `--amount` with `uluna`. - [ ] Post-deploy: `curl http://127.0.0.1:1317/...` factory pair count matches script summary line. - [ ] Link MR to this issue; close when acceptance criteria pass on `main`. ## Related - GitLab **#276** — pair creation fee (on-chain) - GitLab **#302** — verification blocked by deploy failure (2026-06-05)
PlasticDigits commented 2026-06-05 05:42:33 +00:00 (Migrated from gitlab.com)

marked as related to #276

marked as related to #276
PlasticDigits commented 2026-06-05 05:42:34 +00:00 (Migrated from gitlab.com)

marked as related to #302

marked as related to #302
PlasticDigits commented 2026-06-05 10:28:35 +00:00 (Migrated from gitlab.com)

Implementation agent — verification (#320)

Status: Already fixed on `main` (no new MR). The deploy failure described in this issue was addressed in #318 via merge `qa/318-315-deploy-fee-gas` (commit `f5747ed` — `fix(deploy): attach pair-creation fee + gas-prices on local deploy`).

What is on `main`

  • `scripts/deploy-dex-local.sh`: `factory_create_pair()` queries factory `config.pair_creation_fee_uluna` and passes `--amount "${PAIR_CREATION_FEE_ULUNA}uluna"` on every `create_pair`; pre-flight `test1` uluna balance check.
  • `scripts/e2e-seed-wrap-pairs.sh`: same fee via LCD config query + `--amount` on `create_pair`.
  • Docs: `docs/local-development.md`, `docs/security-model.md`, `skills/AGENTS_LOCALNET_TRADING_SWARM.md`.

Acceptance checklist

Criterion Result How verified
`make start && wait-healthy && deploy-local` on fresh chain PASS `make start`, `make wait-healthy`, `make build-optimized`, `./scripts/deploy-dex-local.sh` — exit 0 (~15 min); log shows `Pair creation fee: 100000000 uluna` and all Phase 4 pairs created
`frontend-dapp/.env.local`, `indexer/.env`, `.qa-deploy-stamp` PASS Files present after deploy; stamp `git_sha=1c4ad92`, factory + pair addresses
All `create_pair` in deploy script attach queried fee PASS `grep factory_create_pair` / `PAIR_CREATION_FEE_ULUNA}uluna` — 3 call sites use helper
`e2e-seed-wrap-pairs.sh` PASS Exit 0 — wrap pairs already present (skipped create); script includes `fee_args=(--amount …uluna)`
Contract test `create_pair_charges_fee_to_treasury_and_gov_can_set_it` PASS `cargo test create_pair_charges_fee_to_treasury_and_gov_can_set_it`; `./scripts/qa/verify-issue-276.sh` — 5/5 PASS
Grep `--amount` + `uluna` on create_pair paths PASS See deploy + e2e-seed-wrap-pairs grep above
Re-run deploy / governance fee change SKIP Not re-run in this session; behavior covered by on-chain config query in helper

Commands (Cloud Agent VM, 2026-06-05)

```bash
./scripts/qa/verify-issue-276.sh
make start && make wait-healthy && make build-optimized
./scripts/deploy-dex-local.sh # exit 0
./scripts/e2e-seed-wrap-pairs.sh
```

Closing as duplicate of the delivered #318 work; no additional code changes required for #320.

## Implementation agent — verification (#320) **Status:** Already fixed on \`main\` (no new MR). The deploy failure described in this issue was addressed in [**#318**](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/318) via merge \`qa/318-315-deploy-fee-gas\` (commit \`f5747ed\` — \`fix(deploy): attach pair-creation fee + gas-prices on local deploy\`). ### What is on \`main\` - \`scripts/deploy-dex-local.sh\`: \`factory_create_pair()\` queries factory \`config.pair_creation_fee_uluna\` and passes \`--amount "${PAIR_CREATION_FEE_ULUNA}uluna"\` on every \`create_pair\`; pre-flight \`test1\` uluna balance check. - \`scripts/e2e-seed-wrap-pairs.sh\`: same fee via LCD config query + \`--amount\` on \`create_pair\`. - Docs: \`docs/local-development.md\`, \`docs/security-model.md\`, \`skills/AGENTS_LOCALNET_TRADING_SWARM.md\`. ### Acceptance checklist | Criterion | Result | How verified | |-----------|--------|----------------| | \`make start && wait-healthy && deploy-local\` on fresh chain | **PASS** | \`make start\`, \`make wait-healthy\`, \`make build-optimized\`, \`./scripts/deploy-dex-local.sh\` — exit **0** (~15 min); log shows \`Pair creation fee: 100000000 uluna\` and all Phase 4 pairs created | | \`frontend-dapp/.env.local\`, \`indexer/.env\`, \`.qa-deploy-stamp\` | **PASS** | Files present after deploy; stamp \`git_sha=1c4ad92\`, factory + pair addresses | | All \`create_pair\` in deploy script attach queried fee | **PASS** | \`grep factory_create_pair\` / \`PAIR_CREATION_FEE_ULUNA}uluna\` — 3 call sites use helper | | \`e2e-seed-wrap-pairs.sh\` | **PASS** | Exit **0** — wrap pairs already present (skipped create); script includes \`fee_args=(--amount …uluna)\` | | Contract test \`create_pair_charges_fee_to_treasury_and_gov_can_set_it\` | **PASS** | \`cargo test create_pair_charges_fee_to_treasury_and_gov_can_set_it\`; \`./scripts/qa/verify-issue-276.sh\` — 5/5 PASS | | Grep \`--amount\` + \`uluna\` on create_pair paths | **PASS** | See deploy + e2e-seed-wrap-pairs grep above | | Re-run deploy / governance fee change | **SKIP** | Not re-run in this session; behavior covered by on-chain config query in helper | ### Commands (Cloud Agent VM, 2026-06-05) \`\`\`bash ./scripts/qa/verify-issue-276.sh make start && make wait-healthy && make build-optimized ./scripts/deploy-dex-local.sh # exit 0 ./scripts/e2e-seed-wrap-pairs.sh \`\`\` Closing as duplicate of the delivered **#318** work; no additional code changes required for **#320**.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-06-05 10:28:48 +00:00
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#320
No description provided.