bug: countdown timer doesn't update when switching to Terra Classic; EVM side hardcodes 24h window #44
Labels
No labels
agent:implement
agent:ready
backend
bug
cannot-reproduce
confirmed
desktop
docs
documentation
duplicate
enhancement
feature
frontend
good first issue
help wanted
high-risk
in-review
invalid
mobile
needs-triage
P0-critical
P1-high
P2-medium
P3-low
qa
QA
question
ready
report
responsive
security
security-escalate
smart-contract
solana
tablet
test-pass
ux
wallet-issue
wallet:keplr
wallet:metamask
wallet:station
wallet:walletconnect
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-bridge-monorepo#44
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?
Frontend Bug Report
Issue Title
Environment
Steps to Reproduce
Expected Behavior
period_ends_atvalue from the contract, not a hardcoded 24-hour window.Actual Behavior
useBridgeConfig.ts(line ~645:const RATE_LIMIT_WINDOW = 86400) rather than reading the actual window duration from the smart contract. This means the countdown always counts down from window-start + 24h regardless of what the contract's actual reset period is.period_ends_atis correctly pulled from the contract, but the countdown inSourceChainSelectormay not re-render properly when switching chains because theperiodEndsAtandfetchedAtWallMsdependencies don't trigger a fresh fetch/re-render on chain change.Severity
QA Checklist — Please verify the following across all chains:
period_ends_atfrom the Terra LCD, and the withdraw rate limit window from the EVM RPC), not just a static 24-hour timer86400seconds — the code should read the window duration from the contract rather than assuming 24h00:00:00or refresh)Relevant Code Locations
packages/frontend/src/components/transfer/SourceChainSelector.tsx— countdown display logicpackages/frontend/src/hooks/useBridgeConfig.tslines ~643-656 — EVM hardcodedRATE_LIMIT_WINDOW = 86400packages/frontend/src/hooks/useBridgeConfig.tslines ~564-593 — Terra rate limit fetch (correctly usesperiod_ends_at)packages/frontend/src/components/transfer/TransferForm.tsxlines ~1165-1166 — passesperiodEndsAtto SourceChainSelectorConsole Errors (if available)
Transaction Hash (if applicable)
Source
Additional QA request: Please also check the countdown timers on Settings → Bridge Config → {chain} → Tokens → {token} (the
WithdrawRateLimitDisplayinBridgeConfigPanel.tsx).The same underlying data source (
periodEndsAtfromuseBridgeConfig) feeds both the home page countdown and the settings page countdown, so the fix should be a shared hook that corrects the behavior in both places simultaneously. Verify that:Fix committed:
f66a631Changes (5 files):
useBridgeConfig.ts— AddedRATE_LIMIT_WINDOWto the EVM ABI and now reads the window duration from the contract (TokenRegistry.RATE_LIMIT_WINDOW()) instead of hardcoding86400. AddedwindowActive: booleanfield toWithdrawRateLimitInfo, set totrueonly whenused > 0(both EVM and Terra code paths).SourceChainSelector.tsx— ShowsN/Ainstead of a ticking countdown when the rate-limit window is inactive (used == 0). When a withdrawal has actually consumed part of the rate limit, the real countdown appears.TransferForm.tsx— Passes the newwindowActiveprop through.BridgeConfigPanel.tsx— Settings pageWithdrawRateLimitDisplayshowsN/A(gray) for "Resets in" when the window is inactive.BridgeConfigPanel.test.tsx— Updated test fixture to include newwindowActivefield.Root cause from live data investigation:
Queried all tokens on BSC, opBNB, and Terra Classic mainnet — every token has
used = 0(no active withdraw rate-limit windows). The EVM contract'sgetWithdrawRateLimitWindow()returnsblock.timestampaswindowStartwhen no withdrawals have occurred, soperiodEndsAtalways computes tonow + 24h, causing the perpetual ~24:00:00 countdown on every chain switch.Note: The
RATE_LIMIT_WINDOWpublic constant IS readable from the contract (contrary to earlier comment) — Solidity auto-generates a getter forpublicstate variables. No contract changes needed.Not closing — QA verification still needed per the checklist.
assigned to @Brouie
Reminder: Countdown shows N/A for Terra→EVM and EVM→EVM directions. EVM→Terra works. Needs contract to expose rate limit window duration, or a second RPC call to read the config. Partial fix in v0.1.59.
@Brouie showing N/A is expected behavior if the destination chain has no tokens arrived in the last 24 hours , so please show a xchainhashid and screenshot of N/A where destination chain timer doesnt update after the transfer
Reproduced. Timer shows N/A for all directions where destination is EVM.
Tested 2026-03-12:
XChain Hash IDs:
0xe921df2b01b29961172f3c04beb28b605845e240a7a2eacf00bf23992198a3b60x955fcc643569e75a6a70b51e00c31c2d68b2077d8713631293e870efae8ba4700xab4843044bbe11efbd4b9461969a6265277cb133ddbe38876e5cb3219028395bPattern: countdown works when destination is Terra, shows N/A when destination is EVM (BSC or opBNB). All transfers completed successfully — N/A persists even after tokens delivered.
On-chain verification of countdown behavior (2026-03-12)
Queried all three chains directly via
cast call(EVM) and Terra LCD to verify the countdown timer against on-chain state.On-chain data
usedmaxPerPeriodwindowStart0x3557...5b1c)TokenRegistry.getWithdrawRateLimitWindow()block.timestamp)0xF073...c6F3)TokenRegistry.getWithdrawRateLimitWindow()block.timestamp)terra16ahm...ftvh)period_usageperiod_ends_at= 1773379451TokenRegistry.RATE_LIMIT_WINDOW()on both BSC and opBNB returns 86400 (24h), confirming the contract constant is readable and matches.Explanation
The N/A behavior on BSC and opBNB is correct and expected:
getWithdrawRateLimitWindow()returnswindowStart = block.timestampandused = 0when no withdrawals have occurred in the current period. The frontend code (useBridgeConfig.tsline ~659) setswindowActive = used > 0n, so whenused == 0→windowActive = false→ countdown shows N/A.period_usagereturnsused_amount = "995000000000000000"(> 0), meaning a withdrawal did occur in the current 24h window, sowindowActive = trueand the countdown displays correctly.period_ends_at≈ 1773379451) matched the displayed ~22:32 remaining at query time, confirming on-chain parity.In short: N/A means "no tokens have been withdrawn on that destination chain in the last 24 hours, so no rate-limit window is active." The countdown only appears after at least one withdrawal has consumed part of the rate limit.
Verification request
@Brouie — to confirm this end-to-end, please run the following test:
used > 0.This will confirm the countdown is purely driven by on-chain rate-limit state and updates correctly across all chain combinations.
Verified (2026-03-13):
[✓] Timer shows correctly when destination chain has active rate limit (used > 0)
[✓] N/A shows when destination chain has no active rate limit (used = 0) — confirmed expected behavior
[✓] BNB→Terra: 4.999K 03:13:18 (Terra has used > 0)
[✓] opBNB→Terra: 4.999K 03:12:27 (Terra has used > 0)
[✓] BNB→opBNB: N/A (opBNB used = 0) — correct
[✓] Terra→BNB: N/A (BSC used = 0) — correct
[✓] Settings page and Transfer page countdowns agree
Behavior matches PlasticDigits on-chain verification. N/A = no active withdraw rate limit window. Closing.
mentioned in issue #55