x/mint 模块以可配置的方式处理新代币的定期铸造。

目录

概念

铸造机制

默认的铸造机制旨在:
  • 允许根据市场需求围绕特定的已质押比例灵活调整通胀率
  • 在市场流动性与已质押供给之间取得平衡
为了更准确地确定通胀奖励的合适市场利率,系统使用动态变化率。该机制确保:如果实际已质押比例高于或低于目标已质押比例,通胀率将分别调整,以进一步激励或抑制质押。将目标已质押比例设置为低于 100%,可以鼓励网络保留一部分未质押代币,从而有助于提供流动性。 可以分解为以下几种情况:
  • 如果实际已质押代币比例低于目标已质押比例,通胀率将提高,直到达到最大值
  • 如果目标已质押比例(Cosmos-Hub 中为 67%)得到维持,则通胀率保持不变
  • 如果实际已质押代币比例高于目标已质押比例,通胀率将降低,直到达到最小值

自定义铸币器

自 Cosmos SDK v0.53.0 起,开发者可以为该模块设置自定义 MintFn,以实现专门的代币铸造逻辑。 MintFn 需要实现的函数签名如下:
// MintFn defines the function that needs to be implemented in order to customize the minting process.
type MintFn func(ctx sdk.Context, k *Keeper)

error
可以在创建 Keeper 时通过额外的 Option 传入:
app.MintKeeper = mintkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[minttypes.StoreKey]),
		app.StakingKeeper,
		app.AccountKeeper,
		app.BankKeeper,
		authtypes.FeeCollectorName,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		// mintkeeper.WithMintFn(CUSTOM_MINT_FN), // custom mintFn can be added here
	)

自定义铸币器的 DI 示例

下面展示了一种在 DI 配置中创建带额外依赖的自定义铸币函数的简单方式。 在这个基础示例中,我们让铸币器将 foo 代币的供应量直接翻倍。 首先,定义一个接收所需依赖并返回 MintFn 的函数。
// MyCustomMintFunction is a custom mint function that doubles the supply of `foo` coin.
func MyCustomMintFunction(bank bankkeeper.BaseKeeper)

mintkeeper.MintFn {
    return func(ctx sdk.Context, k *mintkeeper.Keeper)

error {
    supply := bank.GetSupply(ctx, "foo")
    err := k.MintCoins(ctx, sdk.NewCoins(supply.Add(supply)))
    if err != nil {
    return err
}

return nil
}
}
然后,将上面定义的函数连同所需依赖一起传入 depinject.Supply。
// NewSimApp returns a reference to an initialized SimApp.
func NewSimApp(
    logger log.Logger,
    db dbm.DB,
    traceStore io.Writer,
    loadLatest bool,
    appOpts servertypes.AppOptions,
    baseAppOptions ...func(*baseapp.BaseApp),
) *SimApp {
    var (
        app        = &SimApp{
}

appBuilder *runtime.AppBuilder
        appConfig = depinject.Configs(
            AppConfig,
            depinject.Supply(
                appOpts,
                logger,
                // our custom mint function with the necessary dependency passed in.
                MyCustomMintFunction(app.BankKeeper),
            ),
        )
	)
	// ...
}

状态

铸币器(Minter)

铸币器用于保存当前的通胀信息。
  • Minter: 0x00 -> ProtocolBuffer(minter)
// Reference: https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/mint/v1beta1/mint.proto#L10-L24

参数状态(Params)

mint 模块使用前缀 0x01 将其参数存储在状态中, 可通过治理或具有权限的地址进行更新。 注意: MaxSupply 参数控制该模块可铸造代币的最大供应量。值为 0 表示供应量不受限制。
  • Params: mint/params -> legacy_amino(params)
// Reference: https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/mint/v1beta1/mint.proto#L26-L59

区块开始阶段

在每个区块开始时,会重新计算铸造参数并发放通胀奖励。

通胀率计算

通胀率通过传入 NewAppModule 函数的通胀计算函数来计算。如果未传入函数,则会使用 SDK 默认的通胀函数(NextInflationRate)。如果需要自定义通胀计算逻辑,可以定义并传入一个符合 InflationCalculationFn 签名的函数来实现。
type InflationCalculationFn func(ctx sdk.Context, minter Minter, params Params, bondedRatio math.LegacyDec)

math.LegacyDec

下一次通胀率(NextInflationRate)

目标年化通胀率会在每个区块重新计算。 通胀率还会根据与目标比例(67%)之间的偏差发生正向或负向变化。每年可能的最大变化率被定义为 13%,不过年化通胀率会被限制在 7% 到 20% 之间。
NextInflationRate(params Params, bondedRatio math.LegacyDec) (inflation math.LegacyDec) {
    inflationRateChangePerYear = (1 - bondedRatio/params.GoalBonded) * params.InflationRateChange
	inflationRateChange = inflationRateChangePerYear/blocksPerYr

	// increase the new annual inflation for this next block
	inflation += inflationRateChange
    if inflation > params.InflationMax {
    inflation = params.InflationMax
}
    if inflation < params.InflationMin {
    inflation = params.InflationMin
}

return inflation
}

下一次年度增发量(NextAnnualProvisions)

根据当前总供应量和通胀率计算年度增发量。 该值每个区块计算一次。
NextAnnualProvisions(params Params, totalSupply math.LegacyDec) (provisions math.LegacyDec) {
    return Inflation * totalSupply

区块增发量(BlockProvision)

根据当前年度增发量计算每个区块产生的增发额。随后,这些增发额由 mint 模块的 ModuleMinterAccount 铸造,再转入 auth 的 FeeCollector ModuleAccount。
BlockProvision(params Params)

sdk.Coin {
    provisionAmt = AnnualProvisions/ params.BlocksPerYear
	return sdk.NewCoin(params.MintDenom, provisionAmt.Truncate())

参数

铸造模块包含以下参数:
键类型示例
MintDenomstring”uatom”
InflationRateChangestring (dec)“0.130000000000000000”
InflationMaxstring (dec)“0.200000000000000000”
InflationMinstring (dec)“0.070000000000000000”
GoalBondedstring (dec)“0.670000000000000000”
BlocksPerYearstring (uint64)“6311520”
MaxSupplystring (math.Int)“0”
MaxSupply 的值为 0 表示不强制设置最大供应量。一旦总供应量达到配置的 MaxSupply,铸造会自动停止。为了兼容旧版 Amino JSON,即使其值被设置为 "0",max_supply 也会被编码。

事件

铸造模块会发出以下事件:

开始区块处理器(BeginBlocker)

类型属性键属性值
mintbonded_ratio{bondedRatio}
mintinflation{inflation}
mintannual_provisions{annualProvisions}
mintamount{amount}

客户端

CLI

用户可以使用 CLI 查询并与 mint 模块交互。

查询

query 命令允许用户查询 mint 状态。
simd query mint --help
年度增发量(annual-provisions)
annual-provisions 命令允许用户查询当前铸造年度增发量的值
simd query mint annual-provisions [flags]
示例:
simd query mint annual-provisions
示例输出:
22268504368893.612100895088410693
通胀率(inflation)
inflation 命令允许用户查询当前铸造通胀率的值
simd query mint inflation [flags]
示例:
simd query mint inflation
示例输出:
0.199200302563256955
参数(params)
params 命令允许用户查询当前铸造参数
simd query mint params [flags]
示例:
blocks_per_year: "4360000"
goal_bonded: "0.670000000000000000"
inflation_max: "0.200000000000000000"
inflation_min: "0.070000000000000000"
inflation_rate_change: "0.130000000000000000"
max_supply: "0"
mint_denom: stake

gRPC

用户可以使用 gRPC 端点查询 mint 模块。

年度增发量(AnnualProvisions)

AnnualProvisions 端点允许用户查询当前铸造年度增发量的值
/cosmos.mint.v1beta1.Query/AnnualProvisions
示例:
grpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/AnnualProvisions
示例输出:
{
  "annualProvisions": "1432452520532626265712995618"
}

通胀率(Inflation)

Inflation 端点允许用户查询当前铸造通胀率的值
/cosmos.mint.v1beta1.Query/Inflation
示例:
grpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/Inflation
示例输出:
{
  "inflation": "130197115720711261"
}

参数(Params)

Params 端点允许用户查询当前铸造参数
/cosmos.mint.v1beta1.Query/Params
示例:
grpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/Params
示例输出:
{
  "params": {
    "mintDenom": "stake",
    "inflationRateChange": "130000000000000000",
    "inflationMax": "200000000000000000",
    "inflationMin": "70000000000000000",
    "goalBonded": "670000000000000000",
    "blocksPerYear": "6311520",
    "maxSupply": "0"
  }
}

REST

用户可以使用 REST 端点查询 mint 模块。

年度增发量(annual-provisions)

/cosmos/mint/v1beta1/annual_provisions
示例:
curl "localhost:1317/cosmos/mint/v1beta1/annual_provisions"
示例输出:
{
  "annualProvisions": "1432452520532626265712995618"
}

通胀率(inflation)

/cosmos/mint/v1beta1/inflation
示例:
curl "localhost:1317/cosmos/mint/v1beta1/inflation"
示例输出:
{
  "inflation": "130197115720711261"
}

参数(params)

/cosmos/mint/v1beta1/params
示例:
curl "localhost:1317/cosmos/mint/v1beta1/params"
示例输出:
{
  "params": {
    "mintDenom": "stake",
    "inflationRateChange": "130000000000000000",
    "inflationMax": "200000000000000000",
    "inflationMin": "70000000000000000",
    "goalBonded": "670000000000000000",
    "blocksPerYear": "6311520",
    "maxSupply": "0"
  }
}

The x/mint module handles the regular minting of new tokens in a configurable manner.

Contents

Concepts

The Minting Mechanism

The default minting mechanism was designed to:
  • allow for a flexible inflation rate determined by market demand targeting a particular bonded-stake ratio
  • effect a balance between market liquidity and staked supply
In order to best determine the appropriate market rate for inflation rewards, a moving change rate is used. The moving change rate mechanism ensures that if the % bonded is either over or under the goal %-bonded, the inflation rate will adjust to further incentivize or disincentivize being bonded, respectively. Setting the goal %-bonded at less than 100% encourages the network to maintain some non-staked tokens which should help provide some liquidity. It can be broken down in the following way:
  • If the actual percentage of bonded tokens is below the goal %-bonded the inflation rate will increase until a maximum value is reached
  • If the goal % bonded (67% in Cosmos-Hub) is maintained, then the inflation rate will stay constant
  • If the actual percentage of bonded tokens is above the goal %-bonded the inflation rate will decrease until a minimum value is reached

Custom Minters

As of Cosmos SDK v0.53.0, developers can set a custom MintFn for the module for specialized token minting logic. The function signature that a MintFn must implement is as follows:
// MintFn defines the function that needs to be implemented in order to customize the minting process.
type MintFn func(ctx sdk.Context, k *Keeper)

error
This can be passed to the Keeper upon creation with an additional Option:
app.MintKeeper = mintkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[minttypes.StoreKey]),
		app.StakingKeeper,
		app.AccountKeeper,
		app.BankKeeper,
		authtypes.FeeCollectorName,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		// mintkeeper.WithMintFn(CUSTOM_MINT_FN), // custom mintFn can be added here
	)

Custom Minter DI Example

Below is a simple approach to creating a custom mint function with extra dependencies in DI configurations. For this basic example, we will make the minter simply double the supply of foo coin. First, we will define a function that takes our required dependencies, and returns a MintFn.
// MyCustomMintFunction is a custom mint function that doubles the supply of `foo` coin.
func MyCustomMintFunction(bank bankkeeper.BaseKeeper)

mintkeeper.MintFn {
    return func(ctx sdk.Context, k *mintkeeper.Keeper)

error {
    supply := bank.GetSupply(ctx, "foo")
    err := k.MintCoins(ctx, sdk.NewCoins(supply.Add(supply)))
    if err != nil {
    return err
}

return nil
}
}
Then, pass the function defined above into the depinject.Supply function with the required dependencies.
// NewSimApp returns a reference to an initialized SimApp.
func NewSimApp(
    logger log.Logger,
    db dbm.DB,
    traceStore io.Writer,
    loadLatest bool,
    appOpts servertypes.AppOptions,
    baseAppOptions ...func(*baseapp.BaseApp),
) *SimApp {
    var (
        app        = &SimApp{
}

appBuilder *runtime.AppBuilder
        appConfig = depinject.Configs(
            AppConfig,
            depinject.Supply(
                appOpts,
                logger,
                // our custom mint function with the necessary dependency passed in.
                MyCustomMintFunction(app.BankKeeper),
            ),
        )
	)
	// ...
}

State

Minter

The minter is a space for holding current inflation information.
  • Minter: 0x00 -> ProtocolBuffer(minter)
// Reference: https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/mint/v1beta1/mint.proto#L10-L24

Params

The mint module stores its params in state with the prefix of 0x01, it can be updated with governance or the address with authority. Note: The MaxSupply parameter controls the maximum supply of tokens the module can mint. A value of 0 indicates an unlimited supply.
  • Params: mint/params -> legacy_amino(params)
// Reference: https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/mint/v1beta1/mint.proto#L26-L59

Begin-Block

Minting parameters are recalculated and inflation paid at the beginning of each block.

Inflation rate calculation

Inflation rate is calculated using an “inflation calculation function” that’s passed to the NewAppModule function. If no function is passed, then the SDK’s default inflation function will be used (NextInflationRate). In case a custom inflation calculation logic is needed, this can be achieved by defining and passing a function that matches InflationCalculationFn’s signature.
type InflationCalculationFn func(ctx sdk.Context, minter Minter, params Params, bondedRatio math.LegacyDec)

math.LegacyDec

NextInflationRate

The target annual inflation rate is recalculated each block. 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%.
NextInflationRate(params Params, bondedRatio math.LegacyDec) (inflation math.LegacyDec) {
    inflationRateChangePerYear = (1 - bondedRatio/params.GoalBonded) * params.InflationRateChange
	inflationRateChange = inflationRateChangePerYear/blocksPerYr

	// increase the new annual inflation for this next block
	inflation += inflationRateChange
    if inflation > params.InflationMax {
    inflation = params.InflationMax
}
    if inflation < params.InflationMin {
    inflation = params.InflationMin
}

return inflation
}

NextAnnualProvisions

Calculate the annual provisions based on current total supply and inflation rate. This parameter is calculated once per block.
NextAnnualProvisions(params Params, totalSupply math.LegacyDec) (provisions math.LegacyDec) {
    return Inflation * totalSupply

BlockProvision

Calculate the provisions generated for each block based on current annual provisions. The provisions are then minted by the mint module’s ModuleMinterAccount and then transferred to the auth’s FeeCollector ModuleAccount.
BlockProvision(params Params)

sdk.Coin {
    provisionAmt = AnnualProvisions/ params.BlocksPerYear
	return sdk.NewCoin(params.MintDenom, provisionAmt.Truncate())

Parameters

The minting module contains the following parameters:
KeyTypeExample
MintDenomstring”uatom”
InflationRateChangestring (dec)“0.130000000000000000”
InflationMaxstring (dec)“0.200000000000000000”
InflationMinstring (dec)“0.070000000000000000”
GoalBondedstring (dec)“0.670000000000000000”
BlocksPerYearstring (uint64)“6311520”
MaxSupplystring (math.Int)“0”
A MaxSupply value of 0 means no maximum supply is enforced. Minting stops automatically once the total supply reaches the configured MaxSupply. For legacy Amino JSON compatibility, max_supply is encoded even when set to "0".

Events

The minting module emits the following events:

BeginBlocker

TypeAttribute KeyAttribute Value
mintbonded_ratio{bondedRatio}
mintinflation{inflation}
mintannual_provisions{annualProvisions}
mintamount{amount}

Client

CLI

A user can query and interact with the mint module using the CLI.

Query

The query commands allows users to query mint state.
simd query mint --help
annual-provisions
The annual-provisions command allows users to query the current minting annual provisions value
simd query mint annual-provisions [flags]
Example:
simd query mint annual-provisions
Example Output:
22268504368893.612100895088410693
inflation
The inflation command allows users to query the current minting inflation value
simd query mint inflation [flags]
Example:
simd query mint inflation
Example Output:
0.199200302563256955
params
The params command allows users to query the current minting parameters
simd query mint params [flags]
Example:
blocks_per_year: "4360000"
goal_bonded: "0.670000000000000000"
inflation_max: "0.200000000000000000"
inflation_min: "0.070000000000000000"
inflation_rate_change: "0.130000000000000000"
max_supply: "0"
mint_denom: stake

gRPC

A user can query the mint module using gRPC endpoints.

AnnualProvisions

The AnnualProvisions endpoint allows users to query the current minting annual provisions value
/cosmos.mint.v1beta1.Query/AnnualProvisions
Example:
grpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/AnnualProvisions
Example Output:
{
  "annualProvisions": "1432452520532626265712995618"
}

Inflation

The Inflation endpoint allows users to query the current minting inflation value
/cosmos.mint.v1beta1.Query/Inflation
Example:
grpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/Inflation
Example Output:
{
  "inflation": "130197115720711261"
}

Params

The Params endpoint allows users to query the current minting parameters
/cosmos.mint.v1beta1.Query/Params
Example:
grpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/Params
Example Output:
{
  "params": {
    "mintDenom": "stake",
    "inflationRateChange": "130000000000000000",
    "inflationMax": "200000000000000000",
    "inflationMin": "70000000000000000",
    "goalBonded": "670000000000000000",
    "blocksPerYear": "6311520",
    "maxSupply": "0"
  }
}

REST

A user can query the mint module using REST endpoints.

annual-provisions

/cosmos/mint/v1beta1/annual_provisions
Example:
curl "localhost:1317/cosmos/mint/v1beta1/annual_provisions"
Example Output:
{
  "annualProvisions": "1432452520532626265712995618"
}

inflation

/cosmos/mint/v1beta1/inflation
Example:
curl "localhost:1317/cosmos/mint/v1beta1/inflation"
Example Output:
{
  "inflation": "130197115720711261"
}

params

/cosmos/mint/v1beta1/params
Example:
curl "localhost:1317/cosmos/mint/v1beta1/params"
Example Output:
{
  "params": {
    "mintDenom": "stake",
    "inflationRateChange": "130000000000000000",
    "inflationMax": "200000000000000000",
    "inflationMin": "70000000000000000",
    "goalBonded": "670000000000000000",
    "blocksPerYear": "6311520",
    "maxSupply": "0"
  }
}