Skip to content

Commit

Permalink
feat: fix permit2 approval syncing, etc (#341)
Browse files Browse the repository at this point in the history
  • Loading branch information
zzmp authored Dec 21, 2022
1 parent 514be2e commit b5fb70b
Show file tree
Hide file tree
Showing 10 changed files with 237 additions and 199 deletions.
41 changes: 41 additions & 0 deletions src/abis/permit2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"internalType": "uint160",
"name": "amount",
"type": "uint160"
},
{
"internalType": "uint48",
"name": "expiration",
"type": "uint48"
},
{
"internalType": "uint48",
"name": "nonce",
"type": "uint48"
}
],
"stateMutability": "view",
"type": "function"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,23 @@ import { PERMIT2_ADDRESS } from '@uniswap/permit2-sdk'
import ActionButton from 'components/ActionButton'
import EtherscanLink from 'components/EtherscanLink'
import { usePendingApproval } from 'hooks/transactions'
import { Permit, PermitState } from 'hooks/usePermit2'
import { AllowanceRequired } from 'hooks/usePermit2Allowance'
import { Spinner } from 'icons'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { ApprovalTransactionInfo } from 'state/transactions'
import { Colors } from 'theme'
import { ExplorerDataType } from 'utils/getExplorerLink'

interface PermitButtonProps extends Permit {
interface AllowanceButtonProps extends AllowanceRequired {
color: keyof Colors
onSubmit: (submit: () => Promise<ApprovalTransactionInfo | void>) => Promise<void>
}

/**
* An approving PermitButton.
* Should only be rendered if a valid trade exists that is not yet permitted.
* An approving AllowanceButton.
* Should only be rendered if a valid trade exists that is not yet allowed.
*/
export default function PermitButton({ token, state, callback, color, onSubmit }: PermitButtonProps) {
const isApprovalLoading = state === PermitState.APPROVAL_LOADING
export default function AllowanceButton({ token, isApprovalLoading, callback, color, onSubmit }: AllowanceButtonProps) {
const [isPending, setIsPending] = useState(false)
const [isFailed, setIsFailed] = useState(false)
const pendingApproval = usePendingApproval(token, PERMIT2_ADDRESS)
Expand Down Expand Up @@ -68,11 +67,11 @@ export default function PermitButton({ token, state, callback, color, onSubmit }
} else {
return {
tooltipContent: t`Permission is required for Uniswap to swap each token. This will expire after one month for your security.`,
message: t`Approve use of ${token ?? 'token'}`,
message: t`Approve use of ${token?.symbol ?? 'token'}`,
onClick,
}
}
}, [isApprovalLoading, isFailed, isPending, onClick, pendingApproval, token])
}, [isApprovalLoading, isFailed, isPending, onClick, pendingApproval, token?.symbol])

return (
<ActionButton color={color} disabled={!action?.onClick} action={action}>
Expand Down
21 changes: 9 additions & 12 deletions src/components/Swap/SwapActionButton/SwapButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { SwapApprovalState } from 'hooks/swap/useSwapApproval'
import { useSwapCallback } from 'hooks/swap/useSwapCallback'
import { useConditionalHandler } from 'hooks/useConditionalHandler'
import { useSetOldestValidBlock } from 'hooks/useIsValidBlock'
import { PermitState } from 'hooks/usePermit2'
import { usePermit2 } from 'hooks/useSyncFlags'
import { AllowanceState } from 'hooks/usePermit2Allowance'
import { usePermit2 as usePermit2Enabled } from 'hooks/useSyncFlags'
import useTransactionDeadline from 'hooks/useTransactionDeadline'
import { useUniversalRouterSwapCallback } from 'hooks/useUniversalRouter'
import { useAtomValue } from 'jotai/utils'
Expand All @@ -19,8 +19,8 @@ import invariant from 'tiny-invariant'
import ActionButton from '../../ActionButton'
import Dialog from '../../Dialog'
import { SummaryDialog } from '../Summary'
import AllowanceButton from './AllowanceButton'
import ApproveButton from './ApproveButton'
import PermitButton from './Permit2Button'

/**
* A swapping ActionButton.
Expand All @@ -41,14 +41,14 @@ export default function SwapButton({
[Field.OUTPUT]: { usdc: outputUSDC },
trade: { trade, gasUseEstimateUSD },
approval,
permit,
allowance,
slippage,
impact,
} = useSwapInfo()
const deadline = useTransactionDeadline()
const feeOptions = useAtomValue(feeOptionsAtom)

const permit2Enabled = usePermit2()
const permit2Enabled = usePermit2Enabled()
const { callback: swapRouterCallback } = useSwapCallback({
trade: permit2Enabled ? undefined : trade,
allowedSlippage: slippage.allowed,
Expand All @@ -60,7 +60,7 @@ export default function SwapButton({
const universalRouterSwapCallback = useUniversalRouterSwapCallback(permit2Enabled ? trade : undefined, {
slippageTolerance: slippage.allowed,
deadline,
permit: permit.signature,
permit: allowance.state === AllowanceState.ALLOWED ? allowance.permitSignature : undefined,
feeOptions,
})
const swapCallback = permit2Enabled ? universalRouterSwapCallback : swapRouterCallback
Expand Down Expand Up @@ -107,11 +107,8 @@ export default function SwapButton({
}, [onReviewSwapClick])

if (permit2Enabled) {
if (
!disabled &&
(permit.state === PermitState.APPROVAL_OR_PERMIT_NEEDED || permit.state === PermitState.APPROVAL_LOADING)
) {
return <PermitButton color={color} onSubmit={onSubmit} {...permit} />
if (!disabled && allowance.state === AllowanceState.REQUIRED) {
return <AllowanceButton color={color} onSubmit={onSubmit} {...allowance} />
}
} else {
if (!disabled && approval.state !== SwapApprovalState.APPROVED) {
Expand All @@ -124,7 +121,7 @@ export default function SwapButton({
<ActionButton
color={color}
onClick={onClick}
disabled={disabled || (permit2Enabled && permit.state === PermitState.LOADING)}
disabled={disabled || (permit2Enabled && allowance.state === AllowanceState.LOADING)}
>
<Trans>Review swap</Trans>
</ActionButton>
Expand Down
16 changes: 8 additions & 8 deletions src/hooks/swap/useSwapInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { useWeb3React } from '@web3-react/core'
import { RouterPreference, useRouterTrade } from 'hooks/routing/useRouterTrade'
import { useCurrencyBalances } from 'hooks/useCurrencyBalance'
import useOnSupportedNetwork from 'hooks/useOnSupportedNetwork'
import usePermit, { Permit, PermitState } from 'hooks/usePermit2'
import usePermit2Allowance, { Allowance, AllowanceState } from 'hooks/usePermit2Allowance'
import { PriceImpact, usePriceImpact } from 'hooks/usePriceImpact'
import useSlippage, { DEFAULT_SLIPPAGE, Slippage } from 'hooks/useSlippage'
import { usePermit2 } from 'hooks/useSyncFlags'
import { usePermit2 as usePermit2Enabled } from 'hooks/useSyncFlags'
import useUSDCPrice, { useUSDCValue } from 'hooks/useUSDCPrice'
import { useAtomValue } from 'jotai/utils'
import { createContext, PropsWithChildren, useContext, useEffect, useMemo, useRef } from 'react'
Expand Down Expand Up @@ -44,7 +44,7 @@ interface SwapInfo {
gasUseEstimateUSD?: CurrencyAmount<Token>
}
approval: SwapApproval
permit: Permit
allowance: Allowance
slippage: Slippage
impact?: PriceImpact
}
Expand Down Expand Up @@ -101,13 +101,13 @@ function useComputeSwapInfo(routerUrl?: string): SwapInfo {
const slippage = useSlippage(trade)
const impact = usePriceImpact(trade.trade)

const permit2Enabled = usePermit2()
const permit2Enabled = usePermit2Enabled()
const maximumAmountIn = useMemo(() => {
const maximumAmountIn = trade.trade?.maximumAmountIn(slippage.allowed)
return maximumAmountIn?.currency.isToken ? (maximumAmountIn as CurrencyAmount<Token>) : undefined
}, [slippage.allowed, trade.trade])
const approval = useSwapApproval(permit2Enabled ? undefined : maximumAmountIn)
const permit = usePermit(
const allowance = usePermit2Allowance(
permit2Enabled ? maximumAmountIn : undefined,
permit2Enabled && chainId ? UNIVERSAL_ROUTER_ADDRESS(chainId) : undefined
)
Expand All @@ -129,11 +129,12 @@ function useComputeSwapInfo(routerUrl?: string): SwapInfo {
error,
trade,
approval,
permit,
allowance,
slippage,
impact,
}
}, [
allowance,
amountIn,
amountOut,
approval,
Expand All @@ -143,7 +144,6 @@ function useComputeSwapInfo(routerUrl?: string): SwapInfo {
currencyOut,
error,
impact,
permit,
slippage,
trade,
usdcIn,
Expand All @@ -157,7 +157,7 @@ const DEFAULT_SWAP_INFO: SwapInfo = {
error: ChainError.UNCONNECTED_CHAIN,
trade: { state: TradeState.INVALID, trade: undefined },
approval: { state: SwapApprovalState.APPROVED },
permit: { state: PermitState.INVALID },
allowance: { state: AllowanceState.LOADING },
slippage: DEFAULT_SLIPPAGE,
}

Expand Down
1 change: 1 addition & 0 deletions src/hooks/transactions/updater.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export default function Updater({ pendingTransactions, onCheck, onReceipt }: Upd
promise
.then((receipt) => {
if (receipt) {
fastForwardBlockNumber(receipt.blockNumber)
onReceipt({ chainId, hash, receipt })
} else {
onCheck({ chainId, hash, blockNumber: lastBlockNumber })
Expand Down
6 changes: 5 additions & 1 deletion src/hooks/useBlockNumber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ export function BlockNumberProvider({ children }: { children: ReactNode }) {
const value = useMemo(
() => ({
value: chainId === activeChainId ? block : undefined,
fastForward: (block: number) => setChainBlock({ chainId: activeChainId, block }),
fastForward: (update: number) => {
if (block && update > block) {
setChainBlock({ chainId: activeChainId, block: update })
}
},
}),
[activeChainId, block, chainId]
)
Expand Down
124 changes: 0 additions & 124 deletions src/hooks/usePermit2.ts

This file was deleted.

Loading

1 comment on commit b5fb70b

@vercel
Copy link

@vercel vercel bot commented on b5fb70b Dec 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

widgets – ./

widgets-seven-tau.vercel.app
widgets-git-main-uniswap.vercel.app
widgets-uniswap.vercel.app

Please sign in to comment.