Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

concentrated liquidity: further swap/lp work #3101

Merged
merged 9 commits into from
Oct 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
push:
branches:
- "main"
- "concentrated-liquidity-main"
- "v[0-9]**"
workflow_dispatch:

Expand Down Expand Up @@ -124,3 +125,4 @@ jobs:
-
name: Test e2e and Upgrade
run: make test-e2e-ci

30 changes: 15 additions & 15 deletions proto/osmosis/concentrated-liquidity/concentratedPool.proto
Original file line number Diff line number Diff line change
Expand Up @@ -11,47 +11,47 @@ import "gogoproto/gogo.proto";
option go_package = "github.com/osmosis-labs/osmosis/v12/x/concentrated-liquidity";

message Pool {
option (gogoproto.goproto_getters) = false;
option (gogoproto.goproto_stringer) = false;
option (gogoproto.goproto_getters) = false;
option (gogoproto.goproto_stringer) = false;
option (cosmos_proto.implements_interface) = "PoolI";

string address = 1 [(gogoproto.moretags) = "yaml:\"address\""];
uint64 id = 2;
string address = 1 [ (gogoproto.moretags) = "yaml:\"address\"" ];
uint64 id = 2;

// Amount of total liquidity
string liquidity = 3 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"liquidity\"",
(gogoproto.nullable) = false
(gogoproto.moretags) = "yaml:\"liquidity\"",
(gogoproto.nullable) = false
];

string token0 = 4;
string token1 = 5;

string current_sqrt_price = 6 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"spot_price\"",
(gogoproto.nullable) = false
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.moretags) = "yaml:\"spot_price\"",
(gogoproto.nullable) = false
];
string current_tick = 7 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"current_tick\"",
(gogoproto.nullable) = false
(gogoproto.moretags) = "yaml:\"current_tick\"",
(gogoproto.nullable) = false
];
}

message TickInfo {
string liquidity = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"liquidity\"",
(gogoproto.nullable) = false
(gogoproto.moretags) = "yaml:\"liquidity\"",
(gogoproto.nullable) = false
];
}

message Position {
string liquidity = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"liquidity\"",
(gogoproto.nullable) = false
(gogoproto.moretags) = "yaml:\"liquidity\"",
(gogoproto.nullable) = false
];
}
60 changes: 30 additions & 30 deletions x/concentrated-liquidity/concentratedPool.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions x/concentrated-liquidity/export_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package concentrated_liquidity

import (
cltypes "github.com/osmosis-labs/osmosis/v12/x/concentrated-liquidity/types"
)

// OrderInitialPoolDenoms sets the pool denoms of a cl pool
func (p *Pool) OrderInitialPoolDenoms(denom0, denom1 string) error {
return p.orderInitialPoolDenoms(denom0, denom1)
func OrderInitialPoolDenoms(denom0, denom1 string) (string, string, error) {
return cltypes.OrderInitialPoolDenoms(denom0, denom1)
}
24 changes: 10 additions & 14 deletions x/concentrated-liquidity/lp.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
types "github.com/osmosis-labs/osmosis/v12/x/concentrated-liquidity/types"
)

func (k Keeper) Mint(ctx sdk.Context, poolId uint64, owner sdk.AccAddress, liquidityIn sdk.Int, lowerTick, upperTick int64) (amtDenom0, amtDenom1 sdk.Int, err error) {
func (k Keeper) Mint(ctx sdk.Context, poolId uint64, owner sdk.AccAddress, liquidityIn sdk.Dec, lowerTick, upperTick int64) (amtDenom0, amtDenom1 sdk.Int, err error) {
// ensure types.MinTick <= lowerTick < types.MaxTick
// TODO (bez): Add unit tests.
if lowerTick < types.MinTick || lowerTick >= types.MaxTick {
Expand All @@ -24,26 +24,22 @@ func (k Keeper) Mint(ctx sdk.Context, poolId uint64, owner sdk.AccAddress, liqui
if liquidityIn.IsZero() {
return sdk.Int{}, sdk.Int{}, fmt.Errorf("token in amount is zero")
}

// TODO: we need to check if TickInfo is initialized on a specific tick before updating, otherwise get wont work
// k.setTickInfo(ctx, poolId, lowerTick, TickInfo{})
// k.UpdateTickWithNewLiquidity(ctx, poolId, lowerTick, liquidityIn)
// k.setTickInfo(ctx, poolId, upperTick, TickInfo{})
// k.UpdateTickWithNewLiquidity(ctx, poolId, upperTick, liquidityIn)

// k.updatePositionWithLiquidity(ctx, poolId, owner.String(), lowerTick, upperTick, liquidityIn)
// k.setPosition(ctx, poolId, owner, lowerTick, upperTick, Position{})
// k.updatePositionWithLiquidity(ctx, poolId, owner, lowerTick, upperTick, liquidityIn)

pool := k.getPoolbyId(ctx, poolId)

currentSqrtPrice := pool.CurrentSqrtPrice
sqrtRatioUpperTick, err := k.getSqrtRatioAtTick(upperTick)
if err != nil {
return sdk.Int{}, sdk.Int{}, err
}
sqrtRatioLowerTick, err := k.getSqrtRatioAtTick(lowerTick)
if err != nil {
return sdk.Int{}, sdk.Int{}, err
}
sqrtRatioUpperTick, _ := k.tickToSqrtPrice(sdk.NewInt(upperTick))
sqrtRatioLowerTick, _ := k.tickToSqrtPrice(sdk.NewInt(lowerTick))

amtDenom0 = calcAmount0Delta(currentSqrtPrice.ToDec(), sqrtRatioUpperTick, liquidityIn.ToDec()).RoundInt()
amtDenom1 = calcAmount1Delta(currentSqrtPrice.ToDec(), sqrtRatioLowerTick, liquidityIn.ToDec()).RoundInt()
amtDenom0 = calcAmount0Delta(liquidityIn, currentSqrtPrice, sqrtRatioUpperTick).RoundInt()
amtDenom1 = calcAmount1Delta(liquidityIn, currentSqrtPrice, sqrtRatioLowerTick).RoundInt()

return amtDenom0, amtDenom1, nil
}
Expand Down
22 changes: 13 additions & 9 deletions x/concentrated-liquidity/lp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,29 @@ func (s *KeeperTestSuite) TestMint() {
// current tick: 85176
// lower tick: 84222
// upper tick: 86129
// liquidity(token in):1517882343751509868544
// current sqrt price: 5602277097478614198912276234240
// denom0: uosmo
// liquidity(token in):1517882323
// current sqrt price: 70710678
// denom0: eth
// denom1: usdc
poolId := uint64(1)
currentTick := sdk.NewInt(85176)
lowerTick := int64(84222)
upperTick := int64(86129)
liquidity, ok := sdk.NewIntFromString("1517882343751509868544")
s.Require().True(ok)
currentSqrtP, ok := sdk.NewIntFromString("5602277097478614198912276234240")
s.Require().True(ok)
denom0 := "uosmo"
liquidity, err := sdk.NewDecFromStr("1517.882323")
s.Require().NoError(err)
// currentSqrtP, ok := sdk.NewIntFromString("70710678")
currentSqrtP, err := sdk.NewDecFromStr("70.710678")
s.Require().NoError(err)
denom0 := "eth"
denom1 := "usdc"

s.SetupTest()

s.App.ConcentratedLiquidityKeeper.CreateNewConcentratedLiquidityPool(s.Ctx, poolId, denom0, denom1, currentSqrtP, currentTick)

_, _, err := s.App.ConcentratedLiquidityKeeper.Mint(s.Ctx, poolId, s.TestAccs[0], liquidity, lowerTick, upperTick)
asset0, asset1, err := s.App.ConcentratedLiquidityKeeper.Mint(s.Ctx, poolId, s.TestAccs[0], liquidity, lowerTick, upperTick)
s.Require().NoError(err)

s.Require().Equal(sdk.NewInt(1), asset0)
s.Require().Equal(sdk.NewInt(5000), asset1)
}
40 changes: 39 additions & 1 deletion x/concentrated-liquidity/math.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package concentrated_liquidity

import sdk "github.com/cosmos/cosmos-sdk/types"
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)

// liquidity0 takes an amount of asset0 in the pool as well as the sqrtpCur and the nextPrice
// sqrtPriceA is the smaller of sqrtpCur and the nextPrice
Expand Down Expand Up @@ -52,3 +54,39 @@ func calcAmount1Delta(liq, sqrtPriceA, sqrtPriceB sdk.Dec) sdk.Dec {
diff := sqrtPriceB.Sub(sqrtPriceA)
return liq.Mul(diff)
}

// computeSwapStep calculates the amountIn, amountOut, and the next sqrtPrice given current price, price target, tick liquidity, and amount available to swap
// lte is reference to "less than or equal", which determines if we are moving left or right of the current price to find the next initialized tick with liquidity
func computeSwapStep(sqrtPriceCurrent, sqrtPriceTarget, liquidity, amountRemaining sdk.Dec, lte bool) (sqrtPriceNext sdk.Dec, amountIn sdk.Dec, amountOut sdk.Dec) {
czarcas7ic marked this conversation as resolved.
Show resolved Hide resolved
if lte {
sqrtPriceNext = getNextSqrtPriceFromAmount1RoundingDown(sqrtPriceCurrent, liquidity, amountRemaining)
amountIn = calcAmount1Delta(liquidity, sqrtPriceNext, sqrtPriceCurrent)
amountOut = calcAmount0Delta(liquidity, sqrtPriceNext, sqrtPriceCurrent)
} else {
sqrtPriceNext = getNextSqrtPriceFromAmount0RoundingUp(sqrtPriceCurrent, liquidity, amountRemaining)
amountIn = calcAmount0Delta(liquidity, sqrtPriceNext, sqrtPriceCurrent)
amountOut = calcAmount1Delta(liquidity, sqrtPriceNext, sqrtPriceCurrent)
}
return sqrtPriceNext, amountIn, amountOut
}

func getNextSqrtPriceFromAmount0RoundingUp(sqrtPriceCurrent, liquidity, amountRemaining sdk.Dec) (sqrtPriceNext sdk.Dec) {
numerator := liquidity.Mul(sdk.NewDec(2))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we multiply 2 here?

product := amountRemaining.Mul(sqrtPriceCurrent)

if product.Quo(amountRemaining).Equal(sqrtPriceCurrent) {
denominator := numerator.Add(product)
if denominator.GTE(numerator) {
numerator = numerator.Mul(sqrtPriceCurrent)
sqrtPriceNext = numerator.QuoRoundUp(denominator)
return sqrtPriceNext
}
}
denominator := numerator.Quo(sqrtPriceCurrent).Add(amountRemaining)
sqrtPriceNext = numerator.QuoRoundUp(denominator)
return sqrtPriceNext
}

func getNextSqrtPriceFromAmount1RoundingDown(sqrtPriceCurrent, liquidity, amountRemaining sdk.Dec) (sqrtPriceNext sdk.Dec) {
return sqrtPriceCurrent.Add(amountRemaining.Quo(liquidity))
}
Loading