OE-3 UI: Limit Ladder — No crossing-order validation; bids above market and asks below market are accepted and placed on-chain #297
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#297
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?
Found during: OE-3 checklist testing — Limit ladder multiple order placement
Summary: The limit ladder panel places orders without any crossing-price validation. Bids priced above the current market and asks priced below the current market are submitted, broadcast, and confirmed on-chain with no warning or block. This is a correctness and safety failure — crossing orders are economically equivalent to market orders but bypass all market-order UX safeguards (slippage tolerance, min-received display, price-impact warning).
Observed behavior
On the CORAL/EMBER pair (market price floating ~0.8–1.1):
Both ladders transacted successfully with no warning, no block, and no user disclosure.
Reproduction steps
/limitsor/trade/:pairAddrExpected behavior
TradeOrderTicket.tsx)Actual behavior
Verified root cause (code read and confirmed)
LimitOrderLadderPanel.tsxcontains no reference todescribeLimitCrossingBlocker,bestBid,bestAsk,crossingBlocker, or any price gate beyond escrow balance and gas:Compare to
TradeOrderTicket.tsxwhich callsdescribeLimitCrossingBlocker(side, price, bestBid, bestAsk)both in the submit guard (line 406) and as acrossingBlockermemo that disables the submit button (line 322). This guard was never ported to the ladder panel.The ladder's
placeGates(fromuseLimitLadderPlaceGates) covers escrow balance and gas only — no price-level crossing check.Impact assessment
Environment
/limits— Limit Ladder panelSeverity: ~bug — crossing orders are placed silently with no UX safeguard, exposing users to unintended taker fills at arbitrary prices.
Related checklist items: OE-3
cc: @PlasticDigits
mentioned in issue #291
Confirmed, and I checked the contract side so the fix surface is clear (frontend-only).
LimitOrderLadderPanel.tsxhas zero crossing logic — it imports none ofdescribeLimitCrossingBlocker/bestBid/bestAsk(grep of the panel +useLimitLadderPlaceGates/useLimitLadderPlacementPlanis clean); its gates only cover escrow + gas, unlikeTradeOrderTicket.tsx(the single-order form callsdescribeLimitCrossingBlocker(side, price, bestBid, bestAsk)at the submit guard + as acrossingBlockermemo).Key point: I confirmed the pair contract accepts crossing limit orders by design (placement doesn't auto-match or reject crossing prices — they just rest, then fill on the next swap). So this is purely a frontend guard gap — the fix is to port the same
describeLimitCrossingBlockerwarning/block fromTradeOrderTicketinto the ladder panel; no contract change. Real, medium (crossing rungs execute as taker fills with no slippage UX). @totdkingmentioned in merge request !757
Fixed in MR !757. Ported the non-crossing guard the single-order form already uses (describeLimitCrossingBlocker) into the ladder: it checks each rung against best bid/ask, disables submit + shows an inline warning when any rung crosses the market, and hard-guards in the mutation. The contract accepts crossing by design, so this is a frontend guard, same as the single-order path. Browser check is yours. @PlasticDigits
mentioned in commit
6e42a5b6f6mentioned in commit
25f8b8faa7mentioned in merge request !767
Verification pass — GitLab #297 (limit ladder crossing guard)
Verified the fix from MR !757 on
main. Opened follow-up MR !767 with docs cross-links + regression tests.Results
describeLimitCrossingBlockerwired inLimitOrderLadderPanelladderCrossingGatememo + mutation hard-guardLimitOrderLadderPanel.crossing.test.tsxlimitOrderNonCrossingunit teststsc -bdeploy-dex-local.shfails at pair creation:Pair creation requires 100000000 uluna attachedafter freshmake reset(×2). Component tests cover the UI paths.Follow-ups
mentioned in commit
f9bf77b7cdVerification — GitLab #297 (limit ladder crossing guard)
Re-verified on
mainafter MR !757 (implementation) and MR !767 (docs/tests). Branch:cursor/gitlab-issue-verification-a8d9@c0d8ad6.Acceptance criteria
describeLimitCrossingBlockerwired inLimitOrderLadderPanel(imports, per-rung memo, submit disable)grep+ readLimitOrderLadderPanel.tsx(ladderCrossingGate,useTradeBestBookPrices,data-testid="ladder-crossing-guard")N of M rungs will cross the market…LimitOrderLadderPanel.crossing.test.tsxblocks bid ladder when rungs cross best askblocks ask ladder when rungs cross best bidallows non-crossing bid ladder within spreadmutationFnthrows if any rung crosses (describeLimitCrossingBlockerloop)TradeOrderTicketguarduseTradeBestBookPrices; contract still accepts crossing on-chain (#152) — client-only UXlimitOrderNonCrossingunit testsnpm test -- limitOrderNonCrossing→ 4/4npx tsc -b(frontend-dapp)skills/AGENTS_LIMIT_ORDER_BATCH_LADDER.md,docs/limit-orders.md,docs/frontend.mdcross-link #297.env.local/ wasm artifacts on this VM; fullmake setup-cloud-localterranot run (15+ min build+deploy). Component Vitest exercises the same UI paths as the issue repro steps.Commands
Outcome
All product acceptance items for the crossing guard are met on
main. Closing as verified; manual stack QA remains optional once LocalTerra deploy is provisioned.Follow-up (non-blocking): optional Playwright case for
ladder-crossing-guardwhen E2E deploy env is available.Verification
This issue still persists, the ladder section of limits allow for bid tx above current market price and ask tx below current market price
Screen record
This holds the following parameters:
Bids allow for large tx above the current price which is prohibited in the normal limit order. But the ask part of the ladder does not go through.
cc: @PlasticDigits
mentioned in issue #385
mentioned in merge request !914
mentioned in issue #546
mentioned in issue #617
mentioned in issue #619
mentioned in issue #717