From 34d898428aee6905672ac13f6ca3f13dc1b76f76 Mon Sep 17 00:00:00 2001 From: Reece Williams <31943163+Reecepbcups@users.noreply.github.com> Date: Fri, 23 Feb 2024 22:17:53 -0600 Subject: [PATCH] feat!: automatic mint distribution to stakeholders (#8) * sdk fork (removes mint begin blocker req) * x/mint begin blocker -> manifest * `TestStakeholderAutoMint` * `hasInvalidMsgFromPoAAdmin` for TF + new Payout * mod tidy --- app/app.go | 7 +- app/decorators/inflation_disable_minting.go | 31 +++++--- app/decorators/inflation_disable_test.go | 80 ++++++++++++++------ app/test_helpers.go | 2 + go.mod | 12 +-- go.sum | 8 +- x/manifest/abci.go | 84 +++++++++++++++++++++ x/manifest/depinject.go | 2 +- x/manifest/keeper/abci_test.go | 67 ++++++++++++++++ x/manifest/module.go | 15 ++++ 10 files changed, 262 insertions(+), 46 deletions(-) create mode 100644 x/manifest/abci.go create mode 100644 x/manifest/keeper/abci_test.go diff --git a/app/app.go b/app/app.go index 376902d..e4d4983 100644 --- a/app/app.go +++ b/app/app.go @@ -424,6 +424,7 @@ func NewApp( runtime.NewKVStoreService(keys[poa.StoreKey]), app.StakingKeeper, app.SlashingKeeper, + app.BankKeeper, authcodec.NewBech32Codec(sdk.Bech32PrefixValAddr), logger, ) @@ -692,7 +693,7 @@ func NewApp( poamodule.NewAppModule(appCodec, app.POAKeeper), // sdk crisis.NewAppModule(app.CrisisKeeper, skipGenesisInvariants, app.GetSubspace(crisistypes.ModuleName)), // always be last to make sure that it checks for all invariants and not only part of them - manifest.NewAppModule(appCodec, app.ManifestKeeper), + manifest.NewAppModule(appCodec, app.ManifestKeeper, app.MintKeeper, app.BankKeeper), ) // BasicModuleManager defines the module BasicManager is in charge of setting up basic, @@ -723,7 +724,8 @@ func NewApp( // NOTE: staking module is required if HistoricalEntries param > 0 // NOTE: capability module's beginblocker must come before any modules using capabilities (e.g. IBC) app.ModuleManager.SetOrderBeginBlockers( - minttypes.ModuleName, + // minttypes.ModuleName, // we override with the manifest module logic + manifesttypes.ModuleName, // minter to stakeholders distrtypes.ModuleName, slashingtypes.ModuleName, evidencetypes.ModuleName, @@ -738,7 +740,6 @@ func NewApp( icatypes.ModuleName, ibcfeetypes.ModuleName, tokenfactorytypes.ModuleName, - manifesttypes.ModuleName, ) app.ModuleManager.SetOrderEndBlockers( diff --git a/app/decorators/inflation_disable_minting.go b/app/decorators/inflation_disable_minting.go index 89896b3..44c1f2f 100644 --- a/app/decorators/inflation_disable_minting.go +++ b/app/decorators/inflation_disable_minting.go @@ -4,6 +4,7 @@ import ( "context" manifestkeeper "github.com/liftedinit/manifest-ledger/x/manifest/keeper" + manifesttypes "github.com/liftedinit/manifest-ledger/x/manifest/types" tokenfactorytypes "github.com/reecepbcups/tokenfactory/x/tokenfactory/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -24,28 +25,34 @@ func NewMsgManualMintFilterDecorator(mk *manifestkeeper.Keeper, isSudoAdminFunc } func (mfd MsgManualMintFilterDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { - // iterate all messages, see if any are a tokenfactory message from a sudo admin. - // if there is and inflation is current >0%, return an error - if err := mfd.hasInvalidTokenFactoryMsg(ctx, tx.GetMsgs()); err != nil { + if err := mfd.hasInvalidMsgFromPoAAdmin(ctx, tx.GetMsgs()); err != nil { return ctx, err } return next(ctx, tx, simulate) } -func (mfd MsgManualMintFilterDecorator) hasInvalidTokenFactoryMsg(ctx sdk.Context, msgs []sdk.Msg) error { +func (mfd MsgManualMintFilterDecorator) hasInvalidMsgFromPoAAdmin(ctx sdk.Context, msgs []sdk.Msg) error { for _, msg := range msgs { + // only payout stakeholders manually if inflation is 0% & the sender is the admin. + if m, ok := msg.(*manifesttypes.MsgPayoutStakeholders); ok { + return mfd.senderAdminOnMintWithInflation(ctx, m.Authority) + } + + // if the sender is not the admin, continue as normal + // if they are the admin, check if inflation is 0%. if it is, allow. Else, error. if m, ok := msg.(*tokenfactorytypes.MsgMint); ok { - if mfd.isSudoAdminFunc(ctx, m.Sender) { - isInflationEnabled := mfd.mk.IsManualMintingEnabled(ctx) - if isInflationEnabled != nil { - return isInflationEnabled - } - } - - return nil + return mfd.senderAdminOnMintWithInflation(ctx, m.Sender) } } return nil } + +func (mfd MsgManualMintFilterDecorator) senderAdminOnMintWithInflation(ctx context.Context, sender string) error { + if mfd.isSudoAdminFunc(ctx, sender) { + return mfd.mk.IsManualMintingEnabled(ctx) + } + + return nil +} diff --git a/app/decorators/inflation_disable_test.go b/app/decorators/inflation_disable_test.go index a03382c..66aeb05 100644 --- a/app/decorators/inflation_disable_test.go +++ b/app/decorators/inflation_disable_test.go @@ -8,6 +8,7 @@ import ( "github.com/liftedinit/manifest-ledger/app/decorators" appparams "github.com/liftedinit/manifest-ledger/app/params" manifestkeeper "github.com/liftedinit/manifest-ledger/x/manifest/keeper" + manifesttypes "github.com/liftedinit/manifest-ledger/x/manifest/types" tokenfactorytypes "github.com/reecepbcups/tokenfactory/x/tokenfactory/types" poa "github.com/strangelove-ventures/poa" poakeeper "github.com/strangelove-ventures/poa/keeper" @@ -26,6 +27,9 @@ var ( EmptyAnte = func(ctx sdk.Context, tx sdk.Tx, simulate bool) (sdk.Context, error) { return ctx, nil } + + coin = sdk.NewCoin(appparams.BondDenom, sdkmath.NewInt(1)) + tfCoin = sdk.NewCoin("factory", sdkmath.NewInt(1)) ) type AnteTestSuite struct { @@ -72,25 +76,59 @@ func (s *AnteTestSuite) TestAnteInflationAndMinting() { inflation := sdkmath.LegacyNewDecWithPrec(1, 2) // 1% zero := sdkmath.LegacyZeroDec() - // tx: inflation is 0 so manual minting is allowed from the poa admin - s.Require().NoError(s.mintKeeper.Minter.Set(s.ctx, minttypes.InitialMinter(zero))) - msg := tokenfactorytypes.NewMsgMint(poaAdmin.String(), sdk.NewCoin(appparams.BondDenom, sdkmath.NewInt(1))) - _, err := ante.AnteHandle(s.ctx, decorators.NewMockTx(msg), false, EmptyAnte) - s.Require().NoError(err) - - // minting is allowed from the stdUser too - msg = tokenfactorytypes.NewMsgMint(stdUser.String(), sdk.NewCoin(appparams.BondDenom, sdkmath.NewInt(1))) - _, err = ante.AnteHandle(s.ctx, decorators.NewMockTx(msg), false, EmptyAnte) - s.Require().NoError(err) - - // tx: inflation is 1% so manual minting is not allowed from the poa admin - s.Require().NoError(s.mintKeeper.Minter.Set(s.ctx, minttypes.InitialMinter(inflation))) - msg = tokenfactorytypes.NewMsgMint(poaAdmin.String(), sdk.NewCoin(appparams.BondDenom, sdkmath.NewInt(1))) - _, err = ante.AnteHandle(s.ctx, decorators.NewMockTx(msg), false, EmptyAnte) - s.Require().Contains(err.Error(), manifestkeeper.ErrManualMintingDisabled.Error()) - - // tx: inflation is still 1%, but normal users can still mint (non admins) - msg = tokenfactorytypes.NewMsgMint(stdUser.String(), sdk.NewCoin(appparams.BondDenom, sdkmath.NewInt(1))) - _, err = ante.AnteHandle(s.ctx, decorators.NewMockTx(msg), false, EmptyAnte) - s.Require().NoError(err) + type tc struct { + name string + inflation sdkmath.LegacyDec + msg sdk.Msg + err string + } + + tcs := []tc{ + { + name: "success; 0 inflation tokenfactory mint", + inflation: zero, + msg: tokenfactorytypes.NewMsgMint(poaAdmin.String(), coin), + }, + { + name: "success; 0 inflation payout stakeholders", + inflation: zero, + msg: manifesttypes.NewMsgPayoutStakeholders(poaAdmin, coin), + }, + { + name: "success; TF mint from standard user", + inflation: zero, + msg: tokenfactorytypes.NewMsgMint(stdUser.String(), tfCoin), + }, + { + name: "success; TF mint from standard user with inflation still allowed", + inflation: inflation, + msg: tokenfactorytypes.NewMsgMint(stdUser.String(), tfCoin), + }, + { + name: "fail; inflation enabled, no manual mint from admin", + inflation: inflation, + msg: tokenfactorytypes.NewMsgMint(poaAdmin.String(), coin), + err: manifestkeeper.ErrManualMintingDisabled.Error(), + }, + { + name: "fail; inflation enabled, no manual payout from admin", + inflation: inflation, + msg: manifesttypes.NewMsgPayoutStakeholders(poaAdmin, coin), + err: manifestkeeper.ErrManualMintingDisabled.Error(), + }, + } + + for _, tc := range tcs { + tc := tc + + s.Require().NoError(s.mintKeeper.Minter.Set(s.ctx, minttypes.InitialMinter(tc.inflation))) + _, err := ante.AnteHandle(s.ctx, decorators.NewMockTx(tc.msg), false, EmptyAnte) + + if tc.err == "" { + s.Require().NoError(err) + } else { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.err) + } + } } diff --git a/app/test_helpers.go b/app/test_helpers.go index 6540434..56b1e84 100644 --- a/app/test_helpers.go +++ b/app/test_helpers.go @@ -10,6 +10,7 @@ import ( apphelpers "github.com/liftedinit/manifest-ledger/app/helpers" appparams "github.com/liftedinit/manifest-ledger/app/params" + "github.com/liftedinit/manifest-ledger/x/manifest/types" "github.com/strangelove-ventures/poa" "github.com/stretchr/testify/require" @@ -215,6 +216,7 @@ func setup(t *testing.T, withGenesis bool) (*ManifestApp, GenesisState) { app.GovKeeper.Constitution.Set(ctx, "") app.GovKeeper.Params.Set(ctx, govv1types.DefaultParams()) app.ConsensusParamsKeeper.ParamsStore.Set(ctx, *simtestutil.DefaultConsensusParams) + app.ManifestKeeper.Params.Set(ctx, types.DefaultParams()) if withGenesis { return app, NewDefaultGenesisState(t) diff --git a/go.mod b/go.mod index 9d03b0c..744ff7c 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,11 @@ toolchain go1.21.0 replace ( // core v0.12 was tagged wrong (SDK v51) cosmossdk.io/core => cosmossdk.io/core v0.11.0 + + // go get github.com/liftedinit/cosmos-sdk@24d6e6cf46beb55d9789c041db68a5ab3093c064 + // https://github.com/liftedinit/cosmos-sdk/pull/1 + github.com/cosmos/cosmos-sdk => github.com/liftedinit/cosmos-sdk v0.50.5-0.20240222003859-24d6e6cf46be + // Fix upstream GHSA-h395-qcrw-5vmq vulnerability. github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0 github.com/spf13/viper => github.com/spf13/viper v1.17.0 // v1.18+ breaks app overrides @@ -39,6 +44,7 @@ require ( github.com/cosmos/ibc-go/modules/capability v1.0.0 github.com/cosmos/ibc-go/v8 v8.0.0 github.com/golang/protobuf v1.5.3 + github.com/gorilla/mux v1.8.1 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/prometheus/client_golang v1.18.0 // indirect github.com/reecepbcups/tokenfactory v0.50.0-alpha.3 @@ -47,6 +53,7 @@ require ( github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.18.2 + github.com/strangelove-ventures/poa v0.0.1-alpha.3 github.com/stretchr/testify v1.8.4 google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f google.golang.org/grpc v1.60.1 @@ -206,8 +213,3 @@ require ( pgregory.net/rapid v1.1.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) - -require ( - github.com/gorilla/mux v1.8.1 - github.com/strangelove-ventures/poa v0.0.1-alpha.2 -) diff --git a/go.sum b/go.sum index 2fa76df..758e030 100644 --- a/go.sum +++ b/go.sum @@ -959,8 +959,6 @@ github.com/cosmos/cosmos-db v1.0.0 h1:EVcQZ+qYag7W6uorBKFPvX6gRjw6Uq2hIh4hCWjuQ0 github.com/cosmos/cosmos-db v1.0.0/go.mod h1:iBvi1TtqaedwLdcrZVYRSSCb6eSy61NLj4UNmdIgs0U= github.com/cosmos/cosmos-proto v1.0.0-beta.4 h1:aEL7tU/rLOmxZQ9z4i7mzxcLbSCY48OdY7lIWTLG7oU= github.com/cosmos/cosmos-proto v1.0.0-beta.4/go.mod h1:oeB+FyVzG3XrQJbJng0EnV8Vljfk9XvTIpGILNU/9Co= -github.com/cosmos/cosmos-sdk v0.50.4 h1:hQT5/+Z1XXNF7skaPq0i247Ts2dzzqg/j2WO/BPHSto= -github.com/cosmos/cosmos-sdk v0.50.4/go.mod h1:UbShFs6P8Ly29xxJvkNGaNaL/UGj5a686NRtb1Cqra0= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= @@ -1424,6 +1422,8 @@ github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/liftedinit/cosmos-sdk v0.50.5-0.20240222003859-24d6e6cf46be h1:2WAZQdFRwLe97xj5wK6Yz0ic5c9zc6zIVTk7TsnBI44= +github.com/liftedinit/cosmos-sdk v0.50.5-0.20240222003859-24d6e6cf46be/go.mod h1:UbShFs6P8Ly29xxJvkNGaNaL/UGj5a686NRtb1Cqra0= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/linxGnu/grocksdb v1.8.12 h1:1/pCztQUOa3BX/1gR3jSZDoaKFpeHFvQ1XrqZpSvZVo= @@ -1689,8 +1689,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= -github.com/strangelove-ventures/poa v0.0.1-alpha.2 h1:cBzb+iJVICwUt1J/H+hTyTXOSj9UhMWP3UbxEVr+6c8= -github.com/strangelove-ventures/poa v0.0.1-alpha.2/go.mod h1:LcmorSGWRyn/M5hch7dAW7l0aYL+VSw28uzdsjdOduc= +github.com/strangelove-ventures/poa v0.0.1-alpha.3 h1:BtmF6nJDBARDNefO0axuMD82+nkZQWa2OkZXQaQTwpI= +github.com/strangelove-ventures/poa v0.0.1-alpha.3/go.mod h1:LcmorSGWRyn/M5hch7dAW7l0aYL+VSw28uzdsjdOduc= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= diff --git a/x/manifest/abci.go b/x/manifest/abci.go new file mode 100644 index 0000000..e9c2a52 --- /dev/null +++ b/x/manifest/abci.go @@ -0,0 +1,84 @@ +package module + +import ( + "context" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/telemetry" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + "github.com/liftedinit/manifest-ledger/x/manifest/keeper" + manifesttypes "github.com/liftedinit/manifest-ledger/x/manifest/types" +) + +// BeginBlocker mints new tokens for the previous block. +func BeginBlocker(ctx context.Context, k keeper.Keeper, mk mintkeeper.Keeper, bk bankkeeper.Keeper) error { + + ic := minttypes.DefaultInflationCalculationFn + + defer telemetry.ModuleMeasureSince(manifesttypes.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker) + + // fetch stored minter & params + minter, err := mk.Minter.Get(ctx) + if err != nil { + return err + } + + params, err := mk.Params.Get(ctx) + if err != nil { + return err + } + + // recalculate inflation rate + totalSupply := bk.GetSupply(ctx, "umfx").Amount + + // TODO(reece): max bond ratio will always use the minimum inflation value. This is likely desired. + bondedRatio := sdkmath.LegacyOneDec() + + minter.Inflation = ic(ctx, minter, params, bondedRatio) + minter.AnnualProvisions = minter.NextAnnualProvisions(params, totalSupply) + if err = mk.Minter.Set(ctx, minter); err != nil { + return err + } + + // mint coins, update supply + mintedCoin := minter.BlockProvision(params) + mintedCoins := sdk.NewCoins(mintedCoin) + + err = mk.MintCoins(ctx, mintedCoins) + if err != nil { + return err + } + + // Payout + if err := k.PayoutStakeholders(ctx, mintedCoin); err != nil { + return err + } + + // send the minted coins to the fee collector account + err = mk.AddCollectedFees(ctx, mintedCoins) + if err != nil { + return err + } + + if mintedCoin.Amount.IsInt64() { + defer telemetry.ModuleSetGauge(minttypes.ModuleName, float32(mintedCoin.Amount.Int64()), "minted_tokens") + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + sdkCtx.EventManager().EmitEvent( + sdk.NewEvent( + minttypes.EventTypeMint, + sdk.NewAttribute(minttypes.AttributeKeyBondedRatio, bondedRatio.String()), + sdk.NewAttribute(minttypes.AttributeKeyInflation, minter.Inflation.String()), + sdk.NewAttribute(minttypes.AttributeKeyAnnualProvisions, minter.AnnualProvisions.String()), + sdk.NewAttribute(sdk.AttributeKeyAmount, mintedCoin.Amount.String()), + ), + ) + + return nil +} diff --git a/x/manifest/depinject.go b/x/manifest/depinject.go index 0efb94b..4d541a7 100644 --- a/x/manifest/depinject.go +++ b/x/manifest/depinject.go @@ -54,7 +54,7 @@ type ModuleOutputs struct { func ProvideModule(in ModuleInputs) ModuleOutputs { k := keeper.NewKeeper(in.Cdc, in.StoreService, in.MintKeeper, in.BankKeeper, log.NewLogger(os.Stderr), authtypes.NewModuleAddress(govtypes.ModuleName).String()) - m := NewAppModule(in.Cdc, k) + m := NewAppModule(in.Cdc, k, in.MintKeeper, in.BankKeeper) return ModuleOutputs{Module: m, Keeper: k, Out: depinject.Out{}} } diff --git a/x/manifest/keeper/abci_test.go b/x/manifest/keeper/abci_test.go new file mode 100644 index 0000000..d0f9c4c --- /dev/null +++ b/x/manifest/keeper/abci_test.go @@ -0,0 +1,67 @@ +package keeper_test + +import ( + "fmt" + "testing" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + manifest "github.com/liftedinit/manifest-ledger/x/manifest" + "github.com/liftedinit/manifest-ledger/x/manifest/keeper" + "github.com/liftedinit/manifest-ledger/x/manifest/types" + "github.com/stretchr/testify/require" +) + +// Call BeginBlocker and make sure values are as expected + +const ( + MintDenom = "umfx" +) + +func TestStakeholderAutoMint(t *testing.T) { + + // create an account + _, _, authority := testdata.KeyTestPubAddr() + _, _, acc := testdata.KeyTestPubAddr() + + f := initFixture(t) + + k := f.App.ManifestKeeper + k.SetAuthority(f.Ctx, authority.String()) + ms := keeper.NewMsgServerImpl(k) + + // set the mint keeper params + defaultParams := minttypes.DefaultParams() + defaultParams.MintDenom = MintDenom + defaultParams.InflationMax = sdkmath.LegacyNewDec(1) + f.App.MintKeeper.Params.Set(f.Ctx, defaultParams) + + sh := []*types.StakeHolders{ + { + Address: acc.String(), + Percentage: 100_000_000, + }, + } + _, err := ms.UpdateParams(f.Ctx, &types.MsgUpdateParams{ + Authority: authority.String(), + Params: types.NewParams(sh), + }) + require.NoError(t, err) + + // mint a bunch of total supply 100_000_000_000 umfx + f.App.BankKeeper.MintCoins(f.Ctx, "mint", sdk.NewCoins(sdk.NewCoin(MintDenom, sdkmath.NewInt(100_000_000_000)))) + + // get balance of acc + balance := f.App.BankKeeper.GetBalance(f.Ctx, acc, MintDenom) + require.EqualValues(t, 0, balance.Amount.Int64()) + + err = manifest.BeginBlocker(f.Ctx, k, f.App.MintKeeper, f.App.BankKeeper) + require.NoError(t, err) + + balance = f.App.BankKeeper.GetBalance(f.Ctx, acc, MintDenom) + require.True(t, balance.Amount.Int64() > 0) + + fmt.Println("balance", balance.Amount.Int64()) +} diff --git a/x/manifest/module.go b/x/manifest/module.go index 007167b..2f6b14d 100644 --- a/x/manifest/module.go +++ b/x/manifest/module.go @@ -16,6 +16,7 @@ import ( autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" "cosmossdk.io/client/v2/autocli" + "cosmossdk.io/core/appmodule" errorsmod "cosmossdk.io/errors" "github.com/cosmos/cosmos-sdk/client" @@ -23,6 +24,8 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" ) const ( @@ -35,6 +38,8 @@ var ( _ module.AppModuleGenesis = AppModule{} _ module.AppModule = AppModule{} + _ appmodule.HasBeginBlocker = AppModule{} + _ autocli.HasAutoCLIConfig = AppModule{} _ autocli.HasCustomQueryCommand = AppModule{} _ autocli.HasCustomTxCommand = AppModule{} @@ -49,16 +54,22 @@ type AppModule struct { AppModuleBasic keeper keeper.Keeper + mk mintkeeper.Keeper + bk bankkeeper.Keeper } // NewAppModule constructor func NewAppModule( cdc codec.Codec, keeper keeper.Keeper, + mintkeeper mintkeeper.Keeper, + bankkeeper bankkeeper.Keeper, ) *AppModule { return &AppModule{ AppModuleBasic: AppModuleBasic{cdc: cdc}, keeper: keeper, + mk: mintkeeper, + bk: bankkeeper, } } @@ -153,6 +164,10 @@ func (a AppModule) RegisterServices(cfg module.Configurator) { types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQuerier(a.keeper)) } +func (a AppModule) BeginBlock(ctx context.Context) error { + return BeginBlocker(ctx, a.keeper, a.mk, a.bk) +} + // ConsensusVersion is a sequence number for state-breaking change of the // module. It should be incremented on each consensus-breaking change // introduced by the module. To avoid wrong/empty versions, the initial version