From bde279945f413e20b9383a6b81fce70428a55fa2 Mon Sep 17 00:00:00 2001 From: Majorfi Date: Wed, 18 Oct 2023 20:01:47 +0200 Subject: [PATCH] fix: allowance --- .../components/ViewStakeUnstakeGauges.tsx | 29 +++++++----- apps/veyfi/contexts/useGauge.tsx | 45 ++----------------- 2 files changed, 23 insertions(+), 51 deletions(-) diff --git a/apps/veyfi/components/ViewStakeUnstakeGauges.tsx b/apps/veyfi/components/ViewStakeUnstakeGauges.tsx index 25bcd22a5..5c5ff7dda 100644 --- a/apps/veyfi/components/ViewStakeUnstakeGauges.tsx +++ b/apps/veyfi/components/ViewStakeUnstakeGauges.tsx @@ -1,5 +1,6 @@ import {useCallback, useMemo, useState} from 'react'; import Link from 'next/link'; +import {erc20ABI, useContractRead} from 'wagmi'; import {useDeepCompareMemo} from '@react-hookz/web'; import {useGauge} from '@veYFI/contexts/useGauge'; import {useOption} from '@veYFI/contexts/useOption'; @@ -9,7 +10,7 @@ import {SECONDS_PER_YEAR, VEYFI_CHAIN_ID} from '@veYFI/utils/constants'; import {Button} from '@yearn-finance/web-lib/components/Button'; import {useWeb3} from '@yearn-finance/web-lib/contexts/useWeb3'; import {IconLinkOut} from '@yearn-finance/web-lib/icons/IconLinkOut'; -import {allowanceKey, toAddress, truncateHex} from '@yearn-finance/web-lib/utils/address'; +import {toAddress, truncateHex} from '@yearn-finance/web-lib/utils/address'; import {formatToNormalizedValue, toBigInt, toNormalizedBN} from '@yearn-finance/web-lib/utils/format.bigNumber'; import {formatAmount, formatPercent} from '@yearn-finance/web-lib/utils/format.number'; import {defaultTxStatus} from '@yearn-finance/web-lib/utils/web3/transaction'; @@ -34,12 +35,10 @@ type TGaugeData = { gaugeAPR: number, gaugeBoost: number, gaugeStaked: TNormalizedBN, - allowance: TNormalizedBN, - isApproved: boolean, actions: undefined } -function StakeUnstakeButtons({isApproved, vaultAddress, gaugeAddress, vaultDeposited, gaugeStaked}: TGaugeData): ReactElement { +function StakeUnstakeButtons({vaultAddress, gaugeAddress, vaultDeposited, gaugeStaked}: TGaugeData): ReactElement { const {provider, address, isActive} = useWeb3(); const {refresh: refreshGauges} = useGauge(); const {refresh: refreshBalances} = useWallet(); @@ -49,6 +48,18 @@ function StakeUnstakeButtons({isApproved, vaultAddress, gaugeAddress, vaultDepos const userAddress = address as TAddress; const refreshData = useCallback((): unknown => Promise.all([refreshGauges(), refreshBalances()]), [refreshGauges, refreshBalances]); + const {data: allowance, refetch: refreshAllowances} = useContractRead({ + address: vaultAddress, + abi: erc20ABI, + chainId: VEYFI_CHAIN_ID, + functionName: 'allowance', + args: [toAddress(address), gaugeAddress] + }); + + const isApproved = useMemo((): boolean => { + return toBigInt(allowance) >= toBigInt(vaultDeposited?.raw); + }, [allowance, vaultDeposited]); + const onApproveAndStake = useCallback(async (vaultAddress: TAddress, gaugeAddress: TAddress, amount: bigint): Promise => { const response = await approveAndStake({ connector: provider, @@ -60,9 +71,9 @@ function StakeUnstakeButtons({isApproved, vaultAddress, gaugeAddress, vaultDepos }); if (response.isSuccessful) { - await refreshData(); + await Promise.all([refreshData(), refreshAllowances()]); } - }, [provider, refreshData]); + }, [provider, refreshAllowances, refreshData]); const onStake = useCallback(async (gaugeAddress: TAddress, amount: bigint): Promise => { const response = await stake({ @@ -127,7 +138,7 @@ function StakeUnstakeButtons({isApproved, vaultAddress, gaugeAddress, vaultDepos export function StakeUnstakeGauges(): ReactElement { const {isActive, address} = useWeb3(); - const {gaugesMap, positionsMap, allowancesMap} = useGauge(); + const {gaugesMap, positionsMap} = useGauge(); const {vaults, prices} = useYearn(); const {balances} = useWallet(); const {dYFIPrice} = useOption(); @@ -164,14 +175,12 @@ export function StakeUnstakeGauges(): ReactElement { gaugeAPR: APRFor10xBoost, gaugeBoost: boost, gaugeStaked: positionsMap[gauge.address]?.deposit ?? toNormalizedBN(0), - allowance: allowancesMap[allowanceKey(VEYFI_CHAIN_ID, vault.address, gauge.address, toAddress(address))], - isApproved: toBigInt(allowancesMap[allowanceKey(VEYFI_CHAIN_ID, vault.address, gauge.address, toAddress(address))]?.raw) >= toBigInt(balances[vault.address]?.raw), actions: undefined }); } set_isLoadingGauges(false); return data; - }, [gaugesMap, vaults, balances, positionsMap, allowancesMap, address]); + }, [gaugesMap, vaults, balances, positionsMap, address]); const searchedGaugesData = useMemo((): TGaugeData[] => { if (!search) { diff --git a/apps/veyfi/contexts/useGauge.tsx b/apps/veyfi/contexts/useGauge.tsx index b49a79a2c..1a47eaf08 100644 --- a/apps/veyfi/contexts/useGauge.tsx +++ b/apps/veyfi/contexts/useGauge.tsx @@ -3,9 +3,9 @@ import {FixedNumber} from 'ethers'; import {useDeepCompareMemo} from '@react-hookz/web'; import {VEYFI_GAUGE_ABI} from '@veYFI/utils/abi/veYFIGauge.abi'; import {VE_YFI_GAUGES,VEYFI_CHAIN_ID} from '@veYFI/utils/constants'; -import {erc20ABI, readContracts} from '@wagmi/core'; +import {readContracts} from '@wagmi/core'; import {useWeb3} from '@yearn-finance/web-lib/contexts/useWeb3'; -import {allowanceKey, toAddress} from '@yearn-finance/web-lib/utils/address'; +import {toAddress} from '@yearn-finance/web-lib/utils/address'; import {decodeAsAddress, decodeAsBigInt, decodeAsNumber, decodeAsString} from '@yearn-finance/web-lib/utils/decoder'; import {toNormalizedBN} from '@yearn-finance/web-lib/utils/format.bigNumber'; import {useAsyncTrigger} from '@common/hooks/useAsyncEffect'; @@ -35,13 +35,11 @@ export type TGaugePosition = { export type TGaugeContext = { gaugesMap: TDict, positionsMap: TDict, - allowancesMap: TDict, refresh: () => void, } const defaultProps: TGaugeContext = { gaugesMap: {}, positionsMap: {}, - allowancesMap: {}, refresh: (): void => undefined }; @@ -49,7 +47,6 @@ const GaugeContext = createContext(defaultProps); export const GaugeContextApp = memo(function GaugeContextApp({children}: {children: ReactElement}): ReactElement { const {address, isActive} = useWeb3(); const [gauges, set_gauges] = useState([]); - const [allowancesMap, set_allowancesMap] = useState>({}); const [positionsMap, set_positionsMap] = useState>({}); const refreshVotingEscrow = useAsyncTrigger(async (): Promise => { @@ -87,38 +84,6 @@ export const GaugeContextApp = memo(function GaugeContextApp({children}: {childr set_gauges(allGauges); }, []); - const refreshAllowances = useAsyncTrigger(async (): Promise => { - if (!gauges || !address) { - return; - } - const calls = []; - for (const gauge of Object.values(gauges)) { - calls.push({ - address: gauge.vaultAddress, - abi: erc20ABI, - chainId: VEYFI_CHAIN_ID, - functionName: 'allowance', - args: [toAddress(address), gauge.address] - }); - calls.push({ - address: gauge.vaultAddress, - abi: erc20ABI, - chainId: VEYFI_CHAIN_ID, - functionName: 'decimals' - }); - - } - const results = await readContracts({contracts: calls}); - const _allowancesMap: TDict = {}; - let index = 0; - for (const gauge of Object.values(gauges)) { - const allowance = decodeAsBigInt(results[index++]); - const decimals = Number(decodeAsBigInt(results[index++])) || decodeAsNumber(results[index++]); - _allowancesMap[allowanceKey(VEYFI_CHAIN_ID, gauge.vaultAddress, gauge.address, toAddress(address))] = toNormalizedBN(allowance, decimals); - } - set_allowancesMap(_allowancesMap); - }, [address, gauges]); - const refreshPositions = useAsyncTrigger(async (): Promise => { if (!gauges || !isActive || !address) { return; @@ -186,15 +151,13 @@ export const GaugeContextApp = memo(function GaugeContextApp({children}: {childr const refresh = useCallback((): void => { refreshVotingEscrow(); refreshPositions(); - refreshAllowances(); - }, [refreshAllowances, refreshPositions, refreshVotingEscrow]); + }, [refreshPositions, refreshVotingEscrow]); const contextValue = useDeepCompareMemo((): TGaugeContext => ({ gaugesMap: keyBy(gauges, 'address'), positionsMap: positionsMap, - allowancesMap: allowancesMap ?? {}, refresh - }), [allowancesMap, gauges, positionsMap, refresh]); + }), [gauges, positionsMap, refresh]); return (