Commit 4f99ffdf authored by antstalepresh's avatar antstalepresh
Browse files

Merge branch 'main' of github.com:osmosis-labs/osmosis into auto_staking_some_percentage_lp_rewards

parents b0573313 b0c323c8
Showing with 435 additions and 208 deletions
+435 -208
...@@ -339,6 +339,9 @@ func NewOsmosisApp( ...@@ -339,6 +339,9 @@ func NewOsmosisApp(
distrParams.BaseProposerReward = sdk.ZeroDec() distrParams.BaseProposerReward = sdk.ZeroDec()
distrParams.BonusProposerReward = sdk.ZeroDec() distrParams.BonusProposerReward = sdk.ZeroDec()
app.DistrKeeper.SetParams(ctx, distrParams) app.DistrKeeper.SetParams(ctx, distrParams)
// configure upgrade for gamm module's pool creation fee param add
app.GAMMKeeper.SetParams(ctx, gammtypes.NewParams(sdk.Coins{sdk.NewInt64Coin("uosmo", 1000000000)})) // 1000 OSMO
}) })
// Create IBC Keeper // Create IBC Keeper
...@@ -373,7 +376,7 @@ func NewOsmosisApp( ...@@ -373,7 +376,7 @@ func NewOsmosisApp(
app.StakingKeeper = *stakingKeeper.SetHooks( app.StakingKeeper = *stakingKeeper.SetHooks(
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks(), app.ClaimKeeper.Hooks()), stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks(), app.ClaimKeeper.Hooks()),
) )
gammKeeper := gammkeeper.NewKeeper(appCodec, keys[gammtypes.StoreKey], app.AccountKeeper, app.BankKeeper) gammKeeper := gammkeeper.NewKeeper(appCodec, keys[gammtypes.StoreKey], app.GetSubspace(gammtypes.ModuleName), app.AccountKeeper, app.BankKeeper, app.DistrKeeper)
lockupKeeper := lockupkeeper.NewKeeper(appCodec, keys[lockuptypes.StoreKey], app.AccountKeeper, app.BankKeeper) lockupKeeper := lockupkeeper.NewKeeper(appCodec, keys[lockuptypes.StoreKey], app.AccountKeeper, app.BankKeeper)
epochsKeeper := epochskeeper.NewKeeper(appCodec, keys[epochstypes.StoreKey]) epochsKeeper := epochskeeper.NewKeeper(appCodec, keys[epochstypes.StoreKey])
incentivesKeeper := incentiveskeeper.NewKeeper(appCodec, keys[incentivestypes.StoreKey], app.GetSubspace(incentivestypes.ModuleName), app.AccountKeeper, app.BankKeeper, *lockupKeeper, epochsKeeper, app.StakingKeeper) incentivesKeeper := incentiveskeeper.NewKeeper(appCodec, keys[incentivestypes.StoreKey], app.GetSubspace(incentivestypes.ModuleName), app.AccountKeeper, app.BankKeeper, *lockupKeeper, epochsKeeper, app.StakingKeeper)
...@@ -517,6 +520,7 @@ func NewOsmosisApp( ...@@ -517,6 +520,7 @@ func NewOsmosisApp(
claimtypes.ModuleName, claimtypes.ModuleName,
incentivestypes.ModuleName, incentivestypes.ModuleName,
epochstypes.ModuleName, epochstypes.ModuleName,
gammtypes.ModuleName,
) )
app.mm.RegisterInvariants(&app.CrisisKeeper) app.mm.RegisterInvariants(&app.CrisisKeeper)
...@@ -770,6 +774,7 @@ func initParamsKeeper(appCodec codec.BinaryMarshaler, legacyAmino *codec.LegacyA ...@@ -770,6 +774,7 @@ func initParamsKeeper(appCodec codec.BinaryMarshaler, legacyAmino *codec.LegacyA
paramsKeeper.Subspace(ibchost.ModuleName) paramsKeeper.Subspace(ibchost.ModuleName)
paramsKeeper.Subspace(incentivestypes.ModuleName) paramsKeeper.Subspace(incentivestypes.ModuleName)
paramsKeeper.Subspace(poolincentivestypes.ModuleName) paramsKeeper.Subspace(poolincentivestypes.ModuleName)
paramsKeeper.Subspace(gammtypes.ModuleName)
return paramsKeeper return paramsKeeper
} }
package osmomath
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Don't EVER change after initializing
// TODO: Analyze choice here
var powPrecision, _ = sdk.NewDecFromStr("0.00000001")
// Singletons
var zero sdk.Dec = sdk.ZeroDec()
var one_half sdk.Dec = sdk.MustNewDecFromStr("0.5")
var one sdk.Dec = sdk.OneDec()
var two sdk.Dec = sdk.MustNewDecFromStr("2")
/*********************************************************/
// AbsDifferenceWithSign returns | a - b |, (a - b).sign()
// a is mutated and returned
func AbsDifferenceWithSign(a, b sdk.Dec) (sdk.Dec, bool) {
if a.GTE(b) {
return a.SubMut(b), false
} else {
return a.NegMut().AddMut(b), true
}
}
// func largeBasePow(base sdk.Dec, exp sdk.Dec) sdk.Dec {
// // pow requires the base to be <= 2
// }
// Pow computes base^(exp)
// However since the exponent is not an integer, we must do an approximation algorithm.
// TODO: In the future, lets add some optimized routines for common exponents, e.g. for common wIn / wOut ratios
// Many simple exponents like 2:1 pools
func Pow(base sdk.Dec, exp sdk.Dec) sdk.Dec {
// Exponentiation of a negative base with an arbitrary real exponent is not closed within the reals.
// You can see this by recalling that `i = (-1)^(.5)`. We have to go to complex numbers to define this.
// (And would have to implement complex logarithms)
// We don't have a need for negative bases, so we don't include any such logic.
if !base.IsPositive() {
panic(fmt.Errorf("base must be greater than 0"))
}
// TODO: Remove this if we want to generalize the function,
// we can adjust the algorithm in this setting.
if base.GTE(two) {
panic(fmt.Errorf("base must be lesser than two"))
}
// We will use an approximation algorithm to compute the power.
// Since computing an integer power is easy, we split up the exponent into
// an integer component and a fractional component.
integer := exp.TruncateDec()
fractional := exp.Sub(integer)
integerPow := base.Power(uint64(integer.TruncateInt64()))
if fractional.IsZero() {
return integerPow
}
fractionalPow := PowApprox(base, fractional, powPrecision)
return integerPow.Mul(fractionalPow)
}
// Contract: 0 < base <= 2
// 0 < exp < 1
func PowApprox(base sdk.Dec, exp sdk.Dec, precision sdk.Dec) sdk.Dec {
if exp.IsZero() {
return sdk.ZeroDec()
}
// Common case optimization
// Optimize for it being equal to one-half
if exp.Equal(one_half) {
output, err := base.ApproxSqrt()
if err != nil {
panic(err)
}
return output
}
// TODO: Make an approx-equal function, and then check if exp * 3 = 1, and do a check accordingly
// We compute this via taking the maclaurin series of (1 + x)^a
// where x = base - 1.
// The maclaurin series of (1 + x)^a = sum_{k=0}^{infty} binom(a, k) x^k
// Binom(a, k) takes the natural continuation on the first parameter, namely that
// Binom(a, k) = N/D, where D = k!, and N = a(a-1)(a-2)...(a-k+1)
// Next we show that the absolute value of each term is less than the last term.
// Note that the change in term n's value vs term n + 1 is a multiplicative factor of
// v_n = x(a - n) / (n+1)
// So if |v_n| < 1, we know that each term has a lesser impact on the result than the last.
// For our bounds on |x| < 1, |a| < 1,
// it suffices to see for what n is |v_n| < 1,
// in the worst parameterization of x = 1, a = -1.
// v_n = |(-1 + epsilon - n) / (n+1)|
// So |v_n| is always less than 1, as n ranges over the integers.
//
// Note that term_n of the expansion is 1 * prod_{i=0}^{n-1} v_i
// The error if we stop the expansion at term_n is:
// error_n = sum_{k=n+1}^{infty} term_k
// At this point we further restrict a >= 0, so 0 <= a < 1.
// Now we take the _INCORRECT_ assumption that if term_n < p, then
// error_n < p.
// This assumption is obviously wrong.
// However our usages of this function don't use the full domain.
// With a > 0, |x| << 1, and p sufficiently low, perhaps this actually is true.
// TODO: Check with our parameterization
// TODO: If theres a bug, balancer is also wrong here :thonk:
base = base.Clone()
x, xneg := AbsDifferenceWithSign(base, one)
term := sdk.OneDec()
sum := sdk.OneDec()
negative := false
a := exp.Clone()
bigK := sdk.NewDec(0)
// TODO: Document this computation via taylor expansion
for i := int64(1); term.GTE(precision); i++ {
// At each iteration, we need two values, i and i-1.
// To avoid expensive big.Int allocation, we reuse bigK variable.
// On this line, bigK == i-1.
c, cneg := AbsDifferenceWithSign(a, bigK)
// On this line, bigK == i.
bigK.Set(sdk.NewDec(i)) // TODO: O(n) bigint allocation happens
term.MulMut(c).MulMut(x).QuoMut(bigK)
// a is mutated on absDifferenceWithSign, reset
a.Set(exp)
if term.IsZero() {
break
}
if xneg {
negative = !negative
}
if cneg {
negative = !negative
}
if negative {
sum.SubMut(term)
} else {
sum.AddMut(term)
}
}
return sum
}
package osmomath
import (
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
)
func TestAbsDifferenceWithSign(t *testing.T) {
decA, err := sdk.NewDecFromStr("3.2")
require.NoError(t, err)
decB, err := sdk.NewDecFromStr("4.3432389")
require.NoError(t, err)
s, b := AbsDifferenceWithSign(decA, decB)
require.True(t, b)
expectedDec, err := sdk.NewDecFromStr("1.1432389")
require.NoError(t, err)
require.Equal(t, expectedDec, s)
}
func TestPowApprox(t *testing.T) {
base, err := sdk.NewDecFromStr("0.8")
require.NoError(t, err)
exp, err := sdk.NewDecFromStr("0.32")
require.NoError(t, err)
s := PowApprox(base, exp, powPrecision)
expectedDec, err := sdk.NewDecFromStr("0.93108385")
require.NoError(t, err)
require.True(
t,
expectedDec.Sub(s).Abs().LTE(powPrecision),
"expected value & actual value's difference should less than precision",
)
}
func TestPow(t *testing.T) {
base, err := sdk.NewDecFromStr("1.68")
require.NoError(t, err)
exp, err := sdk.NewDecFromStr("0.32")
require.NoError(t, err)
s := Pow(base, exp)
expectedDec, err := sdk.NewDecFromStr("1.18058965")
require.NoError(t, err)
require.True(
t,
expectedDec.Sub(s).Abs().LTE(powPrecision),
"expected value & actual value's difference should less than precision",
)
}
package keeper package osmomath
import ( import (
"testing" "testing"
...@@ -56,7 +56,7 @@ func BenchmarkPow(b *testing.B) { ...@@ -56,7 +56,7 @@ func BenchmarkPow(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for _, test := range tests { for _, test := range tests {
pow(test.base, test.exp) Pow(test.base, test.exp)
} }
} }
} }
...@@ -80,7 +80,7 @@ func BenchmarkSqrtPow(b *testing.B) { ...@@ -80,7 +80,7 @@ func BenchmarkSqrtPow(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for _, test := range tests { for _, test := range tests {
pow(test.base, one_half) Pow(test.base, one_half)
} }
} }
} }
...@@ -4,6 +4,17 @@ package osmosis.gamm; ...@@ -4,6 +4,17 @@ package osmosis.gamm;
import "gogoproto/gogo.proto"; import "gogoproto/gogo.proto";
import "google/protobuf/any.proto"; import "google/protobuf/any.proto";
import "cosmos_proto/cosmos.proto"; import "cosmos_proto/cosmos.proto";
import "cosmos/base/v1beta1/coin.proto";
// Params holds parameters for the incentives module
message Params {
repeated cosmos.base.v1beta1.Coin pool_creation_fee = 1 [
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(gogoproto.moretags) = "yaml:\"pool_creation_fee\"",
(gogoproto.nullable) = false
];
}
option go_package = "github.com/osmosis-labs/osmosis/x/gamm/types"; option go_package = "github.com/osmosis-labs/osmosis/x/gamm/types";
...@@ -12,4 +23,5 @@ message GenesisState { ...@@ -12,4 +23,5 @@ message GenesisState {
repeated google.protobuf.Any pools = 1 repeated google.protobuf.Any pools = 1
[ (cosmos_proto.accepts_interface) = "PoolI" ]; [ (cosmos_proto.accepts_interface) = "PoolI" ];
uint64 next_pool_number = 2; uint64 next_pool_number = 2;
Params params = 3 [ (gogoproto.nullable) = false ];
} }
...@@ -51,7 +51,8 @@ func TestEpochsInitGenesis(t *testing.T) { ...@@ -51,7 +51,8 @@ func TestEpochsInitGenesis(t *testing.T) {
ctx = ctx.WithBlockHeight(1) ctx = ctx.WithBlockHeight(1)
ctx = ctx.WithBlockTime(now) ctx = ctx.WithBlockTime(now)
epochs.InitGenesis(ctx, app.EpochsKeeper, types.GenesisState{ //test genesisState validation
genesisState := types.GenesisState{
Epochs: []types.EpochInfo{ Epochs: []types.EpochInfo{
{ {
Identifier: "monthly", Identifier: "monthly",
...@@ -62,9 +63,34 @@ func TestEpochsInitGenesis(t *testing.T) { ...@@ -62,9 +63,34 @@ func TestEpochsInitGenesis(t *testing.T) {
EpochCountingStarted: true, EpochCountingStarted: true,
CurrentEpochEnded: true, CurrentEpochEnded: true,
}, },
{
Identifier: "monthly",
StartTime: time.Time{},
Duration: time.Hour * 24,
CurrentEpoch: 0,
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: true,
CurrentEpochEnded: true,
},
}, },
}) }
require.EqualError(t, genesisState.Validate(), "epoch identifier should be unique")
genesisState = types.GenesisState{
Epochs: []types.EpochInfo{
{
Identifier: "monthly",
StartTime: time.Time{},
Duration: time.Hour * 24,
CurrentEpoch: 0,
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: true,
CurrentEpochEnded: true,
},
},
}
epochs.InitGenesis(ctx, app.EpochsKeeper, genesisState)
epochInfo := app.EpochsKeeper.GetEpochInfo(ctx, "monthly") epochInfo := app.EpochsKeeper.GetEpochInfo(ctx, "monthly")
require.Equal(t, epochInfo.Identifier, "monthly") require.Equal(t, epochInfo.Identifier, "monthly")
require.Equal(t, epochInfo.StartTime.UTC().String(), now.UTC().String()) require.Equal(t, epochInfo.StartTime.UTC().String(), now.UTC().String())
......
...@@ -41,13 +41,18 @@ func DefaultGenesis() *GenesisState { ...@@ -41,13 +41,18 @@ func DefaultGenesis() *GenesisState {
// failure. // failure.
func (gs GenesisState) Validate() error { func (gs GenesisState) Validate() error {
// TODO: Epochs identifiers should be unique // TODO: Epochs identifiers should be unique
epochIdentifiers := map[string]bool{}
for _, epoch := range gs.Epochs { for _, epoch := range gs.Epochs {
if epoch.Identifier == "" { if epoch.Identifier == "" {
return errors.New("epoch identifier should NOT be empty") return errors.New("epoch identifier should NOT be empty")
} }
if epochIdentifiers[epoch.Identifier] {
return errors.New("epoch identifier should be unique")
}
if epoch.Duration == 0 { if epoch.Duration == 0 {
return errors.New("epoch duration should NOT be 0") return errors.New("epoch duration should NOT be 0")
} }
epochIdentifiers[epoch.Identifier] = true
} }
return nil return nil
} }
package types
import (
"fmt"
)
func ValidateEpochIdentifierInterface(i interface{}) error {
v, ok := i.(string)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
ValidateEpochIdentifierString(v)
return nil
}
func ValidateEpochIdentifierString(s string) error {
if s == "" {
return fmt.Errorf("empty distribution epoch identifier: %+v", s)
}
return nil
}
...@@ -19,7 +19,7 @@ import ( ...@@ -19,7 +19,7 @@ import (
"github.com/osmosis-labs/osmosis/x/gamm/client/cli" "github.com/osmosis-labs/osmosis/x/gamm/client/cli"
gammtestutil "github.com/osmosis-labs/osmosis/x/gamm/client/testutil" gammtestutil "github.com/osmosis-labs/osmosis/x/gamm/client/testutil"
"github.com/osmosis-labs/osmosis/x/gamm/types" "github.com/osmosis-labs/osmosis/x/gamm/types"
gammtypes "github.com/osmosis-labs/osmosis/x/gamm/types"
tmcli "github.com/tendermint/tendermint/libs/cli" tmcli "github.com/tendermint/tendermint/libs/cli"
) )
...@@ -35,6 +35,16 @@ func (s *IntegrationTestSuite) SetupSuite() { ...@@ -35,6 +35,16 @@ func (s *IntegrationTestSuite) SetupSuite() {
s.cfg = app.DefaultConfig() s.cfg = app.DefaultConfig()
encCfg := app.MakeEncodingConfig()
// modification to pay fee with test bond denom "stake"
genesisState := app.ModuleBasics.DefaultGenesis(encCfg.Marshaler)
gammGen := gammtypes.DefaultGenesis()
gammGen.Params.PoolCreationFee = sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 1000000)}
gammGenJson := encCfg.Marshaler.MustMarshalJSON(gammGen)
genesisState[gammtypes.ModuleName] = gammGenJson
s.cfg.GenesisState = genesisState
s.network = network.New(s.T(), s.cfg) s.network = network.New(s.T(), s.cfg)
_, err := s.network.WaitForHeight(1) _, err := s.network.WaitForHeight(1)
...@@ -67,7 +77,7 @@ func (s *IntegrationTestSuite) TestNewCreatePoolCmd() { ...@@ -67,7 +77,7 @@ func (s *IntegrationTestSuite) TestNewCreatePoolCmd() {
val.ClientCtx, val.ClientCtx,
val.Address, val.Address,
newAddr, newAddr,
sdk.NewCoins(sdk.NewInt64Coin(s.cfg.BondDenom, 20000), sdk.NewInt64Coin("node0token", 20000)), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), sdk.NewCoins(sdk.NewInt64Coin(s.cfg.BondDenom, 200000000), sdk.NewInt64Coin("node0token", 20000)), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
) )
......
...@@ -119,8 +119,13 @@ $ %s query gamm pools ...@@ -119,8 +119,13 @@ $ %s query gamm pools
} }
queryClient := types.NewQueryClient(clientCtx) queryClient := types.NewQueryClient(clientCtx)
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
res, err := queryClient.Pools(cmd.Context(), &types.QueryPoolsRequest{ res, err := queryClient.Pools(cmd.Context(), &types.QueryPoolsRequest{
Pagination: nil, Pagination: pageReq,
}) })
if err != nil { if err != nil {
return err return err
...@@ -131,6 +136,7 @@ $ %s query gamm pools ...@@ -131,6 +136,7 @@ $ %s query gamm pools
} }
flags.AddQueryFlagsToCmd(cmd) flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "pools")
return cmd return cmd
} }
......
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
// InitGenesis initializes the capability module's state from a provided genesis // InitGenesis initializes the capability module's state from a provided genesis
// state. // state.
func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState, unpacker codectypes.AnyUnpacker) { func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState, unpacker codectypes.AnyUnpacker) {
k.SetParams(ctx, genState.Params)
k.SetNextPoolNumber(ctx, genState.NextPoolNumber) k.SetNextPoolNumber(ctx, genState.NextPoolNumber)
liquidity := sdk.Coins{} liquidity := sdk.Coins{}
...@@ -56,5 +57,6 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { ...@@ -56,5 +57,6 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState {
return &types.GenesisState{ return &types.GenesisState{
NextPoolNumber: k.GetNextPoolNumber(ctx), NextPoolNumber: k.GetNextPoolNumber(ctx),
Pools: poolAnys, Pools: poolAnys,
Params: k.GetParams(ctx),
} }
} }
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
codectypes "github.com/cosmos/cosmos-sdk/codec/types" codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
simapp "github.com/osmosis-labs/osmosis/app" simapp "github.com/osmosis-labs/osmosis/app"
appparams "github.com/osmosis-labs/osmosis/app/params"
"github.com/osmosis-labs/osmosis/x/gamm" "github.com/osmosis-labs/osmosis/x/gamm"
"github.com/osmosis-labs/osmosis/x/gamm/types" "github.com/osmosis-labs/osmosis/x/gamm/types"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
...@@ -42,6 +43,9 @@ func TestGammInitGenesis(t *testing.T) { ...@@ -42,6 +43,9 @@ func TestGammInitGenesis(t *testing.T) {
gamm.InitGenesis(ctx, app.GAMMKeeper, types.GenesisState{ gamm.InitGenesis(ctx, app.GAMMKeeper, types.GenesisState{
Pools: []*codectypes.Any{any}, Pools: []*codectypes.Any{any},
NextPoolNumber: 2, NextPoolNumber: 2,
Params: types.Params{
PoolCreationFee: sdk.Coins{sdk.NewInt64Coin(appparams.BaseCoinUnit, 1000_000_000)},
},
}, app.AppCodec()) }, app.AppCodec())
require.Equal(t, app.GAMMKeeper.GetNextPoolNumber(ctx), uint64(2)) require.Equal(t, app.GAMMKeeper.GetNextPoolNumber(ctx), uint64(2))
...@@ -68,6 +72,7 @@ func TestGammExportGenesis(t *testing.T) { ...@@ -68,6 +72,7 @@ func TestGammExportGenesis(t *testing.T) {
acc1 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address().Bytes()) acc1 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address().Bytes())
app.BankKeeper.SetBalances(ctx, acc1, sdk.Coins{ app.BankKeeper.SetBalances(ctx, acc1, sdk.Coins{
sdk.NewCoin("uosmo", sdk.NewInt(10000000000)),
sdk.NewInt64Coin("foo", 100000), sdk.NewInt64Coin("foo", 100000),
sdk.NewInt64Coin("bar", 100000), sdk.NewInt64Coin("bar", 100000),
}) })
...@@ -110,6 +115,7 @@ func TestMarshalUnmarshalGenesis(t *testing.T) { ...@@ -110,6 +115,7 @@ func TestMarshalUnmarshalGenesis(t *testing.T) {
am := gamm.NewAppModule(appCodec, app.GAMMKeeper, app.AccountKeeper, app.BankKeeper) am := gamm.NewAppModule(appCodec, app.GAMMKeeper, app.AccountKeeper, app.BankKeeper)
acc1 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address().Bytes()) acc1 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address().Bytes())
app.BankKeeper.SetBalances(ctx, acc1, sdk.Coins{ app.BankKeeper.SetBalances(ctx, acc1, sdk.Coins{
sdk.NewCoin("uosmo", sdk.NewInt(10000000000)),
sdk.NewInt64Coin("foo", 100000), sdk.NewInt64Coin("foo", 100000),
sdk.NewInt64Coin("bar", 100000), sdk.NewInt64Coin("bar", 100000),
}) })
......
...@@ -6,6 +6,8 @@ import ( ...@@ -6,6 +6,8 @@ import (
"fmt" "fmt"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/osmosis-labs/osmosis/osmomath"
"github.com/osmosis-labs/osmosis/x/gamm/types" "github.com/osmosis-labs/osmosis/x/gamm/types"
) )
...@@ -88,9 +90,9 @@ func PoolTotalWeightInvariant(keeper Keeper, bk types.BankKeeper) sdk.Invariant ...@@ -88,9 +90,9 @@ func PoolTotalWeightInvariant(keeper Keeper, bk types.BankKeeper) sdk.Invariant
func genericPow(base, exp sdk.Dec) sdk.Dec { func genericPow(base, exp sdk.Dec) sdk.Dec {
if !base.GTE(sdk.NewDec(2)) { if !base.GTE(sdk.NewDec(2)) {
return pow(base, exp) return osmomath.Pow(base, exp)
} }
return powApprox(sdk.OneDec().Quo(base), exp.Neg(), powPrecision) return osmomath.PowApprox(sdk.OneDec().Quo(base), exp.Neg(), powPrecision)
} }
// constantChange returns the multiplicative factor difference in the pool constant, between two different pools. // constantChange returns the multiplicative factor difference in the pool constant, between two different pools.
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/osmosis-labs/osmosis/x/gamm/types" "github.com/osmosis-labs/osmosis/x/gamm/types"
) )
...@@ -24,14 +25,16 @@ type Keeper struct { ...@@ -24,14 +25,16 @@ type Keeper struct {
storeKey sdk.StoreKey storeKey sdk.StoreKey
cdc codec.BinaryMarshaler cdc codec.BinaryMarshaler
hooks types.GammHooks paramSpace paramtypes.Subspace
hooks types.GammHooks
// keepers // keepers
accountKeeper types.AccountKeeper accountKeeper types.AccountKeeper
bankKeeper types.BankKeeper bankKeeper types.BankKeeper
distrKeeper types.DistrKeeper
} }
func NewKeeper(cdc codec.BinaryMarshaler, storeKey sdk.StoreKey, accountKeeper types.AccountKeeper, bankKeeper types.BankKeeper) Keeper { func NewKeeper(cdc codec.BinaryMarshaler, storeKey sdk.StoreKey, paramSpace paramtypes.Subspace, accountKeeper types.AccountKeeper, bankKeeper types.BankKeeper, distrKeeper types.DistrKeeper) Keeper {
// Ensure that the module account are set. // Ensure that the module account are set.
moduleAddr, perms := accountKeeper.GetModuleAddressAndPermissions(types.ModuleName) moduleAddr, perms := accountKeeper.GetModuleAddressAndPermissions(types.ModuleName)
if moduleAddr == nil { if moduleAddr == nil {
...@@ -43,12 +46,17 @@ func NewKeeper(cdc codec.BinaryMarshaler, storeKey sdk.StoreKey, accountKeeper t ...@@ -43,12 +46,17 @@ func NewKeeper(cdc codec.BinaryMarshaler, storeKey sdk.StoreKey, accountKeeper t
if !permContains(perms, authtypes.Burner) { if !permContains(perms, authtypes.Burner) {
panic(fmt.Sprintf("%s module account should have the burner permission", types.ModuleName)) panic(fmt.Sprintf("%s module account should have the burner permission", types.ModuleName))
} }
if !paramSpace.HasKeyTable() {
paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable())
}
return Keeper{ return Keeper{
storeKey: storeKey, storeKey: storeKey,
cdc: cdc, cdc: cdc,
paramSpace: paramSpace,
// keepers // keepers
accountKeeper: accountKeeper, accountKeeper: accountKeeper,
bankKeeper: bankKeeper, bankKeeper: bankKeeper,
distrKeeper: distrKeeper,
} }
} }
......
...@@ -50,6 +50,7 @@ func (suite *KeeperTestSuite) preparePoolWithPoolParams(poolParams types.PoolPar ...@@ -50,6 +50,7 @@ func (suite *KeeperTestSuite) preparePoolWithPoolParams(poolParams types.PoolPar
suite.ctx, suite.ctx,
acc, acc,
sdk.NewCoins( sdk.NewCoins(
sdk.NewCoin("uosmo", sdk.NewInt(10000000000)),
sdk.NewCoin("foo", sdk.NewInt(10000000)), sdk.NewCoin("foo", sdk.NewInt(10000000)),
sdk.NewCoin("bar", sdk.NewInt(10000000)), sdk.NewCoin("bar", sdk.NewInt(10000000)),
sdk.NewCoin("baz", sdk.NewInt(10000000)), sdk.NewCoin("baz", sdk.NewInt(10000000)),
......
package keeper package keeper
import ( import (
"fmt" "github.com/osmosis-labs/osmosis/osmomath"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
) )
...@@ -67,7 +67,7 @@ func calcOutGivenIn( ...@@ -67,7 +67,7 @@ func calcOutGivenIn(
adjustedIn := sdk.OneDec().Sub(swapFee) adjustedIn := sdk.OneDec().Sub(swapFee)
adjustedIn = tokenAmountIn.Mul(adjustedIn) adjustedIn = tokenAmountIn.Mul(adjustedIn)
y := tokenBalanceIn.Quo(tokenBalanceIn.Add(adjustedIn)) y := tokenBalanceIn.Quo(tokenBalanceIn.Add(adjustedIn))
foo := pow(y, weightRatio) foo := osmomath.Pow(y, weightRatio)
bar := sdk.OneDec().Sub(foo) bar := sdk.OneDec().Sub(foo)
return tokenBalanceOut.Mul(bar) return tokenBalanceOut.Mul(bar)
} }
...@@ -84,7 +84,7 @@ func calcInGivenOut( ...@@ -84,7 +84,7 @@ func calcInGivenOut(
weightRatio := tokenWeightOut.Quo(tokenWeightIn) weightRatio := tokenWeightOut.Quo(tokenWeightIn)
diff := tokenBalanceOut.Sub(tokenAmountOut) diff := tokenBalanceOut.Sub(tokenAmountOut)
y := tokenBalanceOut.Quo(diff) y := tokenBalanceOut.Quo(diff)
foo := pow(y, weightRatio) foo := osmomath.Pow(y, weightRatio)
foo = foo.Sub(one) foo = foo.Sub(one)
tokenAmountIn := sdk.OneDec().Sub(swapFee) tokenAmountIn := sdk.OneDec().Sub(swapFee)
return (tokenBalanceIn.Mul(foo)).Quo(tokenAmountIn) return (tokenBalanceIn.Mul(foo)).Quo(tokenAmountIn)
...@@ -108,7 +108,7 @@ func calcPoolOutGivenSingleIn( ...@@ -108,7 +108,7 @@ func calcPoolOutGivenSingleIn(
tokenInRatio := newTokenBalanceIn.Quo(tokenBalanceIn) tokenInRatio := newTokenBalanceIn.Quo(tokenBalanceIn)
// uint newPoolSupply = (ratioTi ^ weightTi) * poolSupply; // uint newPoolSupply = (ratioTi ^ weightTi) * poolSupply;
poolRatio := pow(tokenInRatio, normalizedWeight) poolRatio := osmomath.Pow(tokenInRatio, normalizedWeight)
newPoolSupply := poolRatio.Mul(poolSupply) newPoolSupply := poolRatio.Mul(poolSupply)
return newPoolSupply.Sub(poolSupply) return newPoolSupply.Sub(poolSupply)
} }
...@@ -128,7 +128,7 @@ func calcSingleInGivenPoolOut( ...@@ -128,7 +128,7 @@ func calcSingleInGivenPoolOut(
//uint newBalTi = poolRatio^(1/weightTi) * balTi; //uint newBalTi = poolRatio^(1/weightTi) * balTi;
boo := sdk.OneDec().Quo(normalizedWeight) boo := sdk.OneDec().Quo(normalizedWeight)
tokenInRatio := pow(poolRatio, boo) tokenInRatio := osmomath.Pow(poolRatio, boo)
newTokenBalanceIn := tokenInRatio.Mul(tokenBalanceIn) newTokenBalanceIn := tokenInRatio.Mul(tokenBalanceIn)
tokenAmountInAfterFee := newTokenBalanceIn.Sub(tokenBalanceIn) tokenAmountInAfterFee := newTokenBalanceIn.Sub(tokenBalanceIn)
// Do reverse order of fees charged in joinswap_ExternAmountIn, this way // Do reverse order of fees charged in joinswap_ExternAmountIn, this way
...@@ -157,7 +157,7 @@ func calcSingleOutGivenPoolIn( ...@@ -157,7 +157,7 @@ func calcSingleOutGivenPoolIn(
// newBalTo = poolRatio^(1/weightTo) * balTo; // newBalTo = poolRatio^(1/weightTo) * balTo;
tokenOutRatio := pow(poolRatio, sdk.OneDec().Quo(normalizedWeight)) tokenOutRatio := osmomath.Pow(poolRatio, sdk.OneDec().Quo(normalizedWeight))
newTokenBalanceOut := tokenOutRatio.Mul(tokenBalanceOut) newTokenBalanceOut := tokenOutRatio.Mul(tokenBalanceOut)
tokenAmountOutBeforeSwapFee := tokenBalanceOut.Sub(newTokenBalanceOut) tokenAmountOutBeforeSwapFee := tokenBalanceOut.Sub(newTokenBalanceOut)
...@@ -190,7 +190,7 @@ func calcPoolInGivenSingleOut( ...@@ -190,7 +190,7 @@ func calcPoolInGivenSingleOut(
tokenOutRatio := newTokenBalanceOut.Quo(tokenBalanceOut) tokenOutRatio := newTokenBalanceOut.Quo(tokenBalanceOut)
//uint newPoolSupply = (ratioTo ^ weightTo) * poolSupply; //uint newPoolSupply = (ratioTo ^ weightTo) * poolSupply;
poolRatio := pow(tokenOutRatio, normalizedWeight) poolRatio := osmomath.Pow(tokenOutRatio, normalizedWeight)
newPoolSupply := poolRatio.Mul(poolSupply) newPoolSupply := poolRatio.Mul(poolSupply)
poolAmountInAfterExitFee := poolSupply.Sub(newPoolSupply) poolAmountInAfterExitFee := poolSupply.Sub(newPoolSupply)
...@@ -198,141 +198,3 @@ func calcPoolInGivenSingleOut( ...@@ -198,141 +198,3 @@ func calcPoolInGivenSingleOut(
// pAi = pAiAfterExitFee/(1-exitFee) // pAi = pAiAfterExitFee/(1-exitFee)
return poolAmountInAfterExitFee.Quo(sdk.OneDec().Sub(exitFee)) return poolAmountInAfterExitFee.Quo(sdk.OneDec().Sub(exitFee))
} }
/*********************************************************/
// absDifferenceWithSign returns | a - b |, (a - b).sign()
// a is mutated and returned
func absDifferenceWithSign(a, b sdk.Dec) (sdk.Dec, bool) {
if a.GTE(b) {
return a.SubMut(b), false
} else {
return a.NegMut().AddMut(b), true
}
}
// func largeBasePow(base sdk.Dec, exp sdk.Dec) sdk.Dec {
// // pow requires the base to be <= 2
// }
// pow computes base^(exp)
// However since the exponent is not an integer, we must do an approximation algorithm.
// TODO: In the future, lets add some optimized routines for common exponents, e.g. for common wIn / wOut ratios
// Many simple exponents like 2:1 pools
func pow(base sdk.Dec, exp sdk.Dec) sdk.Dec {
// Exponentiation of a negative base with an arbitrary real exponent is not closed within the reals.
// You can see this by recalling that `i = (-1)^(.5)`. We have to go to complex numbers to define this.
// (And would have to implement complex logarithms)
// We don't have a need for negative bases, so we don't include any such logic.
if !base.IsPositive() {
panic(fmt.Errorf("base must be greater than 0"))
}
// TODO: Remove this if we want to generalize the function,
// we can adjust the algorithm in this setting.
if base.GTE(two) {
panic(fmt.Errorf("base must be lesser than two"))
}
// We will use an approximation algorithm to compute the power.
// Since computing an integer power is easy, we split up the exponent into
// an integer component and a fractional component.
integer := exp.TruncateDec()
fractional := exp.Sub(integer)
integerPow := base.Power(uint64(integer.TruncateInt64()))
if fractional.IsZero() {
return integerPow
}
fractionalPow := powApprox(base, fractional, powPrecision)
return integerPow.Mul(fractionalPow)
}
// Contract: 0 < base <= 2
// 0 < exp < 1
func powApprox(base sdk.Dec, exp sdk.Dec, precision sdk.Dec) sdk.Dec {
if exp.IsZero() {
return sdk.ZeroDec()
}
// Common case optimization
// Optimize for it being equal to one-half
if exp.Equal(one_half) {
output, err := base.ApproxSqrt()
if err != nil {
panic(err)
}
return output
}
// TODO: Make an approx-equal function, and then check if exp * 3 = 1, and do a check accordingly
// We compute this via taking the maclaurin series of (1 + x)^a
// where x = base - 1.
// The maclaurin series of (1 + x)^a = sum_{k=0}^{infty} binom(a, k) x^k
// Binom(a, k) takes the natural continuation on the first parameter, namely that
// Binom(a, k) = N/D, where D = k!, and N = a(a-1)(a-2)...(a-k+1)
// Next we show that the absolute value of each term is less than the last term.
// Note that the change in term n's value vs term n + 1 is a multiplicative factor of
// v_n = x(a - n) / (n+1)
// So if |v_n| < 1, we know that each term has a lesser impact on the result than the last.
// For our bounds on |x| < 1, |a| < 1,
// it suffices to see for what n is |v_n| < 1,
// in the worst parameterization of x = 1, a = -1.
// v_n = |(-1 + epsilon - n) / (n+1)|
// So |v_n| is always less than 1, as n ranges over the integers.
//
// Note that term_n of the expansion is 1 * prod_{i=0}^{n-1} v_i
// The error if we stop the expansion at term_n is:
// error_n = sum_{k=n+1}^{infty} term_k
// At this point we further restrict a >= 0, so 0 <= a < 1.
// Now we take the _INCORRECT_ assumption that if term_n < p, then
// error_n < p.
// This assumption is obviously wrong.
// However our usages of this function don't use the full domain.
// With a > 0, |x| << 1, and p sufficiently low, perhaps this actually is true.
// TODO: Check with our parameterization
// TODO: If theres a bug, balancer is also wrong here :thonk:
base = base.Clone()
x, xneg := absDifferenceWithSign(base, one)
term := sdk.OneDec()
sum := sdk.OneDec()
negative := false
a := exp.Clone()
bigK := sdk.NewDec(0)
// TODO: Document this computation via taylor expansion
for i := int64(1); term.GTE(precision); i++ {
// At each iteration, we need two values, i and i-1.
// To avoid expensive big.Int allocation, we reuse bigK variable.
// On this line, bigK == i-1.
c, cneg := absDifferenceWithSign(a, bigK)
// On this line, bigK == i.
bigK.Set(sdk.NewDec(i)) // TODO: O(n) bigint allocation happens
term.MulMut(c).MulMut(x).QuoMut(bigK)
// a is mutated on absDifferenceWithSign, reset
a.Set(exp)
if term.IsZero() {
break
}
if xneg {
negative = !negative
}
if cneg {
negative = !negative
}
if negative {
sum.SubMut(term)
} else {
sum.AddMut(term)
}
}
return sum
}
...@@ -8,54 +8,6 @@ import ( ...@@ -8,54 +8,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestAbsDifferenceWithSign(t *testing.T) {
decA, err := sdk.NewDecFromStr("3.2")
require.NoError(t, err)
decB, err := sdk.NewDecFromStr("4.3432389")
require.NoError(t, err)
s, b := absDifferenceWithSign(decA, decB)
require.True(t, b)
expectedDec, err := sdk.NewDecFromStr("1.1432389")
require.NoError(t, err)
require.Equal(t, expectedDec, s)
}
func TestPowApprox(t *testing.T) {
base, err := sdk.NewDecFromStr("0.8")
require.NoError(t, err)
exp, err := sdk.NewDecFromStr("0.32")
require.NoError(t, err)
s := powApprox(base, exp, powPrecision)
expectedDec, err := sdk.NewDecFromStr("0.93108385")
require.NoError(t, err)
require.True(
t,
expectedDec.Sub(s).Abs().LTE(powPrecision),
"expected value & actual value's difference should less than precision",
)
}
func TestPow(t *testing.T) {
base, err := sdk.NewDecFromStr("1.68")
require.NoError(t, err)
exp, err := sdk.NewDecFromStr("0.32")
require.NoError(t, err)
s := pow(base, exp)
expectedDec, err := sdk.NewDecFromStr("1.18058965")
require.NoError(t, err)
require.True(
t,
expectedDec.Sub(s).Abs().LTE(powPrecision),
"expected value & actual value's difference should less than precision",
)
}
func TestCalcSpotPrice(t *testing.T) { func TestCalcSpotPrice(t *testing.T) {
// TODO: Change test to be table driven // TODO: Change test to be table driven
tokenBalanceIn, err := sdk.NewDecFromStr("100") tokenBalanceIn, err := sdk.NewDecFromStr("100")
......
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/osmosis-labs/osmosis/x/gamm/types"
)
// GetParams returns the total set params
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
k.paramSpace.GetParamSet(ctx, &params)
return params
}
// SetParams sets the total set of params
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
k.paramSpace.SetParamSet(ctx, &params)
}
...@@ -28,6 +28,13 @@ func (k Keeper) CreatePool( ...@@ -28,6 +28,13 @@ func (k Keeper) CreatePool(
) )
} }
// send pool creation fee to community pool
params := k.GetParams(ctx)
err := k.distrKeeper.FundCommunityPool(ctx, params.PoolCreationFee, sender)
if err != nil {
return 0, err
}
pool, err := k.newPool(ctx, poolParams, poolAssets, futurePoolGovernor) pool, err := k.newPool(ctx, poolParams, poolAssets, futurePoolGovernor)
if err != nil { if err != nil {
return 0, err return 0, err
......
...@@ -19,6 +19,13 @@ var ( ...@@ -19,6 +19,13 @@ var (
) )
func (suite *KeeperTestSuite) TestCreatePool() { func (suite *KeeperTestSuite) TestCreatePool() {
params := suite.app.GAMMKeeper.GetParams(suite.ctx)
poolCreationFeeDecCoins := sdk.DecCoins{}
for _, coin := range params.PoolCreationFee {
poolCreationFeeDecCoins = poolCreationFeeDecCoins.Add(sdk.NewDecCoin(coin.Denom, coin.Amount))
}
func() { func() {
keeper := suite.app.GAMMKeeper keeper := suite.app.GAMMKeeper
...@@ -41,6 +48,8 @@ func (suite *KeeperTestSuite) TestCreatePool() { ...@@ -41,6 +48,8 @@ func (suite *KeeperTestSuite) TestCreatePool() {
}{{ }{{
fn: func() { fn: func() {
keeper := suite.app.GAMMKeeper keeper := suite.app.GAMMKeeper
prevFeePool := suite.app.DistrKeeper.GetFeePoolCommunityCoins(suite.ctx)
prevAcc1Bal := suite.app.BankKeeper.GetAllBalances(suite.ctx, acc1)
poolId, err := keeper.CreatePool(suite.ctx, acc1, types.PoolParams{ poolId, err := keeper.CreatePool(suite.ctx, acc1, types.PoolParams{
SwapFee: sdk.NewDecWithPrec(1, 2), SwapFee: sdk.NewDecWithPrec(1, 2),
ExitFee: sdk.NewDecWithPrec(1, 2), ExitFee: sdk.NewDecWithPrec(1, 2),
...@@ -59,6 +68,20 @@ func (suite *KeeperTestSuite) TestCreatePool() { ...@@ -59,6 +68,20 @@ func (suite *KeeperTestSuite) TestCreatePool() {
fmt.Sprintf("share token should be minted as %s initially", types.InitPoolSharesSupply.String()), fmt.Sprintf("share token should be minted as %s initially", types.InitPoolSharesSupply.String()),
) )
// check fee is correctly sent to community pool
feePool := suite.app.DistrKeeper.GetFeePoolCommunityCoins(suite.ctx)
suite.Require().Equal(feePool, prevFeePool.Add(poolCreationFeeDecCoins...))
// check account's balance is correctly reduced
acc1Bal := suite.app.BankKeeper.GetAllBalances(suite.ctx, acc1)
suite.Require().Equal(acc1Bal.String(),
prevAcc1Bal.Sub(params.PoolCreationFee).
Sub(sdk.Coins{
sdk.NewCoin("bar", sdk.NewInt(10000)),
sdk.NewCoin("foo", sdk.NewInt(10000)),
}).Add(sdk.NewCoin(types.GetPoolShareDenom(pool.GetId()), types.InitPoolSharesSupply)).String(),
)
liquidity := suite.app.GAMMKeeper.GetTotalLiquidity(suite.ctx) liquidity := suite.app.GAMMKeeper.GetTotalLiquidity(suite.ctx)
suite.Require().Equal("10000bar,10000foo", liquidity.String()) suite.Require().Equal("10000bar,10000foo", liquidity.String())
}, },
...@@ -183,6 +206,48 @@ func (suite *KeeperTestSuite) TestCreatePool() { ...@@ -183,6 +206,48 @@ func (suite *KeeperTestSuite) TestCreatePool() {
}}, defaultFutureGovernor) }}, defaultFutureGovernor)
suite.Require().Error(err, "can't create the pool with duplicated PoolAssets") suite.Require().Error(err, "can't create the pool with duplicated PoolAssets")
}, },
}, {
fn: func() {
keeper := suite.app.GAMMKeeper
keeper.SetParams(suite.ctx, types.Params{
PoolCreationFee: sdk.Coins{},
})
_, err := keeper.CreatePool(suite.ctx, acc1, types.PoolParams{
SwapFee: sdk.NewDecWithPrec(1, 2),
ExitFee: sdk.NewDecWithPrec(1, 2),
}, []types.PoolAsset{{
Weight: sdk.NewInt(100),
Token: sdk.NewCoin("foo", sdk.NewInt(10000)),
}, {
Weight: sdk.NewInt(100),
Token: sdk.NewCoin("bar", sdk.NewInt(10000)),
}}, defaultFutureGovernor)
suite.Require().NoError(err)
pools, err := keeper.GetPools(suite.ctx)
suite.Require().Len(pools, 1)
suite.Require().NoError(err)
},
}, {
fn: func() {
keeper := suite.app.GAMMKeeper
keeper.SetParams(suite.ctx, types.Params{
PoolCreationFee: nil,
})
_, err := keeper.CreatePool(suite.ctx, acc1, types.PoolParams{
SwapFee: sdk.NewDecWithPrec(1, 2),
ExitFee: sdk.NewDecWithPrec(1, 2),
}, []types.PoolAsset{{
Weight: sdk.NewInt(100),
Token: sdk.NewCoin("foo", sdk.NewInt(10000)),
}, {
Weight: sdk.NewInt(100),
Token: sdk.NewCoin("bar", sdk.NewInt(10000)),
}}, defaultFutureGovernor)
suite.Require().NoError(err)
pools, err := keeper.GetPools(suite.ctx)
suite.Require().Len(pools, 1)
suite.Require().NoError(err)
},
}} }}
for _, test := range tests { for _, test := range tests {
...@@ -194,6 +259,7 @@ func (suite *KeeperTestSuite) TestCreatePool() { ...@@ -194,6 +259,7 @@ func (suite *KeeperTestSuite) TestCreatePool() {
suite.ctx, suite.ctx,
acc, acc,
sdk.NewCoins( sdk.NewCoins(
sdk.NewCoin("uosmo", sdk.NewInt(10000000000)),
sdk.NewCoin("foo", sdk.NewInt(10000000)), sdk.NewCoin("foo", sdk.NewInt(10000000)),
sdk.NewCoin("bar", sdk.NewInt(10000000)), sdk.NewCoin("bar", sdk.NewInt(10000000)),
sdk.NewCoin("baz", sdk.NewInt(10000000)), sdk.NewCoin("baz", sdk.NewInt(10000000)),
...@@ -281,6 +347,7 @@ func (suite *KeeperTestSuite) TestJoinPool() { ...@@ -281,6 +347,7 @@ func (suite *KeeperTestSuite) TestJoinPool() {
suite.ctx, suite.ctx,
acc, acc,
sdk.NewCoins( sdk.NewCoins(
sdk.NewCoin("uosmo", sdk.NewInt(10000000000)),
sdk.NewCoin("foo", sdk.NewInt(10000000)), sdk.NewCoin("foo", sdk.NewInt(10000000)),
sdk.NewCoin("bar", sdk.NewInt(10000000)), sdk.NewCoin("bar", sdk.NewInt(10000000)),
sdk.NewCoin("baz", sdk.NewInt(10000000)), sdk.NewCoin("baz", sdk.NewInt(10000000)),
...@@ -389,6 +456,7 @@ func (suite *KeeperTestSuite) TestExitPool() { ...@@ -389,6 +456,7 @@ func (suite *KeeperTestSuite) TestExitPool() {
suite.ctx, suite.ctx,
acc, acc,
sdk.NewCoins( sdk.NewCoins(
sdk.NewCoin("uosmo", sdk.NewInt(10000000000)),
sdk.NewCoin("foo", sdk.NewInt(10000000)), sdk.NewCoin("foo", sdk.NewInt(10000000)),
sdk.NewCoin("bar", sdk.NewInt(10000000)), sdk.NewCoin("bar", sdk.NewInt(10000000)),
sdk.NewCoin("baz", sdk.NewInt(10000000)), sdk.NewCoin("baz", sdk.NewInt(10000000)),
...@@ -436,6 +504,7 @@ func (suite *KeeperTestSuite) TestActivePool() { ...@@ -436,6 +504,7 @@ func (suite *KeeperTestSuite) TestActivePool() {
suite.ctx, suite.ctx,
acc, acc,
sdk.NewCoins( sdk.NewCoins(
sdk.NewCoin("uosmo", sdk.NewInt(10000000000)),
sdk.NewCoin("foo", sdk.NewInt(10000000)), sdk.NewCoin("foo", sdk.NewInt(10000000)),
sdk.NewCoin("bar", sdk.NewInt(10000000)), sdk.NewCoin("bar", sdk.NewInt(10000000)),
sdk.NewCoin("baz", sdk.NewInt(10000000)), sdk.NewCoin("baz", sdk.NewInt(10000000)),
......
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