Incorrect Halving Period Reward Calculation Leads to Significant Token Emission Reduction
rewardDistribution applies the current post-halving block reward to every block since the last distribution, including blocks that occurred before the halving and should have received the higher rate. Distributions spanning a halving emit ~49% fewer tokens than the economic model intends.
Description
The rewardDistribution() function in MATToken contract incorrectly calculates rewards when distribution periods span across halving events. The function uses the current block reward rate (post-halving) for all blocks since the last distribution, including blocks that occurred before the halving when the reward rate should have been higher.
This issue causes the contract to emit significantly fewer tokens than intended by the economic design (approximately 49% fewer rewards when a distribution spans a halving event). As a result, stakers receive fewer rewards than they should, and the timeline to reach the maximum supply cap is substantially extended.
The issue occurs in the reward calculation where the function uses:
uint256 rewardAmount = blockReward * blocksPassed;
Where blockReward is the current block reward (after any halvings) and blocksPassed is the total number of blocks since the last distribution.
The function correctly detects when a halving has occurred:
uint256 lastDistributionPeriod = getHalvingPeriod(_lastRewardDistributionBlock);uint256 currentPeriod = getHalvingPeriod(block.number);if (currentPeriod > lastDistributionPeriod) {currentHalvingPeriod = currentPeriod;}
However, it only updates the currentHalvingPeriod variable without adjusting the reward calculation to account for the different reward rates before and after the halving.
Impact
- Reduced Token Emissions: The contract mints approximately 50% fewer tokens than intended when distributions span a halving event.
- Staker Rewards Reduction: Stakers receive fewer rewards than promised by the protocol design.
- Altered Emission Schedule: The token's maximum supply will be reached much later than intended.
- Economic Model Disruption: The intended token economic model is not functioning as designed.
A test simulating a reward distribution that spans a halving period demonstrated a 49% underemission compared to the expected reward.
Recommendation
Option 1: Per-Halving-Period Calculation. Modify the reward distribution function to calculate rewards separately for each halving period, summing per-period block reward times per-period block count.
Option 2: Cumulative Reward Tracking. Implement a cumulative reward tracking approach that increments rewards based on blocks and halving periods, computing newCumulativeRewards - _cumulativeRewardsAtLastDistribution at distribution time.
function rewardDistribution() external {uint256 newCumulativeRewards = calculateCumulativeRewards(block.number);uint256 rewardAmount = newCumulativeRewards - _cumulativeRewardsAtLastDistribution;_cumulativeRewardsAtLastDistribution = newCumulativeRewards;_lastRewardDistributionBlock = block.number;// continue with existing distribution logic}

