Skip to content

Commit 429dde2

Browse files
kaladinlightclaude
andauthored
fix(contracts): drop address-keyed contract cache (#12786)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 35b1fb5 commit 429dde2

11 files changed

Lines changed: 70 additions & 231 deletions

File tree

‎packages/contracts/src/constants.ts‎

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
11
import type { Address } from 'viem'
2-
import { erc20Abi } from 'viem'
3-
4-
import { EVERGREEN_FARMING_ABI } from './abis/evergreenFarming'
5-
import { FARMING_ABI } from './abis/farming'
6-
import { I_UNISWAP_V2_PAIR_ABI } from './abis/iUniswapV2Pair'
7-
import { THORCHAIN_ROUTER_ABI } from './abis/thorchainRouter'
8-
import { UNISWAP_V2_ROUTER_02_ABI } from './abis/uniswapV2Router02'
9-
import { ContractType } from './types'
102

113
export const WETH_TOKEN_CONTRACT = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'
12-
export const FOX_TOKEN_CONTRACT = '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d'
134

145
// Staking contract addresses as string literals
156
export const ETH_FOX_STAKING_V1_CONTRACT = '0xdd80e21669a664bce83e3ad9a0d74f8dad5d9e72' as const
@@ -61,30 +52,6 @@ export const RFOX_ETH_PROXY_CONTRACT: Address = '0x7AC9c77263473A9e1DC9621F97b88
6152
export const RFOX_REWARD_RATE = 1n * 10n ** 27n
6253
export const RFOX_WAD = 1n * 10n ** 18n
6354

64-
export const CONTRACT_ADDRESS_TO_ABI = {
65-
[ETH_FOX_POOL_CONTRACT]: I_UNISWAP_V2_PAIR_ABI,
66-
[ETH_FOX_STAKING_V1_CONTRACT]: FARMING_ABI,
67-
[ETH_FOX_STAKING_V2_CONTRACT]: FARMING_ABI,
68-
[ETH_FOX_STAKING_V3_CONTRACT]: FARMING_ABI,
69-
[ETH_FOX_STAKING_V4_CONTRACT]: FARMING_ABI,
70-
[ETH_FOX_STAKING_V5_CONTRACT]: FARMING_ABI,
71-
[ETH_FOX_STAKING_V6_CONTRACT]: FARMING_ABI,
72-
[ETH_FOX_STAKING_V7_CONTRACT]: FARMING_ABI,
73-
[ETH_FOX_STAKING_V8_CONTRACT]: FARMING_ABI,
74-
[ETH_FOX_STAKING_V9_CONTRACT]: FARMING_ABI,
75-
[ETH_FOX_STAKING_EVERGREEN_CONTRACT]: EVERGREEN_FARMING_ABI,
76-
[FOX_TOKEN_CONTRACT]: erc20Abi,
77-
[UNISWAP_V2_ROUTER_02_CONTRACT_MAINNET]: UNISWAP_V2_ROUTER_02_ABI,
78-
// THOR Router Mainnet
79-
[THOR_ROUTER_CONTRACT_MAINNET]: THORCHAIN_ROUTER_ABI,
80-
} as const
81-
82-
export const CONTRACT_TYPE_TO_ABI = {
83-
[ContractType.UniV2Pair]: I_UNISWAP_V2_PAIR_ABI,
84-
[ContractType.ERC20]: erc20Abi,
85-
[ContractType.ThorRouter]: THORCHAIN_ROUTER_ABI,
86-
} as const
87-
8855
// 0x proxy contracts - all EVM chains except Optimism have the same address
8956
export const ZRX_ETHEREUM_PROXY_CONTRACT = '0xDef1C0ded9bec7F1a1670819833240f027b25EfF'
9057
export const ZRX_OPTIMISM_PROXY_CONTRACT = '0xDEF1ABE32c034e558Cdd535791643C58a13aCC10'

‎packages/contracts/src/contractManager.ts‎

Lines changed: 26 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,49 @@
1-
import type { AssetId, ChainId } from '@shapeshiftoss/caip'
1+
import type { AssetId } from '@shapeshiftoss/caip'
22
import { fromAssetId, fromChainId } from '@shapeshiftoss/caip'
3-
import type { PartialRecord } from '@shapeshiftoss/types'
4-
import { KnownChainIds } from '@shapeshiftoss/types'
53
import { Pair, Token, TokenAmount } from '@uniswap/sdk'
6-
import assert from 'assert'
74
import memoize from 'lodash/memoize'
8-
import type { Address } from 'viem'
5+
import type { Address, GetContractReturnType, PublicClient } from 'viem'
96
import { erc20Abi, getAddress, getContract } from 'viem'
107

11-
import { CONTRACT_ADDRESS_TO_ABI, CONTRACT_TYPE_TO_ABI } from './constants'
12-
import type {
13-
KnownContract,
14-
KnownContractAbiByAddress,
15-
KnownContractAddress,
16-
KnownContractByAddress,
17-
KnownContractByType,
18-
} from './types'
19-
import { ContractType } from './types'
20-
import { viemClientByChainId, viemEthMainnetClient } from './viemClient'
8+
import { EVERGREEN_FARMING_ABI, FARMING_ABI, I_UNISWAP_V2_PAIR_ABI } from './abis'
9+
import { ETH_FOX_POOL_CONTRACT, ETH_FOX_STAKING_EVERGREEN_CONTRACT } from './constants'
10+
import type { FoxEthStakingContractAbi, FoxEthStakingContractAddress } from './types'
11+
import { assertGetViemClient, viemEthMainnetClient } from './viemClient'
2112

22-
const definedContracts: PartialRecord<Address, KnownContract> = {}
23-
24-
export const getOrCreateContractByAddress: <A extends KnownContractAddress>(
25-
address: A,
26-
) => KnownContractByAddress<A> = <A extends KnownContractAddress>(
27-
address: A,
28-
): KnownContractByAddress<A> => {
29-
const checksumAddress = getAddress(address) as A
30-
const definedContract = definedContracts[checksumAddress]
31-
if (definedContract !== undefined) {
32-
return definedContract as unknown as KnownContractByAddress<A>
33-
}
34-
const contractAbi: KnownContractAbiByAddress<A> = CONTRACT_ADDRESS_TO_ABI[address]
35-
36-
const contract = getContract({
37-
abi: contractAbi,
38-
address: checksumAddress,
13+
export const getFoxEthStakingContract = (
14+
address: FoxEthStakingContractAddress,
15+
): GetContractReturnType<FoxEthStakingContractAbi, PublicClient, Address> =>
16+
getContract({
17+
abi: address === ETH_FOX_STAKING_EVERGREEN_CONTRACT ? EVERGREEN_FARMING_ABI : FARMING_ABI,
18+
address: getAddress(address),
3919
client: viemEthMainnetClient,
4020
})
41-
definedContracts[checksumAddress] = contract as unknown as KnownContract
42-
return contract as KnownContractByAddress<A>
43-
}
4421

45-
export const getOrCreateContractByType: <A extends KnownContractAddress, T extends ContractType>({
46-
address,
47-
type,
48-
chainId,
49-
}: {
50-
address: string | Address
51-
type: T
52-
chainId: ChainId
53-
}) => KnownContractByType<A, T> = <A extends KnownContractAddress, T extends ContractType>({
54-
address,
55-
type,
56-
chainId,
57-
}: {
58-
address: string | Address
59-
type: T
60-
chainId: ChainId
61-
}): KnownContractByType<A, T> => {
62-
const checksumAddress = getAddress(address) as A
63-
const definedContract = definedContracts[checksumAddress]
64-
if (definedContract !== undefined) {
65-
return definedContract as unknown as KnownContractByType<A, T>
66-
}
67-
68-
const publicClient = viemClientByChainId[chainId]
69-
assert(publicClient !== undefined, `no public client found for chainId '${chainId}'`)
70-
71-
const contract = getContract({
72-
abi: CONTRACT_TYPE_TO_ABI[type],
73-
address: checksumAddress,
74-
client: publicClient,
22+
export const getEthFoxPoolContract = (): GetContractReturnType<
23+
typeof I_UNISWAP_V2_PAIR_ABI,
24+
PublicClient,
25+
Address
26+
> =>
27+
getContract({
28+
abi: I_UNISWAP_V2_PAIR_ABI,
29+
address: ETH_FOX_POOL_CONTRACT,
30+
client: viemEthMainnetClient,
7531
})
76-
definedContracts[checksumAddress] = contract as unknown as KnownContract
77-
return contract as unknown as KnownContractByType<A, T>
78-
}
7932

8033
const getUniV2PairTokens = memoize(async (pairAssetId: AssetId) => {
8134
const { assetReference, chainId } = fromAssetId(pairAssetId)
82-
const pair = getOrCreateContractByType({
35+
const client = assertGetViemClient(chainId)
36+
const pair = getContract({
37+
abi: I_UNISWAP_V2_PAIR_ABI,
8338
address: getAddress(assetReference),
84-
type: ContractType.UniV2Pair,
85-
chainId: KnownChainIds.EthereumMainnet,
39+
client,
8640
})
8741

8842
const [token0Address, token1Address] = await Promise.all([pair.read.token0(), pair.read.token1()])
8943

9044
const [decimals0, decimals1] = await Promise.all(
9145
[token0Address, token1Address].map(address =>
92-
viemEthMainnetClient.readContract({ address, abi: erc20Abi, functionName: 'decimals' }),
46+
client.readContract({ address, abi: erc20Abi, functionName: 'decimals' }),
9347
),
9448
)
9549

‎packages/contracts/src/types.ts‎

Lines changed: 1 addition & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,5 @@
1-
import type { Address, GetContractReturnType, PublicClient } from 'viem'
2-
31
import type { EVERGREEN_FARMING_ABI, FARMING_ABI } from './abis'
4-
import type {
5-
CONTRACT_ADDRESS_TO_ABI,
6-
CONTRACT_TYPE_TO_ABI,
7-
ETH_FOX_POOL_CONTRACT,
8-
FOX_TOKEN_CONTRACT,
9-
foxEthStakingContractAddresses,
10-
THOR_ROUTER_CONTRACT_MAINNET,
11-
UNISWAP_V2_ROUTER_02_CONTRACT_MAINNET,
12-
} from './constants'
13-
14-
export enum ContractType {
15-
UniV2Pair = 'UniV2Pair',
16-
ERC20 = 'ERC20',
17-
ThorRouter = 'ThorRouter',
18-
}
19-
20-
export type KnownContractAbiByAddress<T extends KnownContractAddress> =
21-
(typeof CONTRACT_ADDRESS_TO_ABI)[T]
22-
export type KnownContractAbiByType<T extends ContractType> = (typeof CONTRACT_TYPE_TO_ABI)[T]
23-
24-
export type KnownContractByAddress<T extends KnownContractAddress> = GetContractReturnType<
25-
KnownContractAbiByAddress<T>,
26-
PublicClient,
27-
T
28-
>
29-
30-
export type KnownContract = KnownContractByAddress<KnownContractAddress>
31-
32-
export type KnownContractByType<
33-
A extends KnownContractAddress,
34-
T extends ContractType,
35-
> = GetContractReturnType<KnownContractAbiByType<T>, PublicClient, A>
36-
37-
export type KnownContractAddress =
38-
| typeof ETH_FOX_POOL_CONTRACT
39-
| FoxEthStakingContractAddress
40-
| typeof FOX_TOKEN_CONTRACT
41-
| typeof UNISWAP_V2_ROUTER_02_CONTRACT_MAINNET
42-
| typeof THOR_ROUTER_CONTRACT_MAINNET
43-
44-
export type DefinedContract = {
45-
contract: KnownContractByAddress<KnownContractAddress>
46-
address: KnownContractAddress
47-
}
2+
import type { foxEthStakingContractAddresses } from './constants'
483

494
export type FoxEthStakingContractAddress = (typeof foxEthStakingContractAddresses)[number]
505
export type FoxEthStakingContractAbi = typeof FARMING_ABI | typeof EVERGREEN_FARMING_ABI
51-
export type FoxEthStakingContract<T extends FoxEthStakingContractAbi> = T extends typeof FARMING_ABI
52-
? GetContractReturnType<typeof FARMING_ABI, PublicClient, Address>
53-
: GetContractReturnType<typeof EVERGREEN_FARMING_ABI, PublicClient, Address>

‎src/features/defi/providers/fox-farming/hooks/useFoxFarming.ts‎

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { ethAssetId, ethChainId, fromAccountId } from '@shapeshiftoss/caip'
22
import { CONTRACT_INTERACTION, evm } from '@shapeshiftoss/chain-adapters'
33
import type { FoxEthStakingContractAddress } from '@shapeshiftoss/contracts'
4-
import { ETH_FOX_POOL_CONTRACT, getOrCreateContractByAddress } from '@shapeshiftoss/contracts'
4+
import { getEthFoxPoolContract, getFoxEthStakingContract } from '@shapeshiftoss/contracts'
55
import { isGridPlus, supportsETH } from '@shapeshiftoss/hdwallet-core/wallet'
66
import { isTrezor } from '@shapeshiftoss/hdwallet-trezor'
77
import { BigAmount } from '@shapeshiftoss/utils'
8-
import { useQuery } from '@tanstack/react-query'
98
import { useCallback, useMemo } from 'react'
109
import { encodeFunctionData, getAddress, maxUint256 } from 'viem'
1110

@@ -26,7 +25,7 @@ type UseFoxFarmingOptions = {
2625
skip?: boolean
2726
}
2827

29-
const uniV2LPContract = getOrCreateContractByAddress(ETH_FOX_POOL_CONTRACT)
28+
const uniV2LPContract = getEthFoxPoolContract()
3029

3130
/**
3231
* useFoxFarming hook
@@ -53,7 +52,7 @@ export const useFoxFarming = (
5352
const adapter = useMemo(() => assertGetEvmChainAdapter(ethChainId), [])
5453

5554
const foxFarmingContract = useMemo(
56-
() => getOrCreateContractByAddress(contractAddress),
55+
() => getFoxEthStakingContract(contractAddress),
5756
[contractAddress],
5857
)
5958

@@ -375,12 +374,6 @@ export const useFoxFarming = (
375374
skipDeviceDerivation,
376375
])
377376

378-
const periodFinishQuery = useQuery({
379-
queryKey: ['getPeriodFinish'],
380-
queryFn: () => foxFarmingContract.read.periodFinish(),
381-
enabled: !!foxFarmingContract,
382-
})
383-
384377
return {
385378
allowance,
386379
approve,
@@ -391,7 +384,6 @@ export const useFoxFarming = (
391384
stake,
392385
unstake,
393386
claimRewards,
394-
periodFinishQuery,
395387
foxFarmingContract,
396388
skip,
397389
}

‎src/hooks/queries/useApprovalFees.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export const useApprovalFees = ({
6262
}
6363

6464
if (isEvmChainId(chainId)) {
65-
return getApproveContractData({ approvalAmountCryptoBaseUnit, chainId, spender, to })
65+
return getApproveContractData({ approvalAmountCryptoBaseUnit, spender })
6666
}
6767
}, [approvalAmountCryptoBaseUnit, chainId, enabled, spender, to])
6868

‎src/lib/utils/evm/approve.ts‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ export const approve = async ({
2525
const data = getApproveContractData({
2626
approvalAmountCryptoBaseUnit: amountCryptoBaseUnit,
2727
spender,
28-
to,
29-
chainId,
3028
})
3129

3230
const buildCustomTxInput = await createBuildCustomTxInput({

‎src/lib/utils/evm/index.ts‎

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import type { AccountId, ChainId } from '@shapeshiftoss/caip'
22
import { CHAIN_NAMESPACE, fromAccountId } from '@shapeshiftoss/caip'
33
import type { ContractInteraction, EvmChainAdapter, SignTx } from '@shapeshiftoss/chain-adapters'
44
import { evm, evmChainIds, isEvmChainId } from '@shapeshiftoss/chain-adapters'
5-
import { ContractType, getOrCreateContractByType } from '@shapeshiftoss/contracts'
5+
import { assertGetViemClient } from '@shapeshiftoss/contracts'
66
import type { HDWallet } from '@shapeshiftoss/hdwallet-core'
77
import { supportsETH } from '@shapeshiftoss/hdwallet-core/wallet'
88
import type { EvmChainId, KnownChainIds } from '@shapeshiftoss/types'
9-
import { encodeFunctionData, getAddress } from 'viem'
9+
import { encodeFunctionData, erc20Abi, getAddress } from 'viem'
1010

1111
import { getSupportedChainIdsByChainNamespace } from '..'
1212

@@ -15,9 +15,7 @@ import type { PartialFields } from '@/lib/types'
1515

1616
type GetApproveContractDataArgs = {
1717
approvalAmountCryptoBaseUnit: string
18-
to: string
1918
spender: string
20-
chainId: ChainId
2119
}
2220

2321
type BuildArgs = {
@@ -153,18 +151,10 @@ export const signAndBroadcast = async ({
153151

154152
export const getApproveContractData = ({
155153
approvalAmountCryptoBaseUnit,
156-
to,
157154
spender,
158-
chainId,
159155
}: GetApproveContractDataArgs): string => {
160-
const address = getAddress(to)
161-
const contract = getOrCreateContractByType({
162-
address,
163-
type: ContractType.ERC20,
164-
chainId,
165-
})
166156
const data = encodeFunctionData({
167-
abi: contract.abi,
157+
abi: erc20Abi,
168158
functionName: 'approve',
169159
args: [getAddress(spender), BigInt(approvalAmountCryptoBaseUnit)],
170160
})
@@ -177,13 +167,12 @@ export const getErc20Allowance = async ({
177167
spender,
178168
chainId,
179169
}: GetErc20AllowanceArgs): Promise<string> => {
180-
const contract = getOrCreateContractByType({
181-
address,
182-
type: ContractType.ERC20,
183-
chainId,
170+
const allowance = await assertGetViemClient(chainId).readContract({
171+
address: getAddress(address),
172+
abi: erc20Abi,
173+
functionName: 'allowance',
174+
args: [getAddress(from), getAddress(spender)],
184175
})
185-
const allowance = await contract.read.allowance([getAddress(from), getAddress(spender)])
186-
// TODO(gomes): fix types
187176
return allowance.toString()
188177
}
189178

‎src/pages/Fox/components/FoxFarming.tsx‎

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ import {
1515
Text as CText,
1616
} from '@chakra-ui/react'
1717
import { ethChainId, fromAccountId, fromAssetId } from '@shapeshiftoss/caip'
18-
import { ETH_FOX_STAKING_EVERGREEN_CONTRACT } from '@shapeshiftoss/contracts'
18+
import {
19+
ETH_FOX_STAKING_EVERGREEN_CONTRACT,
20+
getFoxEthStakingContract,
21+
} from '@shapeshiftoss/contracts'
1922
import { BigAmount } from '@shapeshiftoss/utils'
2023
import { useQuery, useQueryClient } from '@tanstack/react-query'
2124
import dayjs from 'dayjs'
@@ -31,7 +34,6 @@ import { Amount } from '@/components/Amount/Amount'
3134
import { Text } from '@/components/Text'
3235
import { WalletActions } from '@/context/WalletProvider/actions'
3336
import { DefiAction } from '@/features/defi/contexts/DefiManagerProvider/DefiCommon'
34-
import { useFoxFarming } from '@/features/defi/providers/fox-farming/hooks/useFoxFarming'
3537
import { useFeatureFlag } from '@/hooks/useFeatureFlag/useFeatureFlag'
3638
import { useIsWalletConnected } from '@/hooks/useIsWalletConnected/useIsWalletConnected'
3739
import { useWallet } from '@/hooks/useWallet/useWallet'
@@ -124,12 +126,13 @@ export const FoxFarming = () => {
124126
)
125127

126128
const {
127-
periodFinishQuery: {
128-
data: periodFinish,
129-
isLoading: isGetPeriodFinishQueryLoading,
130-
isFetching: isGetPeriodFetchingLoading,
131-
},
132-
} = useFoxFarming(ETH_FOX_STAKING_EVERGREEN_CONTRACT)
129+
data: periodFinish,
130+
isLoading: isGetPeriodFinishQueryLoading,
131+
isFetching: isGetPeriodFetchingLoading,
132+
} = useQuery({
133+
queryKey: ['getPeriodFinish', ETH_FOX_STAKING_EVERGREEN_CONTRACT],
134+
queryFn: () => getFoxEthStakingContract(ETH_FOX_STAKING_EVERGREEN_CONTRACT).read.periodFinish(),
135+
})
133136

134137
const isGetPeriodFinishLoading = useMemo(
135138
() => isGetPeriodFinishQueryLoading || isGetPeriodFetchingLoading,

0 commit comments

Comments
 (0)