diff --git a/simulation/simtypes/txbuilder.go b/simulation/simtypes/txbuilder.go index 9994893c2d8..f6d4d3c116c 100644 --- a/simulation/simtypes/txbuilder.go +++ b/simulation/simtypes/txbuilder.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/osmosis-labs/osmosis/v15/app/params" + tokenfactorytypes "github.com/osmosis-labs/osmosis/v15/x/tokenfactory/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" authsign "github.com/cosmos/cosmos-sdk/x/auth/signing" @@ -37,11 +38,14 @@ func (sim *SimCtx) defaultTxBuilder( // TODO: Consider making a default tx builder that charges some random fees // Low value for amount of work right now though. fees := sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 25000)) + + gas := getGas(msg) + tx, err := genTx( txConfig, []sdk.Msg{msg}, fees, - helpers.DefaultGenTxGas, + gas, ctx.ChainID(), []uint64{authAcc.GetAccountNumber()}, []uint64{authAcc.GetSequence()}, @@ -122,3 +126,12 @@ func genTx(gen client.TxConfig, msgs []sdk.Msg, feeAmt sdk.Coins, gas uint64, ch return txBuilder.GetTx(), nil } + +// special cases some messages that require higher gas limits +func getGas(msg sdk.Msg) uint64 { + _, ok := msg.(*tokenfactorytypes.MsgCreateDenom) + if ok { + return uint64(tokenfactorytypes.DefaultCreationGasFee + helpers.DefaultGenTxGas) + } + return uint64(helpers.DefaultGenTxGas) +} diff --git a/wasmbinding/test/custom_msg_test.go b/wasmbinding/test/custom_msg_test.go index 268060c726d..fca37986a2d 100644 --- a/wasmbinding/test/custom_msg_test.go +++ b/wasmbinding/test/custom_msg_test.go @@ -6,7 +6,6 @@ import ( "testing" "github.com/osmosis-labs/osmosis/v15/app/apptesting" - "github.com/osmosis-labs/osmosis/v15/x/tokenfactory/types" "github.com/stretchr/testify/require" @@ -27,10 +26,6 @@ func TestCreateDenomMsg(t *testing.T) { reflect := instantiateReflectContract(t, ctx, osmosis, lucky) require.NotEmpty(t, reflect) - // Fund reflect contract with 100 base denom creation fees - reflectAmount := sdk.NewCoins(sdk.NewCoin(types.DefaultParams().DenomCreationFee[0].Denom, types.DefaultParams().DenomCreationFee[0].Amount.MulRaw(100))) - fundAccount(t, ctx, osmosis, reflect, reflectAmount) - msg := bindings.OsmosisMsg{CreateDenom: &bindings.CreateDenom{ Subdenom: "SUN", }} @@ -59,10 +54,6 @@ func TestMintMsg(t *testing.T) { reflect := instantiateReflectContract(t, ctx, osmosis, lucky) require.NotEmpty(t, reflect) - // Fund reflect contract with 100 base denom creation fees - reflectAmount := sdk.NewCoins(sdk.NewCoin(types.DefaultParams().DenomCreationFee[0].Denom, types.DefaultParams().DenomCreationFee[0].Amount.MulRaw(100))) - fundAccount(t, ctx, osmosis, reflect, reflectAmount) - // lucky was broke balances := osmosis.BankKeeper.GetAllBalances(ctx, lucky) require.Empty(t, balances) @@ -188,10 +179,6 @@ func TestBurnMsg(t *testing.T) { reflect := instantiateReflectContract(t, ctx, osmosis, lucky) require.NotEmpty(t, reflect) - // Fund reflect contract with 100 base denom creation fees - reflectAmount := sdk.NewCoins(sdk.NewCoin(types.DefaultParams().DenomCreationFee[0].Denom, types.DefaultParams().DenomCreationFee[0].Amount.MulRaw(100))) - fundAccount(t, ctx, osmosis, reflect, reflectAmount) - // lucky was broke balances := osmosis.BankKeeper.GetAllBalances(ctx, lucky) require.Empty(t, balances) diff --git a/wasmbinding/test/messages_test.go b/wasmbinding/test/messages_test.go index 28d8b25dfa9..19c06b91764 100644 --- a/wasmbinding/test/messages_test.go +++ b/wasmbinding/test/messages_test.go @@ -9,7 +9,6 @@ import ( "github.com/osmosis-labs/osmosis/v15/app/apptesting" "github.com/osmosis-labs/osmosis/v15/wasmbinding" "github.com/osmosis-labs/osmosis/v15/wasmbinding/bindings" - "github.com/osmosis-labs/osmosis/v15/x/tokenfactory/types" "github.com/stretchr/testify/require" ) @@ -19,10 +18,6 @@ func TestCreateDenom(t *testing.T) { actor := RandomAccountAddress() osmosis, ctx := SetupCustomApp(t, actor) - // Fund actor with 100 base denom creation fees - actorAmount := sdk.NewCoins(sdk.NewCoin(types.DefaultParams().DenomCreationFee[0].Denom, types.DefaultParams().DenomCreationFee[0].Amount.MulRaw(100))) - fundAccount(t, ctx, osmosis, actor, actorAmount) - specs := map[string]struct { createDenom *bindings.CreateDenom expErr bool @@ -147,10 +142,6 @@ func TestChangeAdmin(t *testing.T) { // Setup osmosis, ctx := SetupCustomApp(t, tokenCreator) - // Fund actor with 100 base denom creation fees - actorAmount := sdk.NewCoins(sdk.NewCoin(types.DefaultParams().DenomCreationFee[0].Denom, types.DefaultParams().DenomCreationFee[0].Amount.MulRaw(100))) - fundAccount(t, ctx, osmosis, tokenCreator, actorAmount) - err := wasmbinding.PerformCreateDenom(osmosis.TokenFactoryKeeper, osmosis.BankKeeper, ctx, tokenCreator, &bindings.CreateDenom{ Subdenom: validDenom, }) @@ -173,10 +164,6 @@ func TestMint(t *testing.T) { creator := RandomAccountAddress() osmosis, ctx := SetupCustomApp(t, creator) - // Fund actor with 100 base denom creation fees - tokenCreationFeeAmt := sdk.NewCoins(sdk.NewCoin(types.DefaultParams().DenomCreationFee[0].Denom, types.DefaultParams().DenomCreationFee[0].Amount.MulRaw(100))) - fundAccount(t, ctx, osmosis, creator, tokenCreationFeeAmt) - // Create denoms for valid mint tests validDenom := bindings.CreateDenom{ Subdenom: "MOON", @@ -293,10 +280,6 @@ func TestBurn(t *testing.T) { creator := RandomAccountAddress() osmosis, ctx := SetupCustomApp(t, creator) - // Fund actor with 100 base denom creation fees - tokenCreationFeeAmt := sdk.NewCoins(sdk.NewCoin(types.DefaultParams().DenomCreationFee[0].Denom, types.DefaultParams().DenomCreationFee[0].Amount.MulRaw(100))) - fundAccount(t, ctx, osmosis, creator, tokenCreationFeeAmt) - // Create denoms for valid burn tests validDenom := bindings.CreateDenom{ Subdenom: "MOON", diff --git a/x/cosmwasmpool/bytecode/transmuter.wasm b/x/cosmwasmpool/bytecode/transmuter.wasm old mode 100755 new mode 100644 index 7a5029607c1..b9bd7d1ac75 Binary files a/x/cosmwasmpool/bytecode/transmuter.wasm and b/x/cosmwasmpool/bytecode/transmuter.wasm differ diff --git a/x/cosmwasmpool/cosmwasm/msg/transmuter/transmuter_test.go b/x/cosmwasmpool/cosmwasm/msg/transmuter/transmuter_test.go new file mode 100644 index 00000000000..4da050271c3 --- /dev/null +++ b/x/cosmwasmpool/cosmwasm/msg/transmuter/transmuter_test.go @@ -0,0 +1,100 @@ +package transmuter_test + +import ( + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/stretchr/testify/suite" + + "github.com/osmosis-labs/osmosis/v15/app/apptesting" + incentivetypes "github.com/osmosis-labs/osmosis/v15/x/incentives/types" + lockuptypes "github.com/osmosis-labs/osmosis/v15/x/lockup/types" + tokenfactorytypes "github.com/osmosis-labs/osmosis/v15/x/tokenfactory/types" +) + +const ( + denomA = apptesting.DefaultTransmuterDenomA + denomB = apptesting.DefaultTransmuterDenomB +) + +// Suite for the transmuter contract. +type TransmuterSuite struct { + apptesting.KeeperTestHelper +} + +var ( + defaultPoolId = uint64(1) + defaultAmount = sdk.NewInt(100) + initalDefaultSupply = sdk.NewCoins(sdk.NewCoin(denomA, defaultAmount), sdk.NewCoin(denomB, defaultAmount)) + uosmo = "uosmo" + + defaultDenoms = []string{denomA, denomB} +) + +func TestTransmuterSuite(t *testing.T) { + suite.Run(t, new(TransmuterSuite)) +} + +// This test functionally tests that the transmuter contract works as expected. +// It validates: +// - LP and tokenfactory share creation +// - Ability to lock, create gauges for and incentivize such shares +func (s *TransmuterSuite) TestFunctionalTransmuter() { + s.Setup() + + const ( + exppectedDenomPrefix = tokenfactorytypes.ModuleDenomPrefix + "/" + expectedDenomSuffix = "/transmuter/poolshare" + ) + + // Create Transmuter pool + transmuter := s.PrepareCosmWasmPool() + + contractAddress := transmuter.GetContractAddress() + expectedShareDenom := exppectedDenomPrefix + contractAddress + expectedDenomSuffix + + // Validate that tokenfactory denom is created in the desired format. + denomIteraror := s.App.TokenFactoryKeeper.GetAllDenomsIterator(s.Ctx) + defer denomIteraror.Close() + s.Require().True(denomIteraror.Valid()) + s.Require().Equal(expectedShareDenom, string(denomIteraror.Value())) + + // Fund account + s.FundAcc(s.TestAccs[0], initalDefaultSupply) + + // Join pool + s.JoinTransmuterPool(s.TestAccs[0], defaultPoolId, initalDefaultSupply) + + // Check that the number of shares equals to the sum of the initial token amounts. + shareCoin := s.App.BankKeeper.GetBalance(s.Ctx, s.TestAccs[0], expectedShareDenom) + s.Require().Equal(defaultAmount.MulRaw(2), shareCoin.Amount) + + // Attempt to incentivize the tokenfactory shares + + // Lock shares + shareCoins := sdk.NewCoins(shareCoin) + lockDuration := time.Hour + _, err := s.App.LockupKeeper.CreateLock(s.Ctx, s.TestAccs[0], shareCoins, lockDuration) + s.Require().NoError(err) + + // Create gauge + incentive := sdk.NewCoins(sdk.NewCoin(uosmo, sdk.NewInt(1_000_000))) + s.FundAcc(s.TestAccs[1], incentive) + gaugeId, err := s.App.IncentivesKeeper.CreateGauge(s.Ctx, true, s.TestAccs[1], incentive, lockuptypes.QueryCondition{ + LockQueryType: lockuptypes.ByDuration, + Denom: expectedShareDenom, + Duration: lockDuration, + }, s.Ctx.BlockTime(), 1) + s.Require().NoError(err) + gauge, err := s.App.IncentivesKeeper.GetGaugeByID(s.Ctx, gaugeId) + s.Require().NoError(err) + + // Distirbute rewards + coins, err := s.App.IncentivesKeeper.Distribute(s.Ctx, []incentivetypes.Gauge{*gauge}) + s.Require().NoError(err) + + // Confirm that the rewards are distributed with no errors. + s.Require().Equal(incentive.String(), coins.String()) +} diff --git a/x/cosmwasmpool/pool_module_test.go b/x/cosmwasmpool/pool_module_test.go index 63c6acf27e7..25933c29466 100644 --- a/x/cosmwasmpool/pool_module_test.go +++ b/x/cosmwasmpool/pool_module_test.go @@ -185,7 +185,7 @@ func (s *PoolModuleSuite) TestCalcOutAmtGivenIn_SwapOutAmtGivenIn() { initialCoins: initalDefaultSupply, tokenIn: sdk.NewCoin(denomA, defaultAmount.Add(sdk.OneInt())), tokenOutDenom: denomB, - expectedErrorMessage: fmt.Sprintf("Insufficient fund: required: %s, available: %s", sdk.NewCoin(denomB, defaultAmount.Add(sdk.OneInt())), sdk.NewCoin(denomB, defaultAmount)), + expectedErrorMessage: fmt.Sprintf("Insufficient pool asset: required: %s, available: %s", sdk.NewCoin(denomB, defaultAmount.Add(sdk.OneInt())), sdk.NewCoin(denomB, defaultAmount)), }, "non-zero swap fee": { initialCoins: initalDefaultSupply, @@ -310,7 +310,7 @@ func (s *PoolModuleSuite) TestCalcInAmtGivenOut_SwapInAmtGivenOut() { initialCoins: initalDefaultSupply, tokenOut: sdk.NewCoin(denomA, defaultAmount.Add(sdk.OneInt())), tokenInDenom: denomB, - expectedErrorMessage: fmt.Sprintf("Insufficient fund: required: %s, available: %s", sdk.NewCoin(denomA, defaultAmount.Add(sdk.OneInt())), sdk.NewCoin(denomA, defaultAmount)), + expectedErrorMessage: fmt.Sprintf("Insufficient pool asset: required: %s, available: %s", sdk.NewCoin(denomA, defaultAmount.Add(sdk.OneInt())), sdk.NewCoin(denomA, defaultAmount)), }, "non-zero swap fee": { initialCoins: initalDefaultSupply, diff --git a/x/tokenfactory/client/cli/query_test.go b/x/tokenfactory/client/cli/query_test.go index c85c5b7d9ea..790528e935e 100644 --- a/x/tokenfactory/client/cli/query_test.go +++ b/x/tokenfactory/client/cli/query_test.go @@ -22,7 +22,7 @@ func (s *QueryTestSuite) SetupSuite() { s.queryClient = types.NewQueryClient(s.QueryHelper) // fund acc - fundAccsAmount := sdk.NewCoins(sdk.NewCoin(types.DefaultParams().DenomCreationFee[0].Denom, types.DefaultParams().DenomCreationFee[0].Amount.MulRaw(100)), sdk.NewCoin(apptesting.SecondaryDenom, apptesting.SecondaryAmount)) + fundAccsAmount := sdk.NewCoins(sdk.NewCoin(apptesting.SecondaryDenom, apptesting.SecondaryAmount)) s.FundAcc(s.TestAccs[0], fundAccsAmount) // create new token _, err := s.App.TokenFactoryKeeper.CreateDenom(s.Ctx, s.TestAccs[0].String(), "tokenfactory") diff --git a/x/tokenfactory/keeper/createdenom_test.go b/x/tokenfactory/keeper/createdenom_test.go index 0444f9015a4..218a066d0d5 100644 --- a/x/tokenfactory/keeper/createdenom_test.go +++ b/x/tokenfactory/keeper/createdenom_test.go @@ -13,9 +13,20 @@ func (s *KeeperTestSuite) TestMsgCreateDenom() { var ( tokenFactoryKeeper = s.App.TokenFactoryKeeper bankKeeper = s.App.BankKeeper - denomCreationFee = tokenFactoryKeeper.GetParams(s.Ctx).DenomCreationFee + denomCreationFee = sdk.NewCoins(sdk.NewCoin("uosmo", sdk.NewInt(1000000))) ) + // Set the denom creation fee. It is currently turned off in favor + // of gas charge by default. + params := s.App.TokenFactoryKeeper.GetParams(s.Ctx) + params.DenomCreationFee = denomCreationFee + s.App.TokenFactoryKeeper.SetParams(s.Ctx, params) + + // Fund denom creation fee for every execution of MsgCreateDenom. + s.FundAcc(s.TestAccs[0], denomCreationFee) + s.FundAcc(s.TestAccs[0], denomCreationFee) + s.FundAcc(s.TestAccs[1], denomCreationFee) + // Get balance of acc 0 before creating a denom preCreateBalance := bankKeeper.GetBalance(s.Ctx, s.TestAccs[0], denomCreationFee[0].Denom) @@ -63,7 +74,7 @@ func (s *KeeperTestSuite) TestMsgCreateDenom() { func (s *KeeperTestSuite) TestCreateDenom() { var ( - primaryDenom = types.DefaultParams().DenomCreationFee[0].Denom + primaryDenom = "uosmo" secondaryDenom = apptesting.SecondaryDenom defaultDenomCreationFee = types.Params{DenomCreationFee: sdk.NewCoins(sdk.NewCoin(primaryDenom, sdk.NewInt(50000000)))} twoDenomCreationFee = types.Params{DenomCreationFee: sdk.NewCoins(sdk.NewCoin(primaryDenom, sdk.NewInt(50000000)), sdk.NewCoin(secondaryDenom, sdk.NewInt(50000000)))} @@ -133,6 +144,7 @@ func (s *KeeperTestSuite) TestCreateDenom() { tokenFactoryKeeper := s.App.TokenFactoryKeeper bankKeeper := s.App.BankKeeper // Set denom creation fee in params + s.FundAcc(s.TestAccs[0], defaultDenomCreationFee.DenomCreationFee) tokenFactoryKeeper.SetParams(s.Ctx, tc.denomCreationFee) denomCreationFee := tokenFactoryKeeper.GetParams(s.Ctx).DenomCreationFee s.Require().Equal(tc.denomCreationFee.DenomCreationFee, denomCreationFee) diff --git a/x/tokenfactory/keeper/keeper_test.go b/x/tokenfactory/keeper/keeper_test.go index f72438362aa..f75e451f072 100644 --- a/x/tokenfactory/keeper/keeper_test.go +++ b/x/tokenfactory/keeper/keeper_test.go @@ -55,7 +55,7 @@ func (p SudoAuthorizationPolicy) CanModifyCodeAccessConfig(creator, actor sdk.Ac func (s *KeeperTestSuite) SetupTest() { s.Setup() // Fund every TestAcc with two denoms, one of which is the denom creation fee - fundAccsAmount := sdk.NewCoins(sdk.NewCoin(types.DefaultParams().DenomCreationFee[0].Denom, types.DefaultParams().DenomCreationFee[0].Amount.MulRaw(100)), sdk.NewCoin(apptesting.SecondaryDenom, apptesting.SecondaryAmount)) + fundAccsAmount := sdk.NewCoins(sdk.NewCoin(apptesting.SecondaryDenom, apptesting.SecondaryAmount)) for _, acc := range s.TestAccs { s.FundAcc(acc, fundAccsAmount) } diff --git a/x/tokenfactory/keeper/msg_server_test.go b/x/tokenfactory/keeper/msg_server_test.go index b9e23d2f749..2f01643af0f 100644 --- a/x/tokenfactory/keeper/msg_server_test.go +++ b/x/tokenfactory/keeper/msg_server_test.go @@ -102,23 +102,19 @@ func (s *KeeperTestSuite) TestBurnDenomMsg() { // TestCreateDenomMsg tests TypeMsgCreateDenom message is emitted on a successful denom creation func (s *KeeperTestSuite) TestCreateDenomMsg() { - defaultDenomCreationFee := types.Params{DenomCreationFee: sdk.NewCoins(sdk.NewCoin("uosmo", sdk.NewInt(50000000)))} for _, tc := range []struct { desc string - denomCreationFee types.Params subdenom string valid bool expectedMessageEvents int }{ { - desc: "subdenom too long", - denomCreationFee: defaultDenomCreationFee, - subdenom: "assadsadsadasdasdsadsadsadsadsadsadsklkadaskkkdasdasedskhanhassyeunganassfnlksdflksafjlkasd", - valid: false, + desc: "subdenom too long", + subdenom: "assadsadsadasdasdsadsadsadsadsadsadsklkadaskkkdasdasedskhanhassyeunganassfnlksdflksafjlkasd", + valid: false, }, { desc: "success case: defaultDenomCreationFee", - denomCreationFee: defaultDenomCreationFee, subdenom: "evmos", valid: true, expectedMessageEvents: 1, @@ -126,11 +122,9 @@ func (s *KeeperTestSuite) TestCreateDenomMsg() { } { s.SetupTest() s.Run(fmt.Sprintf("Case %s", tc.desc), func() { - tokenFactoryKeeper := s.App.TokenFactoryKeeper ctx := s.Ctx.WithEventManager(sdk.NewEventManager()) s.Require().Equal(0, len(ctx.EventManager().Events())) // Set denom creation fee in params - tokenFactoryKeeper.SetParams(s.Ctx, tc.denomCreationFee) // Test create denom message _, err := s.msgServer.CreateDenom(sdk.WrapSDKContext(ctx), types.NewMsgCreateDenom(s.TestAccs[0].String(), tc.subdenom)) if tc.valid { diff --git a/x/tokenfactory/types/params.go b/x/tokenfactory/types/params.go index 97706221dd5..f1884590457 100644 --- a/x/tokenfactory/types/params.go +++ b/x/tokenfactory/types/params.go @@ -3,8 +3,6 @@ package types import ( "fmt" - appparams "github.com/osmosis-labs/osmosis/v15/app/params" - sdk "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" ) @@ -13,6 +11,9 @@ import ( var ( KeyDenomCreationFee = []byte("DenomCreationFee") KeyDenomCreationGasConsume = []byte("DenomCreationGasConsume") + + // For choice, see: https://github.com/osmosis-labs/osmosis/pull/4983 + DefaultCreationGasFee = 40_000_000 ) // ParamTable for gamm module. @@ -30,8 +31,9 @@ func NewParams(denomCreationFee sdk.Coins, denomCreationGasConsume uint64) Param // default gamm module parameters. func DefaultParams() Params { return Params{ - DenomCreationFee: sdk.NewCoins(sdk.NewInt64Coin(appparams.BaseCoinUnit, 10_000_000)), // 10 OSMO - DenomCreationGasConsume: 0, + // For choice, see: https://github.com/osmosis-labs/osmosis/pull/4983 + DenomCreationFee: sdk.NewCoins(), // used to be 10 OSMO at launch. + DenomCreationGasConsume: uint64(DefaultCreationGasFee), } }