diff --git a/src/api/address-resolver/ERCTokenResolver.ts b/src/api/address-resolver/ERCTokenResolver.ts index 49301bd..18ee2b6 100644 --- a/src/api/address-resolver/ERCTokenResolver.ts +++ b/src/api/address-resolver/ERCTokenResolver.ts @@ -1,18 +1,18 @@ import { BaseProvider } from "@ethersproject/providers"; import { Contract } from "@ethersproject/contracts"; -import { Interface } from "@ethersproject/abi"; +import { AddressZero } from "@ethersproject/constants"; import { IAddressResolver } from "./address-resolver"; import erc20 from "../../erc20.json"; import { TokenMeta } from "../../types"; -const erc20Interface = new Interface(erc20); +const ERC20_PROTOTYPE = new Contract(AddressZero, erc20); export class ERCTokenResolver implements IAddressResolver { async resolveAddress( provider: BaseProvider, address: string ): Promise { - const erc20Contract = new Contract(address, erc20Interface, provider); + const erc20Contract = ERC20_PROTOTYPE.connect(provider).attach(address); try { const name = (await erc20Contract.name()) as string; if (!name.trim()) { diff --git a/src/api/address-resolver/UniswapV1Resolver.ts b/src/api/address-resolver/UniswapV1Resolver.ts index a8cb2e0..f3c33a5 100644 --- a/src/api/address-resolver/UniswapV1Resolver.ts +++ b/src/api/address-resolver/UniswapV1Resolver.ts @@ -12,6 +12,11 @@ const UNISWAP_V1_FACTORY_ABI = [ const NULL_ADDRESS = "0x0000000000000000000000000000000000000000"; +const UNISWAP_V1_FACTORY_PROTOTYPE = new Contract( + UNISWAP_V1_FACTORY, + UNISWAP_V1_FACTORY_ABI +); + export type UniswapV1TokenMeta = { address: ChecksummedAddress; } & TokenMeta; @@ -28,11 +33,7 @@ export class UniswapV1Resolver implements IAddressResolver { provider: BaseProvider, address: string ): Promise { - const factoryContract = new Contract( - UNISWAP_V1_FACTORY, - UNISWAP_V1_FACTORY_ABI, - provider - ); + const factoryContract = UNISWAP_V1_FACTORY_PROTOTYPE.connect(provider); try { // First, probe the getToken() function; if it responds with an UniswapV1 exchange diff --git a/src/api/address-resolver/UniswapV2Resolver.ts b/src/api/address-resolver/UniswapV2Resolver.ts index 761237c..e493ff0 100644 --- a/src/api/address-resolver/UniswapV2Resolver.ts +++ b/src/api/address-resolver/UniswapV2Resolver.ts @@ -1,5 +1,6 @@ import { BaseProvider } from "@ethersproject/providers"; import { Contract } from "@ethersproject/contracts"; +import { AddressZero } from "@ethersproject/constants"; import { IAddressResolver } from "./address-resolver"; import { ChecksummedAddress, TokenMeta } from "../../types"; import { ERCTokenResolver } from "./ERCTokenResolver"; @@ -16,6 +17,16 @@ const UNISWAP_V2_PAIR_ABI = [ "function token1() external view returns (address)", ]; +const UNISWAP_V2_FACTORY_PROTOTYPE = new Contract( + UNISWAP_V2_FACTORY, + UNISWAP_V2_FACTORY_ABI +); + +const UNISWAP_V2_PAIR_PROTOTYPE = new Contract( + AddressZero, + UNISWAP_V2_PAIR_ABI +); + export type UniswapV2TokenMeta = { address: ChecksummedAddress; } & TokenMeta; @@ -33,12 +44,9 @@ export class UniswapV2Resolver implements IAddressResolver { provider: BaseProvider, address: string ): Promise { - const pairContract = new Contract(address, UNISWAP_V2_PAIR_ABI, provider); - const factoryContract = new Contract( - UNISWAP_V2_FACTORY, - UNISWAP_V2_FACTORY_ABI, - provider - ); + const pairContract = + UNISWAP_V2_PAIR_PROTOTYPE.connect(provider).attach(address); + const factoryContract = UNISWAP_V2_FACTORY_PROTOTYPE.connect(provider); try { // First, probe the factory() function; if it responds with UniswapV2 factory diff --git a/src/api/address-resolver/UniswapV3Resolver.ts b/src/api/address-resolver/UniswapV3Resolver.ts index 835e823..c93d8df 100644 --- a/src/api/address-resolver/UniswapV3Resolver.ts +++ b/src/api/address-resolver/UniswapV3Resolver.ts @@ -1,5 +1,6 @@ import { BaseProvider } from "@ethersproject/providers"; import { Contract } from "@ethersproject/contracts"; +import { AddressZero } from "@ethersproject/constants"; import { IAddressResolver } from "./address-resolver"; import { ChecksummedAddress, TokenMeta } from "../../types"; import { ERCTokenResolver } from "./ERCTokenResolver"; @@ -17,6 +18,16 @@ const UNISWAP_V3_PAIR_ABI = [ "function fee() external view returns (uint24)", ]; +const UNISWAP_V3_FACTORY_PROTOTYPE = new Contract( + UNISWAP_V3_FACTORY, + UNISWAP_V3_FACTORY_ABI +); + +const UNISWAP_V3_PAIR_PROTOTYPE = new Contract( + AddressZero, + UNISWAP_V3_PAIR_ABI +); + export type UniswapV3TokenMeta = { address: ChecksummedAddress; } & TokenMeta; @@ -35,12 +46,9 @@ export class UniswapV3Resolver implements IAddressResolver { provider: BaseProvider, address: string ): Promise { - const poolContract = new Contract(address, UNISWAP_V3_PAIR_ABI, provider); - const factoryContract = new Contract( - UNISWAP_V3_FACTORY, - UNISWAP_V3_FACTORY_ABI, - provider - ); + const poolContract = + UNISWAP_V3_PAIR_PROTOTYPE.connect(provider).attach(address); + const factoryContract = UNISWAP_V3_FACTORY_PROTOTYPE.connect(provider); try { // First, probe the factory() function; if it responds with UniswapV2 factory diff --git a/src/useErigonHooks.ts b/src/useErigonHooks.ts index 61037fe..1382715 100644 --- a/src/useErigonHooks.ts +++ b/src/useErigonHooks.ts @@ -10,6 +10,7 @@ import { Contract } from "@ethersproject/contracts"; import { defaultAbiCoder } from "@ethersproject/abi"; import { BigNumber } from "@ethersproject/bignumber"; import { arrayify, hexDataSlice, isHexString } from "@ethersproject/bytes"; +import { AddressZero } from "@ethersproject/constants"; import useSWR from "swr"; import useSWRImmutable from "swr/immutable"; import { @@ -638,13 +639,19 @@ export const useHasCode = ( return data as boolean | undefined; }; +const ERC20_PROTOTYPE = new Contract(AddressZero, erc20); + const tokenMetadataFetcher = (provider: JsonRpcProvider | undefined) => async ( _: "tokenmeta", address: ChecksummedAddress ): Promise => { - const erc20Contract = new Contract(address, erc20, provider); + if (provider === undefined) { + return null; + } + + const erc20Contract = ERC20_PROTOTYPE.connect(provider).attach(address); try { const name = (await erc20Contract.name()) as string; if (!name.trim()) { diff --git a/src/usePriceOracle.ts b/src/usePriceOracle.ts index 1956a52..309aa9e 100644 --- a/src/usePriceOracle.ts +++ b/src/usePriceOracle.ts @@ -1,6 +1,7 @@ import { JsonRpcProvider, BlockTag } from "@ethersproject/providers"; import { Contract } from "@ethersproject/contracts"; import { BigNumber } from "@ethersproject/bignumber"; +import { AddressZero } from "@ethersproject/constants"; import AggregatorV3Interface from "@chainlink/contracts/abi/v0.8/AggregatorV3Interface.json"; import FeedRegistryInterface from "@chainlink/contracts/abi/v0.8/FeedRegistryInterface.json"; import { Fetcher } from "swr"; @@ -26,11 +27,20 @@ const feedRegistryFetcherKey = ( return [tokenAddress, blockTag]; }; +const FEED_REGISTRY_MAINNET_PROTOTYPE = new Contract( + FEED_REGISTRY_MAINNET, + FeedRegistryInterface +); + const feedRegistryFetcher = ( provider: JsonRpcProvider | undefined ): Fetcher => async (tokenAddress, blockTag) => { + if (provider === undefined) { + return [undefined, undefined]; + } + // It work works on ethereum mainnet and kovan, see: // https://docs.chain.link/docs/feed-registry/ if (provider!.network.chainId !== 1) { @@ -38,11 +48,7 @@ const feedRegistryFetcher = } // Let SWR handle error - const feedRegistry = new Contract( - FEED_REGISTRY_MAINNET, - FeedRegistryInterface, - provider - ); + const feedRegistry = FEED_REGISTRY_MAINNET_PROTOTYPE.connect(provider); const priceData = await feedRegistry.latestRoundData(tokenAddress, USD, { blockTag, }); @@ -76,6 +82,8 @@ const ethUSDFetcherKey = (blockTag: BlockTag | undefined) => { return ["ethusd", blockTag]; }; +const ETH_USD_FEED_PROTOTYPE = new Contract(AddressZero, AggregatorV3Interface); + const ethUSDFetcher = ( provider: JsonRpcProvider | undefined @@ -84,7 +92,9 @@ const ethUSDFetcher = if (provider?.network.chainId !== 1) { return undefined; } - const c = new Contract("eth-usd.data.eth", AggregatorV3Interface, provider); + + const c = + ETH_USD_FEED_PROTOTYPE.connect(provider).attach("eth-usd.data.eth"); const priceData = await c.latestRoundData({ blockTag }); return priceData; }; @@ -120,6 +130,11 @@ const fastGasFetcherKey = (blockTag: BlockTag | undefined) => { return ["gasgwei", blockTag]; }; +const FAST_GAS_FEED_PROTOTYPE = new Contract( + AddressZero, + AggregatorV3Interface +); + const fastGasFetcher = ( provider: JsonRpcProvider | undefined @@ -128,10 +143,8 @@ const fastGasFetcher = if (provider?.network.chainId !== 1) { return undefined; } - const c = new Contract( - "fast-gas-gwei.data.eth", - AggregatorV3Interface, - provider + const c = FAST_GAS_FEED_PROTOTYPE.connect(provider).attach( + "fast-gas-gwei.data.eth" ); const priceData = await c.latestRoundData({ blockTag }); return priceData;