import { useEffect, useState } from 'react' import { useAccount, useSwitchChain } from 'wagmi' import { LandingPageWrapper } from '@layouts/LandingPageWrapper' import StandardPageContainer from '@layouts/StandardPageContainer' import { getErc20TokenAllowance } from '@/actions/getErc20TokenAllowance' import { approveToken } from '@/utils/approveToken' import { TransactionButton } from '@/components/buttons/TransactionButton' import { useConnectModal } from '@rainbow-me/rainbowkit' import Image from 'next/image' import { CHAINS_BY_ID } from '@/constants/chains' const CHAIN_IDS = [1, 56, 42161, 10] const LIFI_SPENDER = '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae' const MAX_AMOUNT = 100000000000000000000000000000n const TOKENS = { 1: { // Ethereum Mainnet USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', USDT: '0xdac17f958d2ee523a2206206994597c13d831ec7', WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', }, 42161: { // Arbitrum USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', USDT: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9', WETH: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', }, 10: { // Optimism USDC: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', USDT: '0x94b008aA00579c1307B0EF2c499aD98a8ce58e58', WETH: '0x4200000000000000000000000000000000000006', }, 56: { // BSC USDC: '0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d', USDT: '0x55d398326f99059ff775485246999027b3197955', WETH: '0x4DB5a66E937A9F4473fA95b1cAF1d1E1D62E29EA', }, } interface TokenAllowances { [chainId: number]: { [token: string]: bigint } } const LifiPage = () => { const { address, isConnected, chain } = useAccount() const { chains, switchChain: switchNetwork } = useSwitchChain() const { openConnectModal } = useConnectModal() const [hoveredToken, setHoveredToken] = useState(null) const [allowances, setAllowances] = useState({}) useEffect(() => { const fetchAllowances = async () => { if (address) { const newAllowances: TokenAllowances = {} for (const chainId of CHAIN_IDS) { newAllowances[chainId] = {} for (const [tokenName, tokenAddress] of Object.entries( TOKENS[chainId] )) { const allowance = await getErc20TokenAllowance({ address, chainId, tokenAddress: tokenAddress as `0x${string}`, spender: LIFI_SPENDER, }) newAllowances[chainId][tokenName] = allowance } } setAllowances(newAllowances) } } if (isConnected) { fetchAllowances() } }, [address, isConnected]) const handleRevoke = async (chainId: number, tokenName: string) => { if (chain?.id !== chainId) { await switchNetwork({ chainId: chainId }) } const tokenAddress = TOKENS[chainId][tokenName] await approveToken(LIFI_SPENDER, chainId, tokenAddress, 0n) setAllowances((prev) => ({ ...prev, [chainId]: { ...prev[chainId], [tokenName]: 0n, }, })) } return (
Revoke Li.fi Approvals (Multi-chain)

Li.fi / Jumper is investigating an ongoing exploit, and users should revoke approvals{' '} - Li.fi Tweet


Check to see if you have any approvals at risk below:


{isConnected ? ( CHAIN_IDS.map((chainId) => (
{`${chain.name}
{CHAINS_BY_ID[chainId].name}
{Object.entries(allowances[chainId] || {}).map( ([tokenName, allowance]) => { return (
{tokenName}
setHoveredToken( allowance > MAX_AMOUNT ? tokenName : null ) } onMouseLeave={() => setHoveredToken(null)} className="hover:cursor-pointer" > {allowance > MAX_AMOUNT &&
UNLIMITED
} {hoveredToken && hoveredToken === tokenName && allowance > 0n && (
{allowances[chainId][ hoveredToken ].toString()}
)}
{allowance > 0n ? ( handleRevoke(chainId, tokenName)} /> ) : (
-
)}
) } )}
)) ) : (
new Promise((resolve) => { openConnectModal() resolve(true) }) } />
)}
) } export default LifiPage