资讯详情

cosmos-sdk x/mint 模块完全指南:通胀铸币机制、自定义 MintFn 与查询接口

📅 2026/10/12 3:12:26 | 华诺云谱 👁 阅读
cosmos-sdk x/mint 模块完全指南:通胀铸币机制、自定义 MintFn 与查询接口
区块链【免费下载链接】cosmos-sdkFramework for building performant, customizable blockchains with native interoperability项目地址https://gitcode.com/gh_mirrors/co/cosmos-sdk点击查看免费下载x/mint是 Cosmos SDK 中负责按可配置策略周期性铸造新代币的模块它在每个区块开始时根据链上质押bonded比例动态调整年化通胀率并把铸出的代币转入FeeCollector模块账户。本文基于仓库内 x/mint/README.md 与x/mint目录下的 keeper、types、module、proto 等源码完整讲解其铸币机制、状态存储、Begin-Block 流程、七个核心参数、自定义 Minter 扩展点Cosmos SDK v0.53.0 引入的MintFn以及 CLI、gRPC、REST 三套查询方式帮助你掌握在自建链上配置与定制通胀铸币的完整方案。Concepts通胀铸币机制的设计目标默认铸币机制的设计目标有两点见 x/mint/README.md 的 The Minting Mechanism 一节允许由市场供需决定的弹性通胀率其锚点是某个目标质押比例goal %-bonded即目标 bonded 比例在市场流动性与质押供给之间取得平衡。为了实现这一点模块采用移动变化率moving change rate机制当实际质押比例偏离目标值时通胀率会向相反方向调整从而激励或抑制质押行为。把目标质押比例设定在 100% 以下Cosmos Hub 中为 67%能鼓励网络保留一部分未质押代币以提供流动性。该机制可以归纳为三条规则当实际质押代币比例低于目标比例时通胀率持续上升直到达到最大值InflationMax当实际质押比例等于目标比例Cosmos-Hub 为 67%时通胀率保持不变当实际质押比例高于目标比例时通胀率持续下降直到达到最小值InflationMin。这一逻辑的源码实现位于 x/mint/types/minter.go 的NextInflationRate方法中下文详述。State模块状态存储x/mint的状态由两个 collections 条目构成存储键定义在 x/mint/types/keys.go条目存储前缀内容Minter0x00当前通胀信息Inflation与AnnualProvisionsParams0x01模块参数可通过治理或具有 authority 的地址更新MinterMinter是存放当前通胀信息的空间对应 protobuf 消息定义见 proto/cosmos/mint/v1beta1/mint.proto// Minter represents the minting state. message Minter { // current annual inflation rate string inflation 1; // current annual expected provisions string annual_provisions 2; }两者均为cosmossdk.io/math.LegacyDec类型精度为 18 位小数的十进制数。初始 Minter 由 genesis 写入仓库默认初始通胀率为 13%见 x/mint/types/minter.go 的DefaultInitialMinter。ParamsParams以0x01为前缀存入状态可通过治理提案或 authority 地址默认是x/gov模块账户更新。注意最新版本新增了MaxSupply参数用于控制模块铸造代币的最大供应量值为0表示无上限。完整字段定义同样位于 proto/cosmos/mint/v1beta1/mint.protomessage Params { // type of coin to mint string mint_denom 1; // maximum annual change in inflation rate string inflation_rate_change 2; // maximum inflation rate string inflation_max 3; // minimum inflation rate string inflation_min 4; // goal of percent bonded atoms string goal_bonded 5; // expected blocks per year uint64 blocks_per_year 6; // maximum supply for the token. // // A value of 0 indicates an unlimited (infinite) maximum supply. string max_supply 7; }所有 decimal 字段inflation_rate_change、inflation_max、inflation_min、goal_bonded都带有amino.dont_omitempty true选项因此在 legacy Amino JSON 兼容编码中即使是0也会被编码输出。Begin-Block每区块的铸币流程铸币参数在每个区块开始时重新计算并支付通胀奖励Begin-Block 阶段执行。入口函数在 x/mint/abci.go// BeginBlocker mints new tokens for the previous block. func BeginBlocker(ctx context.Context, k keeper.Keeper) error { defer telemetry.ModuleMeasureSince(types.ModuleName, telemetry.Now(), telemetry.MetricKeyBeginBlocker) sdkCtx : sdk.UnwrapSDKContext(ctx) return k.MintFn(sdkCtx) }BeginBlocker只是透传调用 Keeper 的MintFn。Keeper 在创建时默认挂载DefaultMintFn见 x/mint/keeper/keeper.go 的NewKeeper也可通过WithMintFn选项替换见下文自定义 Minter一节。默认铸币函数 DefaultMintFn 的完整调用链DefaultMintFn的实现位于 x/mint/keeper/mint.go其执行顺序如下从状态读取minter与params通过 staking keeper 获取totalStakingSupply总质押供给与bondedRatio质押比例调用通胀计算函数ic(ctx, minter, params, bondedRatio)更新minter.Inflation调用minter.NextAnnualProvisions(params, totalStakingSupply)更新年化供给将更新后的minter写回状态调用minter.BlockProvision(params)计算本区块铸币数量MaxSupply 截断检查可选功能当MaxSupply非零且totalSupply mintedCoin MaxSupply时把铸币量裁剪为MaxSupply - totalSupply若总供给已超过上限则本次不铸币diff置为 0该参数独立于铸币流程本身代币总量调整包括销毁由外部模块负责通过 bank keeper 的MintCoins从ModuleMinterAccount即mint模块账户铸造代币sdk.NewCoins会自动跳过零金额见 x/mint/keeper/keeper.go 的MintCoins通过AddCollectedFees内部调用SendCoinsFromModuleToModule把代币转入auth模块的FeeCollector模块账户发射mint类型事件并更新遥测指标。这段 MaxSupply 逻辑的源码如下x/mint/keeper/mint.gomaxSupply : params.MaxSupply totalSupply : k.bankKeeper.GetSupply(ctx, params.MintDenom).Amount // fetch total supply from the bank module // if maxSupply is not infinite, and minted coins exceeds maxSupply, adjust minted coins to be the diff if !maxSupply.IsZero() totalSupply.Add(mintedCoin.Amount).GT(maxSupply) { // calculate the difference between maxSupply and totalSupply diff : maxSupply.Sub(totalSupply) if diff.Sign() -1 { // mint nothing if total supply already exceeds max supply diff sdkmath.ZeroInt() } // mint the difference mintedCoin.Amount diff }对应的事件发射x/mint/keeper/mint.goctx.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()), ), )通胀率计算InflationCalculationFn通胀率由通胀计算函数inflation calculation function计算它通过NewAppModule传入。注意版本变化在 Cosmos SDK v0.53 中该参数已弃用——NewAppModule的ic参数必须传nil否则会直接 panic见 x/mint/module.go自定义通胀计算逻辑现在应通过WithMintFn(mintkeeper.DefaultMintFn(customIC))的方式传入自定义的InflationCalculationFn。函数签名定义在 x/mint/types/genesis.gotype InflationCalculationFn func(ctx context.Context, minter Minter, params Params, bondedRatio math.LegacyDec) math.LegacyDec默认实现DefaultInflationCalculationFn只是透传调用minter.NextInflationRate(params, bondedRatio)。NextInflationRate通胀率如何随质押比例调整目标年化通胀率每个区块重新计算一次调整幅度取决于与目标比例67%的距离。年化通胀率变化上限为 13%/年通胀率整体被钳制在 7% 到 20% 之间。源码x/mint/types/minter.gofunc (m Minter) NextInflationRate(params Params, bondedRatio math.LegacyDec) math.LegacyDec { // (1 - bondedRatio/GoalBonded) * InflationRateChange inflationRateChangePerYear : math.LegacyOneDec(). Sub(bondedRatio.Quo(params.GoalBonded)). Mul(params.InflationRateChange) inflationRateChange : inflationRateChangePerYear.Quo(math.LegacyNewDec(int64(params.BlocksPerYear))) // adjust the new annual inflation for this next block inflation : m.Inflation.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 }关键推导关系inflationRateChangePerYear (1 - bondedRatio / GoalBonded) * InflationRateChange每区块变化量 年变化量 /BlocksPerYear当bondedRatio GoalBonded时该值为正通胀上升等于时为零通胀不变大于时为负通胀下降最终结果被InflationMax与InflationMin双向钳制。NextAnnualProvisions年化铸币总量根据当前总供给与通胀率计算年化铸币总量每个区块计算一次x/mint/types/minter.gofunc (m Minter) NextAnnualProvisions(_ Params, totalSupply math.Int) math.LegacyDec { return m.Inflation.MulInt(totalSupply) }即AnnualProvisions Inflation × totalSupply。BlockProvision每区块铸币量根据年化铸币总量与BlocksPerYear计算每个区块的铸币量随后由mint模块账户铸造并转给auth的FeeCollector模块账户x/mint/types/minter.gofunc (m Minter) BlockProvision(params Params) sdk.Coin { provisionAmt : m.AnnualProvisions.QuoInt(math.NewInt(int64(params.BlocksPerYear))) return sdk.NewCoin(params.MintDenom, provisionAmt.TruncateInt()) }即BlockProvision AnnualProvisions / BlocksPerYear向下截断为整数代币mint_denom对应面额。自定义 MinterMintFn 与 WithMintFn从Cosmos SDK v0.53.0开始开发者可以通过设置自定义MintFn实现专门的代币铸币逻辑。MintFn的类型定义与执行入口位于 x/mint/keeper/mint.go// 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传入自定义MintFnWithMintFn定义在 x/mint/keeper/keeper.goapp.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 )这段代码与仓库中 simapp/app.go 的真实实例化方式一致simapp 中保留了WithMintFn的注释示例。注意NewKeeper内部总是先以DefaultMintFn(types.DefaultInflationCalculationFn)初始化WithMintFn选项随后覆盖它。自定义 Minter 的 DI 示例下面是一个在 DI依赖注入配置中创建带额外依赖的自定义铸币函数的简单示例——让 minter 直接把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, 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), ), ) ) // ... }DI 装配的底层支持位于 x/mint/module.go 的ProvideModuleModuleInputs中声明了MintFn keeper.MintFnoptional:true当它非空时会被包装为keeper.WithMintFn(in.MintFn)传入NewKeeper。测试验证仓库 x/mint/keeper/mint_test.go 提供了两个对照测试TestDefaultMintFn_Success设置 staking supply 为1_000_000_000、bondedRatio 为0.50断言通胀率与年化供给按默认公式更新且mint事件被发射TestCustomMintFn通过keeper.WithMintFn(customMintFn)注入自定义函数铸 50 个custom币并发射custom_mint事件断言 minter 值与自定义事件均生效。Parameters七个核心参数详解x/mint模块包含以下参数MaxSupply为0表示无上限Key类型默认值示例MintDenomstringuatomInflationRateChangestring (dec)0.130000000000000000InflationMaxstring (dec)0.200000000000000000InflationMinstring (dec)0.070000000000000000GoalBondedstring (dec)0.670000000000000000BlocksPerYearstring (uint64)6311520MaxSupplystring (math.Int)0默认值在 x/mint/types/params.go 的DefaultParams中定义InflationRateChange 13%、InflationMax 20%、InflationMin 7%、GoalBonded 67%、BlocksPerYear 60 * 60 * 8766 / 5即假设 5 秒一个区块的一年区块数约 6311520、MaxSupply 0无限供给。参数校验规则Params.Validate位于同一文件mint_denom不能为空且必须通过sdk.ValidateDenominflation_rate_change不能为 nil、不能为负、不能大于 1inflation_max/inflation_min不能为 nil、不能为负、不能大于 1goal_bonded必须为正、不能大于 1blocks_per_year必须为正且不超过MaxInt64max_supply不能为负额外约束inflation_max必须大于等于inflation_min。参数更新通过MsgUpdateParams消息完成处理逻辑在 x/mint/keeper/msg_server.go 的UpdateParams——先校验msg.Authority是否匹配 keeper 的authority默认x/gov模块账户再校验新参数最后写入状态。对应的 CLI 命令是simd tx mint update-params-proposal [params]定义见 x/mint/autocli.go注意要求提供完整参数可通过simd query mint params --output json查看字段格式。Events模块事件铸币模块在 BeginBlocker 中发射mint类型事件事件常量定义于 x/mint/types/events.go发射逻辑在 x/mint/keeper/mint.goTypeAttribute KeyAttribute Valuemintbonded_ratio{bondedRatio}mintinflation{inflation}mintannual_provisions{annualProvisions}mintamount{amount}Genesis 初始化模块的 genesis 状态由Minter与Params两部分组成proto/cosmos/mint/v1beta1/genesis.proto。InitGenesis会把二者写入 collections 存储并确保mint模块账户存在ExportGenesis则反向导出x/mint/keeper/genesis.go。默认 genesis 使用DefaultInitialMinter()通胀率 13%与DefaultParams()x/mint/types/genesis.go。当前模块共识版本为ConsensusVersion 3x/mint/module.go并注册了从 v2 到 v3 的迁移对应MaxSupply参数的引入见 x/mint/keeper/migrator.go。ClientCLI、gRPC 与 REST 查询CLI用户可以通过 CLI 查询与交互mint模块AutoCLI 命令定义见 x/mint/autocli.gosimd query mint --helpannual-provisions——查询当前年化铸币量simd query mint annual-provisions [flags]示例输出22268504368893.612100895088410693inflation——查询当前通胀率simd query mint inflation [flags]示例输出0.199200302563256955params——查询当前铸币参数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 mint_denom: stake max_supply: 0gRPCgRPC 查询服务定义于 proto/cosmos/mint/v1beta1/query.proto三个 RPC 端点分别对应Params、Inflation、AnnualProvisions。实现位于 x/mint/keeper/grpc_query.go它们直接从 collections 存储读取Params条目或Minter条目的字段。AnnualProvisions/cosmos.mint.v1beta1.Query/AnnualProvisionsgrpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/AnnualProvisions示例输出{ annualProvisions: 1432452520532626265712995618 }Inflation/cosmos.mint.v1beta1.Query/Inflationgrpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/Inflation示例输出{ inflation: 130197115720711261 }Params/cosmos.mint.v1beta1.Query/Paramsgrpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/Params示例输出{ params: { mintDenom: stake, inflationRateChange: 130000000000000000, inflationMax: 200000000000000000, inflationMin: 70000000000000000, goalBonded: 670000000000000000, blocksPerYear: 6311520, maxSupply: 0, } }RESTREST 端点与 gRPC 服务一一对应HTTP GET 路由注解同样定义于 proto/cosmos/mint/v1beta1/query.proto由 gRPC Gateway 提供annual-provisions/cosmos/mint/v1beta1/annual_provisionscurl localhost:1317/cosmos/mint/v1beta1/annual_provisions示例输出{ annualProvisions: 1432452520532626265712995618 }inflation/cosmos/mint/v1beta1/inflationcurl localhost:1317/cosmos/mint/v1beta1/inflation示例输出{ inflation: 130197115720711261 }params/cosmos/mint/v1beta1/paramscurl localhost:1317/cosmos/mint/v1beta1/params示例输出{ params: { mintDenom: stake, inflationRateChange: 130000000000000000, inflationMax: 200000000000000000, inflationMin: 70000000000000000, goalBonded: 670000000000000000, blocksPerYear: 6311520, maxSupply: 0, } }小结x/mint模块通过目标质押比例 移动变化率机制实现弹性通胀每个区块开始时由BeginBlocker触发MintFn依次计算通胀率、年化铸币量、每区块铸币量经MaxSupply上限检查后从mint模块账户铸币并转入FeeCollector。从 v0.53.0 起MintFn与WithMintFn提供了完整的状态级自定义入口InflationCalculationFn则可在保留默认流程的前提下替换通胀计算公式配合MaxSupply上限参数、MsgUpdateParams治理更新以及 CLI/gRPC/REST 三套查询接口开发者可以按需塑造自建链的代币发行策略。需要动手实践时可参考仓库的 simapp/app.go 中的 Keeper 装配方式以及 x/mint/keeper/mint_test.go 中的默认/自定义铸币函数测试用例。赞分享区块链【免费下载链接】cosmos-sdkFramework for building performant, customizable blockchains with native interoperability项目地址https://gitcode.com/gh_mirrors/co/cosmos-sdk点击查看免费下载相关推荐Diem 框架核心模块深度解析0x1::Diem 货币体系、铸造Mint与销毁Burn机制全指南Diem 框架核心模块深度解析 0x1::Diem 货币体系、铸造Mint与销毁Burn机制全指南 导读 本文以 Diem 框架Diem Fram区块链金融科技yuzu Switch 模拟器使用指南30 秒判定硬件 5 步跑通第一款游戏yuzu Switch 模拟器使用指南30 秒判定硬件 5 步跑通第一款游戏 yuzu 是一款免费开源的 Switch 模拟器用软件完整还原 CPU、内虚拟化图形学逆向工程Cosmos SDK x/epochs 模块完全指南链上定时器、Epoch 钩子与跨模块周期调度Cosmos SDK x/epochs 模块完全指南链上定时器、Epoch 钩子与跨模块周期调度 导读 x/epochs 是 Cosmos SDK 中负责提供区块链上一篇MJRefresh 与代码覆盖率工具使用 Slather 生成覆盖率报告下一篇15分钟打造专业图标选择器react-icons组件开发指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑