v8.1.0 Release Notes
Upgrade Handler
- Runs module-level migrations: tradebin v3→v4, rewards v3→v4, txfeecollector v1→v2
- Tradebin v3→v4 migration also handles order key precision migration
- Store upgrades: removes
crisismodule store
App-Level Changes
- Removed
crisismodule entirely (keeper, begin/end blocker, module config, invariant registration) - Removed
TxFeeConverterHookfrom epoch hooks — fee conversion now handled in txfeecollector EndBlock RewardsKeeperandTxfeecollectorKeeperchanged to pointer typesDeductFeeDecoratornow receivesTxCollectorKeeperinstead ofTxFeeCheckerfor dynamic min gas price calculation- Registered
txfeecollector_burnerandtxfeecollector_cpmodule accounts with fund-receive permissions - Upgrade handler simplified — no longer needs bank/distr/account keepers or params/consensus keepers
- Go version bumped from 1.23 to 1.25
cosmos-sdkdependency updated from v0.50.14 to v0.50.15cometbftdependency updated to v0.38.21- Removed redundant event emission in
bzeutils/safe_ctx_write.go
CI / Build
- Added
test.ymlworkflow: runs keeper and types tests viascripts/testing/test-package.shon push to main and PRs - Makefile: build output binaries now include arch suffix (e.g.
bzed-linux-amd64), Go version check updated to 1.25, removed--x-crisis-skip-assert-invariantsfrom localnet start
Module Changes
Burner (x/burner)
No new parameters introduced. Existing periodic_burning_weeks validation tightened to require value > 0.
Changes:
- Queued periodic burning: burns now processed at EndBlock in bounded batches (up to 100 denoms/block) instead of synchronously in epoch hooks
- Queued raffle cleanup: expired raffles processed at EndBlock in bounded batches (up to 50/block) instead of synchronously in epoch hooks
- IBC token burn strategy changed from
ModuleSwapForNativeDenomtoModuleAddLiquidityWithNativeDenom MsgFundBurnernow classifies coins before sending: lockable (LP) to black hole, burnable/exchangeable to burner module- Added
MsgMoveIbcLockedCoins(permissionless) to move locked IBC coins from the black-hole account into liquidity pools paired with native BZE - Raffle participation rate-limited to 200 participants per block height
- Minimum pot enforcement: raffles require at least 100,000 smallest units
- Stricter raffle expiration check: rejects joins when 2 or fewer epochs remain
GetRaffleCurrentEpoch()now returns(uint64, error)usingSafeGetEpochCountByIdentifierfor proper error handling- Telemetry metric key in EndBlock corrected from
MetricKeyBeginBlockertoMetricKeyEndBlocker - TradeKeeper marked as mandatory dependency to prevent nil pointer issues
Epochs (x/epochs)
- Added
SafeGetEpochCountByIdentifier: returns error when epoch is not found or is catching up (block time past epoch end), used by burner and rewards for safer epoch access
CoinTrunk (x/cointrunk)
No new parameters introduced. Existing parameter validation improved.
Changes:
SetArticlenow takes a pointer receiver, allowing the caller to observe the auto-incremented article ID- Publisher respect tax validation now enforces strict bounds (0 < tax < 1), rejecting values >= 100%
- Removed impossible
uint64 < 0check invalidateAnonArticleLimit
Rewards (x/rewards)
New parameters:
| Parameter | Type | Default | Purpose |
|---|---|---|---|
extra_gas_for_exit_stake |
uint64 |
1,000,000 |
Extra gas consumed when a user exits a staking reward via MsgExitStaking. Introduced to prevent spam/DoS on the exit-stake operation, which triggers unlock queue processing and fund transfers. |
Changes:
- All reward operations moved from synchronous epoch hooks to bounded queue-based processing at EndBlock (up to 100 items/block): unlock participants, staking reward distribution, and trading reward expiration
- Removed
DistrKeeperdependency — creation fees now routed totxfeecollectormodule viaCaptureAndSwapUserFeeinstead ofFundCommunityPool - Expired pending trading rewards now send uncaptured tokens to the burner module instead of community pool
- Leaderboard sorting fix: old code compared the same value for both items; fixed to properly compare
a.Amountvsb.Amount - Trading hook now validates
tradedAmount.IsPositive()before processing - Small reward protection: if calculated reward truncates to zero,
JoinedAtis not updated - Maximum staking reward update duration increased from 10 years to 100 years
- Staking reward counter fix: no longer increments on every operation, only on creation
- Trading reward counter fix: only increments when creating new trading rewards
- Separate expiration logic for pending and active trading rewards
- Prevent claiming zero staking rewards (returns error instead of sending empty coins)
- Send funds immediately for zero lock duration instead of queueing unlock
- Positive staking reward amount validation added to
ValidateBasic - Prevent activation of multiple rewards for the same market (enforcement fix)
- Error handling for sending coins to trading reward winners (logged instead of ignored)
- Invalid leaderboard amounts now logged as errors
- Trade keeper availability validated before capturing staking reward fees
- ConsensusVersion bumped from 3 to 4
TokenFactory (x/tokenfactory)
No new parameters introduced.
Changes:
- Subdenom validation now disallows slash (
/) characters to prevent ambiguous denom paths - Creation fee routing changed from
FundCommunityPool(distribution keeper) toCaptureAndSwapUserFee(trade keeper) with forwarding to fee collector
TradeBin (x/tradebin)
New parameters:
| Parameter | Type | Default | Purpose |
|---|---|---|---|
order_book_extra_gas_window |
uint64 |
100 |
Queue depth threshold before gas surcharges kick in. When the queue counter exceeds this value, additional gas is charged per order submission to discourage spam during high-traffic periods. |
order_book_queue_extra_gas |
uint64 |
25,000 |
Gas charged per queued message when queue depth exceeds order_book_extra_gas_window. Formula: (queueCounter - window) * order_book_queue_extra_gas. Makes order submission progressively more expensive as the queue grows. |
order_book_queue_message_scan_extra_gas |
uint64 |
5,000 |
Gas consumed per queued message scanned during price validation of new orders. Prevents DoS via expensive iteration over large queues when checking order prices. |
fill_orders_extra_gas |
uint64 |
5,000 |
Gas consumed once on MsgFillOrders entry and again per order enqueued. Previously hardcoded; now governance-tunable to adapt to network conditions. |
order_book_per_block_messages |
uint64 |
500 |
Maximum queue messages processed per block in EndBlock. Caps throughput to prevent blocks from becoming too large; remaining messages stay queued. Counter resets only when the queue empties. |
min_native_liquidity_for_module_swap |
math.Int |
100,000,000,000 |
Minimum native reserves required in a pool before module-level swap/add-liquidity helpers execute. Prevents draining shallow pools during automated fee conversion or module-driven swaps. Replaces a previously hardcoded 50,000,000,000 threshold. |
Migrated parameters (string → sdk.Coin):
The v3→v4 migration converts fee fields from string to sdk.Coin for type safety:
create_market_fee(sdk.Coin, default25,000,000,000ubze)market_maker_fee(sdk.Coin, default1,000ubze)market_taker_fee(sdk.Coin, default100,000ubze)
Changes:
- Fee payer service (
CaptureAndSwapUserFee) for fee capture and conversion to native denom via liquidity pools - Queue-based order processing with bounded EndBlock execution
- Duplicate cancel prevention: pending cancel requests tracked via
HasPendingCancelto prevent duplicates - Queue message keys restructured to composite
{market}/{id}format for market-scoped queries - Order key precision migration: keys migrated from 24-char/10-decimal to 32-char/18-decimal format (module migration v3→v4)
MsgFillOrderslimited to 50 orders per transaction- Enforce unique prices in
MsgFillOrdersorder items - Fix consistent reserve computation by handling reversed assets in pool creation
- Liquidity pool existence check added to
MarketExistsfunction - Liquidity pool creation validation: both Base and Quote assets must be provided
- Order fill process improved: continues iteration through opposite orders when min amount is not met
ModuleSwapForNativeDenomreordered to capture coins first then swap; returns zero coin on error- Fallback to native denom when liquidity is insufficient for fee swaps
CalculateMinAmountnow returns error and is properly checked- History order index format changed to
{messageId}{orderId}for correct sorting - Genesis validation: order price validation added
MsgMultiSwaproute length validation corrected- Replaced
ErrUnauthorizedwithErrInvalidAddressfor invalid creator address errors - Fee denomination key replaced with
CtxFeeDenomKeyconstant - Precision improvement:
MulRawapplied beforeQuoRawfor better accuracy - Fee destination sum validation simplified (equality check replaces tolerance)
- Positive reserves validation added to AMM service
DistrKeeperremoved from tradebin dependencies — fee routing viaCaptureAndSwapUserFee- ConsensusVersion bumped from 3 to 4
TxFeeCollector (x/txfeecollector)
New parameters:
| Parameter | Type | Default | Purpose |
|---|---|---|---|
validator_min_gas_fee |
sdk.DecCoin |
0.01ubze |
Baseline minimum gas price enforced by the ante handler. When transactions pay in a non-native denom, the module converts this threshold using trade module spot prices. Only ubze denomination is accepted. Introduced to provide governance-tunable minimum gas pricing instead of relying solely on per-validator config. |
max_balance_iterations |
uint64 |
100 |
Caps the number of coin balances iterated during EndBlock fee conversion. Prevents unbounded iteration and gas exhaustion when the module holds many different denominations. |
Changes:
- Three-way fee distribution: fees split between validators/stakers, burner (
txfeecollector_burner), and community pool (txfeecollector_cp) via dedicated module accounts - Fee conversion moved from epoch hooks to EndBlock processing (
service_fees_handler.go) - Dynamic fee denomination validation: ante handler enforces single-denomination fees per transaction, uses
HasDeepLiquidityWithNativeDenomfor stricter liquidity checks, and tracks fee denom in context viaFeeDenomKey DeductFeeDecoratornow uses the module keeper directly withgetContextMinGasPrices()for dynamic min gas price calculation based on spot prices- Non-swappable coins forwarded to SDK fee collector when they cannot be converted to native denom
- ConsensusVersion bumped from 1 to 2
Upgrade Height
22551810