Skip to content

Commit

Permalink
fix: Stable pool max swap amount, exactOut.
Browse files Browse the repository at this point in the history
  • Loading branch information
johngrantuk committed Dec 5, 2024
1 parent e03b444 commit 2761217
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 34 deletions.
40 changes: 31 additions & 9 deletions typescript/src/stable/stablePool.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { MAX_UINT256, MAX_BALANCE } from '../constants';
import { MathSol } from '../utils/math';
import { toRawUndoRateRoundDown } from '../vault/utils';
import {
MaxSingleTokenRemoveParams,
MaxSwapParams,
Expand All @@ -24,18 +25,39 @@ export class Stable implements PoolBase {
}

/**
* Returns the max amount that can be swapped (in relation to the amount specified by user).
* Returns the max amount that can be swapped in relation to the swapKind.
* @param maxSwapParams
* @returns Returned amount/scaling is respective to the tokenOut because that’s what we’re taking out of the pool and what limits the swap size.
* @returns GivenIn: Returns the max amount in. GivenOut: Returns the max amount out.
*/
getMaxSwapAmount(maxSwapParams: MaxSwapParams): bigint {
const { balancesLiveScaled18, indexIn, tokenRates, scalingFactors } =
maxSwapParams;

const diff = MAX_BALANCE - balancesLiveScaled18[indexIn];
return MathSol.divDownFixed(
diff,
scalingFactors[indexIn] * tokenRates[indexIn],
const {
balancesLiveScaled18,
indexIn,
indexOut,
tokenRates,
scalingFactors,
swapKind,
} = maxSwapParams;
if (swapKind === SwapKind.GivenIn) {
// MAX_BALANCE comes from SC limit and is max pool can hold
const diff = MAX_BALANCE - balancesLiveScaled18[indexIn];
// Scale to token in (and remove rate)
return toRawUndoRateRoundDown(
diff,
scalingFactors[indexIn],
tokenRates[indexIn],
);
}
// 99% of token out balance
const max = MathSol.mulDownFixed(
990000000000000000n,
balancesLiveScaled18[indexOut],
);
// Scale to token out
return toRawUndoRateRoundDown(
max,
scalingFactors[indexOut],
tokenRates[indexOut],
);
}

Expand Down
51 changes: 33 additions & 18 deletions typescript/src/weighted/weightedPool.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { MAX_UINT256 } from '../constants';
import { MathSol } from '../utils/math';
import { toRawUndoRateRoundDown } from '../vault/utils';
import {
MaxSingleTokenRemoveParams,
MaxSwapParams,
Expand All @@ -26,27 +27,41 @@ export class Weighted implements PoolBase {
}

/**
* Returns the max amount that can be swapped (in relation to the amount specified by user).
* Returns the max amount that can be swapped in relation to the swapKind.
* @param maxSwapParams
* @returns Returned amount/scaling is respective to the tokenOut because that’s what we’re taking out of the pool and what limits the swap size.
* @returns GivenIn: Returns the max amount in. GivenOut: Returns the max amount out.
*/
getMaxSwapAmount(swapParams: MaxSwapParams): bigint {
if (swapParams.swapKind === SwapKind.GivenIn)
return MathSol.divDownFixed(
MathSol.mulDownFixed(
swapParams.balancesLiveScaled18[swapParams.indexIn],
_MAX_IN_RATIO,
),
swapParams.scalingFactors[swapParams.indexIn] *
swapParams.tokenRates[swapParams.indexIn],
getMaxSwapAmount(maxSwapParams: MaxSwapParams): bigint {
const {
balancesLiveScaled18,
indexIn,
indexOut,
tokenRates,
scalingFactors,
swapKind,
} = maxSwapParams;
if (swapKind === SwapKind.GivenIn) {
const max18 = MathSol.mulDownFixed(
balancesLiveScaled18[indexIn],
_MAX_IN_RATIO,
);
return MathSol.divDownFixed(
MathSol.mulDownFixed(
swapParams.balancesLiveScaled18[swapParams.indexOut],
_MAX_OUT_RATIO,
),
swapParams.scalingFactors[swapParams.indexOut] *
swapParams.tokenRates[swapParams.indexOut],
// Scale to token in (and remove rate)
return toRawUndoRateRoundDown(
max18,
scalingFactors[indexIn],
tokenRates[indexIn],
);
}

const max18 = MathSol.mulDownFixed(
balancesLiveScaled18[indexOut],
_MAX_OUT_RATIO,
);
// Scale to token out
return toRawUndoRateRoundDown(
max18,
scalingFactors[indexOut],
tokenRates[indexOut],
);
}

Expand Down
44 changes: 38 additions & 6 deletions typescript/test/stablePool.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,25 @@ describe('stable pool', () => {
});
describe('getMaxSwapAmount', () => {
describe('no rate', () => {
test('exact in', () => {
test('exact in, 18 decimals', () => {
const swapParams = {
swapKind: SwapKind.GivenIn,
amountGivenScaled18: 0n,
balancesLiveScaled18: [
60000000000000000000n,
40000000000000000000n,
],
tokenRates: [1000000000000000000n, 1000000000000000000n],
scalingFactors: [1n, 1000000000000n],
indexIn: 0,
indexOut: 1,
};
const maxSwapAmount = pool.getMaxSwapAmount(swapParams);
expect(maxSwapAmount).to.eq(
340282366920938463403374607431768211456n,
);
});
test('exact in, 6 decimals', () => {
const swapParams = {
swapKind: SwapKind.GivenIn,
amountGivenScaled18: 0n,
Expand All @@ -25,7 +43,7 @@ describe('stable pool', () => {
const maxSwapAmount = pool.getMaxSwapAmount(swapParams);
expect(maxSwapAmount).to.eq(340282366920938463403374607n);
});
test('exact out', () => {
test('exact out, 18decimals', () => {
const swapParams = {
swapKind: SwapKind.GivenOut,
amountGivenScaled18: 0n,
Expand All @@ -39,7 +57,23 @@ describe('stable pool', () => {
indexOut: 1,
};
const maxSwapAmount = pool.getMaxSwapAmount(swapParams);
expect(maxSwapAmount).to.eq(340282366920938463403374607n);
expect(maxSwapAmount).to.eq(39600000000000000000n);
});
test('exact out, 6decimals', () => {
const swapParams = {
swapKind: SwapKind.GivenOut,
amountGivenScaled18: 0n,
balancesLiveScaled18: [
60000000000000000000n,
40000000000000000000n,
],
tokenRates: [1000000000000000000n, 1000000000000000000n],
scalingFactors: [1n, 1000000000000n],
indexIn: 0,
indexOut: 1,
};
const maxSwapAmount = pool.getMaxSwapAmount(swapParams);
expect(maxSwapAmount).to.eq(39600000n);
});
});
describe('with rate', () => {
Expand Down Expand Up @@ -75,9 +109,7 @@ describe('stable pool', () => {
indexOut: 1,
};
const maxSwapAmount = pool.getMaxSwapAmount(swapParams);
expect(maxSwapAmount).to.eq(
170141183460469231701687303715884105728n,
);
expect(maxSwapAmount).to.eq(9900000n);
});
});
});
Expand Down
18 changes: 17 additions & 1 deletion typescript/test/weightedPool.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe('weighted pool', () => {
weights: [60000000000000000000n, 40000000000000000000n],
});
describe('getMaxSwapAmount', () => {
test('exact in', () => {
test('exact in, 18 decimals', () => {
const swapParams = {
swapKind: SwapKind.GivenIn,
amountGivenScaled18: 0n,
Expand All @@ -24,6 +24,22 @@ describe('weighted pool', () => {
const maxSwapAmount = pool.getMaxSwapAmount(swapParams);
expect(maxSwapAmount).to.eq(18000000000000000000n);
});
test('exact in, 6 decimals', () => {
const swapParams = {
swapKind: SwapKind.GivenIn,
amountGivenScaled18: 0n,
balancesLiveScaled18: [
60000000000000000000n,
40000000000000000000n,
],
tokenRates: [1000000000000000000n, 1000000000000000000n],
scalingFactors: [1000000000000n, 1n],
indexIn: 0,
indexOut: 1,
};
const maxSwapAmount = pool.getMaxSwapAmount(swapParams);
expect(maxSwapAmount).to.eq(18000000n);
});
test('exact out', () => {
const swapParams = {
swapKind: SwapKind.GivenOut,
Expand Down

0 comments on commit 2761217

Please sign in to comment.