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

[x/gamm][StableSwap] Add boilerplate for stableswap #1214

Merged
merged 6 commits into from
Apr 8, 2022
Merged
Show file tree
Hide file tree
Changes from 2 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
65 changes: 65 additions & 0 deletions proto/osmosis/gamm/pool-models/stableswap/stableswapPool.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
syntax = "proto3";
ValarDragon marked this conversation as resolved.
Show resolved Hide resolved
package osmosis.gamm.stableswap.v1beta1;

import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";

import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";

import "cosmos/auth/v1beta1/auth.proto";
import "cosmos/base/v1beta1/coin.proto";

option go_package = "github.com/osmosis-labs/osmosis/v7/x/gamm/pool-models/stableswap";

// PoolParams defined the parameters that will be managed by the pool
// governance in the future. This params are not managed by the chain
// governance. Instead they will be managed by the token holders of the pool.
// The pool's token holders are specified in future_pool_governor.
message PoolParams {
string swapFee = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.moretags) = "yaml:\"swap_fee\"",
(gogoproto.nullable) = false
];
string exitFee = 2 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.moretags) = "yaml:\"exit_fee\"",
(gogoproto.nullable) = false
];
}

message Pool {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: proto doc :p

Copy link
Member Author

Choose a reason for hiding this comment

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

Not really sure what doc to put here yet, I think It'll become clearer when I go to make one go-side after an initial impl of the math. Added a placeholder for now though

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;

PoolParams poolParams = 3 [
(gogoproto.moretags) = "yaml:\"stableswap_pool_params\"",
(gogoproto.nullable) = false
];

// This string specifies who will govern the pool in the future.
// Valid forms of this are:
// {token name},{duration}
// {duration}
// where {token name} if specified is the token which determines the
// governor, and if not specified is the LP token for this pool.duration is
// a time specified as 0w,1w,2w, etc. which specifies how long the token
// would need to be locked up to count in governance. 0w means no lockup.
string future_pool_governor = 4
[ (gogoproto.moretags) = "yaml:\"future_pool_governor\"" ];
// sum of all LP shares
cosmos.base.v1beta1.Coin totalShares = 5 [
(gogoproto.moretags) = "yaml:\"total_shares\"",
(gogoproto.nullable) = false
];
// assets in the pool
repeated cosmos.base.v1beta1.Coin poolLiquidity = 6 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
}
32 changes: 32 additions & 0 deletions proto/osmosis/gamm/pool-models/stableswap/tx.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
syntax = "proto3";
package osmosis.gamm.stableswap.v1beta1;

import "cosmos/base/v1beta1/coin.proto";
import "gogoproto/gogo.proto";
import "osmosis/gamm/pool-models/stableswap/stableswapPool.proto";

option go_package = "github.com/osmosis-labs/osmosis/v7/x/gamm/pool-models/stableswap";

service Msg {
rpc CreateStableswapPool(MsgCreateStableswapPool)
returns (MsgCreateStableswapPoolResponse);
}

// ===================== MsgCreatePool
ValarDragon marked this conversation as resolved.
Show resolved Hide resolved
message MsgCreateStableswapPool {
string sender = 1 [ (gogoproto.moretags) = "yaml:\"sender\"" ];

PoolParams poolParams = 2 [ (gogoproto.moretags) = "yaml:\"pool_params\"" ];

repeated cosmos.base.v1beta1.Coin initial_pool_liquidity = 3 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];

string future_pool_governor = 4
[ (gogoproto.moretags) = "yaml:\"future_pool_governor\"" ];
}

message MsgCreateStableswapPoolResponse {
uint64 pool_id = 1 [ (gogoproto.customname) = "PoolID" ];
}
3 changes: 2 additions & 1 deletion proto/osmosis/txfees/v1beta1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ service Query {

rpc DenomSpotPrice(QueryDenomSpotPriceRequest)
returns (QueryDenomSpotPriceResponse) {
option (google.api.http).get = "/osmosis/txfees/v1beta1/spot_price_by_denom";
option (google.api.http).get =
"/osmosis/txfees/v1beta1/spot_price_by_denom";
}

rpc DenomPoolId(QueryDenomPoolIdRequest) returns (QueryDenomPoolIdResponse) {
Expand Down
41 changes: 0 additions & 41 deletions x/gamm/pool-models/balancer/balancer_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -517,47 +517,6 @@ func (params PoolParams) GetPoolExitFee() sdk.Dec {
return params.ExitFee
}

func ValidateFutureGovernor(governor string) error {
Comment on lines 519 to -520
Copy link
Member Author

Choose a reason for hiding this comment

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

This function was duplicated, and existed in the types package.

// allow empty governor
if governor == "" {
return nil
}

// validation for future owner
// "osmo1fqlr98d45v5ysqgp6h56kpujcj4cvsjnjq9nck"
_, err := sdk.AccAddressFromBech32(governor)
if err == nil {
return nil
}

lockTimeStr := ""
splits := strings.Split(governor, ",")
if len(splits) > 2 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, fmt.Sprintf("invalid future governor: %s", governor))
}

// token,100h
if len(splits) == 2 {
lpTokenStr := splits[0]
if sdk.ValidateDenom(lpTokenStr) != nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, fmt.Sprintf("invalid future governor: %s", governor))
}
lockTimeStr = splits[1]
}

// 100h
if len(splits) == 1 {
lockTimeStr = splits[0]
}

// Note that a duration of 0 is allowed
_, err = time.ParseDuration(lockTimeStr)
if err != nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, fmt.Sprintf("invalid future governor: %s", governor))
}
return nil
}

// subPoolAssetWeights subtracts the weights of two different pool asset slices.
// It assumes that both pool assets have the same token denominations,
// with the denominations in the same order.
Expand Down
2 changes: 1 addition & 1 deletion x/gamm/pool-models/balancer/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (msg MsgCreateBalancerPool) ValidateBasic() error {
}

// validation for future owner
if err = ValidateFutureGovernor(msg.FuturePoolGovernor); err != nil {
if err = types.ValidateFutureGovernor(msg.FuturePoolGovernor); err != nil {
return err
}

Expand Down
48 changes: 48 additions & 0 deletions x/gamm/pool-models/stableswap/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package stableswap

import (
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/msgservice"

types "github.com/osmosis-labs/osmosis/v7/x/gamm/types"
)

// RegisterLegacyAminoCodec registers the necessary x/gamm interfaces and concrete types
// on the provided LegacyAmino codec. These types are used for Amino JSON serialization.
func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&Pool{}, "osmosis/gamm/StableswapPool", nil)
cdc.RegisterConcrete(&MsgCreateStableswapPool{}, "osmosis/gamm/create-stableswap-pool", nil)
cdc.RegisterConcrete(&PoolParams{}, "osmosis/gamm/StableswapPoolParams", nil)
}

func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
registry.RegisterInterface(
"osmosis.gamm.v1beta1.PoolI",
(*types.PoolI)(nil),
&Pool{},
)
registry.RegisterImplementations(
(*sdk.Msg)(nil),
&MsgCreateStableswapPool{},
)
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
}

var (
amino = codec.NewLegacyAmino()

// ModuleCdc references the global x/bank module codec. Note, the codec should
// ONLY be used in certain instances of tests and for JSON encoding as Amino is
// still used for that purpose.
//
// The actual codec used for serialization should be provided to x/staking and
// defined at the application level.
ModuleCdc = codec.NewAminoCodec(amino)
)

func init() {
RegisterLegacyAminoCodec(amino)
amino.Seal()
}
84 changes: 84 additions & 0 deletions x/gamm/pool-models/stableswap/msgs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package stableswap

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

"github.com/osmosis-labs/osmosis/v7/x/gamm/types"
)

const (
TypeMsgCreateStableswapPool = "create_stableswap_pool"
)

var _ sdk.Msg = &MsgCreateStableswapPool{}
var _ types.CreatePoolMsg = &MsgCreateStableswapPool{}

func NewMsgCreateStableswapPool(
sender sdk.AccAddress,
poolParams PoolParams,
initialLiquidity sdk.Coins,
futurePoolGovernor string) MsgCreateStableswapPool {
return MsgCreateStableswapPool{
Sender: sender.String(),
PoolParams: &poolParams,
InitialPoolLiquidity: initialLiquidity,
FuturePoolGovernor: futurePoolGovernor,
}
}

func (msg MsgCreateStableswapPool) Route() string { return types.RouterKey }
func (msg MsgCreateStableswapPool) Type() string { return TypeMsgCreateStableswapPool }
func (msg MsgCreateStableswapPool) ValidateBasic() error {
_, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid sender address (%s)", err)
}

err = msg.PoolParams.Validate()
if err != nil {
return err
}

// TODO: Add validation for pool initial liquidity

// validation for future owner
if err = types.ValidateFutureGovernor(msg.FuturePoolGovernor); err != nil {
return err
}

return nil
}

func (msg MsgCreateStableswapPool) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg))
}

func (msg MsgCreateStableswapPool) GetSigners() []sdk.AccAddress {
sender, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
panic(err)
}
return []sdk.AccAddress{sender}
}

/// Implement the CreatePoolMsg interface

func (msg MsgCreateStableswapPool) PoolCreator() sdk.AccAddress {
sender, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
panic(err)
}
return sender
}
func (msg MsgCreateStableswapPool) Validate(ctx sdk.Context) error {
return msg.ValidateBasic()
}

func (msg MsgCreateStableswapPool) InitialLiquidity() sdk.Coins {
return msg.InitialPoolLiquidity
}

func (msg MsgCreateStableswapPool) CreatePool(ctx sdk.Context, poolID uint64) (types.PoolI, error) {
return &Pool{}, types.ErrNotImplemented
}
26 changes: 26 additions & 0 deletions x/gamm/pool-models/stableswap/params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package stableswap

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

"github.com/osmosis-labs/osmosis/v7/x/gamm/types"
)

func (params PoolParams) Validate() error {
if params.ExitFee.IsNegative() {
return types.ErrNegativeExitFee
}

if params.ExitFee.GTE(sdk.OneDec()) {
return types.ErrTooMuchExitFee
}

if params.SwapFee.IsNegative() {
return types.ErrNegativeSwapFee
}

if params.SwapFee.GTE(sdk.OneDec()) {
return types.ErrTooMuchSwapFee
}
return nil
}
Loading