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

Refactor coinswap #219

Merged
merged 9 commits into from
Aug 10, 2021
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
22 changes: 13 additions & 9 deletions modules/coinswap/client/rest/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ func (s *IntegrationTestSuite) SetupSuite() {

_, err := s.network.WaitForHeight(1)
s.Require().NoError(err)

sdk.SetCoinDenomRegex(func() string {
return `[a-zA-Z][a-zA-Z0-9/\-]{2,127}`
})
}

func (s *IntegrationTestSuite) TearDownSuite() {
Expand All @@ -73,7 +77,7 @@ func (s *IntegrationTestSuite) TestCoinswap() {
maxSupply := int64(200000000)
mintable := true
baseURL := val.APIAddress
uniKitty := coinswaptypes.GetUniDenomFromDenom(symbol)
lptDenom := "lpt-1"

//------test GetCmdIssueToken()-------------
args := []string{
Expand Down Expand Up @@ -167,7 +171,7 @@ func (s *IntegrationTestSuite) TestCoinswap() {
coins := balances.Balances
s.Require().Equal("99999000", coins.AmountOf(symbol).String())
s.Require().Equal("399985965", coins.AmountOf(sdk.DefaultBondDenom).String())
s.Require().Equal("1000", coins.AmountOf(uniKitty).String())
s.Require().Equal("1000", coins.AmountOf(lptDenom).String())

url := fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, symbol)
resp, err := rest.GetRequest(url)
Expand Down Expand Up @@ -229,7 +233,7 @@ func (s *IntegrationTestSuite) TestCoinswap() {
coins = balances.Balances
s.Require().Equal("99996999", coins.AmountOf(symbol).String())
s.Require().Equal("399983955", coins.AmountOf(sdk.DefaultBondDenom).String())
s.Require().Equal("3000", coins.AmountOf(uniKitty).String())
s.Require().Equal("3000", coins.AmountOf(lptDenom).String())

url = fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, symbol)
resp, err = rest.GetRequest(url)
Expand Down Expand Up @@ -291,7 +295,7 @@ func (s *IntegrationTestSuite) TestCoinswap() {
coins = balances.Balances
s.Require().Equal("99995999", coins.AmountOf(symbol).String())
s.Require().Equal("399984693", coins.AmountOf(sdk.DefaultBondDenom).String())
s.Require().Equal("3000", coins.AmountOf(uniKitty).String())
s.Require().Equal("3000", coins.AmountOf(lptDenom).String())

url = fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, symbol)
resp, err = rest.GetRequest(url)
Expand Down Expand Up @@ -353,7 +357,7 @@ func (s *IntegrationTestSuite) TestCoinswap() {
coins = balances.Balances
s.Require().Equal("99996999", coins.AmountOf(symbol).String())
s.Require().Equal("399983930", coins.AmountOf(sdk.DefaultBondDenom).String())
s.Require().Equal("3000", coins.AmountOf(uniKitty).String())
s.Require().Equal("3000", coins.AmountOf(lptDenom).String())

url = fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, symbol)
resp, err = rest.GetRequest(url)
Expand All @@ -364,7 +368,7 @@ func (s *IntegrationTestSuite) TestCoinswap() {

// Test remove liquidity (remove part)
msgRemoveLiquidity := &coinswaptypes.MsgRemoveLiquidity{
WithdrawLiquidity: sdk.NewCoin(uniKitty, sdk.NewInt(2000)),
WithdrawLiquidity: sdk.NewCoin(lptDenom, sdk.NewInt(2000)),
MinToken: sdk.NewInt(2000),
MinStandardAmt: sdk.NewInt(2000),
Deadline: deadline.Unix(),
Expand Down Expand Up @@ -410,7 +414,7 @@ func (s *IntegrationTestSuite) TestCoinswap() {
coins = balances.Balances
s.Require().Equal("99998999", coins.AmountOf(symbol).String())
s.Require().Equal("399985923", coins.AmountOf(sdk.DefaultBondDenom).String())
s.Require().Equal("1000", coins.AmountOf(uniKitty).String())
s.Require().Equal("1000", coins.AmountOf(lptDenom).String())

url = fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, symbol)
resp, err = rest.GetRequest(url)
Expand All @@ -421,7 +425,7 @@ func (s *IntegrationTestSuite) TestCoinswap() {

// Test remove liquidity (remove all)
msgRemoveLiquidity = &coinswaptypes.MsgRemoveLiquidity{
WithdrawLiquidity: sdk.NewCoin(uniKitty, sdk.NewInt(1000)),
WithdrawLiquidity: sdk.NewCoin(lptDenom, sdk.NewInt(1000)),
MinToken: sdk.NewInt(1000),
MinStandardAmt: sdk.NewInt(1000),
Deadline: deadline.Unix(),
Expand Down Expand Up @@ -467,7 +471,7 @@ func (s *IntegrationTestSuite) TestCoinswap() {
coins = balances.Balances
s.Require().Equal("100000000", coins.AmountOf(symbol).String())
s.Require().Equal("399986915", coins.AmountOf(sdk.DefaultBondDenom).String())
s.Require().Equal("0", coins.AmountOf(uniKitty).String())
s.Require().Equal("0", coins.AmountOf(lptDenom).String())

url = fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, symbol)
resp, err = rest.GetRequest(url)
Expand Down
8 changes: 3 additions & 5 deletions modules/coinswap/client/rest/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ func addLiquidityHandlerFn(cliCtx client.Context) http.HandlerFunc {
func removeLiquidityHandlerFn(cliCtx client.Context) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
denom := vars[RestPoolID]
lptDenom := vars[RestPoolID]

if err := sdk.ValidateDenom(denom); err != nil {
if err := sdk.ValidateDenom(lptDenom); err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
Expand Down Expand Up @@ -151,10 +151,8 @@ func removeLiquidityHandlerFn(cliCtx client.Context) http.HandlerFunc {
return
}

uniDenom := types.GetUniDenomFromDenom(denom)

msg := types.NewMsgRemoveLiquidity(
minToken, sdk.NewCoin(uniDenom, liquidityAmt), minStandard, deadline.Unix(), req.Sender,
minToken, sdk.NewCoin(lptDenom, liquidityAmt), minStandard, deadline.Unix(), req.Sender,
)
if err := msg.ValidateBasic(); err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
Expand Down
18 changes: 11 additions & 7 deletions modules/coinswap/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"google.golang.org/grpc/status"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

"github.com/irisnet/irismod/modules/coinswap/types"
)
Expand All @@ -19,19 +20,22 @@ func (k Keeper) Liquidity(c context.Context, req *types.QueryLiquidityRequest) (
return nil, status.Errorf(codes.InvalidArgument, "empty request")
}

tokenDenom := req.Denom
uniDenom := types.GetUniDenomFromDenom(tokenDenom)

ctx := sdk.UnwrapSDKContext(c)
reservePool, err := k.GetReservePool(ctx, uniDenom)
poolId := types.GetPoolId(req.Denom)
pool, exists := k.GetPool(ctx, poolId)
if !exists {
return nil, sdkerrors.Wrapf(types.ErrReservePoolNotExists, "liquidity pool token: %s", req.Denom)
}

standardDenom := k.GetStandardDenom(ctx)
reservePool, err := k.GetPoolBalancesByLptDenom(ctx, pool.LptDenom)
if err != nil {
return nil, err
}

standardDenom := k.GetStandardDenom(ctx)
standard := sdk.NewCoin(standardDenom, reservePool.AmountOf(standardDenom))
token := sdk.NewCoin(tokenDenom, reservePool.AmountOf(tokenDenom))
liquidity := sdk.NewCoin(uniDenom, k.bk.GetSupply(ctx).GetTotal().AmountOf(uniDenom))
token := sdk.NewCoin(pool.CounterpartyDenom, reservePool.AmountOf(pool.CounterpartyDenom))
liquidity := sdk.NewCoin(pool.LptDenom, k.bk.GetSupply(ctx).GetTotal().AmountOf(pool.LptDenom))

swapParams := k.GetParams(ctx)
fee := swapParams.Fee.String()
Expand Down
104 changes: 40 additions & 64 deletions modules/coinswap/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,30 +105,31 @@ func (k Keeper) AddLiquidity(ctx sdk.Context, msg *types.MsgAddLiquidity) (sdk.C
return sdk.Coin{}, sdkerrors.Wrapf(types.ErrInvalidDenom,
"MaxToken: %s should not be StandardDenom", msg.MaxToken.String())
}
uniDenom := types.GetUniDenomFromDenom(msg.MaxToken.Denom)

liquidity := k.bk.GetSupply(ctx).GetTotal().AmountOf(uniDenom)

var mintLiquidityAmt sdk.Int
var depositToken sdk.Coin
var standardCoin = sdk.NewCoin(standardDenom, msg.ExactStandardAmt)

poolId := types.GetPoolId(msg.MaxToken.Denom)
pool, exists := k.GetPool(ctx, poolId)

// calculate amount of UNI to be minted for sender
// and coin amount to be deposited
if liquidity.IsZero() {
if !exists {
mintLiquidityAmt = msg.ExactStandardAmt
if mintLiquidityAmt.LT(msg.MinLiquidity) {
return sdk.Coin{}, sdkerrors.Wrap(types.ErrConstraintNotMet, fmt.Sprintf("liquidity amount not met, user expected: no less than %s, actual: %s", msg.MinLiquidity.String(), mintLiquidityAmt.String()))
}
depositToken = sdk.NewCoin(msg.MaxToken.Denom, msg.MaxToken.Amount)
pool = k.CreatePool(ctx, msg.MaxToken.Denom)
} else {
reservePool, err := k.GetReservePool(ctx, uniDenom)
balances, err := k.GetPoolBalances(ctx, pool.EscrowAddress)
if err != nil {
return sdk.Coin{}, err
}

standardReserveAmt := reservePool.AmountOf(standardDenom)
tokenReserveAmt := reservePool.AmountOf(msg.MaxToken.Denom)
standardReserveAmt := balances.AmountOf(standardDenom)
tokenReserveAmt := balances.AmountOf(msg.MaxToken.Denom)
liquidity := k.bk.GetSupply(ctx).GetTotal().AmountOf(pool.LptDenom)

mintLiquidityAmt = (liquidity.Mul(msg.ExactStandardAmt)).Quo(standardReserveAmt)
if mintLiquidityAmt.LT(msg.MinLiquidity) {
Expand All @@ -147,26 +148,35 @@ func (k Keeper) AddLiquidity(ctx sdk.Context, msg *types.MsgAddLiquidity) (sdk.C
return sdk.Coin{}, err
}

reservePoolAddress, err := sdk.AccAddressFromBech32(pool.EscrowAddress)
if err != nil {
return sdk.Coin{}, err
}

ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeAddLiquidity,
sdk.NewAttribute(types.AttributeValueSender, msg.Sender),
sdk.NewAttribute(types.AttributeValueTokenPair, types.GetTokenPairByDenom(msg.MaxToken.Denom, standardDenom)),
),
)

return k.addLiquidity(ctx, sender, standardCoin, depositToken, uniDenom, mintLiquidityAmt)
return k.addLiquidity(ctx, sender, reservePoolAddress, standardCoin, depositToken, pool.LptDenom, mintLiquidityAmt)
}

func (k Keeper) addLiquidity(ctx sdk.Context, sender sdk.AccAddress, standardCoin, token sdk.Coin, uniDenom string, mintLiquidityAmt sdk.Int) (sdk.Coin, error) {
func (k Keeper) addLiquidity(ctx sdk.Context,
sender sdk.AccAddress,
reservePoolAddress sdk.AccAddress,
standardCoin, token sdk.Coin,
lptDenom string,
mintLiquidityAmt sdk.Int,
) (sdk.Coin, error) {
depositedTokens := sdk.NewCoins(standardCoin, token)
poolAddr := types.GetReservePoolAddr(uniDenom)
// transfer deposited token into coinswaps Account
if err := k.bk.SendCoins(ctx, sender, poolAddr, depositedTokens); err != nil {
if err := k.bk.SendCoins(ctx, sender, reservePoolAddress, depositedTokens); err != nil {
return sdk.Coin{}, err
}

mintToken := sdk.NewCoin(uniDenom, mintLiquidityAmt)
mintToken := sdk.NewCoin(lptDenom, mintLiquidityAmt)
mintTokens := sdk.NewCoins(mintToken)
if err := k.bk.MintCoins(ctx, types.ModuleName, mintTokens); err != nil {
return sdk.Coin{}, err
Expand All @@ -181,30 +191,31 @@ func (k Keeper) addLiquidity(ctx sdk.Context, sender sdk.AccAddress, standardCoi
// RemoveLiquidity removes liquidity from the specified pool
func (k Keeper) RemoveLiquidity(ctx sdk.Context, msg *types.MsgRemoveLiquidity) (sdk.Coins, error) {
standardDenom := k.GetStandardDenom(ctx)
uniDenom := msg.WithdrawLiquidity.Denom

minTokenDenom, err := types.GetCoinDenomFromUniDenom(uniDenom)
if err != nil {
return nil, err
pool, exists := k.GetPoolByLptDenom(ctx, msg.WithdrawLiquidity.Denom)
if !exists {
return nil, sdkerrors.Wrapf(types.ErrReservePoolNotExists, "liquidity pool token: %s", msg.WithdrawLiquidity.Denom)
}

// check if reserve pool exists
reservePool, err := k.GetReservePool(ctx, uniDenom)
balances, err := k.GetPoolBalances(ctx, pool.EscrowAddress)
if err != nil {
return nil, err
}

standardReserveAmt := reservePool.AmountOf(standardDenom)
tokenReserveAmt := reservePool.AmountOf(minTokenDenom)
liquidityReserve := k.bk.GetSupply(ctx).GetTotal().AmountOf(uniDenom)
lptDenom := msg.WithdrawLiquidity.Denom
minTokenDenom := pool.CounterpartyDenom

standardReserveAmt := balances.AmountOf(standardDenom)
tokenReserveAmt := balances.AmountOf(minTokenDenom)
liquidityReserve := k.bk.GetSupply(ctx).GetTotal().AmountOf(lptDenom)
if standardReserveAmt.LT(msg.MinStandardAmt) {
return nil, sdkerrors.Wrap(types.ErrInsufficientFunds, fmt.Sprintf("insufficient %s funds, user expected: %s, actual: %s", standardDenom, msg.MinStandardAmt.String(), standardReserveAmt.String()))
}
if tokenReserveAmt.LT(msg.MinToken) {
return nil, sdkerrors.Wrap(types.ErrInsufficientFunds, fmt.Sprintf("insufficient %s funds, user expected: %s, actual: %s", minTokenDenom, msg.MinToken.String(), tokenReserveAmt.String()))
}
if liquidityReserve.LT(msg.WithdrawLiquidity.Amount) {
return nil, sdkerrors.Wrap(types.ErrInsufficientFunds, fmt.Sprintf("insufficient %s funds, user expected: %s, actual: %s", uniDenom, msg.WithdrawLiquidity.Amount.String(), liquidityReserve.String()))
return nil, sdkerrors.Wrap(types.ErrInsufficientFunds, fmt.Sprintf("insufficient %s funds, user expected: %s, actual: %s", lptDenom, msg.WithdrawLiquidity.Amount.String(), liquidityReserve.String()))
}

// calculate amount of UNI to be burned for sender
Expand All @@ -222,7 +233,6 @@ func (k Keeper) RemoveLiquidity(ctx sdk.Context, msg *types.MsgRemoveLiquidity)
if tokenWithdrawCoin.Amount.LT(msg.MinToken) {
return nil, sdkerrors.Wrap(types.ErrConstraintNotMet, fmt.Sprintf("token amount not met, user expected: no less than %s, actual: %s", sdk.NewCoin(minTokenDenom, msg.MinToken).String(), tokenWithdrawCoin.String()))
}
poolAddr := types.GetReservePoolAddr(uniDenom)

ctx.EventManager().EmitEvent(
sdk.NewEvent(
Expand All @@ -237,6 +247,11 @@ func (k Keeper) RemoveLiquidity(ctx sdk.Context, msg *types.MsgRemoveLiquidity)
return nil, err
}

poolAddr, err := sdk.AccAddressFromBech32(pool.EscrowAddress)
if err != nil {
return nil, err
}

return k.removeLiquidity(ctx, poolAddr, sender, deductUniCoin, irisWithdrawCoin, tokenWithdrawCoin)
}

Expand All @@ -258,29 +273,6 @@ func (k Keeper) removeLiquidity(ctx sdk.Context, poolAddr, sender sdk.AccAddress
return coins, k.bk.SendCoins(ctx, poolAddr, sender, coins)
}

// GetReservePool returns the total balance of the reserve pool at the provided denomination.
func (k Keeper) GetReservePool(ctx sdk.Context, uniDenom string) (coins sdk.Coins, err error) {
swapPoolAccAddr := types.GetReservePoolAddr(uniDenom)
acc := k.ak.GetAccount(ctx, swapPoolAccAddr)
if acc == nil {
return nil, sdkerrors.Wrap(types.ErrReservePoolNotExists, uniDenom)
}
return k.bk.GetAllBalances(ctx, acc.GetAddress()), nil
}

// ValidatePool Verify the legitimacy of the liquidity pool
func (k Keeper) ValidatePool(ctx sdk.Context, uniDenom string) error {
if err := types.ValidateUniDenom(uniDenom); err != nil {
return err
}

_, err := k.GetReservePool(ctx, uniDenom)
if err != nil {
return err
}
return nil
}

// GetParams gets the parameters for the coinswap module.
func (k Keeper) GetParams(ctx sdk.Context) types.Params {
var swapParams types.Params
Expand Down Expand Up @@ -310,19 +302,3 @@ func (k Keeper) GetStandardDenom(ctx sdk.Context) string {
k.cdc.MustUnmarshalBinaryBare(bz, &denomWrap)
return denomWrap.Value
}

// GetUniDenomFromDenoms returns the uni denom for the provided denominations.
func (k Keeper) GetUniDenomFromDenoms(ctx sdk.Context, denom1, denom2 string) (string, error) {
if denom1 == denom2 {
return "", types.ErrEqualDenom
}

standardDenom := k.GetStandardDenom(ctx)
if denom1 != standardDenom && denom2 != standardDenom {
return "", sdkerrors.Wrap(types.ErrNotContainStandardDenom, fmt.Sprintf("standard denom: %s,denom1: %s,denom2: %s", standardDenom, denom1, denom2))
}
if denom1 == standardDenom {
return fmt.Sprintf(types.FormatUniDenom, denom2), nil
}
return fmt.Sprintf(types.FormatUniDenom, denom1), nil
}
Loading