Skip to content

fix(feed): reject future-dated Chainlink rounds and sample clock after fallback - #41

Closed
Ayush7614 wants to merge 2 commits into
Twigpine:mainfrom
Ayush7614:fix/chainlink-future-guard-v2
Closed

Ayush7614 wants to merge 2 commits into
Twigpine:mainfrom
Ayush7614:fix/chainlink-future-guard-v2

Conversation

@Ayush7614

@Ayush7614 Ayush7614 commented Sep 13, 2026 •

Copy link
Copy Markdown
Contributor

Future rounds (updatedAt > now) from a bad RPC or clock skew previously passed as a valid price, and the ETH price fallback sampled the clock before the Coinbase wait, so a round published while Coinbase was failing was rejected as future.

This PR:

  • baseStocks.ts:feedUsd and ethPrice.ts:feedEthUsd return null when updatedAt > nowS (future) or non-positive / stale (> maxAge), covering BASE_STOCK_MAX_FEED_AGE_S and ETH_FEED_MAX_AGE_S.
  • ethPrice.ts:fromChainlink samples now() after feedFn() completes, so a Chainlink round published mid-fallback (Coinbase 5s timeout) is correctly aged 2s, not rejected as future.
  • Tests: baseStocks.test.ts (future round at +60s and far-future), ethPrice.test.ts (future at +60s, plus PR fix(app): reject future-dated Chainlink rounds in feedUsd #29 regression: slow Coinbase 503 + round published 3s after start still prices at 2441.34).

Verified on upstream/main base:

  • npx tsc --noEmit -p .: pass
  • npm run lint: pass
  • npx tsx --conditions=react-server --tsconfig ./tsconfig.test.json --test src/lib/launchpad/baseStocks.test.ts src/lib/launchpad/ethPrice.test.ts: 22/22 pass
  • npm run build: pass
  • Full app suite: no new failures

Summary by CodeRabbit

  • Bug Fixes
    • Invalid future-dated price feed readings are now rejected, preventing clock-skewed or incorrect prices from being used.
    • ETH price fallback handling now uses the latest feed-read time, ensuring recently published Chainlink prices are accepted correctly.
    • ETH price caching and source selection now reflect the time the feed response completes, improving accuracy during delayed requests.

…are not rejected as future (PR Twigpine#29)

- fromChainlink takes injected now() and samples after await feedFn()
- refresh stamps cache from completion time
- regression test: slow Coinbase failure + round published mid-request returns 2441.34
feedUsd accepted updatedAt in the future (nowS - updatedAt negative
never exceeds maxAgeS), so a skewed clock or bad RPC round served as a
price. feedEthUsd delegates to the same helper, so ETH/USD had the same
hole. Reject r.updatedAt > nowS and cover it in baseStocks + ethPrice
tests.
@coderabbitai

coderabbitai Bot commented Sep 13, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 5888c0d5-bea7-4058-ba57-8d1f608f661f

📥 Commits

Reviewing files that changed from the base of the PR and between ea635bc and df5fdf1.

📒 Files selected for processing (4)
  • app/src/lib/launchpad/baseStocks.test.ts
  • app/src/lib/launchpad/baseStocks.ts
  • app/src/lib/launchpad/ethPrice.test.ts
  • app/src/lib/launchpad/ethPrice.ts

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The change rejects future-dated feed rounds. Chainlink validation samples the clock after feed reads complete. Refresh timestamps also use completion time. Tests cover future rounds and delayed Coinbase fallback behavior.

Changes

Price validation

Layer / File(s) Summary
Base stock timestamp validation
app/src/lib/launchpad/baseStocks.ts, app/src/lib/launchpad/baseStocks.test.ts
feedUsd rejects readings with future timestamps. Tests cover future rounds at two offsets.
ETH Chainlink timing validation
app/src/lib/launchpad/ethPrice.ts, app/src/lib/launchpad/ethPrice.test.ts
Chainlink validation and refresh timestamps use clocks sampled after feed work completes. Tests cover future rounds and delayed Coinbase fallback.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: kevincodex1

Merge Risk: ⚪ Minimal · up to df5fd

Future-dated feed rounds are rejected, while valid rounds returned after a delayed fallback remain accepted. The change is ready to merge after normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 4 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main changes: rejecting future-dated Chainlink rounds and sampling the clock after fallback.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@Vasanthdev2004

Copy link
Copy Markdown
Collaborator

@Ayush7614 I'm closing this as a duplicate of #29. I compared the current diffs: all four files are identical, including the fallback-clock fix and regression test. Please continue in #29 so we keep the existing review history in one place.

Please stop opening parallel PRs for the same change. Keep one active PR per fix, add review follow-ups as commits there, and update that branch when it needs a rebase. If a replacement is genuinely necessary, explain why, link it and close the superseded PR.

Small, independent fixes are welcome. Duplicate submissions are the issue here: they consume another review cycle without adding new work. If there is a distinct change missing from #29, point it out in that thread.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants