Conversation
- Pre-stage Y1 yearMintRemainder in initInflationState so the final-block flush is non-zero (the boundary branch only fires from Y2+). - Cache parsed MachinaDaoAddress on *Protocol; mintAndAllocate no longer reparses the bech32 string each block. - Document Machina credit semantics: pure AddBalance, no receive() / fallback() runs - DAO contract must tolerate passive balance accrual. - Add TestMintAndAllocate_FundInvariant covering high-mint and floor regimes; default MachinaDaoAddress in testProtocol harness. - Drop unused decrementOutstandingSupply / MachinaDaoAddr helper; rewrite base-fee comments to reflect IoTeX's deposit-to-pool reality (not burn). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add TestMintAndAllocate_ReorgSafe_YearBoundary: walk Y1 to its last block, snapshot (inflation, fund, machina) state, execute the Y2-first block, then restore pre-boundary state and re-execute. Assert post-states are byte- identical. Covers the validator-orphan case where the boundary block is re-applied; relies on persisted currentYearIndex to make the boundary branch re-fire deterministically. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
envestcc
reviewed
Jun 16, 2026
| // IsYearBoundary reports whether height is the first block of a new Year ≥ 2. | ||
| // The activation block itself is the start of Year 1 and returns false here — its | ||
| // initialization is the activation hook, not a year transition. | ||
| func IsYearBoundary(activation, blocksPerYear, height uint64) bool { |
… year-boundary writes InflationState was putState'd every block because several fields mutated per-block. They are all deterministic, so store only the year-boundary fields and derive the rest, dropping the per-block _inflKey write (archive growth for this key goes from per-block to once/year). - SplitMint is now stateless: staker = floor(mTotal*bps/denom), Machina = mTotal - staker. Conserves mTotal exactly; drops the dustStaker/dustMachina accumulators (sub-Rau per-block bias, negligible over the chain's lifetime). - outstandingSupply, postActivationMinted, epochRemainderAccumulator, and yearMintRemainder are no longer stored. OutstandingSupply/PostActivationMinted are derived via CumulativeMinted (snapshot + query height from p.state); the year-end remainder is recomputed on the final block; the epoch surplus is derived in closed form via EpochInflationSurplus over the epoch's block range. - mintAndAllocate persists InflationState only on year-boundary blocks; the year-start snapshot is recomputed via the genesis recurrence (ComputeYearStartSupply), which is reorg-deterministic. - proto: reserve fields 1,3,6,7,8,9; InflationState keeps only outstandingSupplyAtYearStart, currentInflationBps, currentYearIndex. Note: EpochInflationSurplus assumes a constant block reward across an epoch (holds post-Wake, where IIP-62 activates). Tests: brute-force cross-checks for CumulativeMinted and EpochInflationSurplus (single-year, year-final, straddle, pre-activation); end-to-end getter coverage via a fixed-height StateReader; fund-invariant and reorg tests updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Implements IIP-62 productive inflation: post-activation, a per-block protocol mint replaces the fixed block/epoch reward, split 80/20 between the staker reward pool and the Machina DAO along the 5‑20‑Half disinflation curve. The curve and split follow the proposal; the notes below cover where this implementation makes decisions the spec does not pin down.
Implementation decisions (beyond IIP-62)
InflationStatepersists only the three year‑boundary fields (outstandingSupplyAtYearStart,currentInflationBps,currentYearIndex). The running supply, cumulative mint, per‑year remainder, and epoch surplus are recomputed on demand (deterministic from genesis + height), so the record is written once per year instead of every block — archive growth for the"inf"key stays bounded.OutstandingSupply/PostActivationMintedderive their answer at the query height.SplitMintis stateless:staker = ⌊mTotal·bps/denom⌋,Machina = mTotal − staker. ConservesmTotalexactly every block; the sub‑Rau truncation biases toward Machina (well under a micro‑IOTX over the chain's lifetime), so no per‑block dust accumulator is carried.EpochInflationSurplus) rather than a stored accumulator. Assumes the block reward is constant within an epoch — holds post‑Wake, where IIP-62 activates.effective_block_reward = min(blockReward, mStaker)so grants track down past the Y12+ floor and the fund never underflows.ToBeEnabledBlockHeightgate (no new hardfork field).OutstandingSupplyAtActivationis a genesis‑pinned snapshot of circulating supply atactivation‑1(produced by a forthcoming snapshot subcommand).AddBalance) — no EVM call into the recipient, which must tolerate passive accrual (a multisig / Safe works natively; a contract relying onreceive()for internal accounting would not see it).OutstandingSupplyonly grows; there is no burn‑side debit.Tests
go test ./action/protocol/rewarding/...— curve spec values (§1.1 / §1.3) and 20‑year table walk; the per‑block and epoch derivations cross‑checked against brute‑force per‑block sums (single‑year, year‑final, straddle, pre‑activation); fund‑invariant and reorg‑safety walks; and end‑to‑endOutstandingSupply/PostActivationMintedgetter coverage.Follow-ups (not in this PR)
Snapshot subcommand for
OutstandingSupplyAtActivation; e2e activation + replay test across a compressed Y1→Y2 boundary; Machina DAO multisig (externally generated — this PR only credits the balance).Dependency
The paired
iotex-protoPR adding theINFLATION_MINT_{STAKER,MACHINA}transaction‑log types must merge first;go.modpins to it.🤖 Generated with Claude Code