Unverified Commit 3eb0dbe4 authored by Matt, Park's avatar Matt, Park Committed by GitHub
Browse files

Implement Swap logic for concentrated liquidity (#3177)


* initial push

* Add swap method

* Revert zeroForOne

* Fix test

Co-authored-by: default avatarAdam Tucker <adamleetucker@outlook.com>
parent 6a08016c
Showing with 241 additions and 101 deletions
+241 -101
......@@ -20,7 +20,7 @@ message Pool {
// Amount of total liquidity
string liquidity = 3 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.moretags) = "yaml:\"liquidity\"",
(gogoproto.nullable) = false
];
......
......@@ -34,7 +34,7 @@ type Pool struct {
Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty" yaml:"address"`
Id uint64 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"`
// Amount of total liquidity
Liquidity github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,3,opt,name=liquidity,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"liquidity" yaml:"liquidity"`
Liquidity github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=liquidity,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"liquidity" yaml:"liquidity"`
Token0 string `protobuf:"bytes,4,opt,name=token0,proto3" json:"token0,omitempty"`
Token1 string `protobuf:"bytes,5,opt,name=token1,proto3" json:"token1,omitempty"`
CurrentSqrtPrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=current_sqrt_price,json=currentSqrtPrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"current_sqrt_price" yaml:"spot_price"`
......@@ -159,39 +159,39 @@ func init() {
}
var fileDescriptor_b144264ce94bcf63 = []byte{
// 497 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x53, 0x3f, 0x6f, 0xd3, 0x40,
0x14, 0xb7, 0xdb, 0x34, 0x6d, 0x8e, 0x12, 0xda, 0xa3, 0xaa, 0x4c, 0x07, 0xbb, 0x3a, 0x09, 0xd4,
0x81, 0xd8, 0x18, 0xc4, 0x52, 0x31, 0x85, 0xbf, 0x59, 0x50, 0x64, 0x10, 0x03, 0x4b, 0x70, 0xce,
0x47, 0x7a, 0xb2, 0x73, 0x17, 0xdf, 0x5d, 0x2a, 0xf2, 0x0d, 0x18, 0x19, 0x19, 0xfb, 0x21, 0xf8,
0x0c, 0xa8, 0x62, 0xea, 0x88, 0x18, 0x2c, 0x94, 0x6c, 0x8c, 0xf9, 0x04, 0xc8, 0xf6, 0xc5, 0x4d,
0x2b, 0x31, 0x64, 0x60, 0xb2, 0xdf, 0xef, 0xbd, 0xf7, 0xfb, 0xfd, 0x74, 0xef, 0x3d, 0xf0, 0x98,
0xcb, 0x21, 0x97, 0x54, 0x7a, 0x98, 0x33, 0x4c, 0x98, 0x12, 0xa1, 0x22, 0x51, 0x2b, 0xa1, 0xe9,
0x98, 0x46, 0x54, 0x4d, 0xae, 0xc0, 0x5d, 0xce, 0x13, 0x77, 0x24, 0xb8, 0xe2, 0xf0, 0xae, 0x6e,
0x73, 0x97, 0xf3, 0x55, 0x97, 0x7b, 0xea, 0xf7, 0x89, 0x0a, 0xfd, 0x83, 0x3b, 0xb8, 0xa8, 0xeb,
0x15, 0x4d, 0x5e, 0x19, 0x94, 0x0c, 0x07, 0x7b, 0x03, 0x3e, 0xe0, 0x25, 0x9e, 0xff, 0x95, 0x28,
0xfa, 0xbe, 0x0e, 0x6a, 0xb9, 0x0c, 0xbc, 0x0f, 0x36, 0xc3, 0x28, 0x12, 0x44, 0x4a, 0xcb, 0x3c,
0x34, 0x8f, 0x1a, 0x6d, 0x38, 0xcf, 0x9c, 0xe6, 0x24, 0x1c, 0x26, 0xc7, 0x48, 0x27, 0x50, 0xb0,
0x28, 0x81, 0x4d, 0xb0, 0x46, 0x23, 0x6b, 0xed, 0xd0, 0x3c, 0xaa, 0x05, 0x6b, 0x34, 0x82, 0x1f,
0x40, 0xa3, 0x32, 0x63, 0xad, 0x17, 0xfd, 0xed, 0xf3, 0xcc, 0x31, 0x7e, 0x65, 0xce, 0xbd, 0x01,
0x55, 0x27, 0xe3, 0xbe, 0x8b, 0xf9, 0x50, 0x1b, 0xd2, 0x9f, 0x96, 0x8c, 0x62, 0x4f, 0x4d, 0x46,
0x44, 0xba, 0x1d, 0xa6, 0xe6, 0x99, 0xb3, 0x53, 0xaa, 0x55, 0x44, 0x28, 0xb8, 0x24, 0x85, 0xfb,
0xa0, 0xae, 0x78, 0x4c, 0xd8, 0x03, 0xab, 0x96, 0xd3, 0x07, 0x3a, 0xaa, 0x70, 0xdf, 0xda, 0x58,
0xc2, 0x7d, 0x98, 0x02, 0x88, 0xc7, 0x42, 0x10, 0xa6, 0x7a, 0x32, 0x15, 0xaa, 0x37, 0x12, 0x14,
0x13, 0xab, 0x5e, 0x58, 0x7b, 0xba, 0x82, 0xb5, 0x67, 0x04, 0xcf, 0x33, 0x67, 0xb7, 0xb4, 0x26,
0x47, 0x5c, 0x33, 0xa1, 0x60, 0x47, 0xd3, 0xbf, 0x49, 0x85, 0xea, 0xe6, 0x10, 0x3c, 0x01, 0xdb,
0x0b, 0x49, 0x45, 0x71, 0x6c, 0x6d, 0x16, 0x62, 0xcf, 0x57, 0x7e, 0x87, 0xdb, 0xa5, 0xd8, 0x32,
0x17, 0x0a, 0x6e, 0xe8, 0xf0, 0x2d, 0xc5, 0xf1, 0xf1, 0xee, 0xe7, 0x33, 0xc7, 0xf8, 0x7a, 0xe6,
0x18, 0x3f, 0xbe, 0xb5, 0x36, 0xf2, 0xf1, 0x75, 0xd0, 0x1f, 0x13, 0x6c, 0xe5, 0xb9, 0x0e, 0xfb,
0xc8, 0x61, 0x0a, 0x6e, 0x55, 0x2f, 0xd7, 0x1b, 0x08, 0x5e, 0x0d, 0xf5, 0xd5, 0xca, 0x66, 0xf6,
0xaf, 0x0d, 0xa5, 0xa4, 0x43, 0x41, 0xb3, 0x42, 0x5e, 0xe6, 0x00, 0x8c, 0xc1, 0xcd, 0xcb, 0x1a,
0x46, 0x54, 0xb1, 0x1c, 0x8d, 0xf6, 0x8b, 0x95, 0x05, 0xf7, 0xae, 0x0b, 0x32, 0xa2, 0x50, 0xb0,
0x5d, 0xc5, 0xaf, 0x89, 0x42, 0x09, 0xd8, 0xea, 0x72, 0x49, 0x15, 0xe5, 0xec, 0xea, 0xea, 0x99,
0xff, 0x61, 0xf5, 0xda, 0xef, 0xce, 0xa7, 0xb6, 0x79, 0x31, 0xb5, 0xcd, 0xdf, 0x53, 0xdb, 0xfc,
0x32, 0xb3, 0x8d, 0x8b, 0x99, 0x6d, 0xfc, 0x9c, 0xd9, 0xc6, 0xfb, 0x27, 0x4b, 0x02, 0xfa, 0x40,
0x5b, 0x49, 0xd8, 0x97, 0x8b, 0xc0, 0x3b, 0xf5, 0x1f, 0x7a, 0x9f, 0xfe, 0x71, 0xea, 0xfd, 0x7a,
0x71, 0x82, 0x8f, 0xfe, 0x06, 0x00, 0x00, 0xff, 0xff, 0x11, 0xb1, 0x92, 0xc3, 0x13, 0x04, 0x00,
0x00,
// 500 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0x3f, 0x6f, 0xd3, 0x40,
0x14, 0xb7, 0xd3, 0x34, 0x6d, 0x8e, 0x12, 0xda, 0xa3, 0xaa, 0x4c, 0x07, 0xbb, 0x3a, 0x09, 0xd4,
0x81, 0xd8, 0x18, 0xc4, 0x52, 0x31, 0x85, 0xbf, 0x59, 0x50, 0x64, 0x10, 0x03, 0x4b, 0x70, 0xec,
0x23, 0x3d, 0xd9, 0xf1, 0xc5, 0x77, 0x97, 0x8a, 0x7c, 0x03, 0x46, 0x46, 0xc6, 0x7e, 0x08, 0x3e,
0x03, 0xaa, 0x98, 0x3a, 0x22, 0x06, 0x0b, 0x25, 0x1b, 0x63, 0x3e, 0x01, 0xb2, 0xef, 0xe2, 0xa6,
0x91, 0x40, 0xf2, 0x64, 0xbf, 0xdf, 0x7b, 0xef, 0xf7, 0xfb, 0xe9, 0xde, 0x7b, 0xe0, 0x31, 0xe5,
0x23, 0xca, 0x09, 0x77, 0x02, 0x9a, 0x04, 0x38, 0x11, 0xcc, 0x17, 0x38, 0x6c, 0xc7, 0x24, 0x9d,
0x90, 0x90, 0x88, 0xe9, 0x35, 0xb8, 0x47, 0x69, 0x6c, 0x8f, 0x19, 0x15, 0x14, 0xde, 0x55, 0x6d,
0xf6, 0x6a, 0xbe, 0xec, 0xb2, 0xcf, 0xdc, 0x01, 0x16, 0xbe, 0x7b, 0x78, 0x27, 0x28, 0xea, 0xfa,
0x45, 0x93, 0x23, 0x03, 0xc9, 0x70, 0xb8, 0x3f, 0xa4, 0x43, 0x2a, 0xf1, 0xfc, 0x4f, 0xa2, 0xe8,
0xfb, 0x06, 0xa8, 0xe7, 0x32, 0xf0, 0x3e, 0xd8, 0xf2, 0xc3, 0x90, 0x61, 0xce, 0x0d, 0xfd, 0x48,
0x3f, 0x6e, 0x76, 0xe0, 0x22, 0xb3, 0x5a, 0x53, 0x7f, 0x14, 0x9f, 0x20, 0x95, 0x40, 0xde, 0xb2,
0x04, 0xb6, 0x40, 0x8d, 0x84, 0x46, 0xed, 0x48, 0x3f, 0xae, 0x7b, 0x35, 0x12, 0xc2, 0x0f, 0xa0,
0x59, 0x9a, 0x31, 0x36, 0x8a, 0xfe, 0xce, 0x45, 0x66, 0x69, 0xbf, 0x32, 0xeb, 0xde, 0x90, 0x88,
0xd3, 0xc9, 0xc0, 0x0e, 0xe8, 0x48, 0x19, 0x52, 0x9f, 0x36, 0x0f, 0x23, 0x47, 0x4c, 0xc7, 0x98,
0xdb, 0xcf, 0x70, 0xb0, 0xc8, 0xac, 0x5d, 0xa9, 0x56, 0x12, 0x21, 0xef, 0x8a, 0x14, 0x1e, 0x80,
0x86, 0xa0, 0x11, 0x4e, 0x1e, 0x18, 0xf5, 0x9c, 0xde, 0x53, 0x51, 0x89, 0xbb, 0xc6, 0xe6, 0x0a,
0xee, 0xc2, 0x14, 0xc0, 0x60, 0xc2, 0x18, 0x4e, 0x44, 0x9f, 0xa7, 0x4c, 0xf4, 0xc7, 0x8c, 0x04,
0xd8, 0x68, 0x14, 0xd6, 0x9e, 0x56, 0xb6, 0xb6, 0x27, 0xad, 0xf1, 0x31, 0x55, 0x4c, 0xc8, 0xdb,
0x55, 0xf4, 0x6f, 0x52, 0x26, 0x7a, 0x39, 0x04, 0x4f, 0xc1, 0xce, 0x52, 0x52, 0x90, 0x20, 0x32,
0xb6, 0x0a, 0xb1, 0xe7, 0x15, 0xc4, 0xba, 0x89, 0x58, 0x64, 0xd6, 0x6d, 0x29, 0xb6, 0xca, 0x85,
0xbc, 0x1b, 0x2a, 0x7c, 0x4b, 0x82, 0xe8, 0x64, 0xef, 0xf3, 0xb9, 0xa5, 0x7d, 0x3d, 0xb7, 0xb4,
0x1f, 0xdf, 0xda, 0x9b, 0xf9, 0xf8, 0xba, 0xe8, 0x8f, 0x0e, 0xb6, 0xf3, 0x5c, 0x37, 0xf9, 0x48,
0x61, 0x0a, 0x6e, 0x95, 0x2f, 0xd7, 0x1f, 0x32, 0x5a, 0x0e, 0xf5, 0x55, 0x65, 0x33, 0x07, 0x6b,
0x43, 0x91, 0x74, 0xc8, 0x6b, 0x95, 0xc8, 0xcb, 0x1c, 0x80, 0x11, 0xb8, 0x79, 0x55, 0x93, 0x60,
0x51, 0x2c, 0x47, 0xb3, 0xf3, 0xa2, 0xb2, 0xe0, 0xfe, 0xba, 0x60, 0x82, 0x05, 0xf2, 0x76, 0xca,
0xf8, 0x35, 0x16, 0x28, 0x06, 0xdb, 0x3d, 0xca, 0x89, 0x20, 0x34, 0xb9, 0xbe, 0x7a, 0x7a, 0xe5,
0xd5, 0x93, 0xa2, 0xff, 0x5b, 0xbd, 0xce, 0xbb, 0x8b, 0x99, 0xa9, 0x5f, 0xce, 0x4c, 0xfd, 0xf7,
0xcc, 0xd4, 0xbf, 0xcc, 0x4d, 0xed, 0x72, 0x6e, 0x6a, 0x3f, 0xe7, 0xa6, 0xf6, 0xfe, 0xc9, 0x8a,
0x80, 0x3a, 0xd0, 0x76, 0xec, 0x0f, 0xf8, 0x32, 0x70, 0xce, 0xdc, 0x87, 0xce, 0xa7, 0x7f, 0x9c,
0xfa, 0xa0, 0x51, 0x9c, 0xe0, 0xa3, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xd9, 0xbf, 0x18,
0x13, 0x04, 0x00, 0x00,
}
func (m *Pool) Marshal() (dAtA []byte, err error) {
......
......@@ -58,3 +58,7 @@ func Liquidity0(amount sdk.Int, sqrtPriceA, sqrtPriceB sdk.Dec) sdk.Dec {
func Liquidity1(amount sdk.Int, sqrtPriceA, sqrtPriceB sdk.Dec) sdk.Dec {
return liquidity1(amount, sqrtPriceA, sqrtPriceB)
}
func (k Keeper) GetPoolbyId(ctx sdk.Context, poolId uint64) Pool {
return k.getPoolbyId(ctx, poolId)
}
......@@ -62,18 +62,20 @@ func (k Keeper) createPosition(ctx sdk.Context, poolId uint64, owner sdk.AccAddr
return sdk.Int{}, sdk.Int{}, sdk.Dec{}, err
}
// update pool state as well only if we're injecting liquidity at the current tick of the pool
if pool.CurrentTick.LT(sdk.NewInt(lowerTick)) {
amtDenom0 = calcAmount0Delta(liquidity, sqrtRatioLowerTick, sqrtRatioUpperTick).RoundInt()
amtDenom1 = sdk.ZeroInt()
} else if pool.CurrentTick.LT(sdk.NewInt(upperTick)) {
amtDenom0 = calcAmount0Delta(liquidity, currentSqrtPrice, sqrtRatioUpperTick).RoundInt()
amtDenom1 = calcAmount1Delta(liquidity, currentSqrtPrice, sqrtRatioLowerTick).RoundInt()
pool.Liquidity = pool.Liquidity.Add(liquidity)
} else {
amtDenom0 = sdk.ZeroInt()
amtDenom1 = calcAmount1Delta(liquidity, sqrtRatioLowerTick, sqrtRatioUpperTick).RoundInt()
}
liquidityCreated = getLiquidityFromAmounts(currentSqrtPrice, sqrtRatioUpperTick, sqrtRatioLowerTick, amtDenom0, amtDenom1)
k.setPoolById(ctx, pool.Id, pool)
return amtDenom0, amtDenom1, liquidityCreated, nil
}
......
......@@ -22,6 +22,7 @@ func (k Keeper) CreateNewConcentratedLiquidityPool(ctx sdk.Context, poolId uint6
Id: poolId,
CurrentSqrtPrice: currSqrtPrice,
CurrentTick: currTick,
Liquidity: sdk.ZeroDec(),
Token0: denom0,
Token1: denom1,
}
......@@ -68,8 +69,15 @@ func (p Pool) GetTotalShares() sdk.Int {
return sdk.Int{}
}
func (p Pool) SwapOutAmtGivenIn(ctx sdk.Context, tokenIn sdk.Coins, tokenOutDenom string, swapFee sdk.Dec) (tokenOut sdk.Coin, err error) {
return sdk.Coin{}, nil
func (k Keeper) SwapOutAmtGivenIn(ctx sdk.Context, tokenIn sdk.Coin, tokenOutDenom string, swapFee sdk.Dec, minPrice, maxPrice sdk.Dec, poolId uint64) (tokenOut sdk.Coin, err error) {
tokenInCoin, newLiquidity, newCurrentTick, newCurrentSqrtPrice, err := k.CalcOutAmtGivenIn(ctx, tokenIn, tokenOutDenom, swapFee, minPrice, maxPrice, poolId)
if err != nil {
return sdk.Coin{}, err
}
k.applySwap(ctx, tokenInCoin, tokenOut, poolId, newLiquidity, newCurrentTick, newCurrentSqrtPrice)
return tokenInCoin, nil
}
func (p Pool) SpotPrice(ctx sdk.Context, baseAssetDenom string, quoteAssetDenom string) (sdk.Dec, error) {
......@@ -85,7 +93,12 @@ type SwapState struct {
}
// this only works on a single directional trade, will implement bi directional trade in next milestone
func (k Keeper) CalcOutAmtGivenIn(ctx sdk.Context, tokenIn sdk.Coin, tokenOutDenom string, swapFee sdk.Dec, minPrice, maxPrice sdk.Dec, poolId uint64) (newTokenIn, tokenOut sdk.Coin, err error) {
func (k Keeper) CalcOutAmtGivenIn(ctx sdk.Context,
tokenIn sdk.Coin,
tokenOutDenom string,
swapFee sdk.Dec,
minPrice, maxPrice sdk.Dec,
poolId uint64) (tokenOut sdk.Coin, newLiquidity sdk.Dec, currTick sdk.Int, currSqrtPrice sdk.Dec, err error) {
p := k.getPoolbyId(ctx, poolId)
asset0 := p.Token0
asset1 := p.Token1
......@@ -98,30 +111,30 @@ func (k Keeper) CalcOutAmtGivenIn(ctx sdk.Context, tokenIn sdk.Coin, tokenOutDen
// validation
if tokenIn.Denom != asset0 && tokenIn.Denom != asset1 {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("tokenIn (%s) does not match any asset in pool", tokenIn.Denom)
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("tokenIn (%s) does not match any asset in pool", tokenIn.Denom)
}
if tokenOutDenom != asset0 && tokenOutDenom != asset1 {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("tokenOutDenom (%s) does not match any asset in pool", tokenOutDenom)
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("tokenOutDenom (%s) does not match any asset in pool", tokenOutDenom)
}
if tokenIn.Denom == tokenOutDenom {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("tokenIn (%s) cannot be the same as tokenOut (%s)", tokenIn.Denom, tokenOutDenom)
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("tokenIn (%s) cannot be the same as tokenOut (%s)", tokenIn.Denom, tokenOutDenom)
}
if minPrice.GTE(curSqrtPrice.Power(2)) {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("minPrice (%s) must be less than current price (%s)", minPrice, curSqrtPrice.Power(2))
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("minPrice (%s) must be less than current price (%s)", minPrice, curSqrtPrice.Power(2))
}
if maxPrice.LTE(curSqrtPrice.Power(2)) {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("maxPrice (%s) must be greater than current price (%s)", maxPrice, curSqrtPrice.Power(2))
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("maxPrice (%s) must be greater than current price (%s)", maxPrice, curSqrtPrice.Power(2))
}
// sqrtPrice of upper and lower user defined price range
sqrtPLowerTick, err := minPrice.ApproxSqrt()
if err != nil {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("issue calculating square root of minPrice")
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("issue calculating square root of minPrice")
}
sqrtPUpperTick, err := maxPrice.ApproxSqrt()
if err != nil {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("issue calculating square root of maxPrice")
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("issue calculating square root of maxPrice")
}
// TODO: How do we remove/generalize this? I am stumped.
......@@ -141,6 +154,7 @@ func (k Keeper) CalcOutAmtGivenIn(ctx sdk.Context, tokenIn sdk.Coin, tokenOutDen
amountCalculated: sdk.ZeroDec(),
sqrtPrice: curSqrtPrice,
tick: priceToTick(curSqrtPrice.Power(2)),
liquidity: p.Liquidity,
}
// TODO: This should be GT 0 but some instances have very small remainder
......@@ -148,11 +162,12 @@ func (k Keeper) CalcOutAmtGivenIn(ctx sdk.Context, tokenIn sdk.Coin, tokenOutDen
for swapState.amountSpecifiedRemaining.GT(sdk.NewDecWithPrec(1, 6)) {
nextTick, ok := k.NextInitializedTick(ctx, poolId, swapState.tick.Int64(), zeroForOne)
if !ok {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("there are no more ticks initialized to fill the swap")
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("there are no more ticks initialized to fill the swap")
}
nextSqrtPrice, err := k.tickToSqrtPrice(sdk.NewInt(nextTick))
if err != nil {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("could not convert next tick (%v) to nextSqrtPrice", sdk.NewInt(nextTick))
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("could not convert next tick (%v) to nextSqrtPrice", sdk.NewInt(nextTick))
}
sqrtPrice, amountIn, amountOut := computeSwapStep(
......@@ -162,20 +177,26 @@ func (k Keeper) CalcOutAmtGivenIn(ctx sdk.Context, tokenIn sdk.Coin, tokenOutDen
swapState.amountSpecifiedRemaining,
zeroForOne,
)
fmt.Println("===sqrt price")
fmt.Println(sqrtPrice.String())
fmt.Println("===next sqrt price")
fmt.Println(nextSqrtPrice.String())
swapState.amountSpecifiedRemaining = swapState.amountSpecifiedRemaining.Sub(amountIn)
swapState.amountCalculated = swapState.amountCalculated.Add(amountOut)
// if we have moved to the next tick,
if nextSqrtPrice.Equal(sqrtPrice) {
liquidityDelta, err := k.crossTick(ctx, p.Id, nextTick)
if err != nil {
return sdk.Coin{}, sdk.Coin{}, err
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), err
}
if zeroForOne {
liquidityDelta = liquidityDelta.Neg()
}
swapState.liquidity = swapState.liquidity.Add(liquidityDelta.ToDec())
if swapState.liquidity.LTE(sdk.ZeroDec()) || swapState.liquidity.IsNil() {
return sdk.Coin{}, sdk.Coin{}, err
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), err
}
if zeroForOne {
swapState.tick = sdk.NewInt(nextTick - 1)
......@@ -186,16 +207,23 @@ func (k Keeper) CalcOutAmtGivenIn(ctx sdk.Context, tokenIn sdk.Coin, tokenOutDen
swapState.tick = priceToTick(sqrtPrice.Power(2))
}
}
tokenOut = sdk.NewCoin(tokenOutDenom, swapState.amountCalculated.RoundInt())
newTokenIn.Amount = tokenIn.Amount.Sub(swapState.amountSpecifiedRemaining.RoundInt())
return sdk.NewCoin(tokenIn.Denom, newTokenIn.Amount), sdk.NewCoin(tokenOutDenom, swapState.amountCalculated.RoundInt()), nil
return tokenOut, swapState.liquidity, swapState.tick, swapState.sqrtPrice, nil
}
func (p Pool) SwapInAmtGivenOut(ctx sdk.Context, tokenOut sdk.Coins, tokenInDenom string, swapFee sdk.Dec) (tokenIn sdk.Coin, err error) {
return sdk.Coin{}, nil
func (k *Keeper) SwapInAmtGivenOut(ctx sdk.Context, tokenOut sdk.Coin, tokenInDenom string, swapFee sdk.Dec, minPrice, maxPrice sdk.Dec, poolId uint64) (tokenIn sdk.Coin, err error) {
tokenInCoin, newLiquidity, newCurrentTick, newCurrentSqrtPrice, err := k.CalcInAmtGivenOut(ctx, tokenOut, tokenInDenom, swapFee, sdk.ZeroDec(), sdk.NewDec(9999999999), poolId)
if err != nil {
return sdk.Coin{}, err
}
k.applySwap(ctx, tokenInCoin, tokenOut, poolId, newLiquidity, newCurrentTick, newCurrentSqrtPrice)
return tokenInCoin, nil
}
func (k Keeper) CalcInAmtGivenOut(ctx sdk.Context, tokenOut sdk.Coin, tokenInDenom string, swapFee sdk.Dec, minPrice, maxPrice sdk.Dec, poolId uint64) (tokenIn, newTokenOut sdk.Coin, err error) {
func (k Keeper) CalcInAmtGivenOut(ctx sdk.Context, tokenOut sdk.Coin, tokenInDenom string, swapFee sdk.Dec, minPrice, maxPrice sdk.Dec, poolId uint64) (sdk.Coin, sdk.Dec, sdk.Int, sdk.Dec, error) {
tokenOutAmt := tokenOut.Amount.ToDec()
p := k.getPoolbyId(ctx, poolId)
asset0 := p.Token0
......@@ -203,35 +231,34 @@ func (k Keeper) CalcInAmtGivenOut(ctx sdk.Context, tokenOut sdk.Coin, tokenInDen
zeroForOne := tokenOut.Denom == asset0
// get current sqrt price from pool
// curSqrtPrice := sdk.NewDecWithPrec(int64(p.CurrentSqrtPrice.Uint64()), 6)
curSqrtPrice := p.CurrentSqrtPrice
// validation
if tokenOut.Denom != asset0 && tokenOut.Denom != asset1 {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("tokenOut denom (%s) does not match any asset in pool", tokenOut.Denom)
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("tokenOut denom (%s) does not match any asset in pool", tokenOut.Denom)
}
if tokenInDenom != asset0 && tokenInDenom != asset1 {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("tokenInDenom (%s) does not match any asset in pool", tokenInDenom)
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("tokenInDenom (%s) does not match any asset in pool", tokenInDenom)
}
if tokenOut.Denom == tokenInDenom {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("tokenOut (%s) cannot be the same as tokenIn (%s)", tokenOut.Denom, tokenInDenom)
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("tokenOut (%s) cannot be the same as tokenIn (%s)", tokenOut.Denom, tokenInDenom)
}
if minPrice.GTE(curSqrtPrice.Power(2)) {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("minPrice (%s) must be less than current price (%s)", minPrice, curSqrtPrice.Power(2))
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("minPrice (%s) must be less than current price (%s)", minPrice, curSqrtPrice.Power(2))
}
if maxPrice.LTE(curSqrtPrice.Power(2)) {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("maxPrice (%s) must be greater than current price (%s)", maxPrice, curSqrtPrice.Power(2))
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("maxPrice (%s) must be greater than current price (%s)", maxPrice, curSqrtPrice.Power(2))
}
// sqrtPrice of upper and lower user defined price range
sqrtPLowerTick, err := minPrice.ApproxSqrt()
if err != nil {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("issue calculating square root of minPrice")
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("issue calculating square root of minPrice")
}
sqrtPUpperTick, err := maxPrice.ApproxSqrt()
if err != nil {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("issue calculating square root of maxPrice")
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("issue calculating square root of maxPrice")
}
// TODO: How do we remove/generalize this? I am stumped.
......@@ -255,14 +282,15 @@ func (k Keeper) CalcInAmtGivenOut(ctx sdk.Context, tokenOut sdk.Coin, tokenInDen
// TODO: This should be GT 0 but some instances have very small remainder
// need to look into fixing this
for swapState.amountSpecifiedRemaining.GT(sdk.NewDecWithPrec(1, 6)) {
nextTick, _ := k.NextInitializedTick(ctx, poolId, swapState.tick.Int64(), zeroForOne)
nextTick, ok := k.NextInitializedTick(ctx, poolId, swapState.tick.Int64(), zeroForOne)
// TODO: we can enable this error checking once we fix tick initialization
// if !ok {
// return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("there are no more ticks initialized to fill the swap")
// }
if !ok {
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("there are no more ticks initialized to fill the swap")
}
nextSqrtPrice, err := k.tickToSqrtPrice(sdk.NewInt(nextTick))
if err != nil {
return sdk.Coin{}, sdk.Coin{}, err
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), err
}
// TODO: In and out get flipped based on if we are calculating for in or out, need to fix this
......@@ -280,14 +308,14 @@ func (k Keeper) CalcInAmtGivenOut(ctx sdk.Context, tokenOut sdk.Coin, tokenInDen
if swapState.sqrtPrice.Equal(sqrtPrice) {
liquidityDelta, err := k.crossTick(ctx, p.Id, nextTick)
if err != nil {
return sdk.Coin{}, sdk.Coin{}, err
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), err
}
if !zeroForOne {
liquidityDelta = liquidityDelta.Neg()
}
swapState.liquidity = swapState.liquidity.Add(liquidityDelta.ToDec())
if swapState.liquidity.LTE(sdk.ZeroDec()) || swapState.liquidity.IsNil() {
return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("no liquidity available, cannot swap")
return sdk.Coin{}, sdk.ZeroDec(), sdk.ZeroInt(), sdk.ZeroDec(), fmt.Errorf("no liquidity available, cannot swap")
}
if !zeroForOne {
swapState.tick = sdk.NewInt(nextTick - 1)
......@@ -298,5 +326,18 @@ func (k Keeper) CalcInAmtGivenOut(ctx sdk.Context, tokenOut sdk.Coin, tokenInDen
swapState.tick = priceToTick(sqrtPrice.Power(2))
}
}
return sdk.NewCoin(tokenInDenom, swapState.amountCalculated.RoundInt()), sdk.NewCoin(tokenOut.Denom, tokenOut.Amount), nil
return sdk.NewCoin(tokenInDenom, swapState.amountCalculated.RoundInt()), swapState.liquidity, swapState.tick, swapState.sqrtPrice, nil
}
// ApplySwap.
func (k *Keeper) applySwap(ctx sdk.Context, tokenIn sdk.Coin, tokenOut sdk.Coin, poolId uint64, newLiquidity sdk.Dec, newCurrentTick sdk.Int, newCurrentSqrtPrice sdk.Dec) {
// Fixed gas consumption per swap to prevent spam
ctx.GasMeter().ConsumeGas(types.BalancerGasFeeForSwap, "cl pool swap computation")
pool := k.getPoolbyId(ctx, poolId)
pool.Liquidity = newLiquidity
pool.CurrentTick = newCurrentTick
pool.CurrentSqrtPrice = newCurrentSqrtPrice
k.setPoolById(ctx, pool.Id, pool)
}
package concentrated_liquidity_test
import (
fmt "fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
cl "github.com/osmosis-labs/osmosis/v12/x/concentrated-liquidity"
......@@ -20,7 +22,7 @@ func (s *KeeperTestSuite) TestCalcOutAmtGivenIn() {
minPrice := sdk.NewDec(4500)
maxPrice := sdk.NewDec(5500)
_, amountOut, err := s.App.ConcentratedLiquidityKeeper.CalcOutAmtGivenIn(ctx, tokenIn, tokenOutDenom, swapFee, minPrice, maxPrice, pool.Id)
amountOut, _, _, _, err := s.App.ConcentratedLiquidityKeeper.CalcOutAmtGivenIn(ctx, tokenIn, tokenOutDenom, swapFee, minPrice, maxPrice, pool.Id)
s.Require().NoError(err)
s.Require().Equal(sdk.NewDec(666975610).String(), amountOut.Amount.ToDec().String())
......@@ -29,7 +31,7 @@ func (s *KeeperTestSuite) TestCalcOutAmtGivenIn() {
tokenOutDenom = "eth"
swapFee = sdk.NewDec(0)
_, amountOut, err = s.App.ConcentratedLiquidityKeeper.CalcOutAmtGivenIn(ctx, tokenIn, tokenOutDenom, swapFee, minPrice, maxPrice, pool.Id)
amountOut, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CalcOutAmtGivenIn(ctx, tokenIn, tokenOutDenom, swapFee, minPrice, maxPrice, pool.Id)
s.Require().NoError(err)
s.Require().Equal(sdk.NewDec(805287), amountOut.Amount.ToDec())
......@@ -38,7 +40,7 @@ func (s *KeeperTestSuite) TestCalcOutAmtGivenIn() {
tokenOutDenom = "eth"
swapFee = sdk.NewDec(0)
_, amountOut, err = s.App.ConcentratedLiquidityKeeper.CalcOutAmtGivenIn(ctx, tokenIn, tokenOutDenom, swapFee, minPrice, maxPrice, pool.Id)
amountOut, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CalcOutAmtGivenIn(ctx, tokenIn, tokenOutDenom, swapFee, minPrice, maxPrice, pool.Id)
s.Require().NoError(err)
s.Require().Equal(sdk.NewDec(8396), amountOut.Amount.ToDec())
......@@ -47,45 +49,136 @@ func (s *KeeperTestSuite) TestCalcOutAmtGivenIn() {
tokenOutDenom = "eth"
swapFee = sdk.NewDecWithPrec(2, 2)
_, amountOut, err = s.App.ConcentratedLiquidityKeeper.CalcOutAmtGivenIn(ctx, tokenIn, tokenOutDenom, swapFee, minPrice, maxPrice, pool.Id)
amountOut, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CalcOutAmtGivenIn(ctx, tokenIn, tokenOutDenom, swapFee, minPrice, maxPrice, pool.Id)
s.Require().NoError(err)
s.Require().Equal(sdk.NewDec(789834), amountOut.Amount.ToDec())
}
func (s *KeeperTestSuite) TestCalcInAmtGivenOut() {
// func (s *KeeperTestSuite) TestCalcInAmtGivenOut() {
// ctx := s.Ctx
// pool, err := s.App.ConcentratedLiquidityKeeper.CreateNewConcentratedLiquidityPool(s.Ctx, 1, "eth", "usdc", sdk.MustNewDecFromStr("70.710678"), sdk.NewInt(85176))
// s.Require().NoError(err)
// s.SetupPosition(pool.Id)
// // test asset a to b logic
// tokenOut := sdk.NewCoin("usdc", sdk.NewInt(4199999999))
// tokenInDenom := "eth"
// swapFee := sdk.NewDec(0)
// minPrice := sdk.NewDec(4500)
// maxPrice := sdk.NewDec(5500)
// amountIn, _, _, _, err := s.App.ConcentratedLiquidityKeeper.CalcInAmtGivenOut(ctx, tokenOut, tokenInDenom, swapFee, minPrice, maxPrice, pool.Id)
// s.Require().NoError(err)
// s.Require().Equal(sdk.NewDec(805287), amountIn.Amount.ToDec())
// // test asset b to a logic
// tokenOut = sdk.NewCoin("eth", sdk.NewInt(133700))
// tokenInDenom = "usdc"
// swapFee = sdk.NewDec(0)
// amountIn, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CalcInAmtGivenOut(ctx, tokenOut, tokenInDenom, swapFee, minPrice, maxPrice, pool.Id)
// s.Require().NoError(err)
// s.Require().Equal(sdk.NewDec(666975610), amountIn.Amount.ToDec())
// // test asset a to b logic
// tokenOut = sdk.NewCoin("usdc", sdk.NewInt(4199999999))
// tokenInDenom = "eth"
// swapFee = sdk.NewDecWithPrec(2, 2)
// amountIn, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CalcInAmtGivenOut(ctx, tokenOut, tokenInDenom, swapFee, minPrice, maxPrice, pool.Id)
// s.Require().NoError(err)
// s.Require().Equal(sdk.NewDec(821722), amountIn.Amount.ToDec())
// }
// func (s *KeeperTestSuite) TestSwapInAmtGivenOut() {
// ctx := s.Ctx
// pool, err := s.App.ConcentratedLiquidityKeeper.CreateNewConcentratedLiquidityPool(ctx, 1, "eth", "usdc", sdk.MustNewDecFromStr("70.710678"), sdk.NewInt(85176))
// s.Require().NoError(err)
// fmt.Printf("%v pool liq pre \n", pool.Liquidity)
// lowerTick := int64(84222)
// upperTick := int64(86129)
// amount0Desired := sdk.NewInt(1)
// amount1Desired := sdk.NewInt(5000)
// s.App.ConcentratedLiquidityKeeper.CreatePosition(ctx, pool.Id, s.TestAccs[0], amount0Desired, amount1Desired, sdk.ZeroInt(), sdk.ZeroInt(), lowerTick, upperTick)
// // test asset a to b logic
// tokenOut := sdk.NewCoin("usdc", sdk.NewInt(4199999999))
// tokenInDenom := "eth"
// swapFee := sdk.NewDec(0)
// minPrice := sdk.NewDec(4500)
// maxPrice := sdk.NewDec(5500)
// amountIn, err := s.App.ConcentratedLiquidityKeeper.SwapInAmtGivenOut(ctx, tokenOut, tokenInDenom, swapFee, minPrice, maxPrice, pool.Id)
// s.Require().NoError(err)
// fmt.Printf("%v amountIn \n", amountIn)
// pool = s.App.ConcentratedLiquidityKeeper.GetPoolbyId(ctx, pool.Id)
// // test asset a to b logic
// tokenOut := sdk.NewCoin("usdc", sdk.NewInt(4199999999))
// tokenInDenom := "eth"
// swapFee := sdk.NewDec(0)
// minPrice := sdk.NewDec(4500)
// maxPrice := sdk.NewDec(5500)
// amountIn, _, _, _, err := s.App.ConcentratedLiquidityKeeper.CalcInAmtGivenOut(ctx, tokenOut, tokenInDenom, swapFee, minPrice, maxPrice, pool.Id)
// s.Require().NoError(err)
// s.Require().Equal(sdk.NewDec(805287), amountIn.Amount.ToDec())
// // test asset b to a logic
// tokenOut = sdk.NewCoin("eth", sdk.NewInt(133700))
// tokenInDenom = "usdc"
// swapFee = sdk.NewDec(0)
// amountIn, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CalcInAmtGivenOut(ctx, tokenOut, tokenInDenom, swapFee, minPrice, maxPrice, pool.Id)
// s.Require().NoError(err)
// s.Require().Equal(sdk.NewDec(666975610), amountIn.Amount.ToDec())
// // test asset a to b logic
// tokenOut = sdk.NewCoin("usdc", sdk.NewInt(4199999999))
// tokenInDenom = "eth"
// swapFee = sdk.NewDecWithPrec(2, 2)
// amountIn, _, _, _, err = s.App.ConcentratedLiquidityKeeper.CalcInAmtGivenOut(ctx, tokenOut, tokenInDenom, swapFee, minPrice, maxPrice, pool.Id)
// s.Require().NoError(err)
// s.Require().Equal(sdk.NewDec(821722), amountIn.Amount.ToDec())
// }
func (s *KeeperTestSuite) TestSwapOutAmtGivenIn() {
ctx := s.Ctx
pool, err := s.App.ConcentratedLiquidityKeeper.CreateNewConcentratedLiquidityPool(s.Ctx, 1, "eth", "usdc", sdk.MustNewDecFromStr("70.710678"), sdk.NewInt(85176))
pool, err := s.App.ConcentratedLiquidityKeeper.CreateNewConcentratedLiquidityPool(ctx, 1, "eth", "usdc", sdk.MustNewDecFromStr("70.710678"), sdk.NewInt(85176))
s.Require().NoError(err)
s.SetupPosition(pool.Id)
fmt.Printf("%v pool liq pre \n", pool.Liquidity)
lowerTick := int64(84222)
upperTick := int64(86129)
amount0Desired := sdk.NewInt(1)
amount1Desired := sdk.NewInt(5000)
s.App.ConcentratedLiquidityKeeper.CreatePosition(ctx, pool.Id, s.TestAccs[0], amount0Desired, amount1Desired, sdk.ZeroInt(), sdk.ZeroInt(), lowerTick, upperTick)
pool = s.App.ConcentratedLiquidityKeeper.GetPoolbyId(ctx, pool.Id)
fmt.Printf("%v pool liq post 1 \n", pool.Liquidity)
fmt.Printf("%v pool.CurrentSqrtPrice post 1 \n", pool.CurrentSqrtPrice)
fmt.Printf("%v pool.CurrentTick post 1 \n", pool.CurrentTick)
// test asset a to b logic
tokenOut := sdk.NewCoin("usdc", sdk.NewInt(4199999999))
tokenInDenom := "eth"
tokenIn := sdk.NewCoin("eth", sdk.NewInt(133700))
tokenOutDenom := "usdc"
swapFee := sdk.NewDec(0)
minPrice := sdk.NewDec(4500)
maxPrice := sdk.NewDec(5500)
amountIn, _, err := s.App.ConcentratedLiquidityKeeper.CalcInAmtGivenOut(ctx, tokenOut, tokenInDenom, swapFee, minPrice, maxPrice, pool.Id)
s.Require().NoError(err)
s.Require().Equal(sdk.NewDec(805287), amountIn.Amount.ToDec())
// test asset b to a logic
tokenOut = sdk.NewCoin("eth", sdk.NewInt(133700))
tokenInDenom = "usdc"
swapFee = sdk.NewDec(0)
amountIn, _, err = s.App.ConcentratedLiquidityKeeper.CalcInAmtGivenOut(ctx, tokenOut, tokenInDenom, swapFee, minPrice, maxPrice, pool.Id)
// this is a test case for swapping within the tick
amountIn, err := s.App.ConcentratedLiquidityKeeper.SwapOutAmtGivenIn(ctx, tokenIn, tokenOutDenom, swapFee, minPrice, maxPrice, pool.Id)
s.Require().NoError(err)
s.Require().Equal(sdk.NewDec(666975610), amountIn.Amount.ToDec())
fmt.Printf("%v amountIn \n", amountIn)
pool = s.App.ConcentratedLiquidityKeeper.GetPoolbyId(ctx, pool.Id)
// test asset a to b logic
tokenOut = sdk.NewCoin("usdc", sdk.NewInt(4199999999))
tokenInDenom = "eth"
swapFee = sdk.NewDecWithPrec(2, 2)
// calculation for this is tested in TestCalcOutAmtGivenInt
s.Require().Equal(sdk.NewInt(666975610), amountIn.Amount)
amountIn, _, err = s.App.ConcentratedLiquidityKeeper.CalcInAmtGivenOut(ctx, tokenOut, tokenInDenom, swapFee, minPrice, maxPrice, pool.Id)
s.Require().NoError(err)
s.Require().Equal(sdk.NewDec(821722), amountIn.Amount.ToDec())
s.Require().Equal(sdk.MustNewDecFromStr("1517.818895638265328110"), pool.Liquidity)
// curr sqrt price and tick remains the same
s.Require().Equal(sdk.MustNewDecFromStr("70.710678000000000000"), pool.CurrentSqrtPrice)
s.Require().Equal(sdk.NewInt(85176), pool.CurrentTick)
}
func (s *KeeperTestSuite) TestOrderInitialPoolDenoms() {
......
......@@ -17,6 +17,7 @@ func (k Keeper) SwapExactAmountIn(
swapFee sdk.Dec,
) (tokenOutAmount sdk.Int, err error) {
panic("not implemented")
//newTokenIn, tokenOut, err := k.CalcOutAmtGivenIn(ctx, tokenIn, tokenOutDenom, swapFee, sdk.ZeroDec(), sdk.NewDec(999999999999), pool.GetId())
}
// TODO: spec here and in gamm
......
......@@ -54,7 +54,6 @@ func (k Keeper) initOrUpdateTick(ctx sdk.Context, poolId uint64, tickIndex int64
return nil
}
// nolint: unused
func (k Keeper) crossTick(ctx sdk.Context, poolId uint64, tickIndex int64) (liquidityDelta sdk.Int, err error) {
tickInfo, err := k.GetTickInfo(ctx, poolId, tickIndex)
if err != nil {
......
......@@ -50,7 +50,7 @@ func (k Keeper) RouteExactAmountIn(
// Chain output of current pool as the input for the next routed pool
tokenIn = sdk.NewCoin(route.TokenOutDenom, tokenOutAmount)
}
return tokenOutAmount, err
return tokenOutAmount, nil
}
// RouteExactAmountOut defines the output denom and output amount for the last pool.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment