Surface fee-discount registry query failures to traders and ops (#365) #874
No reviewers
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!874
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "issue-365-fee-discount-registry-observability"
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
Implements GitLab #365 observability for fee-discount registry LCD outages without changing on-chain fail-closed semantics (pair still charges full
fee_bpswhenGetDiscounterrors).configprobe every 60s; exposesGET /api/v1/health/fee-discountwithfee_discount_registry_okandconsecutive_lcd_failures(no per-trader data, no raw LCD text). Repeated failures log aterror.unregisteredvsregistry_unreachable.Acceptance checklist
Errdocs/contracts-security-audit.mdP5,docs/reference/fee-discount-tiers.mdI10indexer/src/indexer/fee_discount_registry_health.rsprobe + logs;GET /api/v1/health/fee-discountfeeDiscountRegistryWarning.ts; health endpoint + LCD query error pathsswap_uses_full_fee_when_discount_registry_query_failsstill passesmake test-contractsVerification checklist (third parties)
make test-contracts— contract invariant unchanged.make test-frontend— includesfeeDiscountRegistryWarning.test.ts.make setup-indexer-postgres && cd indexer && cargo test --test api_fee_discount_health -- --test-threads=1— health API tests.curl -s http://127.0.0.1:3001/api/v1/health/fee-discount | jq→configured: true,fee_discount_registry_ok: true./swap; if registry LCD is blocked, amberfee-discount-registry-warningbanner appears (swap still allowed).Test plan
make test-contractsmake test-frontendmake setup-indexer-postgres && cd indexer && cargo test --test api_fee_discount_health -- --test-threads=1false+ Swap warningchanged the description
changed the description
Security review — MR !874
Commit reviewed:
8cc60b4acc08a5b30b6a5874b9b18b2ff62a32e3Scope: Off-chain observability for fee-discount registry LCD outages (#365) — indexer background
configprobe +GET /api/v1/health/fee-discount, frontend Swap warning banner, docs/skills. No smart-contract changes.Outcome:
FINDINGS: 0medium+Method
Areas examined
FEE_DISCOUNT_ADDRESSand fixed{"config":{}}query; health handler has no request parameters. No attacker-controlled input reaches LCD or SQL./health); globaltower_governorrate limit applies viaapply_rate_limit_layer.configured,fee_discount_registry_ok,consecutive_lcd_failures. Integration test asserts no LCD URLs,cosmwasmpaths, or raw LCD error text in HTTP body. Probe failure logs use existingLcdErrorformatting (server-side only; not a new client leak vector).RwLocksnapshot (no per-request LCD). Background probe is capped at one query per 60s from indexer config address.Inline threads
None — no medium, high, or critical findings on this diff.
Security review: no medium+ findings on this diff.
added 32 commits
main4d33747d- Merge branch 'main' into issue-365-fee-discount-registry-observabilityCompare with previous version
Resolved merge conflicts with
main:docs/indexer-invariants.md— kept main's #363 rate-limit row (Retry-After,x-ratelimit-*, startup warning) and this branch's #365 fee-discount health observability row.indexer/src/indexer/poller.rs— combined imports for bothreorg_alert(main) andfee_discount_registry_health(this MR).Sanity:
cargo check(indexer),feeDiscountRegistryWarningunit tests.changed the description
Security review — MR !874 (re-review)
Commit reviewed:
4d33747d7f1ccf24239f6e349b2ff394da096ca1Scope: Off-chain observability for fee-discount registry LCD outages (#365) — indexer background
configprobe +GET /api/v1/health/fee-discount, frontend Swap warning banner, docs/skills. Merge-conflict resolution withmain(poller.rsimport combine,indexer-invariants.mdrow merge). No smart-contract changes.Outcome:
FINDINGS: 0medium+Method
main).8cc60b4re-validated; no inline findings to carry forward.Areas examined
FEE_DISCOUNT_ADDRESSand fixed{"config":{}}query viaLcdClient::query_contract; health handler has no request parameters. No attacker-controlled input reaches LCD paths or SQL./health); protected by globaltower_governorviaapply_rate_limit_layeronapi_router(not LCD-heavy subset).configured,fee_discount_registry_ok,consecutive_lcd_failures. Integration test asserts no LCD URLs,cosmwasmpaths, or raw LCD error text in responses. Probe failure logs use existingLcdErrorformatting (server-side only).RwLocksnapshot (no per-request LCD). Background probe capped at one query per 60s from configured address.Inline threads
None — no medium, high, or critical findings on this diff.
Security review: no medium+ findings on this diff.
Stale Security Review comment
Stale Security Review comment
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.
Reviewed by Cursor Bugbot for commit
4d33747d7f. Configure here.Post-sign recovery only on timeout
High Severity
In the split sign-then-broadcast path, recovery polling runs only when
RpcClient.broadcastTxorpollTxfails with the fixed timeout messages. Any other post-sign RPC error is thrown immediately even though a signed tx hash already exists, so the UI can clearisPendingand invite another submit while the first broadcast may still land.Reviewed by Cursor Bugbot for commit
4d33747d7f. Configure here.added 1 commit
1154cb6f- fix(frontend): recover after any post-sign broadcast or poll RPC failureCompare with previous version
changed the description
Stale Security Review comment
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.
Reviewed by Cursor Bugbot for commit
1154cb6ff3. Configure here.Broadcast errors always enter recovery
Medium Severity
In the split sign/broadcast path, any
RpcClient.broadcastTxfailure is caught and handled like an ambiguous timeout: the UI moves toconfirmingand runs post-sign recovery. Synchronous RPC rejections that mean the tx was never accepted no longer propagate immediately, so users wait through the recovery window and lose the original error detail.Reviewed by Cursor Bugbot for commit
1154cb6ff3. Configure here.added 1 commit
5604ea9a- fix(frontend): re-throw non-timeout split-path broadcast errorsCompare with previous version
changed the description
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.
Reviewed by Cursor Bugbot for commit
5604ea9a1a. Configure here.Post-sign broadcast skips recovery
Medium Severity
After a successful sign on the split broadcast path, only errors whose message exactly matches the broadcast/poll timeout strings enter
recoverPostSignBroadcast. OtherRpcClient.broadcastTxrejections (typical RPC or network failures) propagate immediately, so the UI can invite retry while a signed transaction may still be in flight—unlike the poll step, which still recovers on any error per GitLab #359.Reviewed by Cursor Bugbot for commit
5604ea9a1a. Configure here.Post-sign broadcast skips recovery
Medium Severity
After a successful sign on the split broadcast path, only errors whose message exactly matches the broadcast/poll timeout strings enter
recoverPostSignBroadcast. OtherRpcClient.broadcastTxrejections (typical RPC or network failures) propagate immediately, so the UI can invite retry while a signed transaction may still be in flight—unlike the poll step, which still recovers on any error per GitLab #359.Reviewed by Cursor Bugbot for commit
5604ea9a1a. Configure here.changed this line in version 5 of the diff
added 1 commit
77881360- fix(frontend): recover after any post-sign broadcast RPC failure (#359)Compare with previous version
changed the description
added 1 commit
4d1570b7- fix(frontend): narrow post-sign broadcast recovery to ambiguous RPC errorsCompare with previous version
Security fix summary (
4d1570b)1154cb6/7788136; split-path broadcast now enters recovery for ambiguous post-sign RPC failures (not only timeout strings).recoverPostSignBroadcastso submit stays disabled until deadline poll completes (#359).4d1570b: addedisDefiniteBroadcastRejection/shouldRecoverPostSignBroadcastso CheckTx rejections (sequence mismatch, invalid tx, fee/auth validation, etc.) re-throw immediately; ambiguous failures (timeout, 502,tx already exists in cache) still recover. Poll step unchanged — any poll error still recovers per #359.8cc60b4,4d33747).Tests:
make test-frontend(includes newterraBroadcastRecoverycases for ambiguous vs definite broadcast errors).changed the description
Security review — MR !874 (re-review)
Commit reviewed:
4d1570b7e7c16d708eb172e8da905f433d1c944eScope: Off-chain observability for fee-discount registry LCD outages (#365) — indexer background
configprobe +GET /api/v1/health/fee-discount, frontend Swap warning banner, docs/skills. Also includes post-mergeterraBroadcast.tspost-sign recovery narrowing (isDefiniteBroadcastRejection/shouldRecoverPostSignBroadcast, #359). No smart-contract changes.Outcome:
FINDINGS: 0medium+Method
4d1570bbroadcast-recovery fix atop prior #365 work).8cc60b4and4d33747re-validated; Bugbot broadcast-recovery threads assessed against current code — over-broad recovery from intermediate commits is resolved; remaining behavior is duplicate-submit mitigation, not an exploitable regression.Areas examined
FEE_DISCOUNT_ADDRESSand fixed{"config":{}}query viaLcdClient::query_contract; health handler has no request parameters. No attacker-controlled input reaches LCD paths or SQL./health); protected by globaltower_governorviaapply_rate_limit_layeronapi_router(not LCD-heavy subset).configured,fee_discount_registry_ok,consecutive_lcd_failures. Integration test asserts no LCD URLs,cosmwasmpaths, or raw LCD error text in responses. Probe failure logs use existingLcdErrorformatting (server-side only).RwLocksnapshot (no per-request LCD). Background probe capped at one query per 60s from configured address.Inline threads
None — no medium, high, or critical findings on this diff.
Security review: no medium+ findings on this diff.
mentioned in commit
d0a75849a1