From c29d9182fd21b6982ad6d3c2d568be2acaec9a53 Mon Sep 17 00:00:00 2001 From: Peiman <25097709+Rickk137@users.noreply.github.com> Date: Mon, 10 Jun 2024 18:28:05 +0330 Subject: [PATCH] fix: base multicall issue (#299) * fix: base multicall issue * fix: persist account id --- contracts/importers/importMulticall3.js | 37 +++++++++++-------- .../useLiquidityPositions.ts | 1 - liquidity/lib/withERC7412/withERC7412.ts | 3 +- .../src/layouts/Default/NetworkController.tsx | 23 ++++++++++-- liquidity/ui/src/utils/onboard.ts | 8 ++-- 5 files changed, 47 insertions(+), 25 deletions(-) diff --git a/contracts/importers/importMulticall3.js b/contracts/importers/importMulticall3.js index 14c149070..ac9f83ed0 100644 --- a/contracts/importers/importMulticall3.js +++ b/contracts/importers/importMulticall3.js @@ -1,7 +1,5 @@ const abi = [ 'function aggregate(tuple(address target, bytes callData)[] calls) payable returns (uint256 blockNumber, bytes[] returnData)', - 'function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)', - 'function aggregate3Value(tuple(address target, bool allowFailure, uint256 value, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)', 'function blockAndAggregate(tuple(address target, bytes callData)[] calls) payable returns (uint256 blockNumber, bytes32 blockHash, tuple(bool success, bytes returnData)[] returnData)', 'function getBasefee() view returns (uint256 basefee)', 'function getBlockHash(uint256 blockNumber) view returns (bytes32 blockHash)', @@ -17,37 +15,44 @@ const abi = [ 'function tryBlockAndAggregate(bool requireSuccess, tuple(address target, bytes callData)[] calls) payable returns (uint256 blockNumber, bytes32 blockHash, tuple(bool success, bytes returnData)[] returnData)', ]; +const multicall3Abi = [ + ...abi, + 'function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)', + 'function aggregate3Value(tuple(address target, bool allowFailure, uint256 value, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)', +]; + +const trustedMulticallAbi = [ + ...abi, + 'function aggregate3(tuple(address target, bool requireSuccess, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)', + 'function aggregate3Value(tuple(address target, bool requireSuccess, uint256 value, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)', +]; + +const TrustedMulticallForwarder = '0xE2C5658cC5C448B48141168f3e475dF8f65A1e3e'; + export async function importMulticall3(chainId, preset = 'main') { const deployment = `${Number(chainId).toFixed(0)}-${preset}`; switch (deployment) { case '1-main': { const { mainnet } = await import('viem/chains'); - return { address: mainnet.contracts.multicall3.address, abi }; + return { address: mainnet.contracts.multicall3.address, abi: multicall3Abi }; } case '11155111-main': { const { sepolia } = await import('viem/chains'); - return { address: sepolia.contracts.multicall3.address, abi }; + return { address: sepolia.contracts.multicall3.address, abi: multicall3Abi }; } case '10-main': { const { optimism } = await import('viem/chains'); - return { address: optimism.contracts.multicall3.address, abi }; - } - case '8453-andromeda': { - const { base } = await import('viem/chains'); - return { address: base.contracts.multicall3.address, abi }; - } - case '84532-andromeda': { - const { baseSepolia } = await import('viem/chains'); - return { address: baseSepolia.contracts.multicall3.address, abi }; + return { address: optimism.contracts.multicall3.address, abi: multicall3Abi }; } + case '8453-andromeda': + case '84532-andromeda': case '42161-main': case '42161-arbthetix': { - const { arbitrum } = await import('viem/chains'); - return { address: arbitrum.contracts.multicall3.address, abi }; + return { address: TrustedMulticallForwarder, abi: trustedMulticallAbi }; } case '421614-main': { const { arbitrumSepolia } = await import('viem/chains'); - return { address: arbitrumSepolia.contracts.multicall3.address, abi }; + return { address: arbitrumSepolia.contracts.multicall3.address, abi: multicall3Abi }; } default: { throw new Error(`Unsupported deployment ${deployment} for Multicall3`); diff --git a/liquidity/lib/useLiquidityPositions/useLiquidityPositions.ts b/liquidity/lib/useLiquidityPositions/useLiquidityPositions.ts index a94575af1..bfc65ee93 100644 --- a/liquidity/lib/useLiquidityPositions/useLiquidityPositions.ts +++ b/liquidity/lib/useLiquidityPositions/useLiquidityPositions.ts @@ -122,7 +122,6 @@ export const useLiquidityPositions = ({ accountId }: { accountId?: string }) => const prices = priceDecoder(encoded.slice(0, priceCalls.length)); const pricesByAddress = keyBy( 'address', - Array.isArray(prices) ? prices.map((price, i) => ({ price, diff --git a/liquidity/lib/withERC7412/withERC7412.ts b/liquidity/lib/withERC7412/withERC7412.ts index 2465bb085..baec58788 100644 --- a/liquidity/lib/withERC7412/withERC7412.ts +++ b/liquidity/lib/withERC7412/withERC7412.ts @@ -313,7 +313,7 @@ export async function erc7412Call( const res = await provider.call(newCall); - if (newCall.to === multicallAddress) { + if (newCall.to?.toLowerCase() === multicallAddress.toLowerCase()) { // If this was a multicall, decode and remove price updates. const decodedMultiCall: { returnData: string }[] = new ethers.utils.Interface( multicallAbi @@ -323,6 +323,7 @@ export async function erc7412Call( const responseWithoutPriceUpdates = decodedMultiCall.filter( ({ returnData }) => returnData !== '0x' // price updates have 0x as return data ); + return decode(responseWithoutPriceUpdates.map(({ returnData }) => returnData)); } diff --git a/liquidity/ui/src/layouts/Default/NetworkController.tsx b/liquidity/ui/src/layouts/Default/NetworkController.tsx index 365b383ee..0078a8ad7 100644 --- a/liquidity/ui/src/layouts/Default/NetworkController.tsx +++ b/liquidity/ui/src/layouts/Default/NetworkController.tsx @@ -14,7 +14,7 @@ import { Text, } from '@chakra-ui/react'; import { WalletIcon } from '@snx-v3/icons'; -import { NetworkIcon, useNetwork, useWallet, NETWORKS } from '@snx-v3/useBlockchain'; +import { NetworkIcon, useNetwork, useWallet } from '@snx-v3/useBlockchain'; import { prettyString } from '@snx-v3/format'; import { useLocalStorage } from '@snx-v3/useLocalStorage'; import { LOCAL_STORAGE_KEYS } from '../../utils/constants'; @@ -22,6 +22,7 @@ import { CopyIcon, SettingsIcon } from '@chakra-ui/icons'; import { useAccounts, useCreateAccount } from '@snx-v3/useAccounts'; import { useLocation, useNavigate, useSearchParams } from 'react-router-dom'; import { Tooltip } from '@snx-v3/Tooltip'; +import { supportedNetworks } from '../../utils/onboard'; export function NetworkController() { const [toolTipLabel, setTooltipLabel] = useState('Copy'); @@ -39,7 +40,7 @@ export function NetworkController() { const { pathname } = useLocation(); useEffect(() => { - if (!isAccountsLoading && !isAccountsFetching && accounts) { + if (!isAccountsLoading && !isAccountsFetching && !!accounts?.length) { const accountId = queryParams.get('accountId'); if (accountId && !accounts?.includes(accountId)) { @@ -69,12 +70,26 @@ export function NetworkController() { useEffect(() => { const accountId = queryParams.get('accountId'); + if (!accountId && !!accounts?.length) { - queryParams.set('accountId', accounts[0]); + const lastUsedAccount = localStorage.getItem('accountId'); + if (lastUsedAccount && accounts.find((account) => String(account) === lastUsedAccount)) { + queryParams.set('accountId', lastUsedAccount); + } else { + queryParams.set('accountId', accounts[0]); + } navigate({ pathname, search: queryParams.toString() }); } }, [accounts, navigate, pathname, queryParams]); + useEffect(() => { + const accountId = queryParams.get('accountId'); + + if (accountId) { + localStorage.setItem('accountId', accountId); + } + }, [queryParams]); + const onDisconnect = () => { if (walletsInfo) { disconnect(walletsInfo); @@ -100,7 +115,7 @@ export function NetworkController() { - {NETWORKS.map(({ id, preset, label, isTestnet }) => { + {supportedNetworks.map(({ id, preset, label, isTestnet }) => { if (isTestnet && !showTestnets) return null; return ( setNetwork(id)}> diff --git a/liquidity/ui/src/utils/onboard.ts b/liquidity/ui/src/utils/onboard.ts index 9cb7ff9aa..0674d49cf 100644 --- a/liquidity/ui/src/utils/onboard.ts +++ b/liquidity/ui/src/utils/onboard.ts @@ -16,10 +16,12 @@ const supportedDeployments = [ '421614-main', ]; -// Filter networks to only supported ones -export const chains = NETWORKS.filter(({ id, preset }) => +export const supportedNetworks = NETWORKS.filter(({ id, preset }) => supportedDeployments.includes(`${id}-${preset}`) -).map((n) => ({ +); + +// Filter networks to only supported ones +export const chains = supportedNetworks.map((n) => ({ id: n.id, token: n.token, label: n.label,