Skip to content
This repository was archived by the owner on Oct 15, 2024. It is now read-only.

Commit 9bb8342

Browse files
authored
chore: permit2 initial changes (#1104)
* chore: add permit2 support in useTokenApprovalSteps * chore: rename permit2 helpers
1 parent 2d2d189 commit 9bb8342

9 files changed

+41
-7
lines changed

lib/config/config.types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export interface ContractsConfig {
4343
feeDistributor?: Address
4444
veDelegationProxy?: Address
4545
veBAL?: Address
46+
permit2?: Address
4647
}
4748
export interface PoolsConfig {
4849
issues: Partial<Record<PoolIssue, string[]>>

lib/config/networks/sepolia.ts

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const networkConfig: NetworkConfig = {
3636
minter: '0x1783Cd84b3d01854A96B4eD5843753C2CcbD574A',
3737
},
3838
veBAL: '0x150A72e4D4d81BbF045565E232c50Ed0931ad795',
39+
permit2: '0x000000000022D473030F116dDEE9F6B43aC78BA3',
3940
},
4041
pools: convertHexToLowerCase({
4142
issues: {},

lib/modules/pool/actions/LiquidityActionHelpers.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,12 @@ export class LiquidityActionHelpers {
7575
}
7676

7777
public getAmountsToApprove(
78-
humanAmountsIn: HumanTokenAmountWithAddress[]
78+
humanAmountsIn: HumanTokenAmountWithAddress[],
79+
isPermit2 = false
7980
): TokenAmountToApprove[] {
8081
return this.toInputAmounts(humanAmountsIn).map(({ address, rawAmount }) => {
8182
return {
83+
isPermit2,
8284
tokenAddress: address,
8385
requiredRawAmount: rawAmount,
8486
requestedRawAmount: rawAmount, //This amount will be probably replaced by MAX_BIGINT depending on the approval rules

lib/modules/pool/actions/add-liquidity/useAddLiquiditySteps.tsx

+4-5
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ import { useMemo } from 'react'
77
import { usePool } from '../../PoolProvider'
88
import { LiquidityActionHelpers } from '../LiquidityActionHelpers'
99
import { AddLiquidityStepParams, useAddLiquidityStep } from './useAddLiquidityStep'
10-
import { getVaultConfig } from '../../pool.helpers'
10+
import { requiresPermit2Approval } from '../../pool.helpers'
1111
import { useSignRelayerStep } from '@/lib/modules/transactions/transaction-steps/useSignRelayerStep'
12-
import { Address } from 'viem'
13-
import { isCowAmmPool } from '../../pool.helpers'
12+
import { getSpenderForAddLiquidity } from '@/lib/modules/tokens/token.helpers'
1413

1514
type AddLiquidityStepsParams = AddLiquidityStepParams & {
1615
helpers: LiquidityActionHelpers
@@ -22,7 +21,6 @@ export function useAddLiquiditySteps({
2221
simulationQuery,
2322
}: AddLiquidityStepsParams) {
2423
const { pool, chainId, chain } = usePool()
25-
const { vaultAddress } = getVaultConfig(pool)
2624
const relayerMode = useRelayerMode(pool)
2725
const shouldSignRelayerApproval = useShouldSignRelayerApproval(chainId, relayerMode)
2826

@@ -37,10 +35,11 @@ export function useAddLiquiditySteps({
3735

3836
const { isLoading: isLoadingTokenApprovalSteps, steps: tokenApprovalSteps } =
3937
useTokenApprovalSteps({
40-
spenderAddress: isCowAmmPool(pool.type) ? (pool.address as Address) : vaultAddress,
38+
spenderAddress: getSpenderForAddLiquidity(pool),
4139
chain: pool.chain,
4240
approvalAmounts: inputAmounts,
4341
actionType: 'AddLiquidity',
42+
isPermit2: requiresPermit2Approval(pool),
4443
})
4544

4645
const addLiquidityStep = useAddLiquidityStep({

lib/modules/pool/pool.helpers.ts

+4
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,10 @@ export function isV3Pool(pool: Pool): boolean {
316316
return pool.protocolVersion === 3
317317
}
318318

319+
export function requiresPermit2Approval(pool: Pool): boolean {
320+
return isV3Pool(pool)
321+
}
322+
319323
export function getRateProviderWarnings(warnings: string[]) {
320324
return warnings.filter(warning => !isEmpty(warning))
321325
}

lib/modules/tokens/approvals/approval-rules.spec.ts

+5
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,13 @@ describe('getRequiredTokenApprovals', () => {
5252
})
5353
).toEqual([
5454
{
55+
isPermit2: false,
5556
tokenAddress: wETHAddress,
5657
requiredRawAmount: 10000000000000000000n,
5758
requestedRawAmount: MAX_BIGINT,
5859
},
5960
{
61+
isPermit2: false,
6062
tokenAddress: wjAuraAddress,
6163
requiredRawAmount: 20000000000000000000n,
6264
requestedRawAmount: MAX_BIGINT,
@@ -87,11 +89,13 @@ describe('getRequiredTokenApprovals', () => {
8789
requiredRawAmount: 0n,
8890
requestedRawAmount: 0n,
8991
tokenAddress: usdtAddress,
92+
isPermit2: false,
9093
},
9194
{
9295
tokenAddress: usdtAddress,
9396
requiredRawAmount: 10000000000000000000n,
9497
requestedRawAmount: MAX_BIGINT,
98+
isPermit2: false,
9599
},
96100
])
97101
})
@@ -116,6 +120,7 @@ describe('getRequiredTokenApprovals', () => {
116120
})
117121
).toEqual([
118122
{
123+
isPermit2: false,
119124
requiredRawAmount: 10000000000000000000n,
120125
requestedRawAmount: MAX_BIGINT,
121126
tokenAddress: usdtAddress,

lib/modules/tokens/approvals/approval-rules.ts

+5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export type TokenAmountToApprove = {
1010
tokenAddress: Address
1111
requiredRawAmount: bigint // actual amount that the transaction requires
1212
requestedRawAmount: bigint // amount that we are going to request (normally MAX_BIGINT)
13+
isPermit2: boolean // whether the approval is for Permit2 or standard token approval
1314
}
1415

1516
// This is a subtype of InputAmount as we only need rawAmount and address
@@ -19,6 +20,7 @@ type TokenApprovalParams = {
1920
chainId: GqlChain | SupportedChainId | null
2021
rawAmounts: RawAmount[]
2122
allowanceFor: (tokenAddress: Address) => bigint
23+
isPermit2?: boolean
2224
approveMaxBigInt?: boolean
2325
skipAllowanceCheck?: boolean
2426
}
@@ -30,6 +32,7 @@ export function getRequiredTokenApprovals({
3032
chainId,
3133
rawAmounts,
3234
allowanceFor,
35+
isPermit2 = false,
3336
approveMaxBigInt = true,
3437
skipAllowanceCheck = false,
3538
}: TokenApprovalParams): TokenAmountToApprove[] {
@@ -42,6 +45,7 @@ export function getRequiredTokenApprovals({
4245
requiredRawAmount: rawAmount,
4346
// The transaction only requires requiredRawAmount but we will normally request MAX_BIGINT
4447
requestedRawAmount: approveMaxBigInt ? MAX_BIGINT : rawAmount,
48+
isPermit2,
4549
}
4650
})
4751

@@ -59,6 +63,7 @@ export function getRequiredTokenApprovals({
5963
requiredRawAmount: 0n,
6064
requestedRawAmount: 0n,
6165
tokenAddress: t.tokenAddress,
66+
isPermit2,
6267
}
6368
// Prepend approval for ZERO amount
6469
return [zeroTokenAmountToApprove, t]

lib/modules/tokens/approvals/useTokenApprovalSteps.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,20 @@ export type Params = {
2020
chain: GqlChain
2121
approvalAmounts: RawAmount[]
2222
actionType: ApprovalAction
23+
isPermit2?: boolean
2324
bptSymbol?: string //Edge-case for approving
2425
}
2526

2627
/*
27-
Generic hook to creates a Token Approval Step Config for different flows defined by the actionType property
28+
Generic hook to create a Token Approval Step Config for different flows defined by the actionType property
2829
*/
2930
export function useTokenApprovalSteps({
3031
spenderAddress,
3132
chain,
3233
approvalAmounts,
3334
actionType,
3435
bptSymbol,
36+
isPermit2 = false,
3537
}: Params): { isLoading: boolean; steps: TransactionStep[] } {
3638
const { userAddress } = useUserAccount()
3739
const { getToken } = useTokens()
@@ -58,6 +60,7 @@ export function useTokenApprovalSteps({
5860
chainId: chain,
5961
rawAmounts: _approvalAmounts,
6062
allowanceFor: tokenAllowances.allowanceFor,
63+
isPermit2,
6164
})
6265

6366
const steps = useMemo(() => {

lib/modules/tokens/token.helpers.ts

+14
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { Address } from 'viem'
1010
import { HumanTokenAmountWithAddress, TokenBase } from './token.types'
1111
import { InputAmount } from '@balancer/sdk'
1212
import { Pool } from '../pool/PoolProvider'
13+
import { getVaultConfig, isCowAmmPool, isV3Pool } from '../pool/pool.helpers'
1314

1415
export function isNativeAsset(token: TokenBase | string, chain: GqlChain | SupportedChainId) {
1516
return nativeAssetFilter(chain)(token)
@@ -130,3 +131,16 @@ export function getLeafTokens(poolTokens: PoolToken[]) {
130131

131132
return leafTokens
132133
}
134+
135+
export function getSpenderForAddLiquidity(pool: Pool): Address {
136+
if (isCowAmmPool(pool.type)) return pool.address as Address
137+
if (isV3Pool(pool)) {
138+
const permit2Address = getNetworkConfig(pool.chain).contracts.permit2
139+
if (!permit2Address) {
140+
throw new Error(`Permit2 feature is not yet available for this chain (${pool.chain}) `)
141+
}
142+
return permit2Address
143+
}
144+
const { vaultAddress } = getVaultConfig(pool)
145+
return vaultAddress
146+
}

0 commit comments

Comments
 (0)