feat: warn when adding liquidity to an unowned LP position (#6219)

* feat: warn when adding liquidity to an unowned LP position

* update boolean name

* use a better address equivalence check
This commit is contained in:
Jordan Frankfurt 2023-03-23 13:09:22 -04:00 committed by GitHub
parent 1a79bac893
commit 18ec675c52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 0 deletions

@ -0,0 +1,46 @@
import { Trans } from '@lingui/macro'
import { AlertTriangle } from 'react-feather'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
const ExplainerText = styled.div`
color: ${({ theme }) => theme.textSecondary};
`
const TitleRow = styled.div`
align-items: center;
display: flex;
flex-direction: row;
color: ${({ theme }) => theme.accentWarning};
margin-bottom: 8px;
`
const Wrapper = styled.div`
background-color: ${({ theme }) => theme.accentWarningSoft};
border-radius: 16px;
margin-top: 12px;
max-width: 480px;
padding: 12px 20px;
width: 100%;
`
interface OwnershipWarningProps {
ownerAddress: string
}
const OwnershipWarning = ({ ownerAddress }: OwnershipWarningProps) => (
<Wrapper>
<TitleRow>
<AlertTriangle style={{ marginRight: '8px' }} />
<ThemedText.SubHeader color="accentWarning">
<Trans>Warning</Trans>
</ThemedText.SubHeader>
</TitleRow>
<ExplainerText>
<Trans>
You are not the owner of this LP position. You will not be able to withdraw the liquidity from this position
unless you own the following address: {ownerAddress}
</Trans>
</ExplainerText>
</Wrapper>
)
export default OwnershipWarning

@ -6,10 +6,12 @@ import { BrowserEvent, InterfaceElementName, InterfaceEventName } from '@uniswap
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { FeeAmount, NonfungiblePositionManager } from '@uniswap/v3-sdk'
import { useWeb3React } from '@web3-react/core'
import OwnershipWarning from 'components/addLiquidity/OwnershipWarning'
import { sendEvent } from 'components/analytics'
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
import { useToggleWalletDrawer } from 'components/WalletDropdown'
import usePrevious from 'hooks/usePrevious'
import { useSingleCallResult } from 'lib/hooks/multicall'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { AlertTriangle } from 'react-feather'
import { useNavigate, useParams, useSearchParams } from 'react-router-dom'
@ -21,6 +23,7 @@ import {
useV3MintState,
} from 'state/mint/v3/hooks'
import { useTheme } from 'styled-components/macro'
import { addressesAreEquivalent } from 'utils/addressesAreEquivalent'
import { ButtonError, ButtonLight, ButtonPrimary, ButtonText } from '../../components/Button'
import { BlueCard, OutlineCard, YellowCard } from '../../components/Card'
@ -548,6 +551,12 @@ export default function AddLiquidity() {
}),
[usdcValueCurrencyB]
)
const owner = useSingleCallResult(tokenId ? positionManager : null, 'ownerOf', [tokenId]).result?.[0]
const ownsNFT =
addressesAreEquivalent(owner, account) || addressesAreEquivalent(existingPositionDetails?.operator, account)
const showOwnershipWarning = Boolean(account && !ownsNFT)
return (
<>
<ScrollablePage>
@ -912,6 +921,7 @@ export default function AddLiquidity() {
</ResponsiveTwoColumns>
</Wrapper>
</PageWrapper>
{showOwnershipWarning && <OwnershipWarning ownerAddress={owner} />}
{addIsUnsupported && (
<UnsupportedCurrencyFooter
show={addIsUnsupported}

@ -0,0 +1,20 @@
import { addressesAreEquivalent } from './addressesAreEquivalent'
describe('addressesAreEquivalent', () => {
it('should return false for undefined addresses', () => {
expect(addressesAreEquivalent(undefined, undefined)).toBe(false)
})
it('should return true for mismatched checksum equivalence', () => {
expect(
addressesAreEquivalent(
'0x48c89D77ae34Ae475e4523b25aB01e363dce5A78',
'0x48c89D77ae34Ae475e4523b25aB01e363dce5A78'.toLowerCase()
)
).toBe(true)
})
it('should return true for simple equivalence', () => {
expect(
addressesAreEquivalent('0x48c89D77ae34Ae475e4523b25aB01e363dce5A78', '0x48c89D77ae34Ae475e4523b25aB01e363dce5A78')
).toBe(true)
})
})

@ -0,0 +1,4 @@
export function addressesAreEquivalent(a?: string, b?: string) {
if (!a || !b) return false
return a === b || a.toLowerCase() === b.toLowerCase()
}