From e154477e11a8bf10ffafc5b0ebd012659208a485 Mon Sep 17 00:00:00 2001
From: Pearce
Date: Thu, 4 Dec 2025 13:39:33 +0100
Subject: [PATCH 01/10] feat: pool alert banner
---
.../src/dex/components/PoolAlertBanner.tsx | 39 +++++++++++++++++++
apps/main/src/dex/types/main.types.ts | 2 +
2 files changed, 41 insertions(+)
create mode 100644 apps/main/src/dex/components/PoolAlertBanner.tsx
diff --git a/apps/main/src/dex/components/PoolAlertBanner.tsx b/apps/main/src/dex/components/PoolAlertBanner.tsx
new file mode 100644
index 0000000000..ab8941083d
--- /dev/null
+++ b/apps/main/src/dex/components/PoolAlertBanner.tsx
@@ -0,0 +1,39 @@
+import Stack from '@mui/material/Stack'
+import { useDismissBanner } from '@ui-kit/hooks/useLocalStorage'
+import { ExclamationTriangleIcon } from '@ui-kit/shared/icons/ExclamationTriangleIcon'
+import { Banner } from '@ui-kit/shared/ui/Banner'
+import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces'
+import { PoolAlert } from '../types/main.types'
+
+const { IconSize } = SizesAndSpaces
+
+const ONE_DAY_MS = 24 * 60 * 60 * 1000 // 24 hours in milliseconds
+
+const PoolAlertBanner = ({
+ poolAlert,
+ poolAlertBannerKey,
+}: {
+ poolAlert: PoolAlert | null
+ poolAlertBannerKey: string
+}) => {
+ const { shouldShowBanner, dismissBanner } = useDismissBanner(poolAlertBannerKey, ONE_DAY_MS)
+
+ if (poolAlert?.banner)
+ return (
+ shouldShowBanner && (
+
+
+ {' '}
+ {poolAlert.banner.title}
+
+
+ )
+ )
+}
+
+export default PoolAlertBanner
diff --git a/apps/main/src/dex/types/main.types.ts b/apps/main/src/dex/types/main.types.ts
index d0b70ff8cd..9be8453ad7 100644
--- a/apps/main/src/dex/types/main.types.ts
+++ b/apps/main/src/dex/types/main.types.ts
@@ -5,6 +5,7 @@ import type { IChainId, IDict, INetworkName } from '@curvefi/api/lib/interfaces'
import type { PoolTemplate } from '@curvefi/api/lib/pools'
import type { TooltipProps } from '@ui/Tooltip/types'
import type { BaseConfig } from '@ui/utils'
+import { BannerProps } from '@ui-kit/shared/ui/Banner'
export type { CurveApi, Wallet } from '@ui-kit/features/connect-wallet'
@@ -273,6 +274,7 @@ export interface PoolAlert extends TooltipProps {
isInformationOnly?: boolean
isInformationOnlyAndShowInForm?: boolean
isCloseOnTooltipOnly?: boolean
+ banner?: Omit & { title: string }
isPoolPageOnly?: boolean // Don't show the pools overview table
address?: string
message: ReactNode
From a8f73ab7f23ac04f25b7e91c1ccb581c1ef22e70 Mon Sep 17 00:00:00 2001
From: Pearce
Date: Thu, 4 Dec 2025 13:51:49 +0100
Subject: [PATCH 02/10] refactor: replace monad banner alert with pool alert
banner
---
.../src/dex/components/MonadBannerAlert.tsx | 19 -------------
.../src/dex/components/PagePool/index.tsx | 12 +++++---
.../src/dex/components/PoolAlertBanner.tsx | 28 ++++++++-----------
apps/main/src/dex/hooks/usePoolAlert.tsx | 5 ++++
4 files changed, 24 insertions(+), 40 deletions(-)
delete mode 100644 apps/main/src/dex/components/MonadBannerAlert.tsx
diff --git a/apps/main/src/dex/components/MonadBannerAlert.tsx b/apps/main/src/dex/components/MonadBannerAlert.tsx
deleted file mode 100644
index 2052a63fb3..0000000000
--- a/apps/main/src/dex/components/MonadBannerAlert.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { Banner } from '@ui-kit/shared/ui/Banner'
-import { Stack } from '@mui/material'
-import { t } from '@ui-kit/lib/i18n'
-import { PoolUrlParams } from '../types/main.types'
-
-const MonadBannerAlert = ({ params }: { params: PoolUrlParams }) => {
- const showFactoryStableNg11Banner = params.pool === 'factory-stable-ng-11' && params.network === 'monad'
-
- if (showFactoryStableNg11Banner)
- return (
-
-
- {t`This pool has been misconfigured. It has been set to withdraw only. To minimize impact withdraw in balanced proportion instead of single sided.`}
-
-
- )
-}
-
-export default MonadBannerAlert
diff --git a/apps/main/src/dex/components/PagePool/index.tsx b/apps/main/src/dex/components/PagePool/index.tsx
index b27745e184..03920e01b5 100644
--- a/apps/main/src/dex/components/PagePool/index.tsx
+++ b/apps/main/src/dex/components/PagePool/index.tsx
@@ -20,7 +20,7 @@ import useStore from '@/dex/store/useStore'
import { getChainPoolIdActiveKey } from '@/dex/utils'
import { getPath } from '@/dex/utils/utilsRouter'
import { ManageGauge } from '@/dex/widgets/manage-gauge'
-import type { PoolUrlParams } from '@/dex/types/main.types'
+import { notFalsy } from '@curvefi/prices-api/objects.util'
import Stack from '@mui/material/Stack'
import AlertBox from '@ui/AlertBox'
import { AppFormContentWrapper } from '@ui/AppForm'
@@ -45,7 +45,7 @@ import { t } from '@ui-kit/lib/i18n'
import { REFRESH_INTERVAL } from '@ui-kit/lib/model'
import { type TabOption, TabsSwitcher } from '@ui-kit/shared/ui/TabsSwitcher'
import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces'
-import MonadBannerAlert from '../MonadBannerAlert'
+import PoolAlertBanner from '../PoolAlertBanner'
const DEFAULT_SEED: Seed = { isSeed: null, loaded: false }
const { MaxWidth } = SizesAndSpaces
@@ -204,10 +204,14 @@ const Transfer = (pageTransferProps: PageTransferProps) => {
)
-
return (
<>
-
+ {poolAlert?.banner && (
+
+ )}
poolAlertBannerKey: string
}) => {
const { shouldShowBanner, dismissBanner } = useDismissBanner(poolAlertBannerKey, ONE_DAY_MS)
- if (poolAlert?.banner)
- return (
- shouldShowBanner && (
-
-
- {' '}
- {poolAlert.banner.title}
-
-
- )
+ return (
+ shouldShowBanner && (
+
+
+ {' '}
+ {banner.title}
+
+
)
+ )
}
export default PoolAlertBanner
diff --git a/apps/main/src/dex/hooks/usePoolAlert.tsx b/apps/main/src/dex/hooks/usePoolAlert.tsx
index 9d16b03bd1..919c0f11cb 100644
--- a/apps/main/src/dex/hooks/usePoolAlert.tsx
+++ b/apps/main/src/dex/hooks/usePoolAlert.tsx
@@ -7,6 +7,7 @@ import Box from '@ui/Box'
import { ExternalLink, InternalLink } from '@ui/Link'
import { breakpoints } from '@ui/utils'
import { useParams } from '@ui-kit/hooks/router'
+import { t } from '@ui-kit/lib/i18n'
import { shortenAddress } from '@ui-kit/utils'
const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
@@ -212,6 +213,10 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
alertType: 'danger',
isDisableDeposit: true,
isDisableSwap: true,
+ banner: {
+ title: t`Misconfigured pool`,
+ subtitle: t`This pool has been misconfigured. It has been set to withdraw only. To minimize impact withdraw in balanced proportion instead of single sided.`,
+ },
message: (
This pool is in withdraw only mode, as it has been configured incorrectly.
From a4bc1be7b0de5943e240aea8b5bcbd09c22fd33b Mon Sep 17 00:00:00 2001
From: Pearce
Date: Tue, 16 Dec 2025 10:07:54 +0100
Subject: [PATCH 03/10] feat: implement portal for PoolAlertBanner and update
GlobalLayout for rendering
---
.../src/dex/components/PoolAlertBanner.tsx | 28 ++++++++++---------
apps/main/src/routes/GlobalLayout.tsx | 2 ++
.../curve-ui-kit/src/shared/ui/Banner.tsx | 2 +-
3 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/apps/main/src/dex/components/PoolAlertBanner.tsx b/apps/main/src/dex/components/PoolAlertBanner.tsx
index e8559dd05e..3822b2cd7d 100644
--- a/apps/main/src/dex/components/PoolAlertBanner.tsx
+++ b/apps/main/src/dex/components/PoolAlertBanner.tsx
@@ -1,11 +1,10 @@
-import Stack from '@mui/material/Stack'
+import { useEffect, useState } from 'react'
+import { createPortal } from 'react-dom'
import { useDismissBanner } from '@ui-kit/hooks/useLocalStorage'
-import { ExclamationTriangleIcon } from '@ui-kit/shared/icons/ExclamationTriangleIcon'
import { Banner } from '@ui-kit/shared/ui/Banner'
-import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces'
import { PoolAlert } from '../types/main.types'
-const { IconSize } = SizesAndSpaces
+export const DEX_POOL_ALERT_BANNER_PORTAL_ID = 'dex-pool-alert-banner-portal'
const ONE_DAY_MS = 24 * 60 * 60 * 1000 // 24 hours in milliseconds
@@ -17,17 +16,20 @@ const PoolAlertBanner = ({
poolAlertBannerKey: string
}) => {
const { shouldShowBanner, dismissBanner } = useDismissBanner(poolAlertBannerKey, ONE_DAY_MS)
+ const [portalEl, setPortalEl] = useState(null)
- return (
- shouldShowBanner && (
-
-
- {' '}
- {banner.title}
-
-
- )
+ useEffect(() => {
+ setPortalEl(document.getElementById(DEX_POOL_ALERT_BANNER_PORTAL_ID))
+ }, [])
+
+ const content = (
+
+ {banner.title}
+
)
+
+ if (!shouldShowBanner) return null
+ return portalEl ? createPortal(content, portalEl) : content
}
export default PoolAlertBanner
diff --git a/apps/main/src/routes/GlobalLayout.tsx b/apps/main/src/routes/GlobalLayout.tsx
index 093def2e0e..169dd9b9d1 100644
--- a/apps/main/src/routes/GlobalLayout.tsx
+++ b/apps/main/src/routes/GlobalLayout.tsx
@@ -1,5 +1,6 @@
import { type ReactNode } from 'react'
import daoNetworks from '@/dao/networks'
+import { DEX_POOL_ALERT_BANNER_PORTAL_ID } from '@/dex/components/PoolAlertBanner'
import { useDexAppStats, useDexRoutes } from '@/dex/hooks/useDexAppStats'
import lendNetworks from '@/lend/networks'
import { useLlamalendAppStats } from '@/llamalend/hooks/useLlamalendAppStats'
@@ -80,6 +81,7 @@ export const GlobalLayout = ({
appStats={useAppStats(currentApp, network)}
routes={useAppRoutes(network)}
/>
+ {currentApp === 'dex' && }
-
+
{BannerIcons[icon]} {children}
From a4a52c0c06315edc17e6dc672937e122b3394225 Mon Sep 17 00:00:00 2001
From: Pearce
Date: Tue, 16 Dec 2025 12:49:56 +0100
Subject: [PATCH 04/10] refactor: pool alerts splitted into pool banner
maessage and user action messaged
---
.../src/dex/components/PagePool/index.tsx | 1 +
.../src/dex/components/PoolAlertBanner.tsx | 19 +-
.../dex/components/pool-alert-messages.tsx | 49 +++++
apps/main/src/dex/hooks/usePoolAlert.tsx | 206 +++++++++---------
apps/main/src/dex/types/main.types.ts | 4 +-
5 files changed, 171 insertions(+), 108 deletions(-)
create mode 100644 apps/main/src/dex/components/pool-alert-messages.tsx
diff --git a/apps/main/src/dex/components/PagePool/index.tsx b/apps/main/src/dex/components/PagePool/index.tsx
index cf466de425..e05d96ae37 100644
--- a/apps/main/src/dex/components/PagePool/index.tsx
+++ b/apps/main/src/dex/components/PagePool/index.tsx
@@ -209,6 +209,7 @@ const Transfer = (pageTransferProps: PageTransferProps) => {
<>
{poolAlert?.banner && (
diff --git a/apps/main/src/dex/components/PoolAlertBanner.tsx b/apps/main/src/dex/components/PoolAlertBanner.tsx
index 3822b2cd7d..6200c0d968 100644
--- a/apps/main/src/dex/components/PoolAlertBanner.tsx
+++ b/apps/main/src/dex/components/PoolAlertBanner.tsx
@@ -1,19 +1,30 @@
import { useEffect, useState } from 'react'
import { createPortal } from 'react-dom'
import { useDismissBanner } from '@ui-kit/hooks/useLocalStorage'
-import { Banner } from '@ui-kit/shared/ui/Banner'
-import { PoolAlert } from '../types/main.types'
+import { Banner, BannerProps } from '@ui-kit/shared/ui/Banner'
+import { AlertType, PoolAlert } from '../types/main.types'
export const DEX_POOL_ALERT_BANNER_PORTAL_ID = 'dex-pool-alert-banner-portal'
const ONE_DAY_MS = 24 * 60 * 60 * 1000 // 24 hours in milliseconds
+/** Maps AlertType to BannerSeverity */
+const alertTypeToBannerSeverity: Record = {
+ error: 'alert',
+ danger: 'alert',
+ warning: 'warning',
+ info: 'info',
+ '': 'info',
+}
+
const PoolAlertBanner = ({
banner,
poolAlertBannerKey,
+ alertType,
}: {
banner: NonNullable
poolAlertBannerKey: string
+ alertType: AlertType
}) => {
const { shouldShowBanner, dismissBanner } = useDismissBanner(poolAlertBannerKey, ONE_DAY_MS)
const [portalEl, setPortalEl] = useState(null)
@@ -22,8 +33,10 @@ const PoolAlertBanner = ({
setPortalEl(document.getElementById(DEX_POOL_ALERT_BANNER_PORTAL_ID))
}, [])
+ const severity = alertTypeToBannerSeverity[alertType]
+
const content = (
-
+
{banner.title}
)
diff --git a/apps/main/src/dex/components/pool-alert-messages.tsx b/apps/main/src/dex/components/pool-alert-messages.tsx
new file mode 100644
index 0000000000..c689353888
--- /dev/null
+++ b/apps/main/src/dex/components/pool-alert-messages.tsx
@@ -0,0 +1,49 @@
+import Button from '@mui/material/Button'
+import Link from '@mui/material/Link'
+import Stack from '@mui/material/Stack'
+import { ArrowTopRightIcon } from '@ui-kit/shared/icons/ArrowTopRightIcon'
+import { RouterLink } from '@ui-kit/shared/ui/RouterLink'
+import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces'
+
+const { Spacing } = SizesAndSpaces
+
+export const MessageWrapper = ({ children }: { children: React.ReactNode }) => (
+
+ {children}
+
+)
+
+export const ExternalLink = ({ href, children }: { href: string; children: React.ReactNode }) => (
+ }
+ href={href}
+ target="_blank"
+ rel="noreferrer noopener"
+ >
+ {children}
+
+)
+
+export const InternalLink = ({ href, children }: { href: string; children: React.ReactNode }) => (
+
+ {children}
+
+)
diff --git a/apps/main/src/dex/hooks/usePoolAlert.tsx b/apps/main/src/dex/hooks/usePoolAlert.tsx
index 4d98648789..521adf5709 100644
--- a/apps/main/src/dex/hooks/usePoolAlert.tsx
+++ b/apps/main/src/dex/hooks/usePoolAlert.tsx
@@ -1,14 +1,10 @@
import { useMemo } from 'react'
-import { styled } from 'styled-components'
import { ROUTE } from '@/dex/constants'
import { PoolAlert, PoolData, PoolDataCache, type UrlParams } from '@/dex/types/main.types'
-import { getPath } from '@/dex/utils/utilsRouter'
-import Box from '@ui/Box'
-import { ExternalLink, InternalLink } from '@ui/Link'
-import { breakpoints } from '@ui/utils'
import { useParams } from '@ui-kit/hooks/router'
-import { t } from '@ui-kit/lib/i18n'
-import { shortenAddress } from '@ui-kit/utils'
+import { t, Trans } from '@ui-kit/lib/i18n'
+import { getInternalUrl } from '@ui-kit/shared/routes'
+import { ExternalLink, InternalLink, MessageWrapper } from '../components/pool-alert-messages'
const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
const params = useParams()
@@ -23,15 +19,14 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
isDisableDeposit: true,
isInformationOnly: true,
isCloseOnTooltipOnly: true,
+ banner: {
+ title: t`zStables Attack`,
+ subtitle: t`zStables (zETH, UZD) have encountered an attack. `,
+ learnMoreUrl: 'https://twitter.com/ZunamiProtocol/status/1690863406079696896?s=20',
+ },
message: (
-
- zStables (zETH, UZD) have encountered an attack. The collateral remain secure, we delve into the ongoing
- investigation. —Zunami Protocol {' '}
-
- https://twitter.com/ZunamiProtocol/status/1690863406079696896?s=20
-
-
+ {t`Deposit disabled.`}
),
})
@@ -41,21 +36,23 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
isDisableSwap: true,
isInformationOnly: true,
isCloseOnTooltipOnly: true,
+ banner: {
+ title: t`Geist Finance Disabled`,
+ subtitle: t`Deposit and swap are disabled.`,
+ learnMoreUrl: 'https://twitter.com/geistfinance',
+ },
message: (
-
- Deposit and swap are disabled, see{' '}
-
- https://twitter.com/geistfinance
- {' '}
- for additional information.
-
+ {t`This pool is in withdraw only mode.`}
),
})
const yPrismaAlert = (): PoolAlert => {
- const redirectPathname = params && getPath(params, `${ROUTE.PAGE_POOLS}/factory-v2-372${ROUTE.PAGE_POOL_DEPOSIT}`)
- const redirectText = `PRISMA/yPRISMA pool (${shortenAddress('0x69833361991ed76f9e8dbbcdf9ea1520febfb4a7')})`
+ const prismaPoolHref = getInternalUrl(
+ 'dex',
+ params.network,
+ `${ROUTE.PAGE_POOLS}/factory-v2-372${ROUTE.PAGE_POOL_DEPOSIT}`,
+ )
return {
isDisableDeposit: true,
isInformationOnly: true,
@@ -63,19 +60,18 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
alertType: 'warning',
message: (
-
- This pool has been deprecated. Please use the{' '}
- {redirectPathname ? (
-
- {redirectText}
-
- ) : (
- {redirectText}
- )}{' '}
- instead.
-
+ {t`Deposit disabled.`}
),
+ banner: {
+ title: t`Deprecated Pool`,
+ subtitle: (
+
+ This pool has been deprecated. Please use the{' '}
+ PRISMA/yPRISMA pool instead.
+
+ ),
+ },
}
}
const synthetixAlert = (): PoolAlert => ({
@@ -83,28 +79,34 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
isInformationOnly: true,
isCloseOnTooltipOnly: true,
minWidth: '350px',
+ banner: {
+ title: t`Synthetix Synths Disabled`,
+ subtitle: t`Exchanges on Synthetix synths are expected to be disabled. Users should withdraw liquidity or redeem synths to sUSD. Exit pools to avoid value dilution.`,
+ learnMoreUrl: 'https://gov.curve.finance/t/kill-gauges-on-all-non-susd-curve-pools-on-ethereum/10033/2',
+ },
message: (
-
-
+
+
Please note that exchanges on synthetix synths are expected to be disabled and users can either withdraw
liquidity from the underlying token, or redeem their synths to sUSD on{' '}
-
- https://staking.synthetix.io/wallet/balances/
-
-
-
+ synthetix.io
+
+
+
+
Users are encouraged to exit the pools in order to avoid getting their holdings‘ value diluted with
the discountRate For more information please refer to{' '}
-
- https://gov.curve.finance/t/kill-gauges-on-all-non-susd-curve-pools-on-ethereum/10033/2
+
+ gov.curve.finance
-
- Please note that sUSD is not involved, so these would be on the other pools sETH, sBTC, sForex ...
-
+
+
+
+
+ Please note that sUSD is not involved, so these would be on the other pools sETH, sBTC, sForex ...
+
+
),
})
@@ -112,9 +114,13 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
alertType: 'warning',
isInformationOnlyAndShowInForm: true,
isDisableDeposit: true,
+ banner: {
+ title: t`Ironbank Protocol Deprecated`,
+ subtitle: t`The Ironbank protocol is deprecated. Please do not supply liquidity to this pool.`,
+ },
message: (
- Ironbank protocol is deprecated. Please do not supply liquidity to this pool.
+ {t`Deposit disabled.`}
),
})
@@ -124,15 +130,14 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
isDisableSwap: true,
isInformationOnly: true,
isCloseOnTooltipOnly: true,
+ banner: {
+ title: t`Synthetix USD Deprecated`,
+ subtitle: t`Pool is deprecated. Deposit and swap are disabled.`,
+ learnMoreUrl: 'https://x.com/synthetix_io/status/1953054538610688198',
+ },
message: (
-
- Deposit and swap are disabled, see{' '}
-
- https://x.com/synthetix_io/status/1953054538610688198
- {' '}
- for additional information.
-
+ {t`This pool is in withdraw only mode.`}
),
})
@@ -141,16 +146,22 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
isDisableDeposit: true,
isInformationOnly: true,
isCloseOnTooltipOnly: true,
+ banner: {
+ title: t`YieldBasis Managed Pool`,
+ subtitle: (
+
+ This pool is managed by YieldBasis . Only deposits made on the YieldBasis UI earn fees and rewards.
+
+ ),
+ learnMoreUrl: 'https://yieldbasis.com',
+ },
message: (
-
- This pool is managed by YieldBasis . Only deposits made on the YieldBasis UI earn fees and rewards.{' '}
- Go to{' '}
-
- yieldbasis.com
- {' '}
- to deposit.
-
+
+
+ Deposit on yieldbasis.com
+
+
),
})
@@ -160,9 +171,13 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
isDisableDeposit: true,
isInformationOnly: true,
isCloseOnTooltipOnly: true,
+ banner: {
+ title: t`USPD Exploited`,
+ subtitle: t`USPD has been exploited. This pool has been disabled to prevent new users from loss of funds.`,
+ },
message: (
- USPD has been exploited. This pool has been disabled to prevent new users from loss of funds.
+ {t`Deposit disabled. We recommend exiting this pool.`}
),
})
@@ -174,12 +189,12 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
isInformationOnlyAndShowInForm: true,
message: (
-
- Deposit and Swap with wBTC.e will return an error due to an Aave community decision to freeze this asset.{' '}
-
- More details
-
-
+
+
+ Deposit and Swap with wBTC.e will return an error due to an Aave community decision to freeze this asset.{' '}
+ More details
+
+
),
})
@@ -190,32 +205,31 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
isDisableDeposit: true,
isInformationOnly: true,
isCloseOnTooltipOnly: true,
+ banner: {
+ title: t`Vyper Vulnerability Exploit`,
+ subtitle: t`This pool has been exploited due to a vulnerability found in Vyper versions v0.2.15, v0.2.16, or v0.3.0.`,
+ learnMoreUrl: 'https://hackmd.io/@LlamaRisk/BJzSKHNjn',
+ },
message: (
-
- This pool has been exploited due to a vulnerability found in Vyper versions v0.2.15, v0.2.16, or v0.3.0. For
- additional information, please click on the post-mortem link:{' '}
-
- https://hackmd.io/@LlamaRisk/BJzSKHNjn
-
-
+ {t`Deposit disabled. We recommend exiting this pool.`}
),
})
+
const possibleVyperExploitedAlert = (): PoolAlert => ({
alertType: 'danger',
isDisableDeposit: true,
isInformationOnly: true,
isCloseOnTooltipOnly: true,
+ banner: {
+ title: t`Potential Vulnerability Exploit`,
+ subtitle: t`This pool might be at risk of being exploited. We recommend exiting this pool.`,
+ learnMoreUrl: 'https://twitter.com/CurveFinance/status/1685925429041917952',
+ },
message: (
-
- This pool might be at risk of being exploited. While security researchers have not identified a profitable
- exploit, we recommend exiting this pool.{' '}
-
- https://twitter.com/CurveFinance/status/1685925429041917952
-
-
+ {t`Deposit disabled. We recommend exiting this pool.`}
),
})
@@ -229,12 +243,12 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
isInformationOnlyAndShowInForm: true,
isCloseOnTooltipOnly: true,
banner: {
- title: t`Misconfigured pool`,
+ title: t`Misconfigured Pool`,
subtitle: t`This pool has been misconfigured. It has been set to withdraw only. To minimize impact withdraw in balanced proportion instead of single sided.`,
},
message: (
- This pool has been badly configured and is in withdraw only mode.
+ {t`This pool is in withdraw only mode.`}
),
})
@@ -263,7 +277,6 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
'0xd9ff8396554a0d18b2cfbec53e1979b7ecce8373': yieldbasisAlert(),
'0x06cf5f9b93e9fcfdb33d6b3791eb152567cd8d36': uspdioAlert(),
-
// arbitrum
'0x960ea3e3c7fb317332d990873d354e18d7645590': possibleVyperExploitedAlert(), // tricrypto
@@ -285,19 +298,4 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
}, [poolAddress, params, hasVyperVulnerability])
}
-const MessageWrapper = styled.div`
- align-items: flex-start;
- display: flex;
- flex-direction: column;
-
- a {
- word-break: break-word;
- }
-
- @media (min-width: ${breakpoints.sm}rem) {
- align-items: center;
- flex-direction: row;
- }
-`
-
export default usePoolAlert
diff --git a/apps/main/src/dex/types/main.types.ts b/apps/main/src/dex/types/main.types.ts
index b003057498..67528c347b 100644
--- a/apps/main/src/dex/types/main.types.ts
+++ b/apps/main/src/dex/types/main.types.ts
@@ -274,10 +274,12 @@ export interface PoolAlert extends TooltipProps {
isInformationOnly?: boolean
isInformationOnlyAndShowInForm?: boolean
isCloseOnTooltipOnly?: boolean
+ // banner message, related to the market situation
banner?: Omit & { title: string }
isPoolPageOnly?: boolean // Don't show the pools overview table
address?: string
- message: ReactNode
+ // action card message, related to action of user
+ message?: ReactNode
}
export type EstimatedGas = number | number[] | null
From d1fa633fd7e54cbe14ea66967a9b8f7a34ae80bf Mon Sep 17 00:00:00 2001
From: Pearce
Date: Tue, 16 Dec 2025 14:00:42 +0100
Subject: [PATCH 05/10] fix: ensure pool alerts display messages only when
present
---
.../PagePool/Deposit/components/FormDeposit.tsx | 2 +-
.../PagePool/Deposit/components/FormDepositStake.tsx | 2 +-
.../main/src/dex/components/PagePool/Deposit/index.tsx | 2 +-
.../PagePool/PoolDetails/PoolStats/index.tsx | 6 ++++--
apps/main/src/dex/components/PagePool/Swap/index.tsx | 2 +-
apps/main/src/dex/components/PagePool/index.tsx | 2 +-
apps/main/src/dex/components/PoolLabel.tsx | 10 ++++++----
apps/main/src/dex/hooks/usePoolAlert.tsx | 1 +
8 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx b/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx
index 563f47e5b0..5e5caa7cef 100644
--- a/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx
+++ b/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx
@@ -298,7 +298,7 @@ const FormDeposit = ({
/>
- {poolAlert && poolAlert?.isInformationOnlyAndShowInForm && (
+ {poolAlert?.message && poolAlert?.isInformationOnlyAndShowInForm && (
{poolAlert.message}
)}
diff --git a/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx b/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx
index de10456eaa..35a943abc2 100644
--- a/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx
+++ b/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx
@@ -298,7 +298,7 @@ const FormDepositStake = ({
/>
- {poolAlert && poolAlert?.isInformationOnlyAndShowInForm && (
+ {poolAlert?.message && poolAlert?.isInformationOnlyAndShowInForm && (
{poolAlert.message}
)}
diff --git a/apps/main/src/dex/components/PagePool/Deposit/index.tsx b/apps/main/src/dex/components/PagePool/Deposit/index.tsx
index e6f2ae2571..8b7b0e52b1 100644
--- a/apps/main/src/dex/components/PagePool/Deposit/index.tsx
+++ b/apps/main/src/dex/components/PagePool/Deposit/index.tsx
@@ -51,7 +51,7 @@ const Deposit = ({ hasDepositAndStake, ...transferProps }: TransferProps & { has
{poolAlert && poolAlert.isDisableDeposit ? (
- {poolAlert.message}
+ poolAlert.message && {poolAlert.message}
) : (
<>
{formType === 'DEPOSIT' && }
diff --git a/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx b/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx
index 03f1608d70..c6e94e18a5 100644
--- a/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx
+++ b/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx
@@ -46,10 +46,12 @@ const PoolStats = ({ curve, routerParams, poolAlert, poolData, poolDataCacheOrAp
{poolData && }
- {poolAlert && !poolAlert.isDisableDeposit && !poolAlert.isInformationOnlyAndShowInForm && (
+ {poolAlert?.message && !poolAlert.isDisableDeposit && !poolAlert.isInformationOnlyAndShowInForm && (
{poolAlert.message}
)}
- {tokenAlert && tokenAlert.isInformationOnly && {tokenAlert.message} }
+ {tokenAlert?.message && tokenAlert.isInformationOnly && (
+ {tokenAlert.message}
+ )}
{poolDataCacheOrApi.pool.referenceAsset === 'CRYPTO' && (
diff --git a/apps/main/src/dex/components/PagePool/Swap/index.tsx b/apps/main/src/dex/components/PagePool/Swap/index.tsx
index 37821669b1..e6655b17ef 100644
--- a/apps/main/src/dex/components/PagePool/Swap/index.tsx
+++ b/apps/main/src/dex/components/PagePool/Swap/index.tsx
@@ -642,7 +642,7 @@ const Swap = ({
- {poolAlert && poolAlert?.isInformationOnlyAndShowInForm && (
+ {poolAlert?.message && poolAlert?.isInformationOnlyAndShowInForm && (
{poolAlert.message}
)}
diff --git a/apps/main/src/dex/components/PagePool/index.tsx b/apps/main/src/dex/components/PagePool/index.tsx
index e05d96ae37..690d324244 100644
--- a/apps/main/src/dex/components/PagePool/index.tsx
+++ b/apps/main/src/dex/components/PagePool/index.tsx
@@ -234,7 +234,7 @@ const Transfer = (pageTransferProps: PageTransferProps) => {
{rFormType === 'swap' ? (
{poolAlert?.isDisableSwap ? (
- {poolAlert.message}
+ poolAlert.message && {poolAlert.message}
) : (
{!isMobile && (
<>
- {(poolAlert?.isInformationOnly || poolAlert?.isInformationOnlyAndShowInForm) && (
+ {(poolAlert?.isInformationOnly || poolAlert?.isInformationOnlyAndShowInForm) && poolAlert?.message && (
{poolAlert.message}
)}
- {tokenAlert && (
+ {tokenAlert?.message && (
{tokenAlert.message}
@@ -119,8 +119,10 @@ const PoolLabel = ({ className = '', blockchainId, isVisible = true, poolData, q
- {tokenAlert && isMobile && {tokenAlert.message} }
- {poolAlert && !poolAlert.isPoolPageOnly && (
+ {tokenAlert?.message && isMobile && (
+ {tokenAlert.message}
+ )}
+ {poolAlert && poolAlert.message && !poolAlert.isPoolPageOnly && (
<>
{!poolAlert.isInformationOnly && !poolAlert.isInformationOnlyAndShowInForm ? (
{poolAlert.message}
diff --git a/apps/main/src/dex/hooks/usePoolAlert.tsx b/apps/main/src/dex/hooks/usePoolAlert.tsx
index 521adf5709..fe85ed7929 100644
--- a/apps/main/src/dex/hooks/usePoolAlert.tsx
+++ b/apps/main/src/dex/hooks/usePoolAlert.tsx
@@ -24,6 +24,7 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
subtitle: t`zStables (zETH, UZD) have encountered an attack. `,
learnMoreUrl: 'https://twitter.com/ZunamiProtocol/status/1690863406079696896?s=20',
},
+ /* TODO: use Typography component instead of p tag */
message: (
{t`Deposit disabled.`}
From 9ec9dfd9c811cb57642e377191d8576acbeca38b Mon Sep 17 00:00:00 2001
From: Pearce
Date: Tue, 16 Dec 2025 16:59:04 +0100
Subject: [PATCH 06/10] Revert "fix: ensure pool alerts display messages only
when present"
This reverts commit d1fa633fd7e54cbe14ea66967a9b8f7a34ae80bf.
---
.../PagePool/Deposit/components/FormDeposit.tsx | 2 +-
.../PagePool/Deposit/components/FormDepositStake.tsx | 2 +-
.../main/src/dex/components/PagePool/Deposit/index.tsx | 2 +-
.../PagePool/PoolDetails/PoolStats/index.tsx | 6 ++----
apps/main/src/dex/components/PagePool/Swap/index.tsx | 2 +-
apps/main/src/dex/components/PagePool/index.tsx | 2 +-
apps/main/src/dex/components/PoolLabel.tsx | 10 ++++------
7 files changed, 11 insertions(+), 15 deletions(-)
diff --git a/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx b/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx
index 5e5caa7cef..563f47e5b0 100644
--- a/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx
+++ b/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx
@@ -298,7 +298,7 @@ const FormDeposit = ({
/>
- {poolAlert?.message && poolAlert?.isInformationOnlyAndShowInForm && (
+ {poolAlert && poolAlert?.isInformationOnlyAndShowInForm && (
{poolAlert.message}
)}
diff --git a/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx b/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx
index 35a943abc2..de10456eaa 100644
--- a/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx
+++ b/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx
@@ -298,7 +298,7 @@ const FormDepositStake = ({
/>
- {poolAlert?.message && poolAlert?.isInformationOnlyAndShowInForm && (
+ {poolAlert && poolAlert?.isInformationOnlyAndShowInForm && (
{poolAlert.message}
)}
diff --git a/apps/main/src/dex/components/PagePool/Deposit/index.tsx b/apps/main/src/dex/components/PagePool/Deposit/index.tsx
index 8b7b0e52b1..e6f2ae2571 100644
--- a/apps/main/src/dex/components/PagePool/Deposit/index.tsx
+++ b/apps/main/src/dex/components/PagePool/Deposit/index.tsx
@@ -51,7 +51,7 @@ const Deposit = ({ hasDepositAndStake, ...transferProps }: TransferProps & { has
{poolAlert && poolAlert.isDisableDeposit ? (
- poolAlert.message && {poolAlert.message}
+ {poolAlert.message}
) : (
<>
{formType === 'DEPOSIT' && }
diff --git a/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx b/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx
index c6e94e18a5..03f1608d70 100644
--- a/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx
+++ b/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx
@@ -46,12 +46,10 @@ const PoolStats = ({ curve, routerParams, poolAlert, poolData, poolDataCacheOrAp
{poolData && }
- {poolAlert?.message && !poolAlert.isDisableDeposit && !poolAlert.isInformationOnlyAndShowInForm && (
+ {poolAlert && !poolAlert.isDisableDeposit && !poolAlert.isInformationOnlyAndShowInForm && (
{poolAlert.message}
)}
- {tokenAlert?.message && tokenAlert.isInformationOnly && (
- {tokenAlert.message}
- )}
+ {tokenAlert && tokenAlert.isInformationOnly && {tokenAlert.message} }
{poolDataCacheOrApi.pool.referenceAsset === 'CRYPTO' && (
diff --git a/apps/main/src/dex/components/PagePool/Swap/index.tsx b/apps/main/src/dex/components/PagePool/Swap/index.tsx
index e6655b17ef..37821669b1 100644
--- a/apps/main/src/dex/components/PagePool/Swap/index.tsx
+++ b/apps/main/src/dex/components/PagePool/Swap/index.tsx
@@ -642,7 +642,7 @@ const Swap = ({
- {poolAlert?.message && poolAlert?.isInformationOnlyAndShowInForm && (
+ {poolAlert && poolAlert?.isInformationOnlyAndShowInForm && (
{poolAlert.message}
)}
diff --git a/apps/main/src/dex/components/PagePool/index.tsx b/apps/main/src/dex/components/PagePool/index.tsx
index 690d324244..e05d96ae37 100644
--- a/apps/main/src/dex/components/PagePool/index.tsx
+++ b/apps/main/src/dex/components/PagePool/index.tsx
@@ -234,7 +234,7 @@ const Transfer = (pageTransferProps: PageTransferProps) => {
{rFormType === 'swap' ? (
{poolAlert?.isDisableSwap ? (
- poolAlert.message && {poolAlert.message}
+ {poolAlert.message}
) : (
{!isMobile && (
<>
- {(poolAlert?.isInformationOnly || poolAlert?.isInformationOnlyAndShowInForm) && poolAlert?.message && (
+ {(poolAlert?.isInformationOnly || poolAlert?.isInformationOnlyAndShowInForm) && (
{poolAlert.message}
)}
- {tokenAlert?.message && (
+ {tokenAlert && (
{tokenAlert.message}
@@ -119,10 +119,8 @@ const PoolLabel = ({ className = '', blockchainId, isVisible = true, poolData, q
- {tokenAlert?.message && isMobile && (
- {tokenAlert.message}
- )}
- {poolAlert && poolAlert.message && !poolAlert.isPoolPageOnly && (
+ {tokenAlert && isMobile && {tokenAlert.message} }
+ {poolAlert && !poolAlert.isPoolPageOnly && (
<>
{!poolAlert.isInformationOnly && !poolAlert.isInformationOnlyAndShowInForm ? (
{poolAlert.message}
From fda0c3ad6373e592cde96cdec34aee97e6077f8a Mon Sep 17 00:00:00 2001
From: Pearce
Date: Tue, 16 Dec 2025 17:39:24 +0100
Subject: [PATCH 07/10] fix: ensure AlertBox display messages only when present
---
packages/ui/src/AlertBox/AlertBox.tsx | 78 ++++++++++++++-------------
1 file changed, 40 insertions(+), 38 deletions(-)
diff --git a/packages/ui/src/AlertBox/AlertBox.tsx b/packages/ui/src/AlertBox/AlertBox.tsx
index be5f833918..20430ffb94 100644
--- a/packages/ui/src/AlertBox/AlertBox.tsx
+++ b/packages/ui/src/AlertBox/AlertBox.tsx
@@ -33,45 +33,47 @@ const AlertBox = ({ className, alertType, children, title, limitHeight, handleBt
}, [children, limitHeight])
return (
-
- {title ? (
- <>
-
- {IconComp} {title}{' '}
-
- {showFullHeight ? children : cutAlert}
- >
- ) : (
-
- {IconComp}
-
+ (title || children) && (
+
+ {title ? (
+ <>
+
+ {IconComp} {title}{' '}
+
{showFullHeight ? children : cutAlert}
-
- {handleBtnClose !== undefined && (
-
-
-
- )}
-
- )}
- {limitHeight && enabledHeightToggle && (
-
-
- setShowFullHeight(!showFullHeight)}>
- {showFullHeight ? 'Minimize' : 'Expand'}
- {showFullHeight ? : }
-
-
-
- )}
-
+ >
+ ) : (
+
+ {IconComp}
+
+ {showFullHeight ? children : cutAlert}
+
+ {handleBtnClose !== undefined && (
+
+
+
+ )}
+
+ )}
+ {limitHeight && enabledHeightToggle && (
+
+
+ setShowFullHeight(!showFullHeight)}>
+ {showFullHeight ? 'Minimize' : 'Expand'}
+ {showFullHeight ? : }
+
+
+
+ )}
+
+ )
)
}
From d9d755ea14ad0f414fafc9c4cd5fa8f6bf9a9ea4 Mon Sep 17 00:00:00 2001
From: Pearce
Date: Tue, 16 Dec 2025 17:40:32 +0100
Subject: [PATCH 08/10] refactor: update PoolAlertBanner to use useMemo for
portal target and export component
---
.../src/dex/components/PagePool/index.tsx | 2 +-
.../src/dex/components/PoolAlertBanner.tsx | 31 +++++++------------
apps/main/src/routes/GlobalLayout.tsx | 2 --
3 files changed, 13 insertions(+), 22 deletions(-)
diff --git a/apps/main/src/dex/components/PagePool/index.tsx b/apps/main/src/dex/components/PagePool/index.tsx
index e05d96ae37..76d69cf8ac 100644
--- a/apps/main/src/dex/components/PagePool/index.tsx
+++ b/apps/main/src/dex/components/PagePool/index.tsx
@@ -46,7 +46,7 @@ import { t } from '@ui-kit/lib/i18n'
import { REFRESH_INTERVAL } from '@ui-kit/lib/model'
import { type TabOption, TabsSwitcher } from '@ui-kit/shared/ui/TabsSwitcher'
import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces'
-import PoolAlertBanner from '../PoolAlertBanner'
+import { PoolAlertBanner } from '../PoolAlertBanner'
const DEFAULT_SEED: Seed = { isSeed: null, loaded: false }
const { MaxWidth } = SizesAndSpaces
diff --git a/apps/main/src/dex/components/PoolAlertBanner.tsx b/apps/main/src/dex/components/PoolAlertBanner.tsx
index 6200c0d968..1c80f4c343 100644
--- a/apps/main/src/dex/components/PoolAlertBanner.tsx
+++ b/apps/main/src/dex/components/PoolAlertBanner.tsx
@@ -1,11 +1,9 @@
-import { useEffect, useState } from 'react'
+import { useMemo } from 'react'
import { createPortal } from 'react-dom'
import { useDismissBanner } from '@ui-kit/hooks/useLocalStorage'
import { Banner, BannerProps } from '@ui-kit/shared/ui/Banner'
import { AlertType, PoolAlert } from '../types/main.types'
-export const DEX_POOL_ALERT_BANNER_PORTAL_ID = 'dex-pool-alert-banner-portal'
-
const ONE_DAY_MS = 24 * 60 * 60 * 1000 // 24 hours in milliseconds
/** Maps AlertType to BannerSeverity */
@@ -17,7 +15,7 @@ const alertTypeToBannerSeverity: Record = {
'': 'info',
}
-const PoolAlertBanner = ({
+export const PoolAlertBanner = ({
banner,
poolAlertBannerKey,
alertType,
@@ -27,22 +25,17 @@ const PoolAlertBanner = ({
alertType: AlertType
}) => {
const { shouldShowBanner, dismissBanner } = useDismissBanner(poolAlertBannerKey, ONE_DAY_MS)
- const [portalEl, setPortalEl] = useState(null)
-
- useEffect(() => {
- setPortalEl(document.getElementById(DEX_POOL_ALERT_BANNER_PORTAL_ID))
- }, [])
-
+ const portalTarget = useMemo(() => document.getElementsByTagName('header')[0], [])
const severity = alertTypeToBannerSeverity[alertType]
- const content = (
-
- {banner.title}
-
+ return (
+ shouldShowBanner &&
+ portalTarget &&
+ createPortal(
+
+ {banner.title}
+ ,
+ portalTarget,
+ )
)
-
- if (!shouldShowBanner) return null
- return portalEl ? createPortal(content, portalEl) : content
}
-
-export default PoolAlertBanner
diff --git a/apps/main/src/routes/GlobalLayout.tsx b/apps/main/src/routes/GlobalLayout.tsx
index 169dd9b9d1..093def2e0e 100644
--- a/apps/main/src/routes/GlobalLayout.tsx
+++ b/apps/main/src/routes/GlobalLayout.tsx
@@ -1,6 +1,5 @@
import { type ReactNode } from 'react'
import daoNetworks from '@/dao/networks'
-import { DEX_POOL_ALERT_BANNER_PORTAL_ID } from '@/dex/components/PoolAlertBanner'
import { useDexAppStats, useDexRoutes } from '@/dex/hooks/useDexAppStats'
import lendNetworks from '@/lend/networks'
import { useLlamalendAppStats } from '@/llamalend/hooks/useLlamalendAppStats'
@@ -81,7 +80,6 @@ export const GlobalLayout = ({
appStats={useAppStats(currentApp, network)}
routes={useAppRoutes(network)}
/>
- {currentApp === 'dex' && }
Date: Tue, 16 Dec 2025 17:56:26 +0100
Subject: [PATCH 09/10] refactor: rename MessageWrapper to PoolAlertMessage and
update usage in usePoolAlert hook
---
.../dex/components/pool-alert-messages.tsx | 2 +-
apps/main/src/dex/hooks/usePoolAlert.tsx | 50 +++++++++----------
2 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/apps/main/src/dex/components/pool-alert-messages.tsx b/apps/main/src/dex/components/pool-alert-messages.tsx
index c689353888..667dfdeb69 100644
--- a/apps/main/src/dex/components/pool-alert-messages.tsx
+++ b/apps/main/src/dex/components/pool-alert-messages.tsx
@@ -7,7 +7,7 @@ import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces'
const { Spacing } = SizesAndSpaces
-export const MessageWrapper = ({ children }: { children: React.ReactNode }) => (
+export const PoolAlertMessage = ({ children }: { children: React.ReactNode }) => (
{
const params = useParams()
@@ -26,9 +26,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
},
/* TODO: use Typography component instead of p tag */
message: (
-
+
{t`Deposit disabled.`}
-
+
),
})
const geistFinanceAlert = (): PoolAlert => ({
@@ -43,9 +43,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
learnMoreUrl: 'https://twitter.com/geistfinance',
},
message: (
-
+
{t`This pool is in withdraw only mode.`}
-
+
),
})
const yPrismaAlert = (): PoolAlert => {
@@ -60,9 +60,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
isCloseOnTooltipOnly: true,
alertType: 'warning',
message: (
-
+
{t`Deposit disabled.`}
-
+
),
banner: {
title: t`Deprecated Pool`,
@@ -86,7 +86,7 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
learnMoreUrl: 'https://gov.curve.finance/t/kill-gauges-on-all-non-susd-curve-pools-on-ethereum/10033/2',
},
message: (
-
+
Please note that exchanges on synthetix synths are expected to be disabled and users can either withdraw
@@ -108,7 +108,7 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
Please note that sUSD is not involved, so these would be on the other pools sETH, sBTC, sForex ...
-
+
),
})
const ironbankAlert = (): PoolAlert => ({
@@ -120,9 +120,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
subtitle: t`The Ironbank protocol is deprecated. Please do not supply liquidity to this pool.`,
},
message: (
-
+
{t`Deposit disabled.`}
-
+
),
})
const synthetixUsdAlert = (): PoolAlert => ({
@@ -137,9 +137,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
learnMoreUrl: 'https://x.com/synthetix_io/status/1953054538610688198',
},
message: (
-
+
{t`This pool is in withdraw only mode.`}
-
+
),
})
const yieldbasisAlert = (): PoolAlert => ({
@@ -157,13 +157,13 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
learnMoreUrl: 'https://yieldbasis.com',
},
message: (
-
+
Deposit on yieldbasis.com
-
+
),
})
@@ -177,9 +177,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
subtitle: t`USPD has been exploited. This pool has been disabled to prevent new users from loss of funds.`,
},
message: (
-
+
{t`Deposit disabled. We recommend exiting this pool.`}
-
+
),
})
@@ -189,14 +189,14 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
isCloseOnTooltipOnly: true,
isInformationOnlyAndShowInForm: true,
message: (
-
+
Deposit and Swap with wBTC.e will return an error due to an Aave community decision to freeze this asset.{' '}
More details
-
+
),
})
@@ -212,9 +212,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
learnMoreUrl: 'https://hackmd.io/@LlamaRisk/BJzSKHNjn',
},
message: (
-
+
{t`Deposit disabled. We recommend exiting this pool.`}
-
+
),
})
@@ -229,9 +229,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
learnMoreUrl: 'https://twitter.com/CurveFinance/status/1685925429041917952',
},
message: (
-
+
{t`Deposit disabled. We recommend exiting this pool.`}
-
+
),
})
@@ -248,9 +248,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
subtitle: t`This pool has been misconfigured. It has been set to withdraw only. To minimize impact withdraw in balanced proportion instead of single sided.`,
},
message: (
-
+
{t`This pool is in withdraw only mode.`}
-
+
),
})
From 1acfd5d6d50bb086f5854dcd248c70cc667b2b8b Mon Sep 17 00:00:00 2001
From: Pearce
Date: Tue, 16 Dec 2025 17:56:31 +0100
Subject: [PATCH 10/10] fix: re-render pool alert banner on breakpoint change
---
apps/main/src/dex/components/PoolAlertBanner.tsx | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/apps/main/src/dex/components/PoolAlertBanner.tsx b/apps/main/src/dex/components/PoolAlertBanner.tsx
index 1c80f4c343..a1033087a2 100644
--- a/apps/main/src/dex/components/PoolAlertBanner.tsx
+++ b/apps/main/src/dex/components/PoolAlertBanner.tsx
@@ -1,5 +1,6 @@
import { useMemo } from 'react'
import { createPortal } from 'react-dom'
+import { useIsDesktop } from '@ui-kit/hooks/useBreakpoints'
import { useDismissBanner } from '@ui-kit/hooks/useLocalStorage'
import { Banner, BannerProps } from '@ui-kit/shared/ui/Banner'
import { AlertType, PoolAlert } from '../types/main.types'
@@ -25,7 +26,9 @@ export const PoolAlertBanner = ({
alertType: AlertType
}) => {
const { shouldShowBanner, dismissBanner } = useDismissBanner(poolAlertBannerKey, ONE_DAY_MS)
- const portalTarget = useMemo(() => document.getElementsByTagName('header')[0], [])
+ const isDesktop = useIsDesktop()
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- isDesktop triggers re-query when header changes (desktop ↔ mobile)
+ const portalTarget = useMemo(() => document.getElementsByTagName('header')[0], [isDesktop])
const severity = alertTypeToBannerSeverity[alertType]
return (