Skip to content

Commit 6e310b0

Browse files
authored
Merge pull request #6147 from cowprotocol/hotfix/2025-08-12
Hotfix 2025-08-12
2 parents 773e2bb + 33544c2 commit 6e310b0

File tree

28 files changed

+279
-137
lines changed

28 files changed

+279
-137
lines changed

apps/cowswap-frontend/src/common/hooks/useContract.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
} from '@cowprotocol/common-const'
2020
import { getContract } from '@cowprotocol/common-utils'
2121
import { isEns, isProd, isStaging } from '@cowprotocol/common-utils'
22-
import { COW_PROTOCOL_SETTLEMENT_CONTRACT_ADDRESS, SupportedChainId } from '@cowprotocol/cow-sdk'
22+
import { COW_PROTOCOL_SETTLEMENT_CONTRACT_ADDRESS, CowEnv, SupportedChainId } from '@cowprotocol/cow-sdk'
2323
import { useWalletInfo } from '@cowprotocol/wallet'
2424
import { useWalletProvider } from '@cowprotocol/wallet-provider'
2525
import { Contract, ContractInterface } from '@ethersproject/contracts'
@@ -29,7 +29,7 @@ const WETH_CONTRACT_ADDRESS_MAP = Object.fromEntries(
2929
Object.entries(WRAPPED_NATIVE_CURRENCIES).map(([chainId, token]) => [chainId, token.address]),
3030
)
3131

32-
export const ethFlowEnv = isProd || isStaging || isEns ? 'prod' : 'barn'
32+
export const ethFlowEnv: CowEnv = isProd || isStaging || isEns ? 'prod' : 'staging'
3333

3434
export type UseContractResult<T extends Contract = Contract> = {
3535
contract: T | null

apps/cowswap-frontend/src/modules/cowShed/containers/InvalidCoWShedSetup/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { ReactNode } from 'react'
22

33
import { DISCORD_LINK } from '@cowprotocol/common-const'
44
import { ExternalLink, InlineBanner, StatusColorVariant } from '@cowprotocol/ui'
5+
import { useWalletInfo } from '@cowprotocol/wallet'
56

67
import styled from 'styled-components/macro'
78

@@ -22,10 +23,13 @@ const Wrapper = styled.div`
2223
`
2324

2425
export function InvalidCoWShedSetup(): ReactNode {
26+
const { chainId } = useWalletInfo()
2527
const proxyInfo = useCurrentAccountProxy()?.data
2628
const isProxySetupValid = proxyInfo?.isProxySetupValid
2729

28-
if (isProxySetupValid !== false) return null
30+
if (isProxySetupValid !== false || proxyInfo?.chainId !== chainId) return null
31+
32+
console.debug('[CoWShed validation] InvalidCoWShedSetup', proxyInfo)
2933

3034
return (
3135
<Wrapper>

apps/cowswap-frontend/src/modules/cowShed/hooks/useCurrentAccountProxy.ts

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import { ZERO_ADDRESS } from '@cowprotocol/common-const'
12
import { areAddressesEqual, getContract } from '@cowprotocol/common-utils'
23
import { implementationAddress } from '@cowprotocol/contracts'
3-
import type { CowShedHooks } from '@cowprotocol/cow-sdk'
4+
import type { CowShedHooks, SupportedChainId } from '@cowprotocol/cow-sdk'
45
import { useWalletInfo } from '@cowprotocol/wallet'
56
import { useWalletProvider } from '@cowprotocol/wallet-provider'
67
import type { BaseContract } from '@ethersproject/contracts'
@@ -28,6 +29,7 @@ interface CoWShedContract extends BaseContract {
2829
}
2930

3031
interface ProxyAndAccount {
32+
chainId: SupportedChainId
3133
proxyAddress: string
3234
account: string
3335
isProxyDeployed: boolean
@@ -60,18 +62,19 @@ export function useCurrentAccountProxy(): SWRResponse<ProxyAndAccount | undefine
6062

6163
return useSWR(
6264
account && provider && cowShedHooks ? [account, chainId, 'useCurrentAccountProxyAddress'] : null,
63-
async ([account]) => {
65+
async ([account, chainId]) => {
6466
if (!provider || !cowShedHooks) return
6567

6668
const proxyAddress = cowShedHooks.proxyOf(account)
6769
const proxyCode = await provider.getCode(proxyAddress)
6870
const isProxyDeployed = !!proxyCode && proxyCode !== '0x'
6971

7072
const isProxySetupValid = isProxyDeployed
71-
? await getIsProxySetupValid(proxyAddress, provider, cowShedHooks)
73+
? await getIsProxySetupValid(chainId, proxyAddress, provider, cowShedHooks)
7274
: true
7375

7476
return {
77+
chainId,
7578
proxyAddress,
7679
account,
7780
isProxyDeployed,
@@ -87,18 +90,41 @@ export function useCurrentAccountProxyAddress(): string | undefined {
8790
}
8891

8992
async function getIsProxySetupValid(
93+
chainId: SupportedChainId,
9094
proxyAddress: string,
9195
provider: Web3Provider,
9296
cowShedHooks: CowShedHooks,
9397
): Promise<boolean | null> {
98+
const providerNetwork = await provider.getNetwork()
99+
100+
// Skip validation if network mismatch
101+
if (providerNetwork.chainId !== chainId) return true
102+
103+
console.debug('[CoWShed validation] networks', {
104+
providerNetwork,
105+
chainId,
106+
})
107+
94108
const shedContract = getContract(proxyAddress, COW_SHED_ABI, provider) as CoWShedContract
95109
const expectedImplementation = cowShedHooks.getImplementationAddress()
96110
const expectedFactoryAddress = cowShedHooks.getFactoryAddress()
97111

98112
try {
99113
const implementation = await implementationAddress(provider, proxyAddress)
100114

101-
if (!areAddressesEqual(implementation, expectedImplementation)) return false
115+
// If implementation is zero, it means proxy is not deployed and is considered as valid
116+
if (areAddressesEqual(implementation, ZERO_ADDRESS)) {
117+
return true
118+
}
119+
120+
if (!areAddressesEqual(implementation, expectedImplementation)) {
121+
console.debug('[CoWShed validation] implementation', {
122+
implementation,
123+
expectedImplementation,
124+
})
125+
126+
return false
127+
}
102128
} catch (e) {
103129
console.error('[CoWShed validation] Could not get implementationAddress', e)
104130

@@ -108,7 +134,16 @@ async function getIsProxySetupValid(
108134
try {
109135
const trustedExecutor = await shedContract.callStatic.trustedExecutor()
110136

111-
return areAddressesEqual(trustedExecutor, expectedFactoryAddress)
137+
const isTrustedExecutorValid = areAddressesEqual(trustedExecutor, expectedFactoryAddress)
138+
139+
if (!isTrustedExecutorValid) {
140+
console.debug('[CoWShed validation] trustedExecutor', {
141+
trustedExecutor,
142+
expectedFactoryAddress,
143+
})
144+
}
145+
146+
return isTrustedExecutorValid
112147
} catch (e) {
113148
console.error('[CoWShed validation] Could not get trustedExecutor', e)
114149

apps/cowswap-frontend/src/modules/ordersTable/hooks/useTokenAllowances.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,16 @@ export function useTokenAllowances(tokenAddresses: string[]): {
4040
account,
4141
)
4242

43+
const results = data?.results
44+
4345
const state = useMemo(() => {
44-
if (!data) return
46+
if (!results?.length) return
4547

46-
const res = tokenAddresses.reduce<AllowancesState>((acc, address, index) => {
47-
acc[address.toLowerCase()] = data[index]?.[0]
48+
return tokenAddresses.reduce<AllowancesState>((acc, address, index) => {
49+
acc[address.toLowerCase()] = results[index]?.[0]
4850
return acc
4951
}, {})
50-
51-
return res
52-
}, [tokenAddresses, data])
52+
}, [tokenAddresses, results])
5353

5454
return useMemo(() => ({ state, isLoading }), [state, isLoading])
5555
}

apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersAuthMulticall.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,20 @@ const SWR_CONFIG = { refreshInterval: ms`30s` }
1414
export function useTwapOrdersAuthMulticall(
1515
safeAddress: string,
1616
composableCowContract: ComposableCoW,
17-
ordersInfo: TwapOrderInfo[]
17+
ordersInfo: TwapOrderInfo[],
1818
): TwapOrdersAuthResult | null {
1919
const input = useMemo(() => {
2020
return ordersInfo.map(({ id }) => [safeAddress, id])
2121
}, [safeAddress, ordersInfo])
2222

23-
const { data: loadedResults, isLoading } = useSingleContractMultipleData<[boolean]>(
23+
const { data, isLoading } = useSingleContractMultipleData<[boolean]>(
2424
composableCowContract,
2525
'singleOrders',
2626
input,
2727
MULTICALL_OPTIONS,
28-
SWR_CONFIG
28+
SWR_CONFIG,
2929
)
30+
const loadedResults = data?.results
3031

3132
return useMemo(() => {
3233
if (ordersInfo.length === 0) return EMPTY_AUTH_RESULT

apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/index.tsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useAtom, useAtomValue, useSetAtom } from 'jotai'
2-
import React, { useCallback, useEffect, useMemo, useState } from 'react'
2+
import React, { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'
33

44
import { useNativeTokensBalances } from '@cowprotocol/balances-and-allowances'
55
import { NATIVE_CURRENCIES } from '@cowprotocol/common-const'
@@ -24,10 +24,7 @@ import * as styledEl from './styled'
2424

2525
const EMPTY_BALANCES = {}
2626

27-
// TODO: Break down this large function into smaller functions
28-
// TODO: Add proper return type annotation
29-
// eslint-disable-next-line max-lines-per-function, @typescript-eslint/explicit-function-return-type
30-
export function AccountSelectorModal() {
27+
export function AccountSelectorModal(): ReactNode {
3128
const { chainId } = useWalletInfo()
3229
const { isOpen } = useAtomValue(accountSelectorModalAtom)
3330
const closeModal = useSetAtom(toggleAccountSelectorModalAtom)
@@ -43,7 +40,7 @@ export function AccountSelectorModal() {
4340

4441
const [accountsList, setAccountsList] = useState<string[] | null>(null)
4542

46-
const nativeTokensBalances = useNativeTokensBalances(accountsList || undefined)
43+
const nativeTokensBalances = useNativeTokensBalances(chainId, accountsList || undefined)
4744

4845
const balances = useMemo(() => {
4946
if (!nativeTokensBalances) return EMPTY_BALANCES
@@ -57,7 +54,7 @@ export function AccountSelectorModal() {
5754
}
5855
return acc
5956
},
60-
{}
57+
{},
6158
)
6259
}, [nativeTokensBalances, nativeToken])
6360

@@ -76,7 +73,7 @@ export function AccountSelectorModal() {
7673

7774
addSnackbar({ content: <Trans>{walletName} account changed</Trans>, id: 'account-changed', icon: 'success' })
7875
},
79-
[walletName, addSnackbar, setHwAccountIndex, closeModal]
76+
[walletName, addSnackbar, setHwAccountIndex, closeModal],
8077
)
8178

8279
useEffect(() => {

apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/useIsAnySwapAffectedUser.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const SWR_CONFIG: SWRConfiguration = {
3131

3232
export function useIsAnySwapAffectedUser(): boolean {
3333
const { chainId, account } = useWalletInfo()
34-
const { data: allowances } = useMultipleContractSingleData<[BigNumber]>(
34+
const { data } = useMultipleContractSingleData<[BigNumber]>(
3535
chainId,
3636
AFFECTED_TOKENS,
3737
ERC20_INTERFACE,
@@ -42,6 +42,8 @@ export function useIsAnySwapAffectedUser(): boolean {
4242
`useIsAnySwapAffectedUser`,
4343
)
4444

45+
const allowances = data?.results
46+
4547
return useMemo(() => {
4648
// The error affects Mainnet
4749
if (chainId !== ChainId.MAINNET || !allowances) {

apps/cowswap-frontend/src/utils/orderUtils/getOrderFilledAmount.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { ZERO_BIG_NUMBER } from '@cowprotocol/common-const'
21
import { isSellOrder } from '@cowprotocol/common-utils'
32

43
import BigNumber from 'bignumber.js'
54

65
import { Order } from 'legacy/state/orders/actions'
76

7+
const ZERO_BIG_NUMBER = new BigNumber(0)
8+
89
/**
910
* Get order filled amount, both as raw amount (in atoms) and as percentage (from 0 to 1)
1011
*
@@ -25,7 +26,7 @@ export function getOrderFilledAmount(order: Order): FilledAmountResult {
2526

2627
if (isSellOrder(order.kind)) {
2728
executedAmount = new BigNumber(order.apiAdditionalInfo.executedSellAmount).minus(
28-
order.apiAdditionalInfo?.executedFeeAmount
29+
order.apiAdditionalInfo?.executedFeeAmount,
2930
)
3031
totalAmount = new BigNumber(order.sellAmount.toString())
3132
} else {

apps/cowswap-frontend/src/utils/orderUtils/getOrderSurplus.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// Util functions that only pertain to/deal with operator API related stuff
2-
import { ZERO_BIG_NUMBER } from '@cowprotocol/common-const'
31
import { isSellOrder } from '@cowprotocol/common-utils'
42

53
import BigNumber from 'bignumber.js'
@@ -9,6 +7,8 @@ import { Order } from 'legacy/state/orders/actions'
97

108
import { getOrderExecutedAmounts } from './getOrderExecutedAmounts'
119

10+
const ZERO_BIG_NUMBER = new BigNumber(0)
11+
1212
type Surplus = {
1313
amount: BigNumber
1414
percentage: BigNumber

libs/abis/src/abis/Multicall3.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
11
[
2+
{
3+
"inputs": [],
4+
"name": "getBlockNumber",
5+
"outputs": [
6+
{
7+
"internalType": "uint256",
8+
"name": "blockNumber",
9+
"type": "uint256"
10+
}
11+
],
12+
"stateMutability": "view",
13+
"type": "function"
14+
},
215
{
316
"inputs": [
417
{

0 commit comments

Comments
 (0)