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

Set initial LP token price to be one & add unit test for create pool #131

Merged
merged 1 commit into from
Jun 23, 2023
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
9 changes: 9 additions & 0 deletions x/amm/keeper/initialize_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ import (
// - Records total liquidity increase
// - Calls the AfterPoolCreated hook
func (k Keeper) InitializePool(ctx sdk.Context, pool *types.Pool, sender sdk.AccAddress) (err error) {
tvl, err := pool.TVL(ctx, k.oracleKeeper)
Copy link
Contributor

Choose a reason for hiding this comment

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

This one solved the issue that the lp tokens were not balanced?

if err != nil {
return err
}

if tvl.IsPositive() {
pool.TotalShares = sdk.NewCoin(pool.TotalShares.Denom, tvl.Mul(sdk.NewDecFromInt(types.OneShare)).RoundInt())
}

// Mint the initial pool shares share token to the sender
err = k.MintPoolShareToAccount(ctx, *pool, sender, pool.GetTotalShares().Amount)
if err != nil {
Expand Down
38 changes: 33 additions & 5 deletions x/amm/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ package keeper_test
import (
"testing"

"github.com/stretchr/testify/suite"

tmproto "github.com/tendermint/tendermint/proto/tendermint/types"

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"

simapp "github.com/elys-network/elys/app"
oracletypes "github.com/elys-network/elys/x/oracle/types"
"github.com/stretchr/testify/suite"
"github.com/tendermint/tendermint/crypto/ed25519"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
)

const (
Expand All @@ -36,3 +35,32 @@ func (suite *KeeperTestSuite) SetupTest() {
func TestKeeperSuite(t *testing.T) {
suite.Run(t, new(KeeperTestSuite))
}

func (suite *KeeperTestSuite) SetupStableCoinPrices() {
// prices set for USDT and USDC
provider := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address())
suite.app.OracleKeeper.SetAssetInfo(suite.ctx, oracletypes.AssetInfo{
Denom: "uusdc",
Display: "USDC",
Decimal: 6,
})
suite.app.OracleKeeper.SetAssetInfo(suite.ctx, oracletypes.AssetInfo{
Denom: "uusdt",
Display: "USDT",
Decimal: 6,
})
suite.app.OracleKeeper.SetPrice(suite.ctx, oracletypes.Price{
Asset: "USDC",
Price: sdk.NewDec(1),
Source: "elys",
Provider: provider.String(),
Timestamp: uint64(suite.ctx.BlockTime().Unix()),
})
suite.app.OracleKeeper.SetPrice(suite.ctx, oracletypes.Price{
Asset: "USDT",
Price: sdk.NewDec(1),
Source: "elys",
Provider: provider.String(),
Timestamp: uint64(suite.ctx.BlockTime().Unix()),
})
}
2 changes: 0 additions & 2 deletions x/amm/keeper/msg_server_create_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import (
func (k msgServer) CreatePool(goCtx context.Context, msg *types.MsgCreatePool) (*types.MsgCreatePoolResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

_ = ctx

poolId, err := k.Keeper.CreatePool(ctx, msg)
if err != nil {
return &types.MsgCreatePoolResponse{}, err
Expand Down
163 changes: 163 additions & 0 deletions x/amm/keeper/msg_server_create_pool_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package keeper_test

import (
sdk "github.com/cosmos/cosmos-sdk/types"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
"github.com/elys-network/elys/x/amm/keeper"
"github.com/elys-network/elys/x/amm/types"
"github.com/tendermint/tendermint/crypto/ed25519"
)

func (suite *KeeperTestSuite) TestMsgServerCreatePool() {
for _, tc := range []struct {
desc string
senderInitBalance sdk.Coins
poolParams types.PoolParams
poolAssets []types.PoolAsset
expSenderBalance sdk.Coins
expTotalLiquidity sdk.Coins
expLpCommitment sdk.Coin
expPass bool
}{
{
desc: "zero tvl pool creation",
senderInitBalance: sdk.Coins{sdk.NewInt64Coin("ueden", 1000000), sdk.NewInt64Coin("uelys", 1000000)},
poolParams: types.PoolParams{
SwapFee: sdk.ZeroDec(),
ExitFee: sdk.ZeroDec(),
UseOracle: false,
WeightBreakingFeeMultiplier: sdk.ZeroDec(),
SlippageReduction: sdk.ZeroDec(),
LpFeePortion: sdk.ZeroDec(),
StakingFeePortion: sdk.ZeroDec(),
WeightRecoveryFeePortion: sdk.ZeroDec(),
ThresholdWeightDifference: sdk.ZeroDec(),
FeeDenom: "",
},
poolAssets: []types.PoolAsset{
{
Token: sdk.NewInt64Coin("ueden", 1000000),
Weight: sdk.OneInt(),
},
{
Token: sdk.NewInt64Coin("uelys", 1000000),
Weight: sdk.OneInt(),
},
},
expSenderBalance: sdk.Coins{},
expLpCommitment: sdk.NewCoin("amm/pool/0", sdk.NewInt(100).Mul(types.OneShare)),
expPass: true,
},
{
desc: "positive tvl pool creation",
senderInitBalance: sdk.Coins{sdk.NewInt64Coin("ueden", 1000000), sdk.NewInt64Coin("uusdc", 1000000)},
poolParams: types.PoolParams{
SwapFee: sdk.ZeroDec(),
ExitFee: sdk.ZeroDec(),
UseOracle: false,
WeightBreakingFeeMultiplier: sdk.ZeroDec(),
SlippageReduction: sdk.ZeroDec(),
LpFeePortion: sdk.ZeroDec(),
StakingFeePortion: sdk.ZeroDec(),
WeightRecoveryFeePortion: sdk.ZeroDec(),
ThresholdWeightDifference: sdk.ZeroDec(),
FeeDenom: "",
},
poolAssets: []types.PoolAsset{
{
Token: sdk.NewInt64Coin("ueden", 1000000),
Weight: sdk.OneInt(),
},
{
Token: sdk.NewInt64Coin("uusdc", 1000000),
Weight: sdk.OneInt(),
},
},
expSenderBalance: sdk.Coins{},
expLpCommitment: sdk.NewCoin("amm/pool/0", sdk.NewInt(2).Mul(types.OneShare)),
expPass: true,
},
{
desc: "not enough balance to create pool",
senderInitBalance: sdk.Coins{sdk.NewInt64Coin("ueden", 1000000)},
poolParams: types.PoolParams{
SwapFee: sdk.ZeroDec(),
ExitFee: sdk.ZeroDec(),
UseOracle: false,
WeightBreakingFeeMultiplier: sdk.ZeroDec(),
SlippageReduction: sdk.ZeroDec(),
LpFeePortion: sdk.ZeroDec(),
StakingFeePortion: sdk.ZeroDec(),
WeightRecoveryFeePortion: sdk.ZeroDec(),
ThresholdWeightDifference: sdk.ZeroDec(),
FeeDenom: "",
},
poolAssets: []types.PoolAsset{
{
Token: sdk.NewInt64Coin("ueden", 1000000),
Weight: sdk.OneInt(),
},
{
Token: sdk.NewInt64Coin("uusdc", 1000000),
Weight: sdk.OneInt(),
},
},
expSenderBalance: sdk.Coins{},
expLpCommitment: sdk.Coin{},
expPass: false,
},
} {
suite.Run(tc.desc, func() {
suite.SetupTest()
suite.SetupStableCoinPrices()

// bootstrap accounts
sender := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address())

// bootstrap balances
err := suite.app.BankKeeper.MintCoins(suite.ctx, minttypes.ModuleName, tc.senderInitBalance)
suite.Require().NoError(err)
err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, minttypes.ModuleName, sender, tc.senderInitBalance)
suite.Require().NoError(err)

// execute function
msgServer := keeper.NewMsgServerImpl(suite.app.AmmKeeper)
resp, err := msgServer.CreatePool(
sdk.WrapSDKContext(suite.ctx),
&types.MsgCreatePool{
Sender: sender.String(),
PoolParams: &tc.poolParams,
PoolAssets: tc.poolAssets,
})
if !tc.expPass {
suite.Require().Error(err)
} else {
suite.Require().NoError(err)
suite.Require().Equal(resp.PoolID, uint64(0))

pools := suite.app.AmmKeeper.GetAllPool(suite.ctx)
suite.Require().Len(pools, 1)
suite.Require().Equal(pools[0].PoolId, uint64(0))
suite.Require().Equal(pools[0].PoolParams, tc.poolParams)
suite.Require().Equal(pools[0].TotalShares.Amount.String(), tc.expLpCommitment.Amount.String())

totalWeight := sdk.ZeroInt()
for _, poolAsset := range tc.poolAssets {
totalWeight = totalWeight.Add(poolAsset.Weight)
}
suite.Require().Equal(pools[0].TotalWeight.String(), totalWeight.MulRaw(types.GuaranteedWeightPrecision).String())

// check balance change on sender
balances := suite.app.BankKeeper.GetAllBalances(suite.ctx, sender)
suite.Require().Equal(balances.String(), tc.expSenderBalance.String())

// check lp token commitment
commitments, found := suite.app.CommitmentKeeper.GetCommitments(suite.ctx, sender.String())
suite.Require().True(found)
suite.Require().Len(commitments.CommittedTokens, 1)
suite.Require().Equal(commitments.CommittedTokens[0].Denom, tc.expLpCommitment.Denom)
suite.Require().Equal(commitments.CommittedTokens[0].Amount.String(), tc.expLpCommitment.Amount.String())
}
})
}
}
1 change: 0 additions & 1 deletion x/amm/types/create_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
)

func (msg *MsgCreatePool) CreatePool(ctx sdk.Context, poolID uint64) (*Pool, error) {
// poolAssets := make([]PoolAsset, len(msg.PoolAssets))
pool, err := NewBalancerPool(poolID, *msg.PoolParams, msg.PoolAssets, ctx.BlockTime())
return &pool, err
}