Skip to content

Commit

Permalink
Merge branch 'master' into feat/833-aavev3-dynamic-tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
skypper committed Feb 9, 2023
2 parents 1f6c614 + 4688ffa commit 67ac3e3
Show file tree
Hide file tree
Showing 20 changed files with 981 additions and 239 deletions.
22 changes: 22 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: CI
on: push

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node: ['16.x']
name: Node ${{ matrix.node }} sample
steps:
- uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node }}

- name: Install Dependencies
run: yarn

- name: Run Eslint checks
run: yarn check:es
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# ParaSwap DexLib
# ParaSwap DexLib [![CI](https://github.com/paraswap/paraswap-dex-lib/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/paraswap/paraswap-dex-lib/actions/workflows/ci.yaml)

**DexLib** is a library used by ParaSwap backend to integrate with decentralized exchanges. This library enables external DEX developers to integrate their DEX with ParaSwap by creating pull requests to this repository.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@paraswap/dex-lib",
"version": "2.9.56",
"version": "2.9.57",
"main": "build/index.js",
"types": "build/index.d.ts",
"repository": "https://github.com/paraswap/paraswap-dex-lib",
Expand Down
11 changes: 0 additions & 11 deletions src/dex/balancer-v2/LinearPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,11 +346,6 @@ export class LinearPool extends BasePool {
target: pool.address,
callData: this.poolInterface.encodeFunctionData('getScalingFactors'),
});
//getScalingFactors does not include the rate for the phantom bpt, need to fetch it separately
poolCallData.push({
target: pool.address,
callData: this.poolInterface.encodeFunctionData('getRate'),
});
// returns lowerTarget, upperTarget
poolCallData.push({
target: pool.address,
Expand Down Expand Up @@ -389,12 +384,6 @@ export class LinearPool extends BasePool {
data[startIndex++],
pool.address,
)[0];
const rate = decodeThrowError(
this.poolInterface,
'getRate',
data[startIndex++],
pool.address,
)[0];
const [lowerTarget, upperTarget] = decodeThrowError(
this.poolInterface,
'getTargets',
Expand Down
19 changes: 1 addition & 18 deletions src/dex/balancer-v2/PhantomStablePool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,10 +311,6 @@ export class PhantomStablePool extends BasePool {
target: pool.address,
callData: this.poolInterface.encodeFunctionData('getScalingFactors'),
},
{
target: pool.address,
callData: this.poolInterface.encodeFunctionData('getRate'),
},
{
target: pool.address,
callData: this.poolInterface.encodeFunctionData(
Expand Down Expand Up @@ -373,30 +369,17 @@ export class PhantomStablePool extends BasePool {
data[startIndex++],
pool.address,
)[0];
const rate = decodeThrowError(
this.poolInterface,
'getRate',
data[startIndex++],
pool.address,
)[0];
const amp = decodeThrowError(
this.poolInterface,
'getAmplificationParameter',
data[startIndex++],
pool.address,
);

const bptIndex = pool.tokens.findIndex(
t => t.address.toLowerCase() === pool.address.toLowerCase(),
);

const tokens = poolTokens.tokens.map((address: string, idx: number) => ({
address: address.toLowerCase(),
balance: BigInt(poolTokens.balances[idx].toString()),
scalingFactor:
idx === bptIndex
? BigInt(rate.toString())
: BigInt(scalingFactors[idx].toString()),
scalingFactor: BigInt(scalingFactors[idx].toString()),
}));

const poolState: PoolState = {
Expand Down
148 changes: 94 additions & 54 deletions src/dex/balancer-v2/balancer-v2-integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,61 +50,24 @@ const amounts = [0n, BI_POWS[18], 2000000000000000000n];
const dexKey = 'BalancerV2';

describe('BalancerV2', function () {
describe('BeetsFi', () => {
it('FTM -> BOO: getPoolIdentifiers and getPricesVolume', async () => {
const dexKey = 'BeetsFi';
const network = Network.FANTOM;
const srcToken = Tokens[network]['FTM'];
const destToken = Tokens[network]['BOO'];
const amounts = [0n, BI_POWS[18]];
describe('ComposableStable', () => {
it('USDC -> USDT getPoolIdentifiers and getPricesVolume', async () => {
const network = Network.MAINNET;
const srcToken = Tokens[network]['USDC'];
const destToken = Tokens[network]['USDT'];
const amounts = [0n, 10000001000000n];

const dexHelper = new DummyDexHelper(network);
// const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber();
const blockNumber = 54734626;
const beetsFi = new BalancerV2(network, dexKey, dexHelper);

await beetsFi.initializePricing(blockNumber);

const pools = await beetsFi.getPoolIdentifiers(
srcToken,
destToken,
SwapSide.SELL,
blockNumber,
);
console.log('Pool Identifiers: ', pools);
const blockNumber = await dexHelper.web3Provider.eth.getBlockNumber();
// You will need blockTimestamp to check onchain calculation, because
// it depends on timestamp. If you have different values, they are incomparable
// const block = await dexHelper.web3Provider.eth.getBlock(blockNumber);

expect(pools.length).toBeGreaterThan(0);
const balancerV2 = new BalancerV2(network, dexKey, dexHelper);

const poolPrices = await beetsFi.getPricesVolume(
srcToken,
destToken,
amounts,
SwapSide.SELL,
blockNumber,
pools,
);
console.log('Pool Prices: ', poolPrices);
await balancerV2.initializePricing(blockNumber);

expect(poolPrices).not.toBeNull();
checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey);

await beetsFi.releaseResources();
});
it('WETH -> FTM: getPoolIdentifiers and getPricesVolume', async () => {
const dexKey = 'BeetsFi';
const network = Network.FANTOM;
const srcToken = Tokens[network]['WETH'];
const destToken = Tokens[network]['FTM'];
const amounts = [0n, BI_POWS[18]];

const dexHelper = new DummyDexHelper(network);
// const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber();
const blockNumber = 54782005;
const beetsFi = new BalancerV2(network, dexKey, dexHelper);

await beetsFi.initializePricing(blockNumber);

const pools = await beetsFi.getPoolIdentifiers(
const pools = await balancerV2.getPoolIdentifiers(
srcToken,
destToken,
SwapSide.SELL,
Expand All @@ -114,7 +77,7 @@ describe('BalancerV2', function () {

expect(pools.length).toBeGreaterThan(0);

const poolPrices = await beetsFi.getPricesVolume(
const poolPrices = await balancerV2.getPricesVolume(
srcToken,
destToken,
amounts,
Expand All @@ -127,11 +90,9 @@ describe('BalancerV2', function () {
expect(poolPrices).not.toBeNull();
checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey);

await beetsFi.releaseResources();
await balancerV2.releaseResources();
});
});

describe('ComposableStable', () => {
it('getPoolIdentifiers and getPricesVolume', async () => {
const dexHelper = new DummyDexHelper(Network.POLYGON);
const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber();
Expand Down Expand Up @@ -397,3 +358,82 @@ describe('BalancerV2', function () {
});
});
});

describe('BeetsFi', () => {
it('FTM -> BOO: getPoolIdentifiers and getPricesVolume', async () => {
const dexKey = 'BeetsFi';
const network = Network.FANTOM;
const srcToken = Tokens[network]['FTM'];
const destToken = Tokens[network]['BOO'];
const amounts = [0n, BI_POWS[18]];

const dexHelper = new DummyDexHelper(network);
const blockNumber = await dexHelper.web3Provider.eth.getBlockNumber();
const beetsFi = new BalancerV2(network, dexKey, dexHelper);

await beetsFi.initializePricing(blockNumber);

const pools = await beetsFi.getPoolIdentifiers(
srcToken,
destToken,
SwapSide.SELL,
blockNumber,
);
console.log('Pool Identifiers: ', pools);

expect(pools.length).toBeGreaterThan(0);

const poolPrices = await beetsFi.getPricesVolume(
srcToken,
destToken,
amounts,
SwapSide.SELL,
blockNumber,
pools,
);
console.log('Pool Prices: ', poolPrices);

expect(poolPrices).not.toBeNull();
checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey);

await beetsFi.releaseResources();
});
it('WETH -> FTM: getPoolIdentifiers and getPricesVolume', async () => {
const dexKey = 'BeetsFi';
const network = Network.FANTOM;
const srcToken = Tokens[network]['WETH'];
const destToken = Tokens[network]['FTM'];
const amounts = [0n, BI_POWS[18]];

const dexHelper = new DummyDexHelper(network);
const blockNumber = await dexHelper.web3Provider.eth.getBlockNumber();
const beetsFi = new BalancerV2(network, dexKey, dexHelper);

await beetsFi.initializePricing(blockNumber);

const pools = await beetsFi.getPoolIdentifiers(
srcToken,
destToken,
SwapSide.SELL,
blockNumber,
);
console.log('Pool Identifiers: ', pools);

expect(pools.length).toBeGreaterThan(0);

const poolPrices = await beetsFi.getPricesVolume(
srcToken,
destToken,
amounts,
SwapSide.SELL,
blockNumber,
pools,
);
console.log('Pool Prices: ', poolPrices);

expect(poolPrices).not.toBeNull();
checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey);

await beetsFi.releaseResources();
});
});
21 changes: 13 additions & 8 deletions src/dex/balancer-v2/balancer-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ import {
poolGetMainTokens,
poolGetPathForTokenInOut,
} from './utils';
import { MIN_USD_LIQUIDITY_TO_FETCH } from './constants';
import {
MIN_USD_LIQUIDITY_TO_FETCH,
STABLE_GAS_COST,
VARIABLE_GAS_COST_PER_CYCLE,
} from './constants';

const fetchAllPools = `query ($count: Int) {
pools: pools(
Expand Down Expand Up @@ -158,11 +162,11 @@ export class BalancerV2EventPool extends StatefulEventSubscriber<PoolStateMap> {
The difference of note for swaps is ComposableStable must use 'actualSupply' instead of VirtualSupply.
VirtualSupply could be calculated easily whereas actualSupply cannot hence the use of onchain call.
*/
// const composableStable = new PhantomStablePool(
// this.vaultAddress,
// this.vaultInterface,
// true,
// );
const composableStable = new PhantomStablePool(
this.vaultAddress,
this.vaultInterface,
true,
);
const linearPool = new LinearPool(this.vaultAddress, this.vaultInterface);

this.pools = {};
Expand All @@ -177,7 +181,7 @@ export class BalancerV2EventPool extends StatefulEventSubscriber<PoolStateMap> {
// Beets uses "Linear" generically for all linear pool types
this.pools[BalancerPoolTypes.Linear] = linearPool;
this.pools[BalancerPoolTypes.StablePhantom] = stablePhantomPool;
// this.pools[BalancerPoolTypes.ComposableStable] = composableStable;
this.pools[BalancerPoolTypes.ComposableStable] = composableStable;
this.vaultDecoder = (log: Log) => this.vaultInterface.parseLog(log);
this.addressesSubscribed = [vaultAddress];

Expand Down Expand Up @@ -760,7 +764,8 @@ export class BalancerV2
},
poolAddresses: [poolAddress],
exchange: this.dexKey,
gasCost: 150 * 1000 * (path.length - 1),
gasCost:
STABLE_GAS_COST + VARIABLE_GAS_COST_PER_CYCLE * path.length,
poolIdentifier: `${this.dexKey}_${poolAddress}`,
};

Expand Down
9 changes: 9 additions & 0 deletions src/dex/balancer-v2/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
export const MIN_USD_LIQUIDITY_TO_FETCH = 100n;

// Let's take this trade as an example:
// https://dashboard.tenderly.co/paraswap/paraswap/fork/e4c81946-fd6e-4299-b35c-c47b775e3c05/simulation/8839462c-6239-4ae1-9ed0-8013f89b41de/gas-usage

// 271719 - 57856 - 79098 - 51041 = 83724 ~ 84k
export const STABLE_GAS_COST = 84_000;

// I see three pools used in trade: (57856 + 79098 + 51041) / 3 = 62665 ~ 63k
export const VARIABLE_GAS_COST_PER_CYCLE = 63_000;
2 changes: 1 addition & 1 deletion src/dex/balancer-v2/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export enum BalancerPoolTypes {
StablePhantom = 'StablePhantom',
ERC4626Linear = 'ERC4626Linear',
Linear = 'Linear',
// ComposableStable = 'ComposableStable',
ComposableStable = 'ComposableStable',
}

export type TokenState = {
Expand Down
4 changes: 2 additions & 2 deletions src/dex/balancer-v2/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ function isLinearPool(poolType: string) {

function isPhantomStablePool(poolType: string) {
return (
poolType === BalancerPoolTypes.StablePhantom
// || poolType === BalancerPoolTypes.ComposableStable
poolType === BalancerPoolTypes.StablePhantom ||
poolType === BalancerPoolTypes.ComposableStable
);
}

Expand Down
Loading

0 comments on commit 67ac3e3

Please sign in to comment.