Hybrid swap gas (frontend): quote-driven gas limits + single-hop direct-to-pair audit #249
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#249
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
Reduce LUNC fees on hybrid swaps by (1) sizing gas limits from the route quote (makers used per hop) instead of a flat 1.2M/hop, and (2) auditing and standardizing single-hop direct-to-pair execution (skip router SubMsg/reply overhead).
Current codebase
Gas model (flat, padded)
HYBRID_SWAP_GAS_LIMIT = 1_200_000per hop (frontend-dapp/src/services/terraclassic/terraGas.ts).gasLimitForExecuteSwapOperationsscales hops but hybrid floor is still 1.2M × hops when any hop has hybrid params.gas_limit × gas_price; unused gas is not refunded — over-estimation directly costs users LUNC.Route quote already knows book depth
POST /api/v1/route/solvereturns hybrid routing with per-hop simulation (makers touched).TradeMarketOrderPanel/SwapPageuse indexer ops when present; simulation includes book leg sizing.max_maker_fillsinHybridSwapParamsis set from UI/route but gas budget ignores it.Direct-to-pair vs router
TradeMarketOrderPanel.tsx~341–357): ifidxOps.length === 0→swap()direct to pair with hybrid; if multi-hop →executeMultiHopSwapvia router.SwapPage.tsx~564): single-hop uses directswap()with hybrid whendirectPairexists.router.ts,contract.rs): each hop = CW20Send+SubMsg::reply_on_success+ balance delta queries (~2 CW20 balance reads per hop).Gap: Gas preflight still uses flat hybrid constants; any remaining single-hop paths through router should be eliminated;
max_maker_fillsnot tied to quote.Why this is needed
Most retail trades are single-hop, shallow book (0–2 maker fills). Paying for 1.2M gas when ~600–800k suffices wastes LUNC on every swap. Router overhead on unnecessary single-hop adds latency and gas beyond the pair execute itself.
Constraints / guardrails
gas_limit = base + perMaker × (makersUsed + buffer)with buffer ≥ 1–2; never below observedgas_usedfrom QA/localterra (#115, #114 regression floors intransactions.test.ts).traderwhen using router elsewhere; direct pair uses CW20 sender as trader unless discount router pattern applies.max_maker_fillsfrom quote).Relevant files
frontend-dapp/src/services/terraclassic/terraGas.tsgetGasLimitForTxfrontend-dapp/src/services/terraclassic/transactions.tsfrontend-dapp/src/components/trade/TradeMarketOrderPanel.tsxfrontend-dapp/src/pages/SwapPage.tsxfrontend-dapp/src/services/terraclassic/router.tsfrontend-dapp/src/services/terraclassic/pair.tsswap()frontend-dapp/src/utils/constants.tsfrontend-dapp/src/services/terraclassic/__tests__/transactions.test.tsdocs/limit-orders.mdRecommended solution direction
gasLimitForHybridSwap({ makersUsed, hasPoolLeg, hopCount })≈HYBRID_BASE + HYBRID_PER_MAKER × (makersUsed + buffer); calibrate from localterra measurements post-#248 (transfer aggregation).makersUsedfrom indexer sim / pairHybridSimulationinto fee builder at submit time; setmax_maker_fills = makersUsed + bufferin hybrid params (cap atMAX_MAKER_FILLS_HARD_CAP).execute_swap_operations/executeMultiHopSwapcall sites; ensure single-hop never uses router; document matrix in PR.Acceptance criteria
max_maker_fillsaligned with quote + buffer (does not truncate valid fills under normal conditions).evaluateMarketSwapNativeGasPlaceGate).Test plan — functional paths
gasLimitForHybridSwap(0),(2),(10)monotonic, bounded.getGasLimitForTxon direct pairsend+ inner hybrid swap msg.Test plan — attack / abuse
Verification criteria
npm testin frontend-dapp green.gas_usedvsgas_limitfor 0/2/5 makers on localterra in PR ordocs/limit-orders.md./trademarket tab: successful hybrid swap with lower fee than pre-change screenshot/log.mentioned in issue #252
marked as related to #252
mentioned in issue #248
mentioned in commit
0be09de77cmentioned in commit
d58704820cImplementation summary (pushed to
main@d587048)Implemented GitLab #249 — quote-driven hybrid swap gas limits and single-hop direct-to-pair execution.
What changed
Dynamic hybrid gas (
frontend-dapp/src/services/terraclassic/hybridSwapGas.ts)gasWanted ≈ min(1.2M, max(600k, 550k + 65k × (max_maker_fills + 2)))per hop with book legbook_input = 0) → buffered one-hop pool envelope (840k)Single-hop routing (
swapRouting.ts)indexerOperations.length ≥ 2swap()for single-hop (avoids router SubMsg/reply overhead)max_maker_fillscapped at submit viahybridParamsWithSubmitCap(quote cap + buffer)Preflight —
estimateMarketPairSwapSequenceUlunaFeesTotalaccepts live hybrid params for native LUNC gate alignmentDocs / agent playbooks —
docs/limit-orders.md,docs/frontend.md,skills/AGENTS_TERRACLASSIC_GAS.md(rule 14),AGENTS_HYBRID_QUOTING.md,AGENTS_E2E_HYBRID_SWAP.mdLocalnet swarm —
packages/localnet-trading-swarm/src/gas.tskept in lockstepVerification checklist
cd frontend-dapp && npm test— green (includes newhybridSwapGas.test.ts,swapRouting.test.ts, updatedtransactions.test.ts)/trademarket tab — single-hop hybrid swap succeeds with lowergas_wantedthan flat 1.2M whenmax_maker_fills ≤ 2(compare tx log / Keplr fee)gas_used < gas_wantedand tx succeeds (no OOG)estimateMarketPairSwapSequenceUlunaFeesTotal(hybrid)Follow-ups
gas_usedvsgas_wantedfor 0/2/5 makers on LocalTerra in #252 /docs/limit-orders.mdonce QA benchmarks land.@qa-agent-team — please verify the checklist above on LocalTerra (Keplr or dev wallet per #235; not Station). Issue remains open until sign-off.
mentioned in issue #260
marked as related to #260
mentioned in commit
844f27506ementioned in issue #262
#249 verified — good to close. Quote-driven hybrid gas + single-hop direct-to-pair are both in place. (#249 is the base formula that #260/#262 later extended — verified at current main values.)
Checklist:
Note on the "single-hop 0-2 makers <= 1.2M" target: pool-only (book_input=0) is 840k, so the fee saving vs the old flat 1.2M holds there. The shallow book-leg case is now 1,401,200 because #260/#262 raised book-leg sizing to cover the worst-case 500-step scan (MAX_SCAN_STEPS) + 15 parks — a deliberate OOG-safety bump that supersedes the original <=1.2M for book-leg swaps. The quote-driven sizing mechanism and single-hop routing from #249 are unchanged underneath.
Live /trade single-hop hybrid (lower gas_wanted than flat when shallow; gas_used < gas_wanted, no OOG) is the browser layer; the routing + gas logic is fully unit-covered here.
Verified end to end. @PlasticDigits
mentioned in issue #353
mentioned in issue #475
mentioned in issue #501
mentioned in issue #587
mentioned in issue #599
mentioned in issue #679
marked as related to #679
mentioned in issue #681
marked as related to #681