diff --git a/src/components/MultiHopTrade/components/TradeInput/TradeInput.tsx b/src/components/MultiHopTrade/components/TradeInput/TradeInput.tsx index 1e79bd27f1c..9cf7e025d62 100644 --- a/src/components/MultiHopTrade/components/TradeInput/TradeInput.tsx +++ b/src/components/MultiHopTrade/components/TradeInput/TradeInput.tsx @@ -273,10 +273,10 @@ export const TradeInput = ({ isCompact, tradeInputRef }: TradeInputProps) => { const receiveAddress = manualReceiveAddress ?? walletReceiveAddress const { data: _isSmartContractSellAddress, isLoading: isSellAddressByteCodeLoading } = - useIsSmartContractAddress(userAddress, sellAsset.chainId) + useIsSmartContractAddress(userAddress) const { data: _isSmartContractReceiveAddress, isLoading: isReceiveAddressByteCodeLoading } = - useIsSmartContractAddress(receiveAddress ?? '', buyAsset.chainId) + useIsSmartContractAddress(receiveAddress ?? '') const disableSmartContractSwap = useMemo(() => { // Swappers other than THORChain shouldn't be affected by this limitation diff --git a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx index c515342a8e7..c347dce8ec7 100644 --- a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx +++ b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx @@ -334,7 +334,7 @@ export const Confirm: React.FC = ({ accountId, onNext }) => { ) const { data: _isSmartContractAddress, isLoading: isAddressByteCodeLoading } = - useIsSmartContractAddress(fromAddress ?? '', chainId) + useIsSmartContractAddress(fromAddress ?? '') const disableSmartContractDeposit = useMemo(() => { // This is either a smart contract address, or the bytecode is still loading - disable confirm diff --git a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx index eda7a31cc98..98e7c16a168 100644 --- a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx +++ b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx @@ -451,7 +451,7 @@ export const Confirm: React.FC = ({ accountId, onNext }) => { ) const { data: _isSmartContractAddress, isLoading: isAddressByteCodeLoading } = - useIsSmartContractAddress(userAddress, chainId) + useIsSmartContractAddress(userAddress) const disableSmartContractWithdraw = useMemo(() => { // This is either a smart contract address, or the bytecode is still loading - disable confirm diff --git a/src/hooks/useIsSmartContractAddress/useIsSmartContractAddress.ts b/src/hooks/useIsSmartContractAddress/useIsSmartContractAddress.ts index 73b097944ce..cd515c0acb0 100644 --- a/src/hooks/useIsSmartContractAddress/useIsSmartContractAddress.ts +++ b/src/hooks/useIsSmartContractAddress/useIsSmartContractAddress.ts @@ -1,26 +1,25 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import { isEvmChainId } from '@shapeshiftoss/chain-adapters' -import { skipToken, useQuery } from '@tanstack/react-query' +import { useQuery } from '@tanstack/react-query' import { useMemo } from 'react' import { isSmartContractAddress } from 'lib/address/utils' -export const useIsSmartContractAddress = (address: string, chainId: ChainId) => { +export const useIsSmartContractAddress = (address: string) => { // Lowercase the address to ensure proper caching const userAddress = useMemo(() => address.toLowerCase(), [address]) - const query = useQuery({ - queryKey: [ - 'isSmartContractAddress', - { - userAddress, - chainId, - }, - ], - queryFn: - isEvmChainId(chainId) && Boolean(userAddress.length) - ? () => isSmartContractAddress(userAddress, chainId) - : skipToken, - }) + const queryParams = useMemo(() => { + return { + queryKey: [ + 'isSmartContractAddress', + { + userAddress, + }, + ], + queryFn: () => isSmartContractAddress(userAddress), + enabled: Boolean(userAddress.length), + } + }, [userAddress]) + + const query = useQuery(queryParams) return query } diff --git a/src/lib/address/utils.ts b/src/lib/address/utils.ts index 40cc648f93d..527e1ba1192 100644 --- a/src/lib/address/utils.ts +++ b/src/lib/address/utils.ts @@ -1,16 +1,10 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import { isEvmChainId } from '@shapeshiftoss/chain-adapters' import { isAddress } from 'viem' import { getEthersProvider } from 'lib/ethersProviderSingleton' export const isEthAddress = (address: string): boolean => /^0x[0-9A-Fa-f]{40}$/.test(address) -export const isSmartContractAddress = async ( - address: string, - chainId: ChainId, -): Promise => { +export const isSmartContractAddress = async (address: string): Promise => { if (!isAddress(address)) return false - if (!isEvmChainId(chainId)) return false - const bytecode = await getEthersProvider(chainId).getCode(address) + const bytecode = await getEthersProvider().getCode(address) return bytecode !== '0x' } diff --git a/src/lib/ethersProviderSingleton.ts b/src/lib/ethersProviderSingleton.ts index 16995f5b9eb..5e65bb76738 100644 --- a/src/lib/ethersProviderSingleton.ts +++ b/src/lib/ethersProviderSingleton.ts @@ -35,7 +35,9 @@ export const rpcUrlByChainId = (chainId: EvmChainId): string => { const ethersProviders: Map = new Map() const ethersV5Providers: Map = new Map() -export const getEthersProvider = (chainId: EvmChainId): JsonRpcProvider => { +export const getEthersProvider = ( + chainId: EvmChainId = KnownChainIds.EthereumMainnet, +): JsonRpcProvider => { if (!ethersProviders.has(chainId)) { const provider = new JsonRpcProvider(rpcUrlByChainId(chainId), undefined, { staticNetwork: true, diff --git a/src/lib/fees/utils.test.ts b/src/lib/fees/utils.test.ts index edb28844c1a..c9ea5a2cb0c 100644 --- a/src/lib/fees/utils.test.ts +++ b/src/lib/fees/utils.test.ts @@ -1,4 +1,3 @@ -import { KnownChainIds } from '@shapeshiftoss/types' import type { Block } from 'ethers' import { beforeEach, describe, expect, it, vi } from 'vitest' import { getEthersProvider } from 'lib/ethersProviderSingleton' @@ -7,7 +6,7 @@ import { findClosestFoxDiscountDelayBlockNumber } from './utils' vi.unmock('ethers') -const getBlockSpy = vi.spyOn(getEthersProvider(KnownChainIds.EthereumMainnet), 'getBlock') +const getBlockSpy = vi.spyOn(getEthersProvider(), 'getBlock') describe('findClosestFoxDiscountDelayBlockNumber', () => { beforeEach(() => { diff --git a/src/lib/fees/utils.ts b/src/lib/fees/utils.ts index af728938bb5..e7343d8fff2 100644 --- a/src/lib/fees/utils.ts +++ b/src/lib/fees/utils.ts @@ -1,4 +1,3 @@ -import { KnownChainIds } from '@shapeshiftoss/types' import { getEthersProvider } from 'lib/ethersProviderSingleton' export const AVERAGE_BLOCK_TIME_BLOCKS = 1000 @@ -6,14 +5,14 @@ export const AVERAGE_BLOCK_TIME_BLOCKS = 1000 export const findClosestFoxDiscountDelayBlockNumber = async ( delayHours: number, ): Promise => { - const latestBlock = await getEthersProvider(KnownChainIds.EthereumMainnet).getBlock('latest') + const latestBlock = await getEthersProvider().getBlock('latest') if (!latestBlock) throw new Error('Could not get latest block') // No-op - if delay is zero, we don't need to perform any logic to find the closest FOX discounts delay block number // Since the block we're interested in is the current one if (delayHours === 0) return latestBlock.number - const historicalBlock = await getEthersProvider(KnownChainIds.EthereumMainnet).getBlock( + const historicalBlock = await getEthersProvider().getBlock( latestBlock.number - AVERAGE_BLOCK_TIME_BLOCKS, ) if (!historicalBlock) @@ -28,7 +27,7 @@ export const findClosestFoxDiscountDelayBlockNumber = async ( let blockNumber = latestBlock.number - targetBlocksToMove while (true) { - const block = await getEthersProvider(KnownChainIds.EthereumMainnet).getBlock(blockNumber) + const block = await getEthersProvider().getBlock(blockNumber) if (!block) throw new Error(`Could not get block ${blockNumber}`) const timeDifference = targetTimestamp - block.timestamp diff --git a/src/pages/Lending/Pool/components/Borrow/BorrowInput.tsx b/src/pages/Lending/Pool/components/Borrow/BorrowInput.tsx index d714b6b66df..89e59cc2cfb 100644 --- a/src/pages/Lending/Pool/components/Borrow/BorrowInput.tsx +++ b/src/pages/Lending/Pool/components/Borrow/BorrowInput.tsx @@ -358,7 +358,7 @@ export const BorrowInput = ({ }, [collateralAccountId]) const { data: _isSmartContractAddress, isLoading: isAddressByteCodeLoading } = - useIsSmartContractAddress(userAddress, borrowAsset?.chainId ?? '') + useIsSmartContractAddress(userAddress) const disableSmartContractDeposit = useMemo(() => { // This is either a smart contract address, or the bytecode is still loading - disable confirm diff --git a/src/pages/Lending/Pool/components/Repay/RepayInput.tsx b/src/pages/Lending/Pool/components/Repay/RepayInput.tsx index 9132a606867..f7cd2487d5f 100644 --- a/src/pages/Lending/Pool/components/Repay/RepayInput.tsx +++ b/src/pages/Lending/Pool/components/Repay/RepayInput.tsx @@ -461,7 +461,7 @@ export const RepayInput = ({ ]) const { data: _isSmartContractAddress, isLoading: isAddressByteCodeLoading } = - useIsSmartContractAddress(userAddress, repaymentAsset?.chainId ?? '') + useIsSmartContractAddress(userAddress) const disableSmartContractRepayment = useMemo(() => { // This is either a smart contract address, or the bytecode is still loading - disable confirm diff --git a/src/pages/ThorChainLP/components/AddLiquidity/AddLiquidityInput.tsx b/src/pages/ThorChainLP/components/AddLiquidity/AddLiquidityInput.tsx index 8aef2f11fbc..41f08bdfbad 100644 --- a/src/pages/ThorChainLP/components/AddLiquidity/AddLiquidityInput.tsx +++ b/src/pages/ThorChainLP/components/AddLiquidity/AddLiquidityInput.tsx @@ -242,7 +242,7 @@ export const AddLiquidityInput: React.FC = ({ }) const { data: isSmartContractAccountAddress, isLoading: isSmartContractAccountAddressLoading } = - useIsSmartContractAddress(poolAssetAccountAddress ?? '', poolAsset?.chainId ?? '') + useIsSmartContractAddress(poolAssetAccountAddress ?? '') const accountIdsByAssetId = useAppSelector(selectPortfolioAccountIdsByAssetId) diff --git a/src/state/apis/swapper/helpers/validateTradeQuote.ts b/src/state/apis/swapper/helpers/validateTradeQuote.ts index cc96fc0658a..e9e9df2546f 100644 --- a/src/state/apis/swapper/helpers/validateTradeQuote.ts +++ b/src/state/apis/swapper/helpers/validateTradeQuote.ts @@ -238,14 +238,8 @@ export const validateTradeQuote = async ( if (swapperName !== SwapperName.Thorchain) return false // This is either a smart contract address, or the bytecode is still loading - disable confirm - const _isSmartContractSellAddress = await isSmartContractAddress( - sendAddress, - firstHop.sellAsset.chainId, - ) - const _isSmartContractReceiveAddress = await isSmartContractAddress( - quote.receiveAddress, - firstHop.buyAsset.chainId, - ) + const _isSmartContractSellAddress = await isSmartContractAddress(sendAddress) + const _isSmartContractReceiveAddress = await isSmartContractAddress(quote.receiveAddress) // For long-tails, the *destination* address cannot be a smart contract // https://dev.thorchain.org/aggregators/aggregator-overview.html#admonition-warning // This doesn't apply to regular THOR swaps however, which docs have no mention of *destination* having to be an EOA diff --git a/src/state/slices/opportunitiesSlice/resolvers/uniV2/index.ts b/src/state/slices/opportunitiesSlice/resolvers/uniV2/index.ts index ab740c6c36b..ccddb5f3bc2 100644 --- a/src/state/slices/opportunitiesSlice/resolvers/uniV2/index.ts +++ b/src/state/slices/opportunitiesSlice/resolvers/uniV2/index.ts @@ -37,7 +37,7 @@ import { calculateAPRFromToken0 } from './utils' let _blockNumber: number | null = null const getBlockNumber = async () => { - const ethersProvider = getEthersProvider(KnownChainIds.EthereumMainnet) + const ethersProvider = getEthersProvider() if (_blockNumber) return _blockNumber const blockNumber = await ethersProvider.getBlockNumber() _blockNumber = blockNumber