Skip to content

Commit

Permalink
infer unwrapWrapped for remove liquidity boosted
Browse files Browse the repository at this point in the history
  • Loading branch information
MattPereira committed Jan 29, 2025
1 parent ab1df90 commit 347aded
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 30 deletions.
36 changes: 20 additions & 16 deletions src/entities/addLiquidityBoosted/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,7 @@ export class AddLiquidityBoostedV3 {
});

const bptToken = new Token(input.chainId, poolState.address, 18);
const wrapUnderlying: boolean[] = new Array(
poolState.tokens.length,
).fill(false);
const wrapUnderlying: boolean[] = [];

let bptOut: TokenAmount;
let amountsIn: TokenAmount[];
Expand Down Expand Up @@ -89,8 +87,8 @@ export class AddLiquidityBoostedV3 {
switch (input.kind) {
case AddLiquidityKind.Unbalanced: {
// Infer wrapUnderlying from token addreses provided by amountsIn
const tokensIn: ExtendedMinimalToken[] = input.amountsIn.map(
(amountIn) => {
const tokensIn: ExtendedMinimalToken[] = input.amountsIn
.map((amountIn) => {
const amountInAddress = amountIn.address.toLowerCase();
const token = poolStateTokenMap[amountInAddress];
if (!token) {
Expand All @@ -99,10 +97,11 @@ export class AddLiquidityBoostedV3 {
);
}
return token;
},
);
})
.sort((a, b) => a.index - b.index); // sort by index so wrapUnderlying is in correct order

tokensIn.forEach((t) => {
wrapUnderlying[t.index] = t.isUnderlyingToken;
wrapUnderlying.push(t.isUnderlyingToken);
});

// It is allowed not not provide the same amount of TokenAmounts as inputs
Expand Down Expand Up @@ -131,14 +130,19 @@ export class AddLiquidityBoostedV3 {
case AddLiquidityKind.Proportional: {
// User provides tokensIn addresses so we can infer if they need to be wrapped

input.tokensIn.forEach((t) => {
const tokenWithDetails =
poolStateTokenMap[t.toLowerCase() as Address];
if (!tokenWithDetails) {
throw new Error(`Invalid token address: ${t}`);
}
wrapUnderlying[tokenWithDetails.index] =
tokenWithDetails.isUnderlyingToken;
const sortedTokensInWithDetails = input.tokensIn
.map((t) => {
const tokenWithDetails =
poolStateTokenMap[t.toLowerCase() as Address];
if (!tokenWithDetails) {
throw new Error(`Invalid token address: ${t}`);
}
return tokenWithDetails;
})
.sort((a, b) => a.index - b.index);

sortedTokensInWithDetails.forEach((t) => {
wrapUnderlying.push(t.isUnderlyingToken);
});

const bptAmount = await getBptAmountFromReferenceAmountBoosted(
Expand Down
2 changes: 1 addition & 1 deletion src/entities/priceImpact/addLiquidityUnbalancedBoosted.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export async function addLiquidityUnbalancedBoosted(
chainId: input.chainId,
rpcUrl: input.rpcUrl,
bptIn: bptOut.toInputAmount(),
unwrapWrapped: input.wrapUnderlying,
tokensOut: poolTokens.map((t) => t.address),
kind: RemoveLiquidityKind.Proportional,
};
const { amountsOut } = await removeLiquidity.query(
Expand Down
46 changes: 43 additions & 3 deletions src/entities/removeLiquidityBoosted/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { encodeFunctionData, zeroAddress } from 'viem';
import { Address, encodeFunctionData, zeroAddress } from 'viem';

import {
RemoveLiquidityBase,
Expand All @@ -25,6 +25,7 @@ import {
RemoveLiquidityBoostedQueryOutput,
} from './types';
import { InputValidator } from '../inputValidator/inputValidator';
import { MinimalToken } from '@/data';

export class RemoveLiquidityBoostedV3 implements RemoveLiquidityBase {
private readonly inputValidator: InputValidator = new InputValidator();
Expand All @@ -39,6 +40,45 @@ export class RemoveLiquidityBoostedV3 implements RemoveLiquidityBase {
type: 'Boosted',
});

type ExtendedMinimalToken = MinimalToken & {
isUnderlyingToken: boolean;
};

// Build a useful map of all pool tokens with an isUnderlyingToken flag
const poolStateTokenMap: Record<Address, ExtendedMinimalToken> = {};
poolState.tokens.forEach((t) => {
const underlyingToken = t.underlyingToken;
poolStateTokenMap[t.address.toLowerCase()] = {
index: t.index,
decimals: t.decimals,
address: t.address,
isUnderlyingToken: false,
};
if (underlyingToken) {
poolStateTokenMap[underlyingToken.address.toLowerCase()] = {
index: underlyingToken.index,
decimals: underlyingToken.decimals,
address: underlyingToken.address,
isUnderlyingToken: true,
};
}
});

const sortedTokensOutWithDetails = input.tokensOut
.map((t) => {
const tokenWithDetails =
poolStateTokenMap[t.toLowerCase() as Address];
if (!tokenWithDetails) {
throw new Error(`Invalid token address: ${t}`);
}
return tokenWithDetails;
})
.sort((a, b) => a.index - b.index);

const unwrapWrapped: boolean[] = sortedTokensOutWithDetails.map(
(t) => t.isUnderlyingToken,
);

const [tokensOut, underlyingAmountsOut] =
await doRemoveLiquidityProportionalQuery(
input.rpcUrl,
Expand All @@ -47,7 +87,7 @@ export class RemoveLiquidityBoostedV3 implements RemoveLiquidityBase {
input.sender ?? zeroAddress,
input.userData ?? '0x',
poolState.address,
input.unwrapWrapped,
unwrapWrapped,
block,
);

Expand Down Expand Up @@ -77,7 +117,7 @@ export class RemoveLiquidityBoostedV3 implements RemoveLiquidityBase {
to: BALANCER_COMPOSITE_LIQUIDITY_ROUTER_BOOSTED[input.chainId],
poolType: poolState.type,
poolId: poolState.address,
unwrapWrapped: input.unwrapWrapped,
unwrapWrapped,
removeLiquidityKind: RemoveLiquidityKind.Proportional,
bptIn: TokenAmount.fromRawAmount(bptToken, input.bptIn.rawAmount),
amountsOut,
Expand Down
2 changes: 1 addition & 1 deletion src/entities/removeLiquidityBoosted/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export type RemoveLiquidityBoostedProportionalInput = {
chainId: number;
rpcUrl: string;
bptIn: InputAmount;
unwrapWrapped: boolean[];
tokensOut: Address[];
kind: RemoveLiquidityKind.Proportional;
sender?: Address;
userData?: Hex;
Expand Down
2 changes: 0 additions & 2 deletions test/lib/utils/addLiquidityBoostedHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ export async function GetBoostedBpt(
decimals: number;
slot: number;
}[],
wrapUnderlying: boolean[],
): Promise<bigint> {
await setTokenBalances(
client,
Expand All @@ -50,7 +49,6 @@ export async function GetBoostedBpt(

const addLiquidityInput: AddLiquidityBoostedUnbalancedInput = {
amountsIn,
wrapUnderlying,
chainId,
rpcUrl,
kind: AddLiquidityKind.Unbalanced,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ describe('remove liquidity boosted proportional', () => {
decimals: 18,
address: boostedPool_USDC_USDT.address,
},
unwrapWrapped: [true, false],
tokensOut: [USDC.address, stataUSDT.address],
kind: RemoveLiquidityKind.Proportional,
};

Expand Down Expand Up @@ -179,7 +179,7 @@ describe('remove liquidity boosted proportional', () => {
decimals: 18,
address: boostedPool_USDC_USDT.address,
},
unwrapWrapped: [true, true],
tokensOut: [USDC.address, USDT.address],
kind: RemoveLiquidityKind.Proportional,
};

Expand Down Expand Up @@ -271,7 +271,7 @@ describe('remove liquidity boosted proportional', () => {
decimals: 18,
address: boostedPool_USDC_USDT.address,
},
unwrapWrapped: [true, false],
tokensOut: [USDC.address, stataUSDT.address],
kind: RemoveLiquidityKind.Proportional,
};

Expand Down Expand Up @@ -364,7 +364,7 @@ describe('remove liquidity boosted proportional', () => {
decimals: 18,
address: boostedPool_USDC_USDT.address,
},
unwrapWrapped: [true, true],
tokensOut: [USDC.address, USDT.address],
kind: RemoveLiquidityKind.Proportional,
sender: testAddress,
userData: '0x123',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ const parentBptToken = new Token(
// These are the underlying tokens
const usdtToken = new Token(chainId, USDT.address, USDT.decimals);
const wethToken = new Token(chainId, WETH.address, WETH.decimals);
const unwrapWrapped = [false, true]; // unwrapWrapped must match order of on chain state for pool tokens

describe('V3 remove liquidity partial boosted', () => {
let rpcUrl: string;
Expand Down Expand Up @@ -99,7 +98,6 @@ describe('V3 remove liquidity partial boosted', () => {
slot: WETH.slot as number,
},
],
unwrapWrapped,
);

removeLiquidityInput = {
Expand All @@ -110,7 +108,7 @@ describe('V3 remove liquidity partial boosted', () => {
decimals: 18,
rawAmount: bptAmount,
},
unwrapWrapped,
tokensOut: [USDT.address, WETH.address],
kind: RemoveLiquidityKind.Proportional,
};

Expand Down

0 comments on commit 347aded

Please sign in to comment.