Skip to content

Conversation

@shoom3301
Copy link
Collaborator

@shoom3301 shoom3301 commented Nov 14, 2025

Summary

I don't know where it comes from, but I noticed that appData doesn't get updated in time.
Because of that we use appData generated for previous trade.
To fix that, I added useEffect() which resets appDataHooksAtom every time when sellToken changes.

To Test

  1. Have some USDC (permittable) and USDT (non-permittable) on Arbitrum, both with no allowance
  2. Go /limit/0xaf88d065e77c8cC2239327C5EDb3A432268e5831/USDT?tab=all&page=1
  3. Try to place a limit order, sign permit, but DO NOT sign order, reject the signature
  4. Go /swap/USDT/0xaf88d065e77c8cC2239327C5EDb3A432268e5831
  5. Approve USDT and swap (place order)
  • AR: the order includes permit in appData hooks
  • ER: there is no hooks in order appData

Please, try to check other cases related to appData updates:

  • slippage
  • volume fee
  • other hooks

Summary by CodeRabbit

  • Bug Fixes
    • Improved state handling when changing input currency: app data is reset and pending permits are cleared to ensure consistent behavior after switching currencies.

@shoom3301 shoom3301 requested review from a team November 14, 2025 11:04
@shoom3301 shoom3301 self-assigned this Nov 14, 2025
@shoom3301 shoom3301 added the RELEASE Included in the release that is being closed label Nov 14, 2025
@vercel
Copy link

vercel bot commented Nov 14, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
cowfi Ready Ready Preview Nov 14, 2025 11:36am
explorer-dev Ready Ready Preview Nov 14, 2025 11:36am
swap-dev Ready Ready Preview Nov 14, 2025 11:36am
widget-configurator Ready Ready Preview Nov 14, 2025 11:36am
2 Skipped Deployments
Project Deployment Preview Updated (UTC)
cosmos Ignored Ignored Nov 14, 2025 11:36am
sdk-tools Ignored Ignored Preview Nov 14, 2025 11:36am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 14, 2025

Walkthrough

Adds logic to derive inputCurrencyAddress from tradeState.inputCurrency and a new effect that resets appDataHooks to undefined and clears permitHook whenever that address changes.

Changes

Cohort / File(s) Summary
Input currency effect reset
apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts
Imports getCurrencyAddress from utilities, derives inputCurrencyAddress from tradeState.inputCurrency, and adds an effect that resets appDataHooks to undefined and clears permitHook when the input currency address changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as UI / tradeState
  participant Updater as AppDataHooksUpdater
  participant Hooks as appDataHooks
  participant Permit as permitHook

  note over UI,Updater `#D3E4FF`: Input currency changes
  UI->>Updater: tradeState.inputCurrency
  Updater->>Updater: getCurrencyAddress(tradeState.inputCurrency)
  Updater-->>Hooks: updateAppDataHooks(undefined)
  Updater-->>Permit: clear permitHook
  note right of Updater `#E8F5E9`: Effect runs when inputCurrencyAddress changes
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Verify getCurrencyAddress is correct for all currency types used
  • Confirm effect dependency list is complete (no missing vars)
  • Check that resetting appDataHooks and clearing permitHook won't cause unintended re-renders or lost state elsewhere

Suggested reviewers

  • elena-zh
  • alfetopito
  • fairlighteth

Poem

🐰 A nibble, a hop, a currency's new face,
I clear the old hooks to make tidy space.
Fresh trades will bloom with addresses true,
Hoppity code — now ready for you! 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and accurately describes the main change: resetting appData hooks when the sell token (input currency) changes to fix a timing issue.
Description check ✅ Passed The description includes summary, testing steps with checkboxes, and background context. It follows the template structure with all critical sections present.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/app-data-hooks-reset

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bec1e54 and aa1359a.

📒 Files selected for processing (1)
  • apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6351
File: apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveModal/useTradeApproveCallback.ts:87-121
Timestamp: 2025-10-13T19:41:31.440Z
Learning: In apps/cowswap-frontend/src/modules/erc20Approve, useApproveCallback returns Promise<TransactionResponse | undefined> and is distinct from useApproveCurrency, which can return Promise<TransactionReceipt | SafeMultisigTransactionResponse>. When reviewing approval flows, verify which hook is actually being used before flagging Safe wallet concerns.
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6138
File: libs/hook-dapp-lib/src/hookDappsRegistry.ts:1-1
Timestamp: 2025-08-12T05:57:08.021Z
Learning: The matchHooksToDapps function in libs/hook-dapp-lib/src/utils.ts provides backward compatibility for permit hooks through function selector detection (EIP_2612_PERMIT_SELECTOR and DAI_PERMIT_SELECTOR) rather than dappId matching, making it robust against dappId changes.
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 5859
File: apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts:76-82
Timestamp: 2025-06-23T07:03:50.760Z
Learning: In the useTradeQuotePolling hook, there are two useLayoutEffect hooks that work together: one resets the counter to 0 when the confirmation modal closes, and another automatically triggers pollQuote(false, true) whenever the counter reaches 0. This creates an intentional chain reaction for immediate quote updates.
📚 Learning: 2025-09-11T08:25:51.460Z
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 6234
File: libs/tokens/src/index.ts:1-4
Timestamp: 2025-09-11T08:25:51.460Z
Learning: In the cowprotocol/cowswap project, there is currently no SSR (Server-Side Rendering) support, so localStorage access at module import time does not cause SSR-related issues.

Applied to files:

  • apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts
📚 Learning: 2025-10-13T19:41:31.440Z
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6351
File: apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveModal/useTradeApproveCallback.ts:87-121
Timestamp: 2025-10-13T19:41:31.440Z
Learning: In apps/cowswap-frontend/src/modules/erc20Approve, useApproveCallback returns Promise<TransactionResponse | undefined> and is distinct from useApproveCurrency, which can return Promise<TransactionReceipt | SafeMultisigTransactionResponse>. When reviewing approval flows, verify which hook is actually being used before flagging Safe wallet concerns.

Applied to files:

  • apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts
📚 Learning: 2025-06-23T07:03:50.760Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 5859
File: apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts:76-82
Timestamp: 2025-06-23T07:03:50.760Z
Learning: In the useTradeQuotePolling hook, there are two useLayoutEffect hooks that work together: one resets the counter to 0 when the confirmation modal closes, and another automatically triggers pollQuote(false, true) whenever the counter reaches 0. This creates an intentional chain reaction for immediate quote updates.

Applied to files:

  • apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts
📚 Learning: 2025-08-12T05:57:08.021Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6138
File: libs/hook-dapp-lib/src/hookDappsRegistry.ts:1-1
Timestamp: 2025-08-12T05:57:08.021Z
Learning: The matchHooksToDapps function in libs/hook-dapp-lib/src/utils.ts provides backward compatibility for permit hooks through function selector detection (EIP_2612_PERMIT_SELECTOR and DAI_PERMIT_SELECTOR) rather than dappId matching, making it robust against dappId changes.

Applied to files:

  • apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts
🧬 Code graph analysis (1)
apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts (1)
libs/common-utils/src/getCurrencyAddress.ts (1)
  • getCurrencyAddress (6-8)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Cypress
  • GitHub Check: Setup
🔇 Additional comments (2)
apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts (2)

3-3: LGTM! Proper currency address derivation.

The import and usage of getCurrencyAddress correctly handles both native tokens and ERC20 addresses, providing a reliable dependency for the effect hook.

Also applies to: 54-54


21-32: No issues found—the fix correctly addresses the race condition.

The dependency chain is properly constructed:

  1. When inputCurrency changes, useDerivedTradeState() updates synchronously
  2. useGetReceiveAmountInfo() extracts the new inputCurrency and computes receiveAmountInfo
  3. useHasTradeEnoughAllowance() uses this info to determine allowance synchronously
  4. permitData from useAgnosticPermitDataIfUserHasNoAllowance() updates immediately based on the allowance check
  5. The permit effect (lines 92–100) has permitData in its dependency array, so it fires immediately when permitData changes
  6. permitHook is updated by the permit effect before the main effect runs
  7. The main effect (lines 79–90) has permitHook in its dependency array, ensuring it uses the updated hook

All updates are synchronous with proper React effect dependency ordering. There is no window where stale permit data could be included in new orders.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts (1)

56-64: Fix correctly addresses the race condition.

The effect properly resets both appDataHooks and permitHook when the input currency changes, preventing stale permit hooks from persisting across token switches. The effect runs before the main hook-building effect (line 66), ensuring clean state before reconstruction.

Minor: Update comment for accuracy.

The comment could be more precise:

 /**
- * Reset appDataHooks every time sellToken changes
+ * Reset appDataHooks and permitHook when the input currency changes
  */
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aa1359a and 6f23321.

📒 Files selected for processing (1)
  • apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6351
File: apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveModal/useTradeApproveCallback.ts:87-121
Timestamp: 2025-10-13T19:41:31.440Z
Learning: In apps/cowswap-frontend/src/modules/erc20Approve, useApproveCallback returns Promise<TransactionResponse | undefined> and is distinct from useApproveCurrency, which can return Promise<TransactionReceipt | SafeMultisigTransactionResponse>. When reviewing approval flows, verify which hook is actually being used before flagging Safe wallet concerns.
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6138
File: libs/hook-dapp-lib/src/hookDappsRegistry.ts:1-1
Timestamp: 2025-08-12T05:57:08.021Z
Learning: The matchHooksToDapps function in libs/hook-dapp-lib/src/utils.ts provides backward compatibility for permit hooks through function selector detection (EIP_2612_PERMIT_SELECTOR and DAI_PERMIT_SELECTOR) rather than dappId matching, making it robust against dappId changes.
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 5859
File: apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts:76-82
Timestamp: 2025-06-23T07:03:50.760Z
Learning: In the useTradeQuotePolling hook, there are two useLayoutEffect hooks that work together: one resets the counter to 0 when the confirmation modal closes, and another automatically triggers pollQuote(false, true) whenever the counter reaches 0. This creates an intentional chain reaction for immediate quote updates.
📚 Learning: 2025-08-12T05:57:08.021Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6138
File: libs/hook-dapp-lib/src/hookDappsRegistry.ts:1-1
Timestamp: 2025-08-12T05:57:08.021Z
Learning: The matchHooksToDapps function in libs/hook-dapp-lib/src/utils.ts provides backward compatibility for permit hooks through function selector detection (EIP_2612_PERMIT_SELECTOR and DAI_PERMIT_SELECTOR) rather than dappId matching, making it robust against dappId changes.

Applied to files:

  • apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts
📚 Learning: 2025-10-13T19:41:31.440Z
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6351
File: apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveModal/useTradeApproveCallback.ts:87-121
Timestamp: 2025-10-13T19:41:31.440Z
Learning: In apps/cowswap-frontend/src/modules/erc20Approve, useApproveCallback returns Promise<TransactionResponse | undefined> and is distinct from useApproveCurrency, which can return Promise<TransactionReceipt | SafeMultisigTransactionResponse>. When reviewing approval flows, verify which hook is actually being used before flagging Safe wallet concerns.

Applied to files:

  • apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts
📚 Learning: 2025-06-23T07:03:50.760Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 5859
File: apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts:76-82
Timestamp: 2025-06-23T07:03:50.760Z
Learning: In the useTradeQuotePolling hook, there are two useLayoutEffect hooks that work together: one resets the counter to 0 when the confirmation modal closes, and another automatically triggers pollQuote(false, true) whenever the counter reaches 0. This creates an intentional chain reaction for immediate quote updates.

Applied to files:

  • apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts
📚 Learning: 2025-09-11T08:25:51.460Z
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 6234
File: libs/tokens/src/index.ts:1-4
Timestamp: 2025-09-11T08:25:51.460Z
Learning: In the cowprotocol/cowswap project, there is currently no SSR (Server-Side Rendering) support, so localStorage access at module import time does not cause SSR-related issues.

Applied to files:

  • apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts
🧬 Code graph analysis (1)
apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts (1)
libs/common-utils/src/getCurrencyAddress.ts (1)
  • getCurrencyAddress (6-8)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Setup
  • GitHub Check: Cypress
🔇 Additional comments (2)
apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts (2)

3-3: LGTM!

The import is necessary for deriving the input currency address and is used correctly at line 54.


54-54: LGTM!

The currency address derivation correctly handles both native tokens and ERC-20 tokens, and the optional chaining safely handles undefined trade state.

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

Labels

RELEASE Included in the release that is being closed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants