Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { useMemo } from 'react'

import { ETH_FLOW_SLIPPAGE_WARNING_THRESHOLD } from '@cowprotocol/common-const'
import { percentToBps } from '@cowprotocol/common-utils'
import { useWalletInfo } from '@cowprotocol/wallet'

import { useIsCurrentTradeBridging, useIsEoaEthFlow } from 'modules/trade'

import { useIsSlippageModified } from './useIsSlippageModified'
import { useTradeSlippage } from './useTradeSlippage'

/**
* Slippage warning threshold for regular ERC20 orders
* Show slippage prominently when > 2%
*/
const REGULAR_ORDER_SLIPPAGE_WARNING_BPS = 200 // 2%

/**
* Hook to determine if slippage should be displayed prominently (outside the accordion)
*
* Slippage should be prominent when:
* 1. User has manually modified the slippage value, OR
* 2. Slippage exceeds warning thresholds (>2%)
*
* EXCEPT: Never show prominently for Bridge orders
*
* Note: When accordion is expanded, prominent slippage is hidden to avoid duplication
*
* @returns {boolean} true if slippage should be shown outside the accordion
*/
export function useShouldShowSlippageProminent(): boolean {
const { chainId } = useWalletInfo()
const slippage = useTradeSlippage()
const isSlippageModified = useIsSlippageModified()
const isEoaEthFlow = useIsEoaEthFlow()
const isCurrentTradeBridging = useIsCurrentTradeBridging()

return useMemo(() => {
// Never show prominently for Bridge orders
if (isCurrentTradeBridging) {
return false
}

const slippageBps = percentToBps(slippage)

// Determine the warning threshold based on order type
let warningThresholdBps: number

if (isEoaEthFlow) {
// For ETH-flow orders, use 2% threshold
warningThresholdBps = ETH_FLOW_SLIPPAGE_WARNING_THRESHOLD[chainId]
} else {
// For regular ERC20 orders, use 2% threshold
warningThresholdBps = REGULAR_ORDER_SLIPPAGE_WARNING_BPS
}
Comment on lines +49 to +55
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: ETH-flow threshold implementation contradicts requirements.

The implementation uses 2% for ETH-flow orders (line 53), but the PR objectives and linked issue #6317 explicitly state the threshold should be ">5% for ETH-flow orders on Mainnet."

Looking at libs/common-const/src/common.ts, ETH_FLOW_SLIPPAGE_WARNING_THRESHOLD is hardcoded to 200 bps (2%) for all chains. This constant needs to be updated to 500 bps (5%) to match requirements.

You'll need to update the constant definition in libs/common-const/src/common.ts:

export const ETH_FLOW_SLIPPAGE_WARNING_THRESHOLD: Record<SupportedChainId, number> = mapSupportedNetworks(
  500, // 5%
)

Then update the comment on line 52:

     if (isEoaEthFlow) {
-      // For ETH-flow orders, use 2% threshold
+      // For ETH-flow orders, use 5% threshold
       warningThresholdBps = ETH_FLOW_SLIPPAGE_WARNING_THRESHOLD[chainId]
🤖 Prompt for AI Agents
In
apps/cowswap-frontend/src/modules/tradeSlippage/hooks/useShouldShowSlippageProminent.ts
around lines 51–57, the ETH-flow threshold is set to 2% but requirements require
>5% on Mainnet; update the constant definition in
libs/common-const/src/common.ts to set ETH_FLOW_SLIPPAGE_WARNING_THRESHOLD to
500 (bps) via mapSupportedNetworks(500) so chains use 5% instead of 2%, and then
update the inline comment at line ~52 in useShouldShowSlippageProminent.ts to
reflect that ETH-flow orders use a 5% threshold on Mainnet (e.g., “For ETH-flow
orders, use 5% threshold”) ensuring types still match SupportedChainId mapping.


// Show prominently when:
// 1. User manually modified slippage, OR
// 2. Slippage exceeds threshold (>2%)
const shouldShowDueToHighSlippage = slippageBps > warningThresholdBps

return isSlippageModified || shouldShowDueToHighSlippage
}, [chainId, slippage, isSlippageModified, isEoaEthFlow, isCurrentTradeBridging])
}

1 change: 1 addition & 0 deletions apps/cowswap-frontend/src/modules/tradeSlippage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export * from './hooks/useSlippageConfig'
export * from './utils/slippageBpsToPercent'
export * from './hooks/useSlippageConfig'
export * from './hooks/useIsDefaultSlippageApplied'
export * from './hooks/useShouldShowSlippageProminent'
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
useReceiveAmountInfo,
} from 'modules/trade'
import { useTradeQuote } from 'modules/tradeQuote'
import { useIsSlippageModified, useTradeSlippage } from 'modules/tradeSlippage'
import { useIsSlippageModified, useShouldShowSlippageProminent, useTradeSlippage } from 'modules/tradeSlippage'
import { useUsdAmount } from 'modules/usdAmount'

import { QuoteApiError } from 'api/cowProtocol/errors/QuoteError'
Expand Down Expand Up @@ -43,6 +43,7 @@ export function TradeRateDetails({

const slippage = useTradeSlippage()
const isSlippageModified = useIsSlippageModified()
const shouldShowSlippageProminent = useShouldShowSlippageProminent()
// todo replace by useGetReceiveAmountInfo when we decide what to show as bridge total fee
const receiveAmountInfo = useReceiveAmountInfo()
const derivedTradeState = useDerivedTradeState()
Expand Down Expand Up @@ -82,6 +83,15 @@ export function TradeRateDetails({

const totalCosts = getTotalCosts(receiveAmountInfo, bridgeQuoteAmounts?.bridgeFee)

// Slippage row component - can be shown outside or inside accordion
const slippageRow = slippage ? (
<RowSlippage
isTradePriceUpdating={isTradePriceUpdating}
allowedSlippage={slippage}
isSlippageModified={isSlippageModified}
/>
) : null

// Default expanded content if accordionContent prop is not supplied
const defaultExpandedContent = (
<>
Expand All @@ -90,26 +100,28 @@ export function TradeRateDetails({
networkCostsSuffix={shouldPayGas ? <NetworkCostsSuffix /> : null}
networkCostsTooltipSuffix={<NetworkCostsTooltipSuffix />}
/>
{slippage && (
<RowSlippage
isTradePriceUpdating={isTradePriceUpdating}
allowedSlippage={slippage}
isSlippageModified={isSlippageModified}
/>
)}
{/* Always show slippage inside accordion */}
{slippageRow}
<RowDeadline deadline={deadline} />
</>
)

return (
<TradeTotalCostsDetails
totalCosts={totalCosts}
rateInfoParams={rateInfoParams}
isFeeDetailsOpen={isFeeDetailsOpen}
toggleAccordion={toggleAccordion}
feeWrapper={feeWrapper}
>
{accordionContent || defaultExpandedContent}
</TradeTotalCostsDetails>
<>
<TradeTotalCostsDetails
totalCosts={totalCosts}
rateInfoParams={rateInfoParams}
isFeeDetailsOpen={isFeeDetailsOpen}
toggleAccordion={toggleAccordion}
feeWrapper={feeWrapper}
>
{accordionContent || defaultExpandedContent}
</TradeTotalCostsDetails>

{/* Show slippage outside accordion when prominent and accordion is closed (to avoid duplication) */}
{shouldShowSlippageProminent && !isFeeDetailsOpen && (
<div style={{ padding: '0 6px', marginTop: '-5px' }}>{slippageRow}</div>
)}
</>
)
}
Loading