From dbbaecc6f5d83bfbb31e384810e7c19dae4150ff Mon Sep 17 00:00:00 2001 From: Nguyen Duc Minh Date: Thu, 2 Nov 2023 15:18:39 +0700 Subject: [PATCH] level-finance: get reserves --- .../level-finance/abi/LiquidityPool.json | 13 ++++++ pkg/source/level-finance/constant.go | 8 +++- pkg/source/level-finance/math.go | 20 ++++++--- pkg/source/level-finance/pool_simulator.go | 16 ++++++- .../level-finance/pool_simulator_test.go | 43 +++++++++++++++++++ pkg/source/level-finance/pool_tracker.go | 21 ++++++++- 6 files changed, 111 insertions(+), 10 deletions(-) create mode 100644 pkg/source/level-finance/pool_simulator_test.go diff --git a/pkg/source/level-finance/abi/LiquidityPool.json b/pkg/source/level-finance/abi/LiquidityPool.json index 79e8b1d24..2d8734e95 100644 --- a/pkg/source/level-finance/abi/LiquidityPool.json +++ b/pkg/source/level-finance/abi/LiquidityPool.json @@ -2482,5 +2482,18 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [], + "name": "getAllTranches", + "outputs": [ + { + "internalType": "address[]", + "name": "tranches", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/pkg/source/level-finance/constant.go b/pkg/source/level-finance/constant.go index 82b341274..0960f0d1b 100644 --- a/pkg/source/level-finance/constant.go +++ b/pkg/source/level-finance/constant.go @@ -1,6 +1,9 @@ package levelfinance -import "github.com/KyberNetwork/kyberswap-dex-lib/pkg/util/bignumber" +import ( + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/util/bignumber" + "math/big" +) const ( DexTypeLevelFinance = "level-finance" @@ -28,5 +31,6 @@ const ( var ( DefaultGas = Gas{Swap: 125000} - precision = bignumber.TenPowInt(10) + precision = bignumber.TenPowInt(10) + minSwapFee = big.NewInt(10000000) ) diff --git a/pkg/source/level-finance/math.go b/pkg/source/level-finance/math.go index 25a418833..a357844d9 100644 --- a/pkg/source/level-finance/math.go +++ b/pkg/source/level-finance/math.go @@ -8,6 +8,8 @@ import ( ) func swap(tokenIn, tokenOut string, amountIn *big.Int, state *PoolState) (*big.Int, error) { + // Check allowSwap + if tokenIn == tokenOut { return nil, ErrSameTokenSwap } @@ -33,6 +35,8 @@ func swap(tokenIn, tokenOut string, amountIn *big.Int, state *PoolState) (*big.I rebalanceTranches(tokenInInfo, new(big.Int).Sub(amountIn, daoFee), tokenOutInfo, amountOutAfterFee, state) + // _validateMaxLiquidity + return amountOutAfterFee, nil } @@ -40,8 +44,9 @@ func calcSwapOutput(tokenIn, tokenOut *TokenInfo, amountIn *big.Int, state *Pool priceIn := new(big.Int).Set(tokenIn.MinPrice) priceOut := new(big.Int).Set(tokenOut.MaxPrice) valueChange := new(big.Int).Mul(amountIn, priceIn) - feeIn := calcSwapFee(tokenIn, priceIn, valueChange, true, state) - feeOut := calcSwapFee(tokenOut, priceOut, valueChange, false, state) + isStableSwap := tokenIn.IsStableCoin && tokenOut.IsStableCoin + feeIn := calcSwapFee(isStableSwap, tokenIn, priceIn, valueChange, true, state) + feeOut := calcSwapFee(isStableSwap, tokenOut, priceOut, valueChange, false, state) fee := feeIn if feeIn.Cmp(feeOut) <= 0 { @@ -66,9 +71,9 @@ func calcSwapOutput(tokenIn, tokenOut *TokenInfo, amountIn *big.Int, state *Pool return amountOutAfterFee, feeAmount, nil } -func calcSwapFee(token *TokenInfo, tokenPrice, valueChange *big.Int, isSwapIn bool, state *PoolState) *big.Int { +func calcSwapFee(isStableSwap bool, token *TokenInfo, tokenPrice, valueChange *big.Int, isSwapIn bool, state *PoolState) *big.Int { var baseSwapFee, taxBasicPoint *big.Int - if token.IsStableCoin { + if isStableSwap { baseSwapFee = new(big.Int).Set(state.StableCoinBaseSwapFee) taxBasicPoint = new(big.Int).Set(state.StableCoinTaxBasisPoint) } else { @@ -112,7 +117,11 @@ func calcFeeRate(token *TokenInfo, tokenPrice, valueChange, baseFee, taxBasicPoi new(big.Int).Mul(taxBasicPoint, initDiff), targetValue, ) - return zeroCapSub(baseFee, feeAdjust) + rate := zeroCapSub(baseFee, feeAdjust) + if rate.Cmp(minSwapFee) > 0 { + return rate + } + return new(big.Int).Set(minSwapFee) } else { avgDiff := new(big.Int).Div( new(big.Int).Add(initDiff, nextDiff), @@ -166,6 +175,7 @@ func calcTrancheSharesAmount(indexToken, collateralToken *TokenInfo, amount *big maxShare := make(map[string]*big.Int, len(indexToken.TrancheAssets)) for trancheAddress := range indexToken.TrancheAssets { + reserves[trancheAddress] = big.NewInt(0) asset := collateralToken.TrancheAssets[trancheAddress] factors[trancheAddress] = big.NewInt(1) if !indexToken.IsStableCoin { diff --git a/pkg/source/level-finance/pool_simulator.go b/pkg/source/level-finance/pool_simulator.go index 221284e61..53e184a8e 100644 --- a/pkg/source/level-finance/pool_simulator.go +++ b/pkg/source/level-finance/pool_simulator.go @@ -36,7 +36,14 @@ func NewPoolSimulator(entityPool entity.Pool) (*PoolSimulator, error) { }, }, state: &PoolState{ - TokenInfos: extra.TokenInfos, + TokenInfos: extra.TokenInfos, + TotalWeight: extra.TotalWeight, + VirtualPoolValue: extra.VirtualPoolValue, + StableCoinBaseSwapFee: extra.StableCoinBaseSwapFee, + StableCoinTaxBasisPoint: extra.StableCoinTaxBasisPoint, + BaseSwapFee: extra.BaseSwapFee, + TaxBasisPoint: extra.TaxBasisPoint, + DaoFee: extra.DaoFee, }, }, nil } @@ -74,8 +81,13 @@ func (p *PoolSimulator) UpdateBalance(params pool.UpdateBalanceParams) { return } +func (p *PoolSimulator) GetMetaInfo(tokenIn string, tokenOut string) interface{} { + return nil +} + func (p *PoolSimulator) deepCopyState(state *PoolState) *PoolState { newState := &PoolState{ + TokenInfos: make(map[string]*TokenInfo), TotalWeight: new(big.Int).Set(state.TotalWeight), VirtualPoolValue: new(big.Int).Set(state.VirtualPoolValue), StableCoinBaseSwapFee: new(big.Int).Set(state.StableCoinBaseSwapFee), @@ -88,6 +100,8 @@ func (p *PoolSimulator) deepCopyState(state *PoolState) *PoolState { newState.TokenInfos[key] = &TokenInfo{ IsStableCoin: value.IsStableCoin, TargetWeight: new(big.Int).Set(value.TargetWeight), + TrancheAssets: make(map[string]*AssetInfo), + RiskFactor: make(map[string]*big.Int), TotalRiskFactor: new(big.Int).Set(value.TotalRiskFactor), MinPrice: new(big.Int).Set(value.MinPrice), MaxPrice: new(big.Int).Set(value.MaxPrice), diff --git a/pkg/source/level-finance/pool_simulator_test.go b/pkg/source/level-finance/pool_simulator_test.go new file mode 100644 index 000000000..66b73709c --- /dev/null +++ b/pkg/source/level-finance/pool_simulator_test.go @@ -0,0 +1,43 @@ +package levelfinance_test + +import ( + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/entity" + levelfinance "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/level-finance" + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/pool" + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/util/bignumber" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestCalcAmountOut(t *testing.T) { + levelFinancePool, err := levelfinance.NewPoolSimulator(entity.Pool{ + Address: "0x73c3a78e5ff0d216a50b11d51b262ca839fcfe17", + Exchange: "level-finance", + Type: "level-finance", + Reserves: entity.PoolReserves{"779313577917429145001279", "1386752187018865380131"}, + Tokens: []*entity.PoolToken{ + { + Address: "0x2170ed0880ac9a755fd29b2688956bd959f933f8", + Decimals: 18, + }, + { + Address: "0x55d398326f99059ff775485246999027b3197955", + Decimals: 18, + }, + }, + Extra: "{\"oracle\":\"0x347a868537c96650608b0C38a40d65fA8668bb61\",\"tokenInfos\":{\"0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82\":{\"isStableCoin\":false,\"targetWeight\":0,\"trancheAssets\":{\"0x4265af66537F7BE1Ca60Ca6070D97531EC571BDd\":{\"poolAmount\":0,\"reserveAmount\":0},\"0xB5C42F84Ab3f786bCA9761240546AA9cEC1f8821\":{\"poolAmount\":0,\"reserveAmount\":0},\"0xcC5368f152453D497061CB1fB578D2d3C54bD0A0\":{\"poolAmount\":1515612264199876,\"reserveAmount\":0}},\"riskFactor\":{\"0x4265af66537F7BE1Ca60Ca6070D97531EC571BDd\":0,\"0xB5C42F84Ab3f786bCA9761240546AA9cEC1f8821\":0,\"0xcC5368f152453D497061CB1fB578D2d3C54bD0A0\":0},\"totalRiskFactor\":100000,\"minPrice\":1525411950000,\"maxPrice\":1525411950000},\"0x2170ed0880ac9a755fd29b2688956bd959f933f8\":{\"isStableCoin\":false,\"targetWeight\":25000,\"trancheAssets\":{\"0x4265af66537F7BE1Ca60Ca6070D97531EC571BDd\":{\"poolAmount\":88409477196046758709,\"reserveAmount\":3758081405615144417},\"0xB5C42F84Ab3f786bCA9761240546AA9cEC1f8821\":{\"poolAmount\":1273285914369262213583,\"reserveAmount\":19626301909258985334},\"0xcC5368f152453D497061CB1fB578D2d3C54bD0A0\":{\"poolAmount\":25056795453556407839,\"reserveAmount\":4829823313157371109}},\"riskFactor\":{\"0x4265af66537F7BE1Ca60Ca6070D97531EC571BDd\":0,\"0xB5C42F84Ab3f786bCA9761240546AA9cEC1f8821\":0,\"0xcC5368f152453D497061CB1fB578D2d3C54bD0A0\":0},\"totalRiskFactor\":1,\"minPrice\":1800186152960000,\"maxPrice\":1800186152960000},\"0x55d398326f99059ff775485246999027b3197955\":{\"isStableCoin\":true,\"targetWeight\":41000,\"trancheAssets\":{\"0x4265af66537F7BE1Ca60Ca6070D97531EC571BDd\":{\"poolAmount\":184341536385327250951544,\"reserveAmount\":29495041636499676110955},\"0xB5C42F84Ab3f786bCA9761240546AA9cEC1f8821\":{\"poolAmount\":521599008999365338023501,\"reserveAmount\":14800885608374279815880},\"0xcC5368f152453D497061CB1fB578D2d3C54bD0A0\":{\"poolAmount\":73373032532736556026234,\"reserveAmount\":35744357844692178501361}},\"riskFactor\":{\"0x4265af66537F7BE1Ca60Ca6070D97531EC571BDd\":0,\"0xB5C42F84Ab3f786bCA9761240546AA9cEC1f8821\":0,\"0xcC5368f152453D497061CB1fB578D2d3C54bD0A0\":0},\"totalRiskFactor\":0,\"minPrice\":1000270130000,\"maxPrice\":1000270130000},\"0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c\":{\"isStableCoin\":false,\"targetWeight\":30800,\"trancheAssets\":{\"0x4265af66537F7BE1Ca60Ca6070D97531EC571BDd\":{\"poolAmount\":5816697803176260078,\"reserveAmount\":3383010407777685588},\"0xB5C42F84Ab3f786bCA9761240546AA9cEC1f8821\":{\"poolAmount\":111906233603518278521,\"reserveAmount\":4501534065981811378},\"0xcC5368f152453D497061CB1fB578D2d3C54bD0A0\":{\"poolAmount\":4938928540475400967,\"reserveAmount\":3832600695744573765}},\"riskFactor\":{\"0x4265af66537F7BE1Ca60Ca6070D97531EC571BDd\":0,\"0xB5C42F84Ab3f786bCA9761240546AA9cEC1f8821\":0,\"0xcC5368f152453D497061CB1fB578D2d3C54bD0A0\":0},\"totalRiskFactor\":1,\"minPrice\":34699370809700000,\"maxPrice\":34699370809700000},\"0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c\":{\"isStableCoin\":false,\"targetWeight\":3000,\"trancheAssets\":{\"0x4265af66537F7BE1Ca60Ca6070D97531EC571BDd\":{\"poolAmount\":359302236490299536203,\"reserveAmount\":103226605503390418504},\"0xB5C42F84Ab3f786bCA9761240546AA9cEC1f8821\":{\"poolAmount\":454243991764384413972,\"reserveAmount\":7741757526752034806},\"0xcC5368f152453D497061CB1fB578D2d3C54bD0A0\":{\"poolAmount\":264772809488184251242,\"reserveAmount\":140152480740415789817}},\"riskFactor\":{\"0x4265af66537F7BE1Ca60Ca6070D97531EC571BDd\":0,\"0xB5C42F84Ab3f786bCA9761240546AA9cEC1f8821\":0,\"0xcC5368f152453D497061CB1fB578D2d3C54bD0A0\":0},\"totalRiskFactor\":1,\"minPrice\":230162156910000,\"maxPrice\":230162156910000},\"0xe9e7cea3dedca5984780bafc599bd69add087d56\":{\"isStableCoin\":true,\"targetWeight\":0,\"trancheAssets\":{\"0x4265af66537F7BE1Ca60Ca6070D97531EC571BDd\":{\"poolAmount\":0,\"reserveAmount\":0},\"0xB5C42F84Ab3f786bCA9761240546AA9cEC1f8821\":{\"poolAmount\":0,\"reserveAmount\":0},\"0xcC5368f152453D497061CB1fB578D2d3C54bD0A0\":{\"poolAmount\":4351267527855370,\"reserveAmount\":0}},\"riskFactor\":{\"0x4265af66537F7BE1Ca60Ca6070D97531EC571BDd\":0,\"0xB5C42F84Ab3f786bCA9761240546AA9cEC1f8821\":0,\"0xcC5368f152453D497061CB1fB578D2d3C54bD0A0\":0},\"totalRiskFactor\":0,\"minPrice\":1000370160000,\"maxPrice\":1000370160000}},\"totalWeight\":99800,\"virtualPoolValue\":7631639747905684688745700698456428608,\"stableCoinBaseSwapFee\":1000000,\"stableCoinTaxBasisPoint\":5000000,\"baseSwapFee\":25000000,\"taxBasisPoint\":40000000,\"daoFee\":5500000000}", + }) + + assert.Nil(t, err) + + result, err := levelFinancePool.CalcAmountOut( + pool.TokenAmount{ + Token: "0x2170ed0880ac9a755fd29b2688956bd959f933f8", + Amount: bignumber.NewBig10("1000000000000000000"), + }, + "0x55d398326f99059ff775485246999027b3197955", + ) + + assert.Nil(t, err) + assert.Equal(t, "1789789741024165775187", result.TokenAmountOut.Amount.String()) +} diff --git a/pkg/source/level-finance/pool_tracker.go b/pkg/source/level-finance/pool_tracker.go index 77eaab151..0c93e0e72 100644 --- a/pkg/source/level-finance/pool_tracker.go +++ b/pkg/source/level-finance/pool_tracker.go @@ -141,8 +141,8 @@ func (d *PoolTracker) GetNewPoolState( var tranches = make([]common.Address, 0) if d.config.ChainID == int(valueobject.ChainIDBSC) { + tranches = make([]common.Address, trancheLength.Int64()) for i := 0; i < int(trancheLength.Int64()); i++ { - tranches = append(tranches, common.Address{}) calls.AddCall(ðrpc.Call{ ABI: LiquidityPoolAbi, Target: p.Address, @@ -209,7 +209,6 @@ func (d *PoolTracker) GetNewPoolState( return entity.Pool{}, err } - reserves := make(entity.PoolReserves, len(p.Tokens)) var extra = Extra{ Oracle: oracle.Hex(), TotalWeight: totalWeight, @@ -255,6 +254,12 @@ func (d *PoolTracker) GetNewPoolState( return entity.Pool{}, err } + reserves := make([]string, len(p.Tokens)) + for i, token := range p.Tokens { + reserve := d.getReserve(extra.TokenInfos[token.Address]) + reserves[i] = reserve.PoolAmount.String() + } + p.Extra = string(extraBytes) p.Reserves = reserves p.Timestamp = time.Now().Unix() @@ -266,3 +271,15 @@ func (d *PoolTracker) GetNewPoolState( return p, nil } + +func (d *PoolTracker) getReserve(token *TokenInfo) *AssetInfo { + asset := &AssetInfo{ + PoolAmount: big.NewInt(0), + ReserveAmount: big.NewInt(0), + } + for _, tranche := range token.TrancheAssets { + asset.PoolAmount = new(big.Int).Add(asset.PoolAmount, tranche.PoolAmount) + asset.ReserveAmount = new(big.Int).Add(asset.ReserveAmount, tranche.ReserveAmount) + } + return asset +}