Skip to content

Commit

Permalink
add new token emission implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
gsk967 committed Jul 14, 2023
1 parent 0d519e7 commit 50880a8
Show file tree
Hide file tree
Showing 16 changed files with 779 additions and 71 deletions.
5 changes: 3 additions & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ import (
"github.com/cosmos/cosmos-sdk/x/group"
groupkeeper "github.com/cosmos/cosmos-sdk/x/group/keeper"
groupmodule "github.com/cosmos/cosmos-sdk/x/group/module"
"github.com/cosmos/cosmos-sdk/x/mint"
mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
"github.com/cosmos/cosmos-sdk/x/nft"
Expand Down Expand Up @@ -143,6 +142,8 @@ import (
uibcoracle "github.com/umee-network/umee/v5/x/uibc/oracle"
uibcquota "github.com/umee-network/umee/v5/x/uibc/quota"
uibcquotakeeper "github.com/umee-network/umee/v5/x/uibc/quota/keeper"

umint "github.com/umee-network/umee/v5/x/mint/module"
)

var (
Expand Down Expand Up @@ -667,7 +668,7 @@ func New(
crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants),
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil),
umint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, app.UGovKeeperB),
// need to dereference StakingKeeper because x/distribution uses interface casting :(
// TODO: in the next SDK version we can remove the dereference
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, *app.StakingKeeper),
Expand Down
3 changes: 3 additions & 0 deletions proto/umee/ugov/v1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package umee.ugov.v1;

import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";

Check failure on line 7 in proto/umee/ugov/v1/genesis.proto

View workflow job for this annotation

GitHub Actions / buf-lint

Import "google/protobuf/duration.proto" is unused.
import "cosmos_proto/cosmos.proto";
import "umee/ugov/v1/ugov.proto";
Expand All @@ -19,4 +20,6 @@ message GenesisState {

// LiquidationParams is params for new liquidation inflation rate params for staking denoms
LiquidationParams liquidation_params = 3 [(gogoproto.nullable) = false];
// Unix timestamp when the inflation cycle is started
google.protobuf.Timestamp inflation_cycle_start_time = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
}
17 changes: 16 additions & 1 deletion proto/umee/ugov/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import "cosmos/base/v1beta1/coin.proto";
import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";

import "umee/ugov/v1/ugov.proto";

option go_package = "github.com/umee-network/umee/v5/x/ugov";
Expand All @@ -27,6 +29,11 @@ service Query {
rpc LiquidationParams(QueryLiquidationParams) returns (QueryLiquidationParamsResponse) {
option (google.api.http).get = "/umee/ugov/v1/liquidation-params";
}

// InflationCycleStartTime returns when inflation cycle is started
rpc InflationCycleStartTime(QueryInflationCycleStartTime) returns (QueryInflationCycleStartTimeResponse) {
option (google.api.http).get = "/umee/ugov/v1/inflation-cycle";
}
}

// QueryMinGasPrice is a request type.
Expand All @@ -51,4 +58,12 @@ message QueryLiquidationParams {}
// QueryLiquidationParamsResponse response type.
message QueryLiquidationParamsResponse {
LiquidationParams liquidation_params = 1 [(gogoproto.nullable) = false];
}
}

// QueryInflationCycleStartTime request type.
message QueryInflationCycleStartTime {}

// QueryInflationCycleStartTimeResponse response type.
message QueryInflationCycleStartTimeResponse {
google.protobuf.Timestamp inflation_cycle_start_time = 1 [(gogoproto.nullable) = true, (gogoproto.stdtime) = true];
}
110 changes: 110 additions & 0 deletions x/mint/module/abci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package mint

import (
"time"

"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
mk "github.com/cosmos/cosmos-sdk/x/mint/keeper"
"github.com/cosmos/cosmos-sdk/x/mint/types"
"github.com/umee-network/umee/v5/util"
ugov "github.com/umee-network/umee/v5/x/ugov"
ugovkeeper "github.com/umee-network/umee/v5/x/ugov/keeper"
)

// BeginBlock implements BeginBlock for the x/mint module.
func BeginBlock(ctx sdk.Context, ugovKeeper ugovkeeper.Keeper, mintKeeper mk.Keeper) {
defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker)
// liquidation params
lp := ugovKeeper.LiquidationParams()

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

path flow from Begin/EndBlock to a panic call
// mint module params
mintParams := mintKeeper.GetParams(ctx)

totalStakingSupply := mintKeeper.StakingTokenSupply(ctx)
if totalStakingSupply.GTE(lp.MaxSupply.Amount) {
// supply is already reached the maximum amount, so no more minting the staking token
return
}

// fetch stored minter & params
minter := mintKeeper.GetMinter(ctx)
bondedRatio := mintKeeper.BondedRatio(ctx)
// recalculate inflation rate
minter.Inflation = InflationCalculationFn(ctx, ugovKeeper, mintKeeper, lp, mintParams, bondedRatio, minter.Inflation)

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

path flow from Begin/EndBlock to a panic call
minter.AnnualProvisions = minter.NextAnnualProvisions(mintParams, totalStakingSupply)
mintKeeper.SetMinter(ctx, minter)

// mint coins, update supply
mintedCoin := minter.BlockProvision(mintParams)
mintedCoins := sdk.NewCoins(mintedCoin)

err := mintKeeper.MintCoins(ctx, mintedCoins)
util.Panic(err)

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

path flow from Begin/EndBlock to a panic call

// send the minted coins to the fee collector account
err = mintKeeper.AddCollectedFees(ctx, mintedCoins)
util.Panic(err)

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

path flow from Begin/EndBlock to a panic call

if mintedCoin.Amount.IsInt64() {
defer telemetry.ModuleSetGauge(types.ModuleName, float32(mintedCoin.Amount.Int64()), "minted_tokens")
}

ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeMint,
sdk.NewAttribute(types.AttributeKeyBondedRatio, bondedRatio.String()),
sdk.NewAttribute(types.AttributeKeyInflation, minter.Inflation.String()),
sdk.NewAttribute(types.AttributeKeyAnnualProvisions, minter.AnnualProvisions.String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, mintedCoin.Amount.String()),
),
)
}

func InflationCalculationFn(ctx sdk.Context, ugovKeeper ugovkeeper.Keeper, mintKeeper mk.Keeper,
lp ugov.LiquidationParams, params types.Params, bondedRatio sdk.Dec, currentInflation sdk.Dec) sdk.Dec {

// inflation cycle is completed , so we need to update the inflation max and min rate
icst, err := ugovKeeper.GetInflationCycleStartTime()
util.Panic(err)

// TODO: needs to verify when to update this cycle time like in migrations or in this BeginBlock ?
// first time start time is zero
if !icst.IsZero() && ctx.BlockTime().After(icst.Add(lp.InflationCycleDuration)) {
params.InflationMax = params.InflationMax.Mul(sdk.OneDec().Sub(lp.InflationReductionRate))
params.InflationMin = params.InflationMin.Mul(sdk.OneDec().Sub(lp.InflationReductionRate))

// update the changed inflation min and max rates
mintKeeper.SetParams(ctx, params)

// update the executed time of inflation cycle
err := ugovKeeper.SetInflationCycleStartTime(ctx.BlockTime())
util.Panic(err)
ctx.Logger().Info("inflation rates are updated",
"inflation_max", params.InflationMax, "inflation_min", params.InflationMin,
"inflation_cycle_start_time", ctx.BlockTime().String(),
)
}

// The target annual inflation rate is recalculated for each previsions cycle. The
// inflation is also subject to a rate change (positive or negative) depending on
// the distance from the desired ratio (67%). The maximum rate change possible is
// defined to be 13% per year, however the annual inflation is capped as between
// 7% and 20%.

// (1 - bondedRatio/GoalBonded) * InflationRateChange
inflationRateChangePerYear := sdk.OneDec().
Sub(bondedRatio.Quo(params.GoalBonded)).
Mul(params.InflationRateChange)
inflationRateChange := inflationRateChangePerYear.Quo(sdk.NewDec(int64(params.BlocksPerYear)))

// adjust the new annual inflation for this next cycle
inflation := currentInflation.Add(inflationRateChange) // note inflationRateChange may be negative
if inflation.GT(params.InflationMax) {
inflation = params.InflationMax
}
if inflation.LT(params.InflationMin) {
inflation = params.InflationMin
}

return inflation
}
42 changes: 42 additions & 0 deletions x/mint/module/module.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package mint

import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/mint"
mk "github.com/cosmos/cosmos-sdk/x/mint/keeper"
"github.com/cosmos/cosmos-sdk/x/mint/types"
abci "github.com/tendermint/tendermint/abci/types"

ugovkeeper "github.com/umee-network/umee/v5/x/ugov/keeper"
)

var (
_ module.AppModule = AppModule{}
)

type AppModule struct {
mint.AppModule
mintKeeper mk.Keeper
ugovKB ugovkeeper.Builder
}

func NewAppModule(cdc codec.Codec, keeper mk.Keeper, ak types.AccountKeeper, ugovkb ugovkeeper.Builder,
) AppModule {
return AppModule{
AppModule: mint.NewAppModule(cdc, keeper, ak, nil),
mintKeeper: keeper,
ugovKB: ugovkb,
}
}

// Name implements module.AppModule.
func (AppModule) Name() string {
return types.ModuleName
}

// BeginBlock executes all ABCI BeginBlock logic respective to the x/uibc module.
func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {
BeginBlock(ctx, am.ugovKB.Keeper(&ctx), am.mintKeeper)

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

path flow from Begin/EndBlock to a panic call
path flow from Begin/EndBlock to a panic call
}
24 changes: 24 additions & 0 deletions x/ugov/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func GetQueryCmd() *cobra.Command {
cmd.AddCommand(
QueryMinGasPrice(),
QueryLiquidationParams(),
QueryInflationCyleStartedTime(),
)

return cmd
Expand Down Expand Up @@ -73,3 +74,26 @@ func QueryLiquidationParams() *cobra.Command {

return cmd
}

// QueryInflationCyleStartedTime create the Msg/QueryInflationCyleStartedTime CLI.
func QueryInflationCyleStartedTime() *cobra.Command {
cmd := &cobra.Command{
Use: "inflation-cycle-start-time",
Args: cobra.NoArgs,
Short: "Query the When the Inflation Cycle is Started",
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}

queryClient := ugov.NewQueryClient(clientCtx)
resp, err := queryClient.InflationCycleStartTime(cmd.Context(), &ugov.QueryInflationCycleStartTime{})
return cli.PrintOrErr(resp, err, clientCtx)
},
}

flags.AddQueryFlagsToCmd(cmd)

return cmd
}
Loading

0 comments on commit 50880a8

Please sign in to comment.